diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3fbaf10507cdda0aac9ac0f0efb12811a876f874..cd0831e508f5cb7f4d89f70eb2a0db7e4bee588b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,28 +1,28 @@ # This does not cover all the code in edx-platform but it's a good start. # Core -common/djangoapps/student/ @edx/platform-core -common/djangoapps/third_party_auth/ @edx/platform-authn -common/lib/xmodule/xmodule/ @edx/platform-core -lms/djangoapps/course_api/blocks @edx/platform-core -lms/djangoapps/courseware/ @edx/platform-core -lms/djangoapps/grades/ @edx/platform-grades -lms/djangoapps/instructor/ @edx/platform-core -lms/djangoapps/instructor_task/ @edx/platform-core -lms/djangoapps/mobile_api/ @edx/platform-mobile -openedx/core/djangoapps/contentserver/ @edx/platform-core -openedx/core/djangoapps/heartbeat/ @edx/platform-core -openedx/core/djangoapps/oauth_dispatch @edx/platform-authn -openedx/core/djangoapps/user_api/ @edx/platform-authn -openedx/core/djangoapps/user_authn/ @edx/platform-authn -openedx/features/course_experience/ @edx/platform-courseware +common/djangoapps/student/ +common/djangoapps/third_party_auth/ +common/lib/xmodule/xmodule/ +lms/djangoapps/course_api/blocks +lms/djangoapps/courseware/ +lms/djangoapps/grades/ +lms/djangoapps/instructor/ +lms/djangoapps/instructor_task/ +lms/djangoapps/mobile_api/ +openedx/core/djangoapps/contentserver/ +openedx/core/djangoapps/heartbeat/ +openedx/core/djangoapps/oauth_dispatch +openedx/core/djangoapps/user_api/ +openedx/core/djangoapps/user_authn/ +openedx/features/course_experience/ -# Core Extensions -common/lib/xmodule/xmodule/capa_module.py @edx/platform-core-extensions -common/lib/xmodule/xmodule/html_module.py @edx/platform-core-extensions -common/lib/xmodule/xmodule/video_module @edx/platform-core-extensions -lms/djangoapps/discussion/ @edx/platform-core-extensions -lms/djangoapps/edxnotes @edx/platform-core-extensions +# Core Extensions +common/lib/xmodule/xmodule/capa_module.py +common/lib/xmodule/xmodule/html_module.py +common/lib/xmodule/xmodule/video_module +lms/djangoapps/discussion/ +lms/djangoapps/edxnotes # Analytics common/djangoapps/track/ @edx/edx-data-engineering @@ -38,4 +38,4 @@ lms/djangoapps/experiments/ @edx/rev-team lms/djangoapps/learner_dashboard/ @edx/platform-discovery openedx/features/content_type_gating/ @edx/rev-team openedx/features/course_duration_limits/ @edx/rev-team -openedx/features/discounts/ @edx/rev-team \ No newline at end of file +openedx/features/discounts/ @edx/rev-team diff --git a/Makefile b/Makefile index 586ab8d88431dea81756e4fcc363e282f467ccf5..d07f2b5fb1df9982be47fc3d2c9a40072990b4d8 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,8 @@ pull: ## update the Docker image used by "make shell" docker pull edxops/edxapp:latest requirements: ## install development environment requirements - pip install -qr requirements/edx/development.txt --exists-action w + pip install -qr requirements/edx/pip-tools.txt + pip-sync -q requirements/edx/development.txt requirements/edx/private.* shell: ## launch a bash shell in a Docker container with all edx-platform dependencies installed docker run -it -e "NO_PYTHON_UNINSTALL=1" -e "PIP_INDEX_URL=https://pypi.python.org/simple" -e TERM \ @@ -95,7 +96,7 @@ upgrade: ## update the pip requirements files to use the latest releases satisfy done # Post process all of the files generated above to work around open pip-tools issues scripts/post-pip-compile.sh $(REQ_FILES:=.txt) - # Let tox control the Django version & django-oauth-toolkit version for tests - grep -e "^django==" -e "^django-oauth-toolkit==" requirements/edx/base.txt > requirements/edx/django.txt - sed '/^[dD]jango==/d;/^django-oauth-toolkit==/d' requirements/edx/testing.txt > requirements/edx/testing.tmp + # Let tox control the Django version for tests + grep -e "^django==" requirements/edx/base.txt > requirements/edx/django.txt + sed '/^[dD]jango==/d' requirements/edx/testing.txt > requirements/edx/testing.tmp mv requirements/edx/testing.tmp requirements/edx/testing.txt diff --git a/cms/djangoapps/api/v1/views/course_runs.py b/cms/djangoapps/api/v1/views/course_runs.py index 83531461b8d27a9347d8a55cef9638f4434b8dd8..662ac95368a0b8ef067913c229014f4e219750e5 100644 --- a/cms/djangoapps/api/v1/views/course_runs.py +++ b/cms/djangoapps/api/v1/views/course_runs.py @@ -20,7 +20,6 @@ from ..serializers.course_runs import ( ) -# pylint: disable=unused-argument class CourseRunViewSet(viewsets.GenericViewSet): authentication_classes = (JwtAuthentication, SessionAuthentication,) lookup_value_regex = settings.COURSE_KEY_REGEX diff --git a/cms/djangoapps/cms_user_tasks/apps.py b/cms/djangoapps/cms_user_tasks/apps.py index a35e142aaa884a0b12d7cec46c9028a00cc92977..6df4b7f953abb54d2765a9371b4cf40067928b88 100644 --- a/cms/djangoapps/cms_user_tasks/apps.py +++ b/cms/djangoapps/cms_user_tasks/apps.py @@ -17,4 +17,4 @@ class CmsUserTasksConfig(AppConfig): """ Connect signal handlers. """ - from . import signals # pylint: disable=unused-variable + from . import signals # pylint: disable=unused-import diff --git a/cms/djangoapps/cms_user_tasks/signals.py b/cms/djangoapps/cms_user_tasks/signals.py index 55d8288b0073a040de5602380886bb6538ed2908..f5fc8d7d030a19fe004580be7ba7c023df2e4c7b 100644 --- a/cms/djangoapps/cms_user_tasks/signals.py +++ b/cms/djangoapps/cms_user_tasks/signals.py @@ -10,7 +10,7 @@ from django.dispatch import receiver from user_tasks.models import UserTaskArtifact from user_tasks.signals import user_task_stopped -from six.moves.urllib.parse import urljoin # pylint: disable=import-error +from six.moves.urllib.parse import urljoin from .tasks import send_task_complete_email diff --git a/cms/djangoapps/contentstore/api/views/course_quality.py b/cms/djangoapps/contentstore/api/views/course_quality.py index caebbcf4c95180c1ee9935fd920f86217c8fc7e2..cbd262e7c81d8ef483b0bfd04e516e693a1e4ebc 100644 --- a/cms/djangoapps/contentstore/api/views/course_quality.py +++ b/cms/djangoapps/contentstore/api/views/course_quality.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - import logging import time diff --git a/cms/djangoapps/contentstore/api/views/course_validation.py b/cms/djangoapps/contentstore/api/views/course_validation.py index af5812fac46fa6d040f76ea92e2a1f657f076e1e..f230048d0e3c147cb4aa21ceb688e695c467488b 100644 --- a/cms/djangoapps/contentstore/api/views/course_validation.py +++ b/cms/djangoapps/contentstore/api/views/course_validation.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - import logging import dateutil diff --git a/cms/djangoapps/contentstore/apps.py b/cms/djangoapps/contentstore/apps.py index 00ad73d377a6f99700e7332978174b9d47824594..7f4bc6b37c38eaa8ac262e3bcff8dea02ef1b789 100644 --- a/cms/djangoapps/contentstore/apps.py +++ b/cms/djangoapps/contentstore/apps.py @@ -20,4 +20,4 @@ class ContentstoreConfig(AppConfig): """ # Can't import models at module level in AppConfigs, and models get # included from the signal handlers - from .signals import handlers # pylint: disable=unused-variable + from .signals import handlers # pylint: disable=unused-import diff --git a/cms/djangoapps/contentstore/config/waffle.py b/cms/djangoapps/contentstore/config/waffle.py index f1087c65205d0738d9373f5f3b91049f877206ef..021020c1f28073fd6d61669edb508fee874a9763 100644 --- a/cms/djangoapps/contentstore/config/waffle.py +++ b/cms/djangoapps/contentstore/config/waffle.py @@ -33,6 +33,7 @@ ENABLE_PROCTORING_PROVIDER_OVERRIDES = CourseWaffleFlag( flag_undefined_default=False ) +# TODO: After removing this flag, add a migration to remove waffle flag in a follow-up deployment. ENABLE_CHECKLISTS_QUALITY = CourseWaffleFlag( waffle_namespace=waffle_flags(), flag_name=u'enable_checklists_quality', diff --git a/cms/djangoapps/contentstore/course_info_model.py b/cms/djangoapps/contentstore/course_info_model.py index b32605f91269c655b65ee644730b2dcecabf9b1b..14d20e3162ef4d50574f3a45a6eef1bf488a6e56 100644 --- a/cms/djangoapps/contentstore/course_info_model.py +++ b/cms/djangoapps/contentstore/course_info_model.py @@ -57,20 +57,26 @@ def update_course_updates(location, update, passed_id=None, user=None): course_updates = modulestore().create_item(user.id, location.course_key, location.block_type, location.block_id) course_update_items = list(reversed(get_course_update_items(course_updates))) + course_update_dict = None if passed_id is not None: passed_index = _get_index(passed_id) - # oldest update at start of list - if 0 < passed_index <= len(course_update_items): - course_update_dict = course_update_items[passed_index - 1] - course_update_dict["date"] = update["date"] - course_update_dict["content"] = update["content"] - course_update_items[passed_index - 1] = course_update_dict - else: + + # if passed_index in course_update_items_ids: + for course_update_item in course_update_items: + if course_update_item["id"] == passed_index: + course_update_dict = course_update_item + course_update_item["date"] = update["date"] + course_update_item["content"] = update["content"] + break + if course_update_dict is None: return HttpResponseBadRequest(_("Invalid course update id.")) else: + course_update_items_ids = [course_update_item['id'] for course_update_item in course_update_items] + course_update_dict = { - "id": len(course_update_items) + 1, + # if no course updates then the id will be 1 otherwise maxid + 1 + "id": max(course_update_items_ids) + 1 if course_update_items_ids else 1, "date": update["date"], "content": update["content"], "status": CourseInfoBlock.STATUS_VISIBLE @@ -131,17 +137,15 @@ def delete_course_update(location, update, passed_id, user): passed_index = _get_index(passed_id) # delete update item from given index - if 0 < passed_index <= len(course_update_items): - course_update_item = course_update_items[passed_index - 1] - # soft delete course update item - course_update_item["status"] = CourseInfoBlock.STATUS_DELETED - course_update_items[passed_index - 1] = course_update_item - - # update db record - save_course_update_items(location, course_updates, course_update_items, user) - return _get_visible_update(course_update_items) - else: - return HttpResponseBadRequest(_("Invalid course update id.")) + for course_update_item in course_update_items: + if course_update_item["id"] == passed_index: + # soft delete course update item + course_update_item["status"] = CourseInfoBlock.STATUS_DELETED + # update db record + save_course_update_items(location, course_updates, course_update_items, user) + return _get_visible_update(course_update_items) + + return HttpResponseBadRequest(_("Invalid course update id.")) def _get_index(passed_id=None): diff --git a/cms/djangoapps/contentstore/git_export_utils.py b/cms/djangoapps/contentstore/git_export_utils.py index 78141fc761d793c8634d9b8a022a72388e3105cf..07c46322dd42b0911a996c020fd156ab2ecda3b8 100644 --- a/cms/djangoapps/contentstore/git_export_utils.py +++ b/cms/djangoapps/contentstore/git_export_utils.py @@ -13,7 +13,7 @@ from django.conf import settings from django.contrib.auth.models import User from django.utils import timezone from django.utils.translation import ugettext_lazy as _ -from six.moves.urllib.parse import urlparse # pylint: disable=import-error +from six.moves.urllib.parse import urlparse from xmodule.contentstore.django import contentstore from xmodule.modulestore.django import modulestore diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_cleanup_assets.py b/cms/djangoapps/contentstore/management/commands/tests/test_cleanup_assets.py index c106701dfd48fa1f6507073fa4244b9a817526ef..0f4441fbcb9ea162f7d4f3a46a2745c26e8f7da9 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_cleanup_assets.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_cleanup_assets.py @@ -64,9 +64,9 @@ class ExportAllCourses(ModuleStoreTestCase): query['_id.name'] = all_assets[0]['_id']['name'] asset_doc = self.content_store.fs_files.find_one(query) asset_doc['_id']['name'] = u'._example_test.txt' - self.content_store.fs_files.insert(asset_doc) + self.content_store.fs_files.insert_one(asset_doc) asset_doc['_id']['name'] = u'.DS_Store' - self.content_store.fs_files.insert(asset_doc) + self.content_store.fs_files.insert_one(asset_doc) # check that now course has four assets all_assets, count = self.content_store.get_all_content_for_course(course.id) diff --git a/cms/djangoapps/contentstore/migrations/0005_add_enable_checklists_quality_waffle_flag.py b/cms/djangoapps/contentstore/migrations/0005_add_enable_checklists_quality_waffle_flag.py new file mode 100644 index 0000000000000000000000000000000000000000..e0ca1c99e62849dd298c997f499e3c9fe8a6e941 --- /dev/null +++ b/cms/djangoapps/contentstore/migrations/0005_add_enable_checklists_quality_waffle_flag.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +from django.db import migrations + +from cms.djangoapps.contentstore.config.waffle import ENABLE_CHECKLISTS_QUALITY + + +def create_flag(apps, schema_editor): + Flag = apps.get_model('waffle', 'Flag') + # Replacement for flag_undefined_default=True on flag definition + Flag.objects.get_or_create(name=ENABLE_CHECKLISTS_QUALITY.namespaced_flag_name, defaults={'everyone': True}) + + +class Migration(migrations.Migration): + dependencies = [ + ('contentstore', '0004_remove_push_notification_configmodel_table'), + ('waffle', '0001_initial'), + ] + + operations = [ + # Do not remove the flag for rollback. We don't want to lose original if + # it already existed, and it won't hurt if it was created. + migrations.RunPython(create_flag, reverse_code=migrations.RunPython.noop), + ] diff --git a/cms/djangoapps/contentstore/tasks.py b/cms/djangoapps/contentstore/tasks.py index 0fa1f56f83fd0f933be6d7aad8e0469ee9801b83..227a207b4110fdc69a1035adcea4a979465e1634 100644 --- a/cms/djangoapps/contentstore/tasks.py +++ b/cms/djangoapps/contentstore/tasks.py @@ -260,7 +260,7 @@ def export_olx(self, user_id, course_key_string, language): self.status.set_state(u'Exporting') tarball = create_export_tarball(courselike_module, courselike_key, {}, self.status) artifact = UserTaskArtifact(status=self.status, name=u'Output') - artifact.file.save(name=os.path.basename(tarball.name), content=File(tarball)) # pylint: disable=no-member + artifact.file.save(name=os.path.basename(tarball.name), content=File(tarball)) artifact.save() # catch all exceptions so we can record useful error messages except Exception as exception: # pylint: disable=broad-except diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py index 3d434ef93e09ab8ffdf363b7750ad85cf6c8e1d0..457b284cfa83264f8359a21c5b76459c46e6cf11 100644 --- a/cms/djangoapps/contentstore/tests/test_course_settings.py +++ b/cms/djangoapps/contentstore/tests/test_course_settings.py @@ -613,13 +613,13 @@ class CourseGradingTest(CourseTestCase): GRADING_POLICY_CHANGED_EVENT_TYPE, { 'course_id': six.text_type(self.course.id), - 'event_transaction_type': 'edx.grades.grading_policy_changed', - 'grading_policy_hash': policy_hash, 'user_id': six.text_type(self.user.id), + 'grading_policy_hash': policy_hash, 'event_transaction_id': 'mockUUID', + 'event_transaction_type': 'edx.grades.grading_policy_changed', } ) for policy_hash in {grading_policy_1, grading_policy_2, grading_policy_3} - ]) + ], any_order=True) @mock.patch('track.event_transaction_utils.uuid4') @mock.patch('models.settings.course_grading.tracker') @@ -881,6 +881,32 @@ class CourseMetadataEditingTest(CourseTestCase): test_model = CourseMetadata.fetch(self.fullcourse) self.assertNotIn('giturl', test_model) + @override_settings( + PROCTORING_BACKENDS={ + 'DEFAULT': 'test_proctoring_provider', + 'proctortrack': {} + }, + ) + def test_fetch_proctoring_escalation_email_present(self): + """ + If 'proctortrack' is an available provider, show the escalation email setting + """ + test_model = CourseMetadata.fetch(self.fullcourse) + self.assertIn('proctoring_escalation_email', test_model) + + @override_settings( + PROCTORING_BACKENDS={ + 'DEFAULT': 'test_proctoring_provider', + 'alternate_provider': {} + }, + ) + def test_fetch_proctoring_escalation_email_not_present(self): + """ + If 'proctortrack' is not an available provider, don't show the escalation email setting + """ + test_model = CourseMetadata.fetch(self.fullcourse) + self.assertNotIn('proctoring_escalation_email', test_model) + @patch.dict(settings.FEATURES, {'ENABLE_EXPORT_GIT': False}) def test_validate_update_filtered_off(self): """ @@ -1082,7 +1108,8 @@ class CourseMetadataEditingTest(CourseTestCase): fresh = modulestore().get_course(self.course.id) test_model = CourseMetadata.fetch(fresh) - self.assertNotEqual(test_model['advertised_start']['value'], 1, 'advertised_start should not be updated to a wrong value') # pylint: disable=line-too-long + self.assertNotEqual(test_model['advertised_start']['value'], 1, + 'advertised_start should not be updated to a wrong value') self.assertNotEqual(test_model['days_early_for_beta']['value'], "supposed to be an integer", 'days_early_for beta should not be updated to a wrong value') @@ -1199,6 +1226,73 @@ class CourseMetadataEditingTest(CourseTestCase): test_model = CourseMetadata.fetch(self.fullcourse) self.assertIn('proctoring_provider', test_model) + @ddt.data(True, False) + @override_settings( + PROCTORING_BACKENDS={ + 'DEFAULT': 'test_proctoring_provider', + 'valid_provider': {} + }, + PARTNER_SUPPORT_EMAIL='support@foobar.com' + ) + @override_waffle_flag(ENABLE_PROCTORING_PROVIDER_OVERRIDES, True) + def test_validate_update_does_not_allow_proctoring_provider_changes_after_course_start(self, staff_user): + """ + Course staff cannot modify proctoring provder after the course start date. + Only admin users may update the provider if the course has started. + """ + field_name = "proctoring_provider" + course = CourseFactory.create(start=datetime.datetime.now(UTC) - datetime.timedelta(days=1)) + user = UserFactory.create(is_staff=staff_user) + + did_validate, errors, test_model = CourseMetadata.validate_and_update_from_json( + course, + { + field_name: {"value": 'valid_provider'}, + }, + user=user + ) + + if staff_user: + self.assertTrue(did_validate) + self.assertEqual(len(errors), 0) + self.assertIn(field_name, test_model) + else: + self.assertFalse(did_validate) + self.assertEqual(len(errors), 1) + self.assertEqual( + errors[0].get('message'), + ( + 'The proctoring provider cannot be modified after a course has started.' + ' Contact support@foobar.com for assistance' + ) + ) + self.assertIsNone(test_model) + + @ddt.data(True, False) + @override_waffle_flag(ENABLE_PROCTORING_PROVIDER_OVERRIDES, False) + def test_validate_update_allows_changes_to_settings_when_proctoring_provider_disabled(self, staff_user): + """ + Course staff can modify Advanced Settings when the proctoring_provider settings is not available (i.e. when + the ENABLE_PROCTORING_PROVIDER_OVERRIDES is not enabled for the course). This ensures that our restrictions + on changing the proctoring_provider do not inhibit users from changing Advanced Settings when the + proctoring_provider setting is not available. + """ + # It doesn't matter what the field is - just check that we can change any field. + field_name = "enable_proctored_exams" + course = CourseFactory.create(start=datetime.datetime.now(UTC) - datetime.timedelta(days=1)) + user = UserFactory.create(is_staff=staff_user) + + did_validate, errors, test_model = CourseMetadata.validate_and_update_from_json( + course, + { + field_name: {"value": True}, + }, + user=user + ) + self.assertTrue(did_validate) + self.assertEqual(len(errors), 0) + self.assertIn(field_name, test_model) + @override_settings( PROCTORING_BACKENDS={ 'DEFAULT': 'test_proctoring_provider', @@ -1286,6 +1380,101 @@ class CourseMetadataEditingTest(CourseTestCase): ) self.assertNotIn(field_name, test_model) + @ddt.data(True, False) + @override_settings( + PROCTORING_BACKENDS={ + 'DEFAULT': 'test_proctoring_provider', + 'test_proctoring_provider': {}, + 'proctortrack': {} + } + ) + @override_waffle_flag(ENABLE_PROCTORING_PROVIDER_OVERRIDES, True) + def test_validate_update_requires_escalation_email_for_proctortrack(self, include_blank_email): + json_data = { + "proctoring_provider": {"value": 'proctortrack'}, + } + if include_blank_email: + json_data["proctoring_escalation_email"] = {"value": ""} + + did_validate, errors, test_model = CourseMetadata.validate_and_update_from_json( + self.course, + json_data, + user=self.user + ) + self.assertFalse(did_validate) + self.assertEqual(len(errors), 1) + self.assertIsNone(test_model) + self.assertEqual( + errors[0].get('message'), + 'Provider \'proctortrack\' requires an exam escalation contact.' + ) + + @override_settings( + PROCTORING_BACKENDS={ + 'DEFAULT': 'test_proctoring_provider', + 'test_proctoring_provider': {}, + 'proctortrack': {} + } + ) + @override_waffle_flag(ENABLE_PROCTORING_PROVIDER_OVERRIDES, True) + def test_validate_update_does_not_require_escalation_email_by_default(self): + did_validate, errors, test_model = CourseMetadata.validate_and_update_from_json( + self.course, + { + "proctoring_provider": {"value": "test_proctoring_provider"}, + }, + user=self.user + ) + self.assertTrue(did_validate) + self.assertEqual(len(errors), 0) + self.assertIn('proctoring_provider', test_model) + + @override_settings( + PROCTORING_BACKENDS={ + 'DEFAULT': 'proctortrack', + 'proctortrack': {} + } + ) + @override_waffle_flag(ENABLE_PROCTORING_PROVIDER_OVERRIDES, True) + def test_validate_update_cannot_unset_escalation_email_when_proctortrack_is_provider(self): + course = CourseFactory.create() + CourseMetadata.update_from_dict({"proctoring_provider": 'proctortrack'}, course, self.user) + did_validate, errors, test_model = CourseMetadata.validate_and_update_from_json( + course, + { + "proctoring_escalation_email": {"value": ""}, + }, + user=self.user + ) + self.assertFalse(did_validate) + self.assertEqual(len(errors), 1) + self.assertIsNone(test_model) + self.assertEqual( + errors[0].get('message'), + 'Provider \'proctortrack\' requires an exam escalation contact.' + ) + + @override_settings( + PROCTORING_BACKENDS={ + 'DEFAULT': 'proctortrack', + 'proctortrack': {} + } + ) + @override_waffle_flag(ENABLE_PROCTORING_PROVIDER_OVERRIDES, True) + def test_validate_update_set_proctortrack_provider_with_valid_escalation_email(self): + did_validate, errors, test_model = CourseMetadata.validate_and_update_from_json( + self.course, + { + "proctoring_provider": {"value": "proctortrack"}, + "proctoring_escalation_email": {"value": "foo@bar.com"}, + }, + user=self.user + ) + self.assertTrue(did_validate) + self.assertEqual(len(errors), 0) + self.assertIn('proctoring_provider', test_model) + self.assertIn('proctoring_escalation_email', test_model) + def test_create_zendesk_tickets_present_for_edx_staff(self): """ Tests that create zendesk tickets field is not filtered out when the user is an edX staff member. diff --git a/cms/djangoapps/contentstore/tests/test_tasks.py b/cms/djangoapps/contentstore/tests/test_tasks.py index 2ac18b78b64f5fdb5ea6c0cd7d7433dedfd4f856..d4f30f66ef2e22fa2091f52e4819fa7da31b1ee6 100644 --- a/cms/djangoapps/contentstore/tests/test_tasks.py +++ b/cms/djangoapps/contentstore/tests/test_tasks.py @@ -27,7 +27,7 @@ TEST_DATA_CONTENTSTORE = copy.deepcopy(settings.CONTENTSTORE) TEST_DATA_CONTENTSTORE['DOC_STORE_CONFIG']['db'] = 'test_xcontent_%s' % uuid4().hex -def side_effect_exception(*args, **kwargs): # pylint: disable=unused-argument +def side_effect_exception(*args, **kwargs): """ Side effect for mocking which raises an exception """ diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index 2fce317d70820b423d0aa605a256919e810d087f..b4eed24e840a335e5904dc15eee0df473930ebf4 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -176,13 +176,13 @@ class AuthTestCase(ContentStoreTestCase): assertion_method = getattr(self, assertion_method_name) assertion_method( response, - u'<a class="action action-signup" href="{}/register?next=http%3A%2F%2Ftestserver%2F">Sign Up</a>'.format( # pylint: disable=line-too-long - settings.LMS_ROOT_URL - ) + u'<a class="action action-signup" href="{}/register?next=http%3A%2F%2Ftestserver%2F">Sign Up</a>'.format + (settings.LMS_ROOT_URL) ) self.assertContains( response, - u'<a class="action action-signin" href="/signin_redirect_to_lms?next=http%3A%2F%2Ftestserver%2F">Sign In</a>' # pylint: disable=line-too-long + '<a class="action action-signin" href="/signin_redirect_to_lms?next=http%3A%2F%2Ftestserver%2F">' + 'Sign In</a>' ) diff --git a/cms/djangoapps/contentstore/video_utils.py b/cms/djangoapps/contentstore/video_utils.py index cbee8ce61984a6ceef410c954922a053be1c10ce..c05eda96841b55aef069b4789f6ab753eb537a58 100644 --- a/cms/djangoapps/contentstore/video_utils.py +++ b/cms/djangoapps/contentstore/video_utils.py @@ -13,7 +13,7 @@ from django.core.files.images import get_image_dimensions from django.core.files.uploadedfile import SimpleUploadedFile from django.utils.translation import ugettext as _ from edxval.api import get_course_video_image_url, update_video_image -from six.moves.urllib.parse import urljoin # pylint: disable=import-error +from six.moves.urllib.parse import urljoin # Youtube thumbnail sizes. # https://img.youtube.com/vi/{youtube_id}/{thumbnail_quality}.jpg diff --git a/cms/djangoapps/contentstore/views/__init__.py b/cms/djangoapps/contentstore/views/__init__.py index 3f81e7f8f92a4eef3d3e1fd8ed2fe356a0ec5e77..896789407d7cdd42abe395927c77907edb17cc97 100644 --- a/cms/djangoapps/contentstore/views/__init__.py +++ b/cms/djangoapps/contentstore/views/__init__.py @@ -1,5 +1,3 @@ -# pylint: disable=wildcard-import - "All view functions for contentstore, broken out into submodules" from .assets import * diff --git a/cms/djangoapps/contentstore/views/checklists.py b/cms/djangoapps/contentstore/views/checklists.py index 51b82c0f3eedb230e8635250901a7f85fbc47b65..4ea8e3a3279f2e20c8499bd4f6c72b477b84aa9c 100644 --- a/cms/djangoapps/contentstore/views/checklists.py +++ b/cms/djangoapps/contentstore/views/checklists.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - 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/component.py b/cms/djangoapps/contentstore/views/component.py index 1a22ec1a6b871294c80a36625442a08eadca45e6..4e91d8e627c55f7fd99cc33de6435095bf08406a 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -14,7 +14,7 @@ from django.utils.translation import ugettext as _ from django.views.decorators.http import require_GET from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import UsageKey -from six.moves.urllib.parse import quote_plus # pylint: disable=import-error +from six.moves.urllib.parse import quote_plus from xblock.core import XBlock from xblock.django.request import django_to_webob_request, webob_to_django_response from xblock.exceptions import NoSuchHandlerError diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index 3effe650e728e607476f0f41731e620370073b10..dd541849d69ae00269e77e8f1ea28a24addde106 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -207,7 +207,7 @@ def _course_notifications_json_get(course_action_state_id): return JsonResponse(action_state_info) -def _dismiss_notification(request, course_action_state_id): # pylint: disable=unused-argument +def _dismiss_notification(request, course_action_state_id): """ Update the display of the course notification """ @@ -381,7 +381,6 @@ def _accessible_courses_summary_iter(request, org=None): """ Filter out unusable and inaccessible courses """ - # pylint: disable=fixme # TODO remove this condition when templates purged from db if course_summary.location.course == 'templates': return False @@ -412,7 +411,6 @@ def _accessible_courses_iter(request): if isinstance(course.id, CCXLocator): return False - # pylint: disable=fixme # TODO remove this condition when templates purged from db if course.location.course == 'templates': return False @@ -441,7 +439,6 @@ def _accessible_courses_iter_for_tests(request): if isinstance(course.id, CCXLocator): return False - # pylint: disable=fixme # TODO remove this condition when templates purged from db if course.location.course == 'templates': return False diff --git a/cms/djangoapps/contentstore/views/dev.py b/cms/djangoapps/contentstore/views/dev.py index 21c4646aea2fb2c47486508165e27e8cabe9788a..f04818e08e82927465548d523686e20a396e50ab 100644 --- a/cms/djangoapps/contentstore/views/dev.py +++ b/cms/djangoapps/contentstore/views/dev.py @@ -3,8 +3,6 @@ Views that are only activated when the project is running in development mode. These views will NOT be shown on production: trying to access them will result in a 404 error. """ -# pylint: disable=unused-argument - from edxmako.shortcuts import render_to_response diff --git a/cms/djangoapps/contentstore/views/entrance_exam.py b/cms/djangoapps/contentstore/views/entrance_exam.py index 35f44de0ef92c88ea777ff617c0a854fdccbe3e0..dcb62eb13b41cf92083724e558c8ac063f5a7a74 100644 --- a/cms/djangoapps/contentstore/views/entrance_exam.py +++ b/cms/djangoapps/contentstore/views/entrance_exam.py @@ -41,7 +41,6 @@ def _get_default_entrance_exam_minimum_pct(): return entrance_exam_minimum_score_pct -# pylint: disable=missing-docstring def check_feature_enabled(feature_name): """ Ensure the specified feature is turned on. Return an HTTP 400 code if not. @@ -164,7 +163,7 @@ def _create_entrance_exam(request, course_key, entrance_exam_minimum_score_pct=N return HttpResponse(status=201) -def _get_entrance_exam(request, course_key): # pylint: disable=W0613 +def _get_entrance_exam(request, course_key): """ Internal workflow operation to retrieve an entrance exam """ diff --git a/cms/djangoapps/contentstore/views/error.py b/cms/djangoapps/contentstore/views/error.py index 88b90ba01675a33ef812e8b114b12cbf19258270..eb4b234e40c15e51e7b6170315373506f10649de 100644 --- a/cms/djangoapps/contentstore/views/error.py +++ b/cms/djangoapps/contentstore/views/error.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring,unused-argument - - import functools from django.http import HttpResponse, HttpResponseNotFound, HttpResponseServerError diff --git a/cms/djangoapps/contentstore/views/helpers.py b/cms/djangoapps/contentstore/views/helpers.py index 1a30ac322c3de719b41529c09ec3dd2577e5fe57..a42f47b6960043ab82d92e3349a2f152a06d138c 100644 --- a/cms/djangoapps/contentstore/views/helpers.py +++ b/cms/djangoapps/contentstore/views/helpers.py @@ -2,10 +2,10 @@ Helper methods for Studio views. """ - +import hashlib +import six from uuid import uuid4 -import six from django.conf import settings from django.http import HttpResponse from django.utils.translation import ugettext as _ @@ -291,3 +291,18 @@ def is_item_in_course_tree(item): ancestor = ancestor.get_parent() return ancestor is not None + + +def get_course_hash_value(course_key): + """ + Returns a hash value for the given course key. + + If course key is None, function returns an out of bound value which will + never satisfy the vem_enabled_courses_percentage condition + """ + out_of_bound_value = 100 + if course_key: + m = hashlib.md5(str(course_key).encode()) + return int(m.hexdigest(), base=16) % 100 + + return out_of_bound_value diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py index c61a85c7c6387dd573451c236012a479d8bfca08..f6d5824bcd9fd2e66337fec5a09bf08e0fec610a 100644 --- a/cms/djangoapps/contentstore/views/item.py +++ b/cms/djangoapps/contentstore/views/item.py @@ -15,7 +15,12 @@ from django.core.exceptions import PermissionDenied from django.http import Http404, HttpResponse, HttpResponseBadRequest from django.utils.translation import ugettext as _ from django.views.decorators.http import require_http_methods -from edx_proctoring.api import does_backend_support_onboarding, get_exam_configuration_dashboard_url +from edx_proctoring.api import ( + does_backend_support_onboarding, + get_exam_by_content_id, + get_exam_configuration_dashboard_url +) +from edx_proctoring.exceptions import ProctoredExamNotFoundException from help_tokens.core import HelpUrlExpert from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locator import LibraryUsageLocator @@ -1244,6 +1249,9 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F xblock_info.update({ 'is_proctored_exam': xblock.is_proctored_exam, + 'was_ever_special_exam': _was_xblock_ever_special_exam( + course, xblock + ), 'online_proctoring_rules': rules_url, 'is_practice_exam': xblock.is_practice_exam, 'is_onboarding_exam': xblock.is_onboarding_exam, @@ -1295,6 +1303,32 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F return xblock_info +def _was_xblock_ever_special_exam(course, xblock): + """ + Determine whether this XBlock is or was ever configured as a special exam. + + If this block is *not* currently a special exam, the best way for us to tell + whether it was was *ever* configured as a special exam is by checking whether + edx-proctoring has an exam record associated with the block's ID. + If an exception is not raised, then we know that such a record exists, + indicating that this *was* once a special exam. + + Arguments: + course (CourseDescriptor) + xblock (XBlock) + + Returns: bool + """ + if xblock.is_time_limited: + return True + try: + get_exam_by_content_id(course.id, xblock.location) + except ProctoredExamNotFoundException: + return False + else: + return True + + def add_container_page_publishing_info(xblock, xblock_info): """ Adds information about the xblock's publish state to the supplied @@ -1394,10 +1428,10 @@ def _compute_visibility_state(xblock, child_info, is_unit_with_changes, is_cours return VisibilityState.live if is_live else VisibilityState.needs_attention else: return VisibilityState.ready if not is_unscheduled else VisibilityState.needs_attention - if is_unscheduled: - return VisibilityState.unscheduled - elif is_live: + if is_live: return VisibilityState.live + elif is_unscheduled: + return VisibilityState.unscheduled else: return VisibilityState.ready diff --git a/cms/djangoapps/contentstore/views/tests/test_course_updates.py b/cms/djangoapps/contentstore/views/tests/test_course_updates.py index 8b94d08fab9b0198eb60e402a09d49102ebb87b4..390dea6b60f83480bea03d00ad14a12436349277 100644 --- a/cms/djangoapps/contentstore/views/tests/test_course_updates.py +++ b/cms/djangoapps/contentstore/views/tests/test_course_updates.py @@ -11,6 +11,7 @@ from opaque_keys.edx.keys import UsageKey from contentstore.tests.test_course_settings import CourseTestCase from contentstore.utils import reverse_course_url, reverse_usage_url +from openedx.core.lib.xblock_utils import get_course_update_items from xmodule.modulestore.django import modulestore @@ -280,3 +281,42 @@ class CourseUpdateTest(CourseTestCase): payload = json.loads(resp.content.decode('utf-8')) self.assertHTMLEqual(payload['data'], content) + + def test_course_update_id(self): + """ + Test that a user can successfully update a course update without a sequential ids + """ + # create two course updates + self.post_course_update() + self.post_course_update() + + updates_location = self.course.id.make_usage_key('course_info', 'updates') + self.assertTrue(isinstance(updates_location, UsageKey)) + self.assertEqual(updates_location.block_id, u'updates') + + course_updates = modulestore().get_item(updates_location) + course_update_items = list(reversed(get_course_update_items(course_updates))) + + # Delete the course update with id 1 + course_update_items = [ + course_update_item for course_update_item in course_update_items if course_update_item.get('id') != 1 + ] + + course_updates.items = course_update_items + course_updates.data = "" + + # update db record + modulestore().update_item(course_updates, self.user.id) + + update_content = 'Testing' + update_date = u"January 23, 2014" + course_update_url = self.create_update_url() + payload = {'content': update_content, 'date': update_date} + resp = self.client.ajax_post( + course_update_url + '2', payload, HTTP_X_HTTP_METHOD_OVERRIDE="PUT", REQUEST_METHOD="POST" + ) + + self.assertHTMLEqual(update_content, json.loads(resp.content.decode('utf-8'))['content']) + course_updates = modulestore().get_item(updates_location) + del course_updates.items[0]["status"] + self.assertEqual(course_updates.items, [{u'date': update_date, u'content': update_content, u'id': 2}]) diff --git a/cms/djangoapps/contentstore/views/tests/test_import_export.py b/cms/djangoapps/contentstore/views/tests/test_import_export.py index 831b9a1e311a3da7d5b914e9e4db761d1e4ce60b..81ee02b1243799210d462eb2ab0cae650c044b29 100644 --- a/cms/djangoapps/contentstore/views/tests/test_import_export.py +++ b/cms/djangoapps/contentstore/views/tests/test_import_export.py @@ -2,7 +2,6 @@ Unit tests for course import and export """ - import copy import json import logging @@ -55,6 +54,7 @@ class ImportEntranceExamTestCase(CourseTestCase, MilestonesTestCaseMixin): """ Unit tests for importing a course with entrance exam """ + def setUp(self): super(ImportEntranceExamTestCase, self).setUp() self.url = reverse_course_url('import_handler', self.course.id) @@ -533,6 +533,7 @@ class ExportTestCase(CourseTestCase): """ Tests for export_handler. """ + def setUp(self): """ Sets up the test course. @@ -788,9 +789,9 @@ class ExportTestCase(CourseTestCase): @patch('contentstore.views.import_export._latest_task_status') @patch('user_tasks.models.UserTaskArtifact.objects.get') def test_export_status_handler_other( - self, - mock_get_user_task_artifact, - mock_latest_task_status, + self, + mock_get_user_task_artifact, + mock_latest_task_status, ): """ Verify that the export status handler generates the correct export path @@ -808,9 +809,9 @@ class ExportTestCase(CourseTestCase): @patch('contentstore.views.import_export._latest_task_status') @patch('user_tasks.models.UserTaskArtifact.objects.get') def test_export_status_handler_s3( - self, - mock_get_user_task_artifact, - mock_latest_task_status, + self, + mock_get_user_task_artifact, + mock_latest_task_status, ): """ Verify that the export status handler generates the correct export path @@ -828,9 +829,9 @@ class ExportTestCase(CourseTestCase): @patch('contentstore.views.import_export._latest_task_status') @patch('user_tasks.models.UserTaskArtifact.objects.get') def test_export_status_handler_filesystem( - self, - mock_get_user_task_artifact, - mock_latest_task_status, + self, + mock_get_user_task_artifact, + mock_latest_task_status, ): """ Verify that the export status handler generates the correct export path @@ -849,6 +850,7 @@ class TestLibraryImportExport(CourseTestCase): """ Tests for importing content libraries from XML and exporting them to XML. """ + def setUp(self): super(TestLibraryImportExport, self).setUp() self.export_dir = tempfile.mkdtemp() @@ -906,6 +908,7 @@ class TestCourseExportImport(LibraryTestCase): """ Tests for importing after exporting the course containing content libraries from XML. """ + def setUp(self): super(TestCourseExportImport, self).setUp() self.export_dir = tempfile.mkdtemp() @@ -1022,18 +1025,20 @@ class TestCourseExportImport(LibraryTestCase): ) +@ddt.ddt @override_settings(CONTENTSTORE=TEST_DATA_CONTENTSTORE) class TestCourseExportImportProblem(CourseTestCase): """ Tests for importing after exporting the course containing problem with pre tags from XML. """ + def setUp(self): super(TestCourseExportImportProblem, self).setUp() self.export_dir = tempfile.mkdtemp() self.source_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) self.addCleanup(shutil.rmtree, self.export_dir, ignore_errors=True) - def _setup_source_course_with_problem_content(self, publish_item=False): + def _setup_source_course_with_problem_content(self, data, publish_item=False): """ Sets up course with problem content. """ @@ -1058,8 +1063,7 @@ class TestCourseExportImportProblem(CourseTestCase): category='problem', display_name='Test Problem', publish_item=publish_item, - data='<problem><pre><code>x=10 print("hello \n")</code></pre>' - '<multiplechoiceresponse></multiplechoiceresponse></problem>', + data=data, ) def get_problem_content(self, block_location): @@ -1071,21 +1075,38 @@ class TestCourseExportImportProblem(CourseTestCase): return self.get_problem_content(self.store.get_item(block_location).children[0]) - def assert_problem_definition(self, course_location): + def assert_problem_definition(self, course_location, expected_problem_content): """ Asserts that problems' data is as expected with pre-tag content maintained. """ - expected_problem_content = '<problem>\n <pre>\n <code>x=10 print("hello \n")</code>\n </pre>\n ' \ - '<multiplechoiceresponse/>\n</problem>\n' problem_content = self.get_problem_content(course_location) self.assertEqual(expected_problem_content, problem_content) - def test_problem_content_on_course_export_import(self): + @ddt.data( + [ + '<problem><pre><code>x=10 print("hello \n")</code></pre>' + '<pre><div><pre><code>x=10 print("hello \n")</code></pre></div></pre>' + '<multiplechoiceresponse></multiplechoiceresponse></problem>', + + '<problem>\n <pre>\n <code>x=10 print("hello \n")</code>\n </pre>\n <pre>\n <div>\n <pre>\n ' + ' <code>x=10 print("hello \n")</code>\n </pre>\n </div>\n </pre>\n ' + '<multiplechoiceresponse/>\n</problem>\n' + ], + [ + '<problem><pre><code>x=10 print("hello \n")</code></pre>' + '<multiplechoiceresponse></multiplechoiceresponse></problem>', + + '<problem>\n <pre>\n <code>x=10 print("hello \n")</code>\n </pre>\n ' + '<multiplechoiceresponse/>\n</problem>\n' + ] + ) + @ddt.unpack + def test_problem_content_on_course_export_import(self, problem_data, expected_problem_content): """ Verify that problem content in destination matches expected problem content, specifically concerned with pre tag data with problem. """ - self._setup_source_course_with_problem_content() + self._setup_source_course_with_problem_content(problem_data) dest_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) @@ -1109,4 +1130,4 @@ class TestCourseExportImportProblem(CourseTestCase): create_if_not_present=True, ) - self.assert_problem_definition(dest_course.location) + self.assert_problem_definition(dest_course.location, expected_problem_content) diff --git a/cms/djangoapps/contentstore/views/tests/test_item.py b/cms/djangoapps/contentstore/views/tests/test_item.py index f236436fca18e85f19af05f515aea31ebed5bd1f..8d3dcf4f359d84c3e3646efedc3ae87316725d01 100644 --- a/cms/djangoapps/contentstore/views/tests/test_item.py +++ b/cms/djangoapps/contentstore/views/tests/test_item.py @@ -12,6 +12,7 @@ from django.http import Http404 from django.test import TestCase from django.test.client import RequestFactory from django.urls import reverse +from edx_proctoring.exceptions import ProctoredExamNotFoundException from mock import Mock, PropertyMock, patch from opaque_keys import InvalidKeyError from opaque_keys.edx.asides import AsideUsageKeyV2 @@ -32,6 +33,7 @@ from xblock.validation import ValidationMessage from contentstore.tests.utils import CourseTestCase from contentstore.utils import reverse_course_url, reverse_usage_url +from contentstore.views import item as item_module from contentstore.views.component import component_handler, get_component_templates from contentstore.views.item import ( ALWAYS, @@ -208,7 +210,7 @@ class GetItemTest(ItemTest): # XBlock messages are added by the Studio wrapper. self.assertIn('wrapper-xblock-message', html) # Make sure that "wrapper-xblock" does not appear by itself (without -message at end). - self.assertNotRegexpMatches(html, r'wrapper-xblock[^-]+') + self.assertNotRegex(html, r'wrapper-xblock[^-]+') # Verify that the header and article tags are still added self.assertIn('<header class="xblock-header xblock-header-vertical">', html) @@ -2202,7 +2204,7 @@ class TestComponentHandler(TestCase): """ test get_aside_from_xblock called """ - def create_response(handler, request, suffix): # pylint: disable=unused-argument + def create_response(handler, request, suffix): """create dummy response""" return Response(status_code=200) @@ -2473,7 +2475,6 @@ class TestXBlockInfo(ItemTest): """ Unit tests for XBlock's outline handling. """ - def setUp(self): super(TestXBlockInfo, self).setUp() user_id = self.user.id @@ -2783,15 +2784,37 @@ class TestXBlockInfo(ItemTest): else: self.assertIsNone(xblock_info.get('child_info', None)) - @patch.dict('django.conf.settings.FEATURES', {'ENABLE_SPECIAL_EXAMS': True}) - @patch('contentstore.views.item.does_backend_support_onboarding') - @patch('contentstore.views.item.get_exam_configuration_dashboard_url') - def test_proctored_exam_xblock_info(self, get_exam_configuration_dashboard_url_patch, - does_backend_support_onboarding_patch): + +@patch.dict('django.conf.settings.FEATURES', {'ENABLE_SPECIAL_EXAMS': True}) +class TestSpecialExamXBlockInfo(ItemTest): + """ + Unit tests for XBlock outline handling, specific to special exam XBlocks. + """ + patch_get_exam_configuration_dashboard_url = patch.object( + item_module, 'get_exam_configuration_dashboard_url', return_value='test_url' + ) + patch_does_backend_support_onboarding = patch.object( + item_module, 'does_backend_support_onboarding', return_value=True + ) + patch_get_exam_by_content_id_success = patch.object( + item_module, 'get_exam_by_content_id' + ) + patch_get_exam_by_content_id_not_found = patch.object( + item_module, 'get_exam_by_content_id', side_effect=ProctoredExamNotFoundException + ) + + def setUp(self): + super().setUp() + user_id = self.user.id + self.chapter = ItemFactory.create( + parent_location=self.course.location, category='chapter', display_name="Week 1", user_id=user_id, + highlights=['highlight'], + ) self.course.enable_proctored_exams = True self.course.save() self.store.update_item(self.course, self.user.id) + def test_proctoring_is_enabled_for_course(self): course = modulestore().get_item(self.course.location) xblock_info = create_xblock_info( course, @@ -2799,31 +2822,97 @@ class TestXBlockInfo(ItemTest): include_children_predicate=ALWAYS, ) # exam proctoring should be enabled and time limited. - self.assertEqual(xblock_info['enable_proctored_exams'], True) - + assert xblock_info['enable_proctored_exams'] + + @patch_get_exam_configuration_dashboard_url + @patch_does_backend_support_onboarding + @patch_get_exam_by_content_id_success + def test_special_exam_xblock_info( + self, + mock_get_exam_by_content_id, + _mock_does_backend_support_onboarding, + mock_get_exam_configuration_dashboard_url, + ): sequential = ItemFactory.create( - parent_location=self.chapter.location, category='sequential', - display_name="Test Lesson 1", user_id=self.user.id, - is_proctored_exam=True, is_time_limited=True, - default_time_limit_minutes=100, is_onboarding_exam=False + parent_location=self.chapter.location, + category='sequential', + display_name="Test Lesson 1", + user_id=self.user.id, + is_proctored_exam=True, + is_time_limited=True, + default_time_limit_minutes=100, + is_onboarding_exam=False, ) sequential = modulestore().get_item(sequential.location) - - get_exam_configuration_dashboard_url_patch.return_value = 'test_url' - does_backend_support_onboarding_patch.return_value = True xblock_info = create_xblock_info( sequential, include_child_info=True, include_children_predicate=ALWAYS, ) # exam proctoring should be enabled and time limited. - self.assertEqual(xblock_info['is_proctored_exam'], True) - self.assertEqual(xblock_info['is_time_limited'], True) - self.assertEqual(xblock_info['default_time_limit_minutes'], 100) - self.assertEqual(xblock_info['proctoring_exam_configuration_link'], 'test_url') - self.assertEqual(xblock_info['supports_onboarding'], True) - self.assertEqual(xblock_info['is_onboarding_exam'], False) - get_exam_configuration_dashboard_url_patch.assert_called_with(self.course.id, xblock_info['id']) + assert xblock_info['is_proctored_exam'] is True + assert xblock_info['was_ever_special_exam'] is True + assert xblock_info['is_time_limited'] is True + assert xblock_info['default_time_limit_minutes'] == 100 + assert xblock_info['proctoring_exam_configuration_link'] == 'test_url' + assert xblock_info['supports_onboarding'] is True + assert xblock_info['is_onboarding_exam'] is False + mock_get_exam_configuration_dashboard_url.assert_called_with(self.course.id, xblock_info['id']) + assert mock_get_exam_by_content_id.call_count == 0 + + @patch_get_exam_configuration_dashboard_url + @patch_does_backend_support_onboarding + @patch_get_exam_by_content_id_success + def test_xblock_was_ever_special_exam( + self, + mock_get_exam_by_content_id, + _mock_does_backend_support_onboarding_patch, + _mock_get_exam_configuration_dashboard_url, + ): + sequential = ItemFactory.create( + parent_location=self.chapter.location, + category='sequential', + display_name="Test Lesson 1", + user_id=self.user.id, + is_proctored_exam=False, + is_time_limited=False, + is_onboarding_exam=False, + ) + sequential = modulestore().get_item(sequential.location) + xblock_info = create_xblock_info( + sequential, + include_child_info=True, + include_children_predicate=ALWAYS, + ) + assert xblock_info['was_ever_special_exam'] is True + assert mock_get_exam_by_content_id.call_count == 1 + + @patch_get_exam_configuration_dashboard_url + @patch_does_backend_support_onboarding + @patch_get_exam_by_content_id_not_found + def test_xblock_was_never_proctored_exam( + self, + mock_get_exam_by_content_id, + _mock_does_backend_support_onboarding_patch, + _mock_get_exam_configuration_dashboard_url, + ): + sequential = ItemFactory.create( + parent_location=self.chapter.location, + category='sequential', + display_name="Test Lesson 1", + user_id=self.user.id, + is_proctored_exam=False, + is_time_limited=False, + is_onboarding_exam=False, + ) + sequential = modulestore().get_item(sequential.location) + xblock_info = create_xblock_info( + sequential, + include_child_info=True, + include_children_predicate=ALWAYS, + ) + assert xblock_info['was_ever_special_exam'] is False + assert mock_get_exam_by_content_id.call_count == 1 class TestLibraryXBlockInfo(ModuleStoreTestCase): @@ -3027,6 +3116,18 @@ class TestXBlockPublishingInfo(ItemTest): xblock_info = self._get_xblock_info(empty_chapter.location) self._verify_visibility_state(xblock_info, VisibilityState.unscheduled) + @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) + def test_chapter_self_paced_default_start_date(self, store_type): + course = CourseFactory.create(default_store=store_type) + course.self_paced = True + self.store.update_item(course, self.user.id) + chapter = self._create_child(course, 'chapter', "Test Chapter") + sequential = self._create_child(chapter, 'sequential', "Test Sequential") + self._create_child(sequential, 'vertical', "Published Unit", publish_item=True) + self._set_release_date(chapter.location, DEFAULT_START_DATE) + xblock_info = self._get_xblock_info(chapter.location) + self._verify_visibility_state(xblock_info, VisibilityState.live) + def test_empty_sequential(self): chapter = self._create_child(self.course, 'chapter', "Test Chapter") self._create_child(chapter, 'sequential', "Empty Sequential") diff --git a/cms/djangoapps/contentstore/views/tests/test_preview.py b/cms/djangoapps/contentstore/views/tests/test_preview.py index 5b82e049481f007ee3df056183b715a3d57be18a..ce110e042572f21aa254b11cbd2927e691a5f165 100644 --- a/cms/djangoapps/contentstore/views/tests/test_preview.py +++ b/cms/djangoapps/contentstore/views/tests/test_preview.py @@ -70,13 +70,13 @@ class GetPreviewHtmlTestCase(ModuleStoreTestCase): self.assertRegex(html, r"data-block-type=[\"\']test_aside[\"\']") self.assertRegex(html, "Aside rendered") # Now ensure the acid_aside is not in the result - self.assertNotRegexpMatches(html, r"data-block-type=[\"\']acid_aside[\"\']") + self.assertNotRegex(html, r"data-block-type=[\"\']acid_aside[\"\']") # Ensure about pages don't have asides about = modulestore().get_item(course.id.make_usage_key('about', 'overview')) html = get_preview_fragment(request, about, context).content - self.assertNotRegexpMatches(html, r"data-block-type=[\"\']test_aside[\"\']") - self.assertNotRegexpMatches(html, "Aside rendered") + self.assertNotRegex(html, r"data-block-type=[\"\']test_aside[\"\']") + self.assertNotRegex(html, "Aside rendered") @XBlockAside.register_temp_plugin(AsideTestType, 'test_aside') def test_preview_no_asides(self): @@ -106,8 +106,8 @@ class GetPreviewHtmlTestCase(ModuleStoreTestCase): } html = get_preview_fragment(request, html, context).content - self.assertNotRegexpMatches(html, r"data-block-type=[\"\']test_aside[\"\']") - self.assertNotRegexpMatches(html, "Aside rendered") + self.assertNotRegex(html, r"data-block-type=[\"\']test_aside[\"\']") + self.assertNotRegex(html, "Aside rendered") @mock.patch('xmodule.conditional_module.ConditionalModule.is_condition_satisfied') def test_preview_conditional_module_children_context(self, mock_is_condition_satisfied): diff --git a/cms/djangoapps/contentstore/views/tests/test_transcript_settings.py b/cms/djangoapps/contentstore/views/tests/test_transcript_settings.py index 67d67f4f98d4d32d99d948523beea8ea12c53077..d7b6351c42d64c865054ba3173c83e0b11973eac 100644 --- a/cms/djangoapps/contentstore/views/tests/test_transcript_settings.py +++ b/cms/djangoapps/contentstore/views/tests/test_transcript_settings.py @@ -15,11 +15,6 @@ from contentstore.tests.utils import CourseTestCase from contentstore.utils import reverse_course_url from contentstore.views.transcript_settings import TranscriptionProviderErrorType, validate_transcript_credentials from openedx.core.djangoapps.profile_images.tests.helpers import make_image_file -from openedx.core.djangoapps.video_pipeline.config.waffle import ( - SAVE_CREDENTIALS_IN_VAL, - waffle_flags -) -from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from student.roles import CourseStaffRole @@ -113,56 +108,6 @@ class TranscriptCredentialsTest(CourseTestCase): self.assertEqual(response.status_code, expected_status_code) self.assertEqual(response.content.decode('utf-8'), expected_response) - @override_waffle_flag(waffle_flags()[SAVE_CREDENTIALS_IN_VAL], True) - @ddt.data( - ( - { - 'provider': '3PlayMedia', - 'api_key': '11111', - 'api_secret_key': '44444' - }, - {'error_type': TranscriptionProviderErrorType.INVALID_CREDENTIALS}, - 400, - '{\n "error": "The information you entered is incorrect."\n}' - ), - ( - { - 'provider': 'Cielo24', - 'api_key': '12345', - 'username': 'test_user' - }, - {'error_type': None}, - 200, - '' - ), - ( - { - 'provider': '3PlayMedia', - 'api_key': '12345', - 'api_secret_key': '44444' - }, - {'error_type': None}, - 200, - '' - ) - ) - @ddt.unpack - @patch('edxval.api.create_or_update_transcript_credentials') - def test_val_transcript_credentials_handler(self, request_payload, update_credentials_response, - expected_status_code, expected_response, api_patch): - """ - Test that credentials handler works fine with VAL api endpoint. - """ - api_patch.return_value = update_credentials_response - transcript_credentials_url = self.get_url_for_course_key(self.course.id) - response = self.client.post( - transcript_credentials_url, - data=json.dumps(request_payload), - content_type='application/json' - ) - self.assertEqual(response.status_code, expected_status_code) - self.assertEqual(response.content.decode('utf-8'), expected_response) - @ddt.ddt class TranscriptCredentialsValidationTest(TestCase): diff --git a/cms/djangoapps/contentstore/views/tests/test_videos.py b/cms/djangoapps/contentstore/views/tests/test_videos.py index 8585e64768a5fe4e67383947f6444392064e3e44..558c18a5d00e2b26deeb1ecdf41794fe39c6b6da 100644 --- a/cms/djangoapps/contentstore/views/tests/test_videos.py +++ b/cms/djangoapps/contentstore/views/tests/test_videos.py @@ -48,8 +48,10 @@ from openedx.core.djangoapps.profile_images.tests.helpers import make_image_file from openedx.core.djangoapps.video_pipeline.config.waffle import ( DEPRECATE_YOUTUBE, ENABLE_DEVSTACK_VIDEO_UPLOADS, + ENABLE_VEM_PIPELINE, waffle_flags ) +from openedx.core.djangoapps.video_pipeline.models import VEMPipelineIntegration from openedx.core.djangoapps.waffle_utils.models import WaffleFlagCourseOverrideModel from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from xmodule.modulestore.tests.factories import CourseFactory @@ -224,7 +226,9 @@ class VideoUploadTestMixin(VideoUploadTestBase): @ddt.ddt @patch.dict("django.conf.settings.FEATURES", {"ENABLE_VIDEO_UPLOAD_PIPELINE": True}) -@override_settings(VIDEO_UPLOAD_PIPELINE={"BUCKET": "test_bucket", "ROOT_PATH": "test_root"}) +@override_settings(VIDEO_UPLOAD_PIPELINE={ + "VEM_S3_BUCKET": "vem_test_bucket", "BUCKET": "test_bucket", "ROOT_PATH": "test_root" +}) class VideosHandlerTestCase(VideoUploadTestMixin, CourseTestCase): """Test cases for the main video upload endpoint""" @@ -248,7 +252,8 @@ class VideosHandlerTestCase(VideoUploadTestMixin, CourseTestCase): 'status', 'course_video_image_url', 'transcripts', - 'transcription_status' + 'transcription_status', + 'error_description' ]) ) dateutil.parser.parse(response_video['created']) @@ -264,6 +269,7 @@ class VideosHandlerTestCase(VideoUploadTestMixin, CourseTestCase): [ 'edx_video_id', 'client_video_id', 'created', 'duration', 'status', 'course_video_image_url', 'transcripts', 'transcription_status', + 'error_description' ], [ { @@ -280,6 +286,7 @@ class VideosHandlerTestCase(VideoUploadTestMixin, CourseTestCase): [ 'edx_video_id', 'client_video_id', 'created', 'duration', 'status', 'course_video_image_url', 'transcripts', 'transcription_status', + 'error_description' ], [ { @@ -467,9 +474,6 @@ class VideosHandlerTestCase(VideoUploadTestMixin, CourseTestCase): 'secret_key': 'test_secret', 'session_token': 'test_session_token' } - - bucket = Mock() - mock_conn.return_value = Mock(get_bucket=Mock(return_value=bucket)) mock_key_instances = [ Mock( generate_url=Mock( @@ -478,7 +482,7 @@ class VideosHandlerTestCase(VideoUploadTestMixin, CourseTestCase): ) for file_info in files ] - mock_key.side_effect = mock_key_instances + [Mock()] + mock_key.side_effect = mock_key_instances with patch.object(AssumeRole, 'get_instance') as assume_role: assume_role.return_value.credentials = credentials @@ -496,6 +500,112 @@ class VideosHandlerTestCase(VideoUploadTestMixin, CourseTestCase): security_token=credentials['session_token'] ) + @patch('boto.s3.key.Key') + @patch('boto.s3.connection.S3Connection') + @override_flag(waffle_flags()[ENABLE_VEM_PIPELINE].namespaced_flag_name, active=True) + def test_enable_vem_pipeline(self, mock_conn, mock_key): + """ + Test that if VEM pipeline is enabled, objects are uploaded to the correct s3 bucket + even if course_hash_value is bigger than vem_enabled_courses_percentage. + """ + files = [{'file_name': 'first.mp4', 'content_type': 'video/mp4'}] + mock_key_instances = [ + Mock( + generate_url=Mock( + return_value='http://example.com/url_{}'.format(file_info['file_name']) + ) + ) + for file_info in files + ] + mock_key.side_effect = mock_key_instances + + response = self.client.post( + self.url, + json.dumps({'files': files}), + content_type='application/json' + ) + + self.assertEqual(response.status_code, 200) + mock_conn.return_value.get_bucket.assert_called_once_with( + settings.VIDEO_UPLOAD_PIPELINE['VEM_S3_BUCKET'], validate=False # pylint: disable=unsubscriptable-object + ) + + @patch('contentstore.views.videos.get_course_hash_value', Mock(return_value=50)) + @patch('contentstore.views.videos.LOGGER') + @patch('boto.s3.key.Key') + @patch('boto.s3.connection.S3Connection') + def test_send_course_to_vem_pipeline(self, mock_conn, mock_key, mock_logger): + """ + Test that if course hash value lies under the VEM config `vem_enabled_courses_percentage` + value, then video for that course is uploaded to VEM. + """ + vem_pipeline_integration_defaults = { + 'enabled': True, + 'api_url': 'https://video-encode-manager.example.com/api/v1/', + 'service_username': 'vem_pipeline_service_user', + 'client_name': 'vem_pipeline', + 'vem_enabled_courses_percentage': 100 + } + VEMPipelineIntegration.objects.create(**vem_pipeline_integration_defaults) + + files = [{'file_name': 'first.mp4', 'content_type': 'video/mp4'}] + mock_key_instances = [ + Mock( + generate_url=Mock( + return_value='http://example.com/url_{}'.format(file_info['file_name']) + ) + ) + for file_info in files + ] + mock_key.side_effect = mock_key_instances + + response = self.client.post( + self.url, + json.dumps({'files': files}), + content_type='application/json' + ) + + self.assertEqual(response.status_code, 200) + mock_conn.return_value.get_bucket.assert_called_once_with( + settings.VIDEO_UPLOAD_PIPELINE['VEM_S3_BUCKET'], validate=False # pylint: disable=unsubscriptable-object + ) + mock_logger.info.assert_called_with('Uploading course: {} to VEM bucket.'.format(self.course.id)) + + @patch('contentstore.views.videos.get_course_hash_value', Mock(return_value=50)) + @patch('boto.s3.key.Key') + @patch('boto.s3.connection.S3Connection') + def test_vem_pipeline_integration_not_enabled(self, mock_conn, mock_key): + """ + Test that if VEMPipelineIntegration is not enabled and course override waffle flag is not + set to True, the video goes to VEDA bucket. + """ + vem_pipeline_integration_defaults = { + 'enabled': False, 'vem_enabled_courses_percentage': 100 + } + VEMPipelineIntegration.objects.create(**vem_pipeline_integration_defaults) + + files = [{'file_name': 'first.mp4', 'content_type': 'video/mp4'}] + mock_key_instances = [ + Mock( + generate_url=Mock( + return_value='http://example.com/url_{}'.format(file_info['file_name']) + ) + ) + for file_info in files + ] + mock_key.side_effect = mock_key_instances + + response = self.client.post( + self.url, + json.dumps({'files': files}), + content_type='application/json' + ) + + self.assertEqual(response.status_code, 200) + mock_conn.return_value.get_bucket.assert_called_once_with( + settings.VIDEO_UPLOAD_PIPELINE['BUCKET'], validate=False # pylint: disable=unsubscriptable-object + ) + @override_settings(AWS_ACCESS_KEY_ID='test_key_id', AWS_SECRET_ACCESS_KEY='test_secret') @patch('boto.s3.key.Key') @patch('boto.s3.connection.S3Connection') @@ -721,20 +831,19 @@ class VideosHandlerTestCase(VideoUploadTestMixin, CourseTestCase): status = convert_video_status(video) self.assertEqual(status, StatusDisplayStrings.get('youtube_duplicate')) - # `transcript_ready` should be converted to `file_complete` - video['status'] = 'transcript_ready' - status = convert_video_status(video) - self.assertEqual(status, StatusDisplayStrings.get('file_complete')) - - # The encode status should be converted to `file_complete` if video encodes are complete + # The "encode status" should be converted to `file_complete` if video encodes are complete video['status'] = 'transcription_in_progress' status = convert_video_status(video, is_video_encodes_ready=True) self.assertEqual(status, StatusDisplayStrings.get('file_complete')) + # If encoding is not complete return the status as it is + video['status'] = 's3_upload_failed' + status = convert_video_status(video) + self.assertEqual(status, StatusDisplayStrings.get('s3_upload_failed')) + # for all other status, there should not be any conversion statuses = list(StatusDisplayStrings._STATUS_MAP.keys()) # pylint: disable=protected-access statuses.remove('invalid_token') - statuses.remove('transcript_ready') for status in statuses: video['status'] = status new_status = convert_video_status(video) @@ -1492,7 +1601,7 @@ class VideoUrlsCsvTestCase(VideoUploadTestMixin, CourseTestCase): self.assertEqual(response_video["Video ID"], original_video["edx_video_id"]) self.assertEqual(response_video["Status"], convert_video_status(original_video)) for profile in expected_profiles: - response_profile_url = response_video["{} URL".format(profile)] # pylint: disable=unicode-format-string + response_profile_url = response_video["{} URL".format(profile)] original_encoded_for_profile = next( ( original_encoded diff --git a/cms/djangoapps/contentstore/views/transcript_settings.py b/cms/djangoapps/contentstore/views/transcript_settings.py index 7c6f33121974ff03f11868b83d0153306bf923f4..920592f988dcd5affcf94af964ea6f09bf6315b9 100644 --- a/cms/djangoapps/contentstore/views/transcript_settings.py +++ b/cms/djangoapps/contentstore/views/transcript_settings.py @@ -11,6 +11,9 @@ from django.core.files.base import ContentFile from django.http import HttpResponse, HttpResponseNotFound from django.utils.translation import ugettext as _ from django.views.decorators.http import require_GET, require_http_methods, require_POST +from opaque_keys.edx.keys import CourseKey + +from contentstore.views.videos import TranscriptProvider from edxval.api import ( create_or_update_video_transcript, delete_video_transcript, @@ -19,14 +22,7 @@ from edxval.api import ( get_video_transcript_data, update_transcript_credentials_state_for_org ) -from opaque_keys.edx.keys import CourseKey - -from contentstore.views.videos import TranscriptProvider from openedx.core.djangoapps.video_config.models import VideoTranscriptEnabledFlag -from openedx.core.djangoapps.video_pipeline.config.waffle import ( - SAVE_CREDENTIALS_IN_VAL, - waffle_flags -) from openedx.core.djangoapps.video_pipeline.api import update_3rd_party_transcription_service_credentials from student.auth import has_studio_write_access from util.json_request import JsonResponse, expect_json @@ -112,14 +108,9 @@ def transcript_credentials_handler(request, course_key_string): if error_message: response = JsonResponse({'error': error_message}, status=400) else: - # Send the validated credentials to edx-video-pipeline. + # Send the validated credentials to edx-video-pipeline and video-encode-manager credentials_payload = dict(validated_credentials, org=course_key.org, provider=provider) - if waffle_flags()[SAVE_CREDENTIALS_IN_VAL].is_enabled(course_key): - from edxval.api import create_or_update_transcript_credentials - response = create_or_update_transcript_credentials(**credentials_payload) - error_response, is_updated = response, not response.get('error_type') - else: - error_response, is_updated = update_3rd_party_transcription_service_credentials(**credentials_payload) + error_response, is_updated = update_3rd_party_transcription_service_credentials(**credentials_payload) # Send appropriate response based on whether credentials were updated or not. if is_updated: # Cache credentials state in edx-val. diff --git a/cms/djangoapps/contentstore/views/videos.py b/cms/djangoapps/contentstore/views/videos.py index c0477cfee929278514ce79d59f99750f33e7b35a..d2486c6a300cf191cf5d12f09c1d8907605cc453 100644 --- a/cms/djangoapps/contentstore/views/videos.py +++ b/cms/djangoapps/contentstore/views/videos.py @@ -21,6 +21,7 @@ from django.http import HttpResponse, HttpResponseNotFound from django.urls import reverse from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_noop +from openedx.core.djangoapps.video_pipeline.models import VEMPipelineIntegration from django.views.decorators.http import require_GET, require_http_methods, require_POST from edxval.api import ( SortDirection, @@ -43,11 +44,13 @@ from pytz import UTC from contentstore.models import VideoUploadConfig from contentstore.utils import reverse_course_url from contentstore.video_utils import validate_video_image +from contentstore.views.helpers import get_course_hash_value from edxmako.shortcuts import render_to_response from openedx.core.djangoapps.video_config.models import VideoTranscriptEnabledFlag from openedx.core.djangoapps.video_pipeline.config.waffle import ( DEPRECATE_YOUTUBE, ENABLE_DEVSTACK_VIDEO_UPLOADS, + ENABLE_VEM_PIPELINE, waffle_flags ) from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag, WaffleFlagNamespace, WaffleSwitchNamespace @@ -171,6 +174,10 @@ class StatusDisplayStrings(object): _TRANSCRIPTION_IN_PROGRESS = ugettext_noop("Transcription in Progress") # Translators: This is the status for a video whose transcription is complete _TRANSCRIPT_READY = ugettext_noop("Transcript Ready") + # Translators: This is the status for a video whose transcription job was failed for some languages + _PARTIAL_FAILURE = ugettext_noop("Partial Failure") + # Translators: This is the status for a video whose transcription job has failed altogether + _TRANSCRIPT_FAILED = ugettext_noop("Transcript Failed") _STATUS_MAP = { "upload": _UPLOADING, @@ -191,6 +198,9 @@ class StatusDisplayStrings(object): "imported": _IMPORTED, "transcription_in_progress": _TRANSCRIPTION_IN_PROGRESS, "transcript_ready": _TRANSCRIPT_READY, + "partial_failure": _PARTIAL_FAILURE, + # TODO: Add a related unit tests when the VAL update is part of platform + "transcript_failed": _TRANSCRIPT_FAILED, } @staticmethod @@ -524,7 +534,7 @@ def convert_video_status(video, is_video_encodes_ready=False): ]) elif video['status'] == 'invalid_token': status = StatusDisplayStrings.get('youtube_duplicate') - elif is_video_encodes_ready or video['status'] == 'transcript_ready': + elif is_video_encodes_ready: status = StatusDisplayStrings.get('file_complete') else: status = StatusDisplayStrings.get(video['status']) @@ -546,21 +556,19 @@ def _get_videos(course, pagination_conf=None): # This is required to see if edx video pipeline is enabled while converting the video status. course_video_upload_token = course.video_upload_pipeline.get('course_video_upload_token') + transcription_statuses = ['transcription_in_progress', 'transcript_ready', 'partial_failure', 'transcript_failed'] # convert VAL's status to studio's Video Upload feature status. for video in videos: - # If we are using "new video workflow" and status is `transcription_in_progress` then video encodes are ready. + # If we are using "new video workflow" and status is in `transcription_statuses` then video encodes are ready. # This is because Transcription starts once all the encodes are complete except for YT, but according to # "new video workflow" YT is disabled as well as deprecated. So, Its precise to say that the Transcription # starts once all the encodings are complete *for the new video workflow*. - is_video_encodes_ready = not course_video_upload_token and video['status'] == 'transcription_in_progress' + is_video_encodes_ready = not course_video_upload_token and (video['status'] in transcription_statuses) # Update with transcript languages video['transcripts'] = get_available_transcript_languages(video_id=video['edx_video_id']) - # Transcription status should only be visible if 3rd party transcripts are pending. video['transcription_status'] = ( - StatusDisplayStrings.get(video['status']) - if not video['transcripts'] and is_video_encodes_ready else - '' + StatusDisplayStrings.get(video['status']) if is_video_encodes_ready else '' ) # Convert the video status. video['status'] = convert_video_status(video, is_video_encodes_ready) @@ -583,6 +591,7 @@ def _get_index_videos(course, pagination_conf=None): attrs = [ 'edx_video_id', 'client_video_id', 'created', 'duration', 'status', 'courses', 'transcripts', 'transcription_status', + 'error_description' ] def _get_values(video): @@ -740,7 +749,7 @@ def videos_post(course, request): if error: return JsonResponse({'error': error}, status=400) - bucket = storage_service_bucket() + bucket = storage_service_bucket(course.id) req_files = data['files'] resp_files = [] @@ -798,9 +807,10 @@ def videos_post(course, request): return JsonResponse({'files': resp_files}, status=200) -def storage_service_bucket(): +def storage_service_bucket(course_key=None): """ - Returns an S3 bucket for video uploads. + Returns an S3 bucket for video upload. The S3 bucket returned depends on + which pipeline, VEDA or VEM, is enabled. """ if waffle_flags()[ENABLE_DEVSTACK_VIDEO_UPLOADS].is_enabled(): credentials = AssumeRole.get_instance().credentials @@ -816,11 +826,21 @@ def storage_service_bucket(): } conn = s3.connection.S3Connection(**params) + vem_pipeline = VEMPipelineIntegration.current() + course_hash_value = get_course_hash_value(course_key) + + vem_override = course_key and waffle_flags()[ENABLE_VEM_PIPELINE].is_enabled(course_key) + allow_course_to_use_vem = vem_pipeline.enabled and course_hash_value < vem_pipeline.vem_enabled_courses_percentage + # We don't need to validate our bucket, it requires a very permissive IAM permission # set since behind the scenes it fires a HEAD request that is equivalent to get_all_keys() # meaning it would need ListObjects on the whole bucket, not just the path used in each # environment (since we share a single bucket for multiple deployments in some configurations) - return conn.get_bucket(settings.VIDEO_UPLOAD_PIPELINE["BUCKET"], validate=False) + if vem_override or allow_course_to_use_vem: + LOGGER.info('Uploading course: {} to VEM bucket.'.format(course_key)) + return conn.get_bucket(settings.VIDEO_UPLOAD_PIPELINE['VEM_S3_BUCKET'], validate=False) + else: + return conn.get_bucket(settings.VIDEO_UPLOAD_PIPELINE['BUCKET'], validate=False) def storage_service_key(bucket, file_name): diff --git a/cms/djangoapps/models/settings/course_metadata.py b/cms/djangoapps/models/settings/course_metadata.py index 3483f09fedc1d005885e835981f77fa737b859a8..f9e05b9089030ece216c6382d628ac0a865e8072 100644 --- a/cms/djangoapps/models/settings/course_metadata.py +++ b/cms/djangoapps/models/settings/course_metadata.py @@ -3,10 +3,13 @@ Django module for Course Metadata class -- manages advanced settings and related """ +from datetime import datetime import six from crum import get_current_user +from django.core.exceptions import ValidationError from django.conf import settings from django.utils.translation import ugettext as _ +import pytz from six import text_type from xblock.fields import Scope @@ -25,9 +28,9 @@ class CourseMetadata(object): editable metadata. ''' # The list of fields that wouldn't be shown in Advanced Settings. - # Should not be used directly. Instead the get_blacklist_of_fields method should + # Should not be used directly. Instead the get_exclude_list_of_fields method should # be used if the field needs to be filtered depending on the feature flag. - FIELDS_BLACK_LIST = [ + FIELDS_EXCLUDE_LIST = [ 'cohort_config', 'xml_attributes', 'start', @@ -71,77 +74,82 @@ class CourseMetadata(object): ] @classmethod - def get_blacklist_of_fields(cls, course_key): + def get_exclude_list_of_fields(cls, course_key): """ - Returns a list of fields to not include in Studio Advanced settings based on a + Returns a list of fields to exclude from the Studio Advanced settings based on a feature flag (i.e. enabled or disabled). """ # Copy the filtered list to avoid permanently changing the class attribute. - black_list = list(cls.FIELDS_BLACK_LIST) + exclude_list = list(cls.FIELDS_EXCLUDE_LIST) # Do not show giturl if feature is not enabled. if not settings.FEATURES.get('ENABLE_EXPORT_GIT'): - black_list.append('giturl') + exclude_list.append('giturl') # Do not show edxnotes if the feature is disabled. if not settings.FEATURES.get('ENABLE_EDXNOTES'): - black_list.append('edxnotes') + exclude_list.append('edxnotes') # Do not show video auto advance if the feature is disabled if not settings.FEATURES.get('ENABLE_OTHER_COURSE_SETTINGS'): - black_list.append('other_course_settings') + exclude_list.append('other_course_settings') # Do not show video_upload_pipeline if the feature is disabled. if not settings.FEATURES.get('ENABLE_VIDEO_UPLOAD_PIPELINE'): - black_list.append('video_upload_pipeline') + exclude_list.append('video_upload_pipeline') # Do not show video auto advance if the feature is disabled if not settings.FEATURES.get('ENABLE_AUTOADVANCE_VIDEOS'): - black_list.append('video_auto_advance') + exclude_list.append('video_auto_advance') # Do not show social sharing url field if the feature is disabled. if (not hasattr(settings, 'SOCIAL_SHARING_SETTINGS') or not getattr(settings, 'SOCIAL_SHARING_SETTINGS', {}).get("CUSTOM_COURSE_URLS")): - black_list.append('social_sharing_url') + exclude_list.append('social_sharing_url') # Do not show teams configuration if feature is disabled. if not settings.FEATURES.get('ENABLE_TEAMS'): - black_list.append('teams_configuration') + exclude_list.append('teams_configuration') if not settings.FEATURES.get('ENABLE_VIDEO_BUMPER'): - black_list.append('video_bumper') + exclude_list.append('video_bumper') # Do not show enable_ccx if feature is not enabled. if not settings.FEATURES.get('CUSTOM_COURSES_EDX'): - black_list.append('enable_ccx') - black_list.append('ccx_connector') + exclude_list.append('enable_ccx') + exclude_list.append('ccx_connector') # Do not show "Issue Open Badges" in Studio Advanced Settings # if the feature is disabled. if not settings.FEATURES.get('ENABLE_OPENBADGES'): - black_list.append('issue_badges') + exclude_list.append('issue_badges') # If the XBlockStudioConfiguration table is not being used, there is no need to # display the "Allow Unsupported XBlocks" setting. if not XBlockStudioConfigurationFlag.is_enabled(): - black_list.append('allow_unsupported_xblocks') + exclude_list.append('allow_unsupported_xblocks') # If the ENABLE_PROCTORING_PROVIDER_OVERRIDES waffle flag is not enabled, # do not show "Proctoring Configuration" in Studio Advanced Settings. if not ENABLE_PROCTORING_PROVIDER_OVERRIDES.is_enabled(course_key): - black_list.append('proctoring_provider') + exclude_list.append('proctoring_provider') # Do not show "Course Visibility For Unenrolled Learners" in Studio Advanced Settings # if the enable_anonymous_access flag is not enabled if not COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled(course_key=course_key): - black_list.append('course_visibility') + exclude_list.append('course_visibility') # Do not show "Create Zendesk Tickets For Suspicious Proctored Exam Attempts" in # Studio Advanced Settings if the user is not edX staff. if not GlobalStaff().has_user(get_current_user()): - black_list.append('create_zendesk_tickets') + exclude_list.append('create_zendesk_tickets') - return black_list + # Do not show "Proctortrack Exam Escalation Contact" if Proctortrack is not + # an available proctoring backend. + if not settings.PROCTORING_BACKENDS or settings.PROCTORING_BACKENDS.get('proctortrack') is None: + exclude_list.append('proctoring_escalation_email') + + return exclude_list @classmethod def fetch(cls, descriptor): @@ -151,10 +159,10 @@ class CourseMetadata(object): """ result = {} metadata = cls.fetch_all(descriptor) - black_list_of_fields = cls.get_blacklist_of_fields(descriptor.id) + exclude_list_of_fields = cls.get_exclude_list_of_fields(descriptor.id) for key, value in six.iteritems(metadata): - if key in black_list_of_fields: + if key in exclude_list_of_fields: continue result[key] = value return result @@ -188,19 +196,19 @@ class CourseMetadata(object): """ Decode the json into CourseMetadata and save any changed attrs to the db. - Ensures none of the fields are in the blacklist. + Ensures none of the fields are in the exclude list. """ - blacklist_of_fields = cls.get_blacklist_of_fields(descriptor.id) + exclude_list_of_fields = cls.get_exclude_list_of_fields(descriptor.id) # Don't filter on the tab attribute if filter_tabs is False. if not filter_tabs: - blacklist_of_fields.remove("tabs") + exclude_list_of_fields.remove("tabs") # Validate the values before actually setting them. key_values = {} for key, model in six.iteritems(jsondict): # should it be an error if one of the filtered list items is in the payload? - if key in blacklist_of_fields: + if key in exclude_list_of_fields: continue try: val = model['value'] @@ -226,12 +234,12 @@ class CourseMetadata(object): errors: list of error objects result: the updated course metadata or None if error """ - blacklist_of_fields = cls.get_blacklist_of_fields(descriptor.id) + exclude_list_of_fields = cls.get_exclude_list_of_fields(descriptor.id) if not filter_tabs: - blacklist_of_fields.remove("tabs") + exclude_list_of_fields.remove("tabs") - filtered_dict = dict((k, v) for k, v in six.iteritems(jsondict) if k not in blacklist_of_fields) + filtered_dict = dict((k, v) for k, v in six.iteritems(jsondict) if k not in exclude_list_of_fields) did_validate = True errors = [] key_values = {} @@ -242,10 +250,15 @@ class CourseMetadata(object): val = model['value'] if hasattr(descriptor, key) and getattr(descriptor, key) != val: key_values[key] = descriptor.fields[key].from_json(val) - except (TypeError, ValueError) as err: + except (TypeError, ValueError, ValidationError) as err: did_validate = False errors.append({'message': text_type(err), 'model': model}) + proctoring_errors = cls._validate_proctoring_settings(descriptor, filtered_dict, user) + if proctoring_errors: + errors = errors + proctoring_errors + did_validate = False + # If did validate, go ahead and update the metadata if did_validate: updated_data = cls.update_from_dict(key_values, descriptor, user, save=False) @@ -264,3 +277,66 @@ class CourseMetadata(object): modulestore().update_item(descriptor, user.id) return cls.fetch(descriptor) + + @classmethod + def _validate_proctoring_settings(cls, descriptor, settings_dict, user): + """ + Verify proctoring settings + + Returns a list of error objects + """ + errors = [] + + # If the user is not edX staff, the user has requested a change to the proctoring_provider + # Advanced Setting, and it is after course start, prevent the user from changing the + # proctoring provider. + proctoring_provider_model = settings_dict.get('proctoring_provider', {}) + if ( + not user.is_staff and + cls._has_requested_proctoring_provider_changed( + descriptor.proctoring_provider, proctoring_provider_model.get('value') + ) and + datetime.now(pytz.UTC) > descriptor.start + ): + message = ( + 'The proctoring provider cannot be modified after a course has started.' + ' Contact {support_email} for assistance' + ).format(support_email=settings.PARTNER_SUPPORT_EMAIL or 'support') + errors.append({'message': message, 'model': proctoring_provider_model}) + + # Require a valid escalation email if Proctortrack is chosen as the proctoring provider + escalation_email_model = settings_dict.get('proctoring_escalation_email') + if escalation_email_model: + escalation_email = escalation_email_model.get('value') + else: + escalation_email = descriptor.proctoring_escalation_email + + missing_escalation_email_msg = 'Provider \'{provider}\' requires an exam escalation contact.' + if proctoring_provider_model and proctoring_provider_model.get('value') == 'proctortrack': + if not escalation_email: + message = missing_escalation_email_msg.format(provider=proctoring_provider_model.get('value')) + errors.append({'message': message, 'model': proctoring_provider_model}) + + if ( + escalation_email_model and not proctoring_provider_model and + descriptor.proctoring_provider == 'proctortrack' + ): + if not escalation_email: + message = missing_escalation_email_msg.format(provider=descriptor.proctoring_provider) + errors.append({'message': message, 'model': escalation_email_model}) + + return errors + + @staticmethod + def _has_requested_proctoring_provider_changed(current_provider, requested_provider): + """ + Return whether the requested proctoring provider is different than the current proctoring provider, indicating + that the user has requested a change to the proctoring_provider Advanced Setting. + The requested_provider will be None if the proctoring_provider setting is not available (e.g. if the + ENABLE_PROCTORING_PROVIDER_OVERRIDES waffle flag is not enabled for the course). In this case, we consider + that there is no change in the requested proctoring provider. + """ + if requested_provider is None: + return False + else: + return current_provider != requested_provider diff --git a/cms/envs/common.py b/cms/envs/common.py index 531721413e995912ea2dc284f18603b90cd3b903..a8ba7ef032d0d45af4df68fd577d5555689dc6a1 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -40,7 +40,7 @@ When refering to XBlocks, we use the entry-point name. For example, # pylint: disable=unused-import, useless-suppression, wrong-import-order, wrong-import-position -import imp +import importlib.util import os import sys from datetime import timedelta @@ -1264,9 +1264,10 @@ YOUTUBE = { YOUTUBE_API_KEY = 'PUT_YOUR_API_KEY_HERE' -############################# VIDEO UPLOAD PIPELINE ############################# +############################# SETTINGS FOR VIDEO UPLOAD PIPELINE ############################# VIDEO_UPLOAD_PIPELINE = { + 'VEM_S3_BUCKET': '', 'BUCKET': '', 'ROOT_PATH': '', 'CONCURRENT_UPLOAD_LIMIT': 4, @@ -1402,6 +1403,9 @@ INSTALLED_APPS = [ # Catalog integration 'openedx.core.djangoapps.catalog', + # Programs support + 'openedx.core.djangoapps.programs.apps.ProgramsConfig', + # django-oauth-toolkit 'oauth2_provider', @@ -1468,6 +1472,7 @@ INSTALLED_APPS = [ 'openedx.features.discounts', 'experiments', + 'openedx.core.djangoapps.external_user_ids', # so sample_task is available to celery workers 'openedx.core.djangoapps.heartbeat', @@ -1477,6 +1482,9 @@ INSTALLED_APPS = [ # Management of per-user schedules 'openedx.core.djangoapps.schedules', 'rest_framework_jwt', + + # Learning Sequence Navigation + 'openedx.core.djangoapps.content.learning_sequences.apps.LearningSequencesConfig', ] @@ -1622,10 +1630,8 @@ OPTIONAL_APPS = ( for app_name, insert_before in OPTIONAL_APPS: # First attempt to only find the module rather than actually importing it, # to avoid circular references - only try to import if it can't be found - # by find_module, which doesn't work with import hooks - try: - imp.find_module(app_name) - except ImportError: + # by find_spec, which doesn't work with import hooks + if importlib.util.find_spec(app_name) is None: try: __import__(app_name) except ImportError: @@ -2055,12 +2061,6 @@ CORS_ORIGIN_ALLOW_ALL = False LOGIN_REDIRECT_WHITELIST = [] -############### Settings for video pipeline ################## -VIDEO_UPLOAD_PIPELINE = { - 'BUCKET': '', - 'ROOT_PATH': '', -} - DEPRECATED_ADVANCED_COMPONENT_TYPES = [] ########################## VIDEO IMAGE STORAGE ############################ @@ -2095,16 +2095,6 @@ VIDEO_TRANSCRIPTS_SETTINGS = dict( VIDEO_TRANSCRIPTS_MAX_AGE = 31536000 -############################ TRANSCRIPT PROVIDERS SETTINGS ######################## - -# Note: These settings will also exist in video-encode-manager, so any update here -# should also be done there. Additionally, the BASE & LOGIN URL will be overridden at -# deployment as the actual URL is different from sandboxing URL. -CIELO24_SETTINGS = dict( - CIELO24_API_VERSION=1, - CIELO24_BASE_API_URL="https://sandbox.cielo24.com/api", - CIELO24_LOGIN_URL="https://sandbox.cielo24.com/api/account/login" -) ##### shoppingcart Payment ##### PAYMENT_SUPPORT_EMAIL = 'billing@example.com' @@ -2243,3 +2233,6 @@ DISABLE_DEPRECATED_SIGNIN_URL = False # .. toggle_tickets: ARCH-1253 # .. toggle_status: supported DISABLE_DEPRECATED_SIGNUP_URL = False + +##### LOGISTRATION RATE LIMIT SETTINGS ##### +LOGISTRATION_RATELIMIT_RATE = '500/5m' diff --git a/cms/envs/devstack.py b/cms/envs/devstack.py index af08727339a3c480ddc81f887ecb6b3677a3d2e4..84f5c6cd54914df9ad3487b935078d2158ccad46 100644 --- a/cms/envs/devstack.py +++ b/cms/envs/devstack.py @@ -151,8 +151,13 @@ REQUIRE_DEBUG = DEBUG ########################### OAUTH2 ################################# JWT_AUTH.update({ - 'JWT_SECRET_KEY': 'lms-secret', 'JWT_ISSUER': '{}/oauth2'.format(LMS_ROOT_URL), + 'JWT_ISSUERS': [{ + 'AUDIENCE': 'lms-key', + 'ISSUER': '{}/oauth2'.format(LMS_ROOT_URL), + 'SECRET_KEY': 'lms-secret', + }], + 'JWT_SECRET_KEY': 'lms-secret', 'JWT_AUDIENCE': 'lms-key', 'JWT_PUBLIC_SIGNING_JWK_SET': ( '{"keys": [{"kid": "devstack_key", "e": "AQAB", "kty": "RSA", "n": "smKFSYowG6nNUAdeqH1jQQnH1PmIHphzBmwJ5vRf1vu' diff --git a/cms/envs/production.py b/cms/envs/production.py index 0d478ee089bcd2a5083b17beae3eadc9eb8e3275..45850fa03efcd7acf0e80997eea708e51d332c0e 100644 --- a/cms/envs/production.py +++ b/cms/envs/production.py @@ -4,7 +4,7 @@ This is the default template for our main set of AWS servers. # We intentionally define lots of variables that aren't used, and # want to import all variables from base settings files -# pylint: disable=wildcard-import, unused-wildcard-import, wrong-import-order +# pylint: disable=wildcard-import, unused-wildcard-import import codecs @@ -33,6 +33,21 @@ def get_env_setting(setting): error_msg = u"Set the %s env variable" % setting raise ImproperlyConfigured(error_msg) +############### ALWAYS THE SAME ################################ + +DEBUG = False + +SESSION_ENGINE = 'django.contrib.sessions.backends.cache' + +# IMPORTANT: With this enabled, the server must always be behind a proxy that +# strips the header HTTP_X_FORWARDED_PROTO from client requests. Otherwise, +# a user can fool our server into thinking it was an https connection. +# See +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header +# for other warnings. +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +############### END ALWAYS THE SAME ################################ + # A file path to a YAML file from which to load all the configuration for the edx platform CONFIG_FILE = get_env_setting('STUDIO_CFG') @@ -64,10 +79,10 @@ with codecs.open(CONFIG_FILE, encoding='utf-8') as f: vars().update(__config_copy__) -# A file path to a YAML file from which to load all the code revisions currently deployed -REVISION_CONFIG_FILE = get_env_setting('REVISION_CFG') - try: + # A file path to a YAML file from which to load all the code revisions currently deployed + REVISION_CONFIG_FILE = get_env_setting('REVISION_CFG') + with codecs.open(REVISION_CONFIG_FILE, encoding='utf-8') as f: REVISION_CONFIG = yaml.safe_load(f) except Exception: # pylint: disable=broad-except @@ -90,21 +105,6 @@ CONFIG_ROOT = path(os.environ.get('CONFIG_ROOT', ENV_ROOT)) # prefix. CONFIG_PREFIX = SERVICE_VARIANT + "." if SERVICE_VARIANT else "" -############### ALWAYS THE SAME ################################ - -DEBUG = False - -EMAIL_BACKEND = 'django_ses.SESBackend' -SESSION_ENGINE = 'django.contrib.sessions.backends.cache' - -# IMPORTANT: With this enabled, the server must always be behind a proxy that -# strips the header HTTP_X_FORWARDED_PROTO from client requests. Otherwise, -# a user can fool our server into thinking it was an https connection. -# See -# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header -# for other warnings. -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') - ###################################### CELERY ################################ # Don't use a connection pool, since connections are dropped by ELB. @@ -149,9 +149,6 @@ if STATIC_URL_BASE: STATIC_URL += "/" STATIC_URL += 'studio/' -# DEFAULT_COURSE_ABOUT_IMAGE_URL specifies the default image to show for courses that don't provide one -DEFAULT_COURSE_ABOUT_IMAGE_URL = ENV_TOKENS.get('DEFAULT_COURSE_ABOUT_IMAGE_URL', DEFAULT_COURSE_ABOUT_IMAGE_URL) - DEFAULT_COURSE_VISIBILITY_IN_CATALOG = ENV_TOKENS.get( 'DEFAULT_COURSE_VISIBILITY_IN_CATALOG', DEFAULT_COURSE_VISIBILITY_IN_CATALOG @@ -166,14 +163,6 @@ DEFAULT_MOBILE_AVAILABLE = ENV_TOKENS.get( # How long to cache OpenAPI schemas and UI, in seconds. OPENAPI_CACHE_TIMEOUT = ENV_TOKENS.get('OPENAPI_CACHE_TIMEOUT', 60 * 60) -# MEDIA_ROOT specifies the directory where user-uploaded files are stored. -MEDIA_ROOT = ENV_TOKENS.get('MEDIA_ROOT', MEDIA_ROOT) -MEDIA_URL = ENV_TOKENS.get('MEDIA_URL', MEDIA_URL) - -# GITHUB_REPO_ROOT is the base directory -# for course data -GITHUB_REPO_ROOT = ENV_TOKENS.get('GITHUB_REPO_ROOT', GITHUB_REPO_ROOT) - # STATIC_ROOT specifies the directory where static files are # collected @@ -183,12 +172,8 @@ if STATIC_ROOT_BASE: WEBPACK_LOADER['DEFAULT']['STATS_FILE'] = STATIC_ROOT / "webpack-stats.json" WEBPACK_LOADER['WORKERS']['STATS_FILE'] = STATIC_ROOT / "webpack-worker-stats.json" -EMAIL_BACKEND = ENV_TOKENS.get('EMAIL_BACKEND', EMAIL_BACKEND) EMAIL_FILE_PATH = ENV_TOKENS.get('EMAIL_FILE_PATH', None) -EMAIL_HOST = ENV_TOKENS.get('EMAIL_HOST', EMAIL_HOST) -EMAIL_PORT = ENV_TOKENS.get('EMAIL_PORT', EMAIL_PORT) -EMAIL_USE_TLS = ENV_TOKENS.get('EMAIL_USE_TLS', EMAIL_USE_TLS) # CMS_BASE: Public domain name of Studio (should be resolvable from the end-user's browser) CMS_BASE = ENV_TOKENS.get('CMS_BASE') @@ -199,7 +184,6 @@ ENTERPRISE_API_URL = ENV_TOKENS.get('ENTERPRISE_API_URL', LMS_INTERNAL_ROOT_URL ENTERPRISE_CONSENT_API_URL = ENV_TOKENS.get('ENTERPRISE_CONSENT_API_URL', LMS_INTERNAL_ROOT_URL + '/consent/api/v1/') # Note that FEATURES['PREVIEW_LMS_BASE'] gets read in from the environment file. -COURSE_CATALOG_API_URL = ENV_TOKENS.get('COURSE_CATALOG_API_URL', COURSE_CATALOG_API_URL) # List of logout URIs for each IDA that the learner should be logged out of when they logout of # Studio. Only applies to IDA for which the social auth flow uses DOT (Django OAuth Toolkit). @@ -233,7 +217,6 @@ if 'staticfiles' in CACHES: # Once we have migrated to service assets off S3, then we can convert this back to # managed by the yaml file contents STATICFILES_STORAGE = os.environ.get('STATICFILES_STORAGE', ENV_TOKENS.get('STATICFILES_STORAGE', STATICFILES_STORAGE)) -STATICFILES_STORAGE_KWARGS = ENV_TOKENS.get('STATICFILES_STORAGE_KWARGS', STATICFILES_STORAGE_KWARGS) # Load all AWS_ prefixed variables to allow an S3Boto3Storage to be configured _locals = locals() @@ -243,12 +226,6 @@ for key, value in ENV_TOKENS.items(): SESSION_COOKIE_DOMAIN = ENV_TOKENS.get('SESSION_COOKIE_DOMAIN') SESSION_COOKIE_HTTPONLY = ENV_TOKENS.get('SESSION_COOKIE_HTTPONLY', True) -SESSION_ENGINE = ENV_TOKENS.get('SESSION_ENGINE', SESSION_ENGINE) -SESSION_COOKIE_SECURE = ENV_TOKENS.get('SESSION_COOKIE_SECURE', SESSION_COOKIE_SECURE) -SESSION_SAVE_EVERY_REQUEST = ENV_TOKENS.get('SESSION_SAVE_EVERY_REQUEST', SESSION_SAVE_EVERY_REQUEST) - -# social sharing settings -SOCIAL_SHARING_SETTINGS = ENV_TOKENS.get('SOCIAL_SHARING_SETTINGS', SOCIAL_SHARING_SETTINGS) REGISTRATION_EMAIL_PATTERNS_ALLOWED = ENV_TOKENS.get('REGISTRATION_EMAIL_PATTERNS_ALLOWED') @@ -259,12 +236,6 @@ if ENV_TOKENS.get('SESSION_COOKIE_NAME', None): # NOTE, there's a bug in Django (http://bugs.python.org/issue18012) which necessitates this being a str() SESSION_COOKIE_NAME = str(ENV_TOKENS.get('SESSION_COOKIE_NAME')) -# Set the names of cookies shared with the marketing site -# These have the same cookie domain as the session, which in production -# usually includes subdomains. -EDXMKTG_LOGGED_IN_COOKIE_NAME = ENV_TOKENS.get('EDXMKTG_LOGGED_IN_COOKIE_NAME', EDXMKTG_LOGGED_IN_COOKIE_NAME) -EDXMKTG_USER_INFO_COOKIE_NAME = ENV_TOKENS.get('EDXMKTG_USER_INFO_COOKIE_NAME', EDXMKTG_USER_INFO_COOKIE_NAME) - # Determines whether the CSRF token can be transported on # unencrypted channels. It is set to False here for backward compatibility, # but it is highly recommended that this is True for environments accessed @@ -272,14 +243,8 @@ EDXMKTG_USER_INFO_COOKIE_NAME = ENV_TOKENS.get('EDXMKTG_USER_INFO_COOKIE_NAME', CSRF_COOKIE_SECURE = ENV_TOKENS.get('CSRF_COOKIE_SECURE', False) #Email overrides -DEFAULT_FROM_EMAIL = ENV_TOKENS.get('DEFAULT_FROM_EMAIL', DEFAULT_FROM_EMAIL) -DEFAULT_FEEDBACK_EMAIL = ENV_TOKENS.get('DEFAULT_FEEDBACK_EMAIL', DEFAULT_FEEDBACK_EMAIL) -ADMINS = ENV_TOKENS.get('ADMINS', ADMINS) -SERVER_EMAIL = ENV_TOKENS.get('SERVER_EMAIL', SERVER_EMAIL) -MKTG_URLS = ENV_TOKENS.get('MKTG_URLS', MKTG_URLS) MKTG_URL_LINK_MAP.update(ENV_TOKENS.get('MKTG_URL_LINK_MAP', {})) MKTG_URL_OVERRIDES.update(ENV_TOKENS.get('MKTG_URL_OVERRIDES', MKTG_URL_OVERRIDES)) -TECH_SUPPORT_EMAIL = ENV_TOKENS.get('TECH_SUPPORT_EMAIL', TECH_SUPPORT_EMAIL) for name, value in ENV_TOKENS.get("CODE_JAIL", {}).items(): oldvalue = CODE_JAIL.get(name) @@ -291,35 +256,18 @@ for name, value in ENV_TOKENS.get("CODE_JAIL", {}).items(): COURSES_WITH_UNSAFE_CODE = ENV_TOKENS.get("COURSES_WITH_UNSAFE_CODE", []) -ASSET_IGNORE_REGEX = ENV_TOKENS.get('ASSET_IGNORE_REGEX', ASSET_IGNORE_REGEX) - -COMPREHENSIVE_THEME_DIRS = ENV_TOKENS.get('COMPREHENSIVE_THEME_DIRS', COMPREHENSIVE_THEME_DIRS) or [] - # COMPREHENSIVE_THEME_LOCALE_PATHS contain the paths to themes locale directories e.g. # "COMPREHENSIVE_THEME_LOCALE_PATHS" : [ # "/edx/src/edx-themes/conf/locale" # ], COMPREHENSIVE_THEME_LOCALE_PATHS = ENV_TOKENS.get('COMPREHENSIVE_THEME_LOCALE_PATHS', []) -DEFAULT_SITE_THEME = ENV_TOKENS.get('DEFAULT_SITE_THEME', DEFAULT_SITE_THEME) -ENABLE_COMPREHENSIVE_THEMING = ENV_TOKENS.get('ENABLE_COMPREHENSIVE_THEMING', ENABLE_COMPREHENSIVE_THEMING) - #Timezone overrides TIME_ZONE = ENV_TOKENS.get('CELERY_TIMEZONE', CELERY_TIMEZONE) # Push to LMS overrides GIT_REPO_EXPORT_DIR = ENV_TOKENS.get('GIT_REPO_EXPORT_DIR', '/edx/var/edxapp/export_course_repos') -# Translation overrides -LANGUAGES = ENV_TOKENS.get('LANGUAGES', LANGUAGES) -LANGUAGE_CODE = ENV_TOKENS.get('LANGUAGE_CODE', LANGUAGE_CODE) -LANGUAGE_COOKIE = ENV_TOKENS.get('LANGUAGE_COOKIE', LANGUAGE_COOKIE) - -USE_I18N = ENV_TOKENS.get('USE_I18N', USE_I18N) -ALL_LANGUAGES = ENV_TOKENS.get('ALL_LANGUAGES', ALL_LANGUAGES) - -DEFAULT_COURSE_LANGUAGE = ENV_TOKENS.get('DEFAULT_COURSE_LANGUAGE', DEFAULT_COURSE_LANGUAGE) - ENV_FEATURES = ENV_TOKENS.get('FEATURES', {}) for feature, value in ENV_FEATURES.items(): FEATURES[feature] = value @@ -328,14 +276,10 @@ for feature, value in ENV_FEATURES.items(): for app in ENV_TOKENS.get('ADDL_INSTALLED_APPS', []): INSTALLED_APPS.append(app) -WIKI_ENABLED = ENV_TOKENS.get('WIKI_ENABLED', WIKI_ENABLED) - LOGGING = get_logger_config(LOG_DIR, logging_env=ENV_TOKENS['LOGGING_ENV'], service_variant=SERVICE_VARIANT) -#theming start: - # The following variables use (or) instead of the default value inside (get). This is to enforce using the Lazy Text # values when the varibale is an empty string. Therefore, setting these variable as empty text in related # json files will make the system reads thier values from django translation files @@ -348,21 +292,8 @@ STUDIO_SHORT_NAME = ENV_TOKENS.get('STUDIO_SHORT_NAME') or STUDIO_SHORT_NAME if "TRACKING_IGNORE_URL_PATTERNS" in ENV_TOKENS: TRACKING_IGNORE_URL_PATTERNS = ENV_TOKENS.get("TRACKING_IGNORE_URL_PATTERNS") -# Heartbeat -HEARTBEAT_CHECKS = ENV_TOKENS.get('HEARTBEAT_CHECKS', HEARTBEAT_CHECKS) -HEARTBEAT_EXTENDED_CHECKS = ENV_TOKENS.get('HEARTBEAT_EXTENDED_CHECKS', HEARTBEAT_EXTENDED_CHECKS) -HEARTBEAT_CELERY_TIMEOUT = ENV_TOKENS.get('HEARTBEAT_CELERY_TIMEOUT', HEARTBEAT_CELERY_TIMEOUT) - LOGIN_REDIRECT_WHITELIST = [reverse_lazy('home')] -# Specific setting for the File Upload Service to store media in a bucket. -FILE_UPLOAD_STORAGE_BUCKET_NAME = ENV_TOKENS.get('FILE_UPLOAD_STORAGE_BUCKET_NAME', FILE_UPLOAD_STORAGE_BUCKET_NAME) -FILE_UPLOAD_STORAGE_PREFIX = ENV_TOKENS.get('FILE_UPLOAD_STORAGE_PREFIX', FILE_UPLOAD_STORAGE_PREFIX) - -# Zendesk -ZENDESK_URL = ENV_TOKENS.get('ZENDESK_URL', ZENDESK_URL) -ZENDESK_CUSTOM_FIELDS = ENV_TOKENS.get('ZENDESK_CUSTOM_FIELDS', ZENDESK_CUSTOM_FIELDS) -ZENDESK_GROUP_ID_MAPPING = ENV_TOKENS.get('ZENDESK_GROUP_ID_MAPPING', ZENDESK_GROUP_ID_MAPPING) ############### XBlock filesystem field config ########## if 'DJFS' in AUTH_TOKENS and AUTH_TOKENS['DJFS'] is not None: @@ -370,8 +301,6 @@ if 'DJFS' in AUTH_TOKENS and AUTH_TOKENS['DJFS'] is not None: if 'url_root' in DJFS: DJFS['url_root'] = DJFS['url_root'].format(platform_revision=EDX_PLATFORM_REVISION) -EMAIL_HOST_USER = AUTH_TOKENS.get('EMAIL_HOST_USER', EMAIL_HOST_USER) -EMAIL_HOST_PASSWORD = AUTH_TOKENS.get('EMAIL_HOST_PASSWORD', EMAIL_HOST_PASSWORD) AWS_SES_REGION_NAME = ENV_TOKENS.get('AWS_SES_REGION_NAME', 'us-east-1') AWS_SES_REGION_ENDPOINT = ENV_TOKENS.get('AWS_SES_REGION_ENDPOINT', 'email.us-east-1.amazonaws.com') @@ -501,9 +430,6 @@ CELERY_QUEUES.update( # Queue to use for updating grades due to grading policy change POLICY_CHANGE_GRADES_ROUTING_KEY = ENV_TOKENS.get('POLICY_CHANGE_GRADES_ROUTING_KEY', DEFAULT_PRIORITY_QUEUE) -# Rate limit for regrading tasks that a grading policy change can kick off -POLICY_CHANGE_TASK_RATE_LIMIT = ENV_TOKENS.get('POLICY_CHANGE_TASK_RATE_LIMIT', POLICY_CHANGE_TASK_RATE_LIMIT) - SOFTWARE_SECURE_VERIFICATION_ROUTING_KEY = ENV_TOKENS.get( 'SOFTWARE_SECURE_VERIFICATION_ROUTING_KEY', HIGH_PRIORITY_QUEUE @@ -530,27 +456,7 @@ AUTH_PASSWORD_VALIDATORS = ENV_TOKENS.get("AUTH_PASSWORD_VALIDATORS", AUTH_PASSW ### INACTIVITY SETTINGS #### SESSION_INACTIVITY_TIMEOUT_IN_SECONDS = AUTH_TOKENS.get("SESSION_INACTIVITY_TIMEOUT_IN_SECONDS") -##### X-Frame-Options response header settings ##### -X_FRAME_OPTIONS = ENV_TOKENS.get('X_FRAME_OPTIONS', X_FRAME_OPTIONS) - -################ ADVANCED COMPONENT/PROBLEM TYPES ############### - -ADVANCED_PROBLEM_TYPES = ENV_TOKENS.get('ADVANCED_PROBLEM_TYPES', ADVANCED_PROBLEM_TYPES) - -################ VIDEO UPLOAD PIPELINE ############### - -VIDEO_UPLOAD_PIPELINE = ENV_TOKENS.get('VIDEO_UPLOAD_PIPELINE', VIDEO_UPLOAD_PIPELINE) - -################ VIDEO IMAGE STORAGE ############### - -VIDEO_IMAGE_SETTINGS = ENV_TOKENS.get('VIDEO_IMAGE_SETTINGS', VIDEO_IMAGE_SETTINGS) - -################ VIDEO TRANSCRIPTS STORAGE ############### - -VIDEO_TRANSCRIPTS_SETTINGS = ENV_TOKENS.get('VIDEO_TRANSCRIPTS_SETTINGS', VIDEO_TRANSCRIPTS_SETTINGS) - ################ PUSH NOTIFICATIONS ############### - PARSE_KEYS = AUTH_TOKENS.get("PARSE_KEYS", {}) @@ -578,16 +484,6 @@ JWT_AUTH.update(AUTH_TOKENS.get('JWT_AUTH', {})) if FEATURES.get('CUSTOM_COURSES_EDX'): INSTALLED_APPS.append('openedx.core.djangoapps.ccxcon.apps.CCXConnectorConfig') -# Partner support link for CMS footer -PARTNER_SUPPORT_EMAIL = ENV_TOKENS.get('PARTNER_SUPPORT_EMAIL', PARTNER_SUPPORT_EMAIL) - -# Affiliate cookie tracking -AFFILIATE_COOKIE_NAME = ENV_TOKENS.get('AFFILIATE_COOKIE_NAME', AFFILIATE_COOKIE_NAME) - -############## Settings for Studio Context Sensitive Help ############## - -HELP_TOKENS_BOOKS = ENV_TOKENS.get('HELP_TOKENS_BOOKS', HELP_TOKENS_BOOKS) - ############## Settings for CourseGraph ############################ COURSEGRAPH_JOB_QUEUE = ENV_TOKENS.get('COURSEGRAPH_JOB_QUEUE', DEFAULT_PRIORITY_QUEUE) @@ -600,15 +496,6 @@ SCRAPE_YOUTUBE_THUMBNAILS_JOB_QUEUE = ENV_TOKENS.get('SCRAPE_YOUTUBE_THUMBNAILS_ ########## Settings update search index task ############ UPDATE_SEARCH_INDEX_JOB_QUEUE = ENV_TOKENS.get('UPDATE_SEARCH_INDEX_JOB_QUEUE', DEFAULT_PRIORITY_QUEUE) -########################## Parental controls config ####################### - -# The age at which a learner no longer requires parental consent, or None -# if parental consent is never required. -PARENTAL_CONSENT_AGE_LIMIT = ENV_TOKENS.get( - 'PARENTAL_CONSENT_AGE_LIMIT', - PARENTAL_CONSENT_AGE_LIMIT -) - ########################## Extra middleware classes ####################### # Allow extra middleware classes to be added to the app through configuration. @@ -623,9 +510,6 @@ COMPLETION_VIDEO_COMPLETE_PERCENTAGE = ENV_TOKENS.get( COMPLETION_VIDEO_COMPLETE_PERCENTAGE, ) -############### Settings for django-fernet-fields ################## -FERNET_KEYS = AUTH_TOKENS.get('FERNET_KEYS', FERNET_KEYS) - ####################### Enterprise Settings ###################### # A default dictionary to be used for filtering out enterprise customer catalog. @@ -638,24 +522,11 @@ ENTERPRISE_CATALOG_INTERNAL_ROOT_URL = ENV_TOKENS.get( ENTERPRISE_CATALOG_INTERNAL_ROOT_URL ) -# This limits the type of roles that are submittable via the `student` app's manual enrollment -# audit API. While this isn't used in CMS, it is used via Enterprise which is installed in -# the CMS. Without this, we get errors. -MANUAL_ENROLLMENT_ROLE_CHOICES = ENV_TOKENS.get('MANUAL_ENROLLMENT_ROLE_CHOICES', MANUAL_ENROLLMENT_ROLE_CHOICES) - ############### Settings for Retirement ##################### -RETIRED_USERNAME_PREFIX = ENV_TOKENS.get('RETIRED_USERNAME_PREFIX', RETIRED_USERNAME_PREFIX) -RETIRED_EMAIL_PREFIX = ENV_TOKENS.get('RETIRED_EMAIL_PREFIX', RETIRED_EMAIL_PREFIX) -RETIRED_EMAIL_DOMAIN = ENV_TOKENS.get('RETIRED_EMAIL_DOMAIN', RETIRED_EMAIL_DOMAIN) -RETIRED_USER_SALTS = ENV_TOKENS.get('RETIRED_USER_SALTS', RETIRED_USER_SALTS) RETIREMENT_SERVICE_WORKER_USERNAME = ENV_TOKENS.get( 'RETIREMENT_SERVICE_WORKER_USERNAME', RETIREMENT_SERVICE_WORKER_USERNAME ) -RETIREMENT_STATES = ENV_TOKENS.get('RETIREMENT_STATES', RETIREMENT_STATES) - -############## Settings for Course Enrollment Modes ###################### -COURSE_ENROLLMENT_MODES = ENV_TOKENS.get('COURSE_ENROLLMENT_MODES', COURSE_ENROLLMENT_MODES) ############### Settings for edx-rbac ############### SYSTEM_WIDE_ROLE_CLASSES = ENV_TOKENS.get('SYSTEM_WIDE_ROLE_CLASSES') or SYSTEM_WIDE_ROLE_CLASSES diff --git a/cms/envs/test.py b/cms/envs/test.py index a94687c0083ac9578eb4a7ef48c5536cdfc9519f..b0a0ca8ed987ed89cda32ac4980c7dc0c9bc22f2 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -11,7 +11,7 @@ sessions. Assumes structure: # We intentionally define lots of variables that aren't used, and # want to import all variables from base settings files -# pylint: disable=wildcard-import, unused-wildcard-import, wrong-import-order +# pylint: disable=wildcard-import, unused-wildcard-import from .common import * @@ -25,7 +25,6 @@ from openedx.core.lib.derived import derive_settings from util.db import NoOpMigrationModules # import settings from LMS for consistent behavior with CMS -# pylint: disable=unused-import from lms.envs.test import ( COMPREHENSIVE_THEME_DIRS, DEFAULT_FILE_STORAGE, @@ -132,11 +131,6 @@ DATABASES = { }, } -if os.environ.get('DISABLE_MIGRATIONS'): - # Create tables directly from apps' models. This can be removed once we upgrade - # to Django 1.9, which allows setting MIGRATION_MODULES to None in order to skip migrations. - MIGRATION_MODULES = NoOpMigrationModules() - LMS_BASE = "localhost:8000" LMS_ROOT_URL = "http://{}".format(LMS_BASE) FEATURES['PREVIEW_LMS_BASE'] = "preview.localhost" diff --git a/cms/lib/xblock/field_data.py b/cms/lib/xblock/field_data.py index c4bfcc6456212375c708fa7bc87836334fbb946c..dc687e257e9fef8362a813711473220bb6692471 100644 --- a/cms/lib/xblock/field_data.py +++ b/cms/lib/xblock/field_data.py @@ -16,7 +16,7 @@ class CmsFieldData(SplitFieldData): def __init__(self, authored_data, student_data): # Make sure that we don't repeatedly nest CmsFieldData instances if isinstance(authored_data, CmsFieldData): - authored_data = authored_data._authored_data # pylint: disable=protected-access + authored_data = authored_data._authored_data self._authored_data = authored_data self._student_data = student_data diff --git a/cms/lib/xblock/tagging/tagging.py b/cms/lib/xblock/tagging/tagging.py index 3643e78a32df1e7e6580561365ac05a3e407e157..cfd2fbf442c4cfb923d744ab283dc6ff8981fcfd 100644 --- a/cms/lib/xblock/tagging/tagging.py +++ b/cms/lib/xblock/tagging/tagging.py @@ -77,7 +77,7 @@ class StructuredTagsAside(XBlockAside): return Fragment(u'') @XBlock.handler - def save_tags(self, request=None, suffix=None): # pylint: disable=unused-argument + def save_tags(self, request=None, suffix=None): """ Handler to save choosen tags with connected XBlock """ diff --git a/cms/lib/xblock/test/test_runtime.py b/cms/lib/xblock/test/test_runtime.py index 7b7df1bf23aefc69707a0a8a39c4593f8cfe334f..b9f6a9932a4c520883a627ffe2f10f071c193285 100644 --- a/cms/lib/xblock/test/test_runtime.py +++ b/cms/lib/xblock/test/test_runtime.py @@ -6,7 +6,7 @@ Tests of edX Studio runtime functionality from unittest import TestCase from mock import Mock -from six.moves.urllib.parse import urlparse # pylint: disable=import-error +from six.moves.urllib.parse import urlparse from cms.lib.xblock.runtime import handler_url diff --git a/cms/static/js/certificates/views/certificate_editor.js b/cms/static/js/certificates/views/certificate_editor.js index e08ac582b46de4a2d6f94192c2501d3f29304ae2..fa19bd2de2588225bdea64dd710d4912e571e6eb 100644 --- a/cms/static/js/certificates/views/certificate_editor.js +++ b/cms/static/js/certificates/views/certificate_editor.js @@ -8,10 +8,11 @@ define([ 'js/views/list_item_editor', 'js/certificates/models/signatory', 'js/certificates/views/signatory_editor', - 'text!templates/certificate-editor.underscore' + 'text!templates/certificate-editor.underscore', + 'edx-ui-toolkit/js/utils/html-utils' ], function($, _, Backbone, gettext, - ListItemEditorView, SignatoryModel, SignatoryEditorView, certificateEditorTemplate) { + ListItemEditorView, SignatoryModel, SignatoryEditorView, certificateEditorTemplate, HtmlUtils) { 'use strict'; // If signatories limit is required to specific value then we can change it. @@ -75,7 +76,7 @@ function($, _, Backbone, gettext, isEditingAllCollections: true, eventAgg: self.eventAgg }); - self.$('div.signatory-edit-list').append($(signatory_view.render())); + self.$('div.signatory-edit-list').append(HtmlUtils.HTML((signatory_view.render())).toString()); }); this.disableAddSignatoryButton(); return this; diff --git a/cms/static/js/certificates/views/certificate_preview.js b/cms/static/js/certificates/views/certificate_preview.js index d07f3d1fdcaecb772db8172db15330c2cae5d011..5300f784c9fe46fd609614ec874e0d4fed8c7f8c 100644 --- a/cms/static/js/certificates/views/certificate_preview.js +++ b/cms/static/js/certificates/views/certificate_preview.js @@ -8,9 +8,10 @@ define([ 'js/views/baseview', 'common/js/components/utils/view_utils', 'common/js/components/views/feedback_notification', - 'text!templates/certificate-web-preview.underscore' + 'text!templates/certificate-web-preview.underscore', + 'edx-ui-toolkit/js/utils/html-utils' ], -function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPreviewTemplate) { +function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPreviewTemplate, HtmlUtils) { 'use strict'; var CertificateWebPreview = BaseView.extend({ el: $('.preview-certificate'), @@ -27,7 +28,7 @@ function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPrevie }, render: function() { - this.$el.html(_.template(certificateWebPreviewTemplate)({ + HtmlUtils.setHtml(this.$el, HtmlUtils.template(certificateWebPreviewTemplate)({ course_modes: this.course_modes, certificate_web_view_url: this.certificate_web_view_url, is_active: this.is_active @@ -36,13 +37,8 @@ function(_, gettext, BaseView, ViewUtils, NotificationView, certificateWebPrevie }, toggleCertificateActivation: function() { - var msg = 'Activating'; - if (this.is_active) { - msg = 'Deactivating'; - } - var notification = new NotificationView.Mini({ - title: gettext(msg) + title: gettext(this.is_active ? 'Deactivating' : 'Activating') }); $.ajax({ diff --git a/cms/static/js/certificates/views/signatory_details.js b/cms/static/js/certificates/views/signatory_details.js index 9d6543e27939053cdc08fa13ddea2698c48b8616..9286b28259919d6b184f58a1b524d63518cd232c 100644 --- a/cms/static/js/certificates/views/signatory_details.js +++ b/cms/static/js/certificates/views/signatory_details.js @@ -11,10 +11,11 @@ define([ 'js/views/baseview', 'js/certificates/views/signatory_editor', 'text!templates/signatory-details.underscore', - 'text!templates/signatory-actions.underscore' + 'text!templates/signatory-actions.underscore', + 'edx-ui-toolkit/js/utils/html-utils' ], function($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, SignatoryEditorView, - signatoryDetailsTemplate, signatoryActionsTemplate) { + signatoryDetailsTemplate, signatoryActionsTemplate, HtmlUtils) { 'use strict'; var SignatoryDetailsView = BaseView.extend({ tagName: 'div', @@ -52,20 +53,20 @@ function($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, Signa editSignatory: function(event) { // Retrieve the edit view for this model if (event && event.preventDefault) { event.preventDefault(); } - this.$el.html(this.edit_view.render()); - $(_.template(signatoryActionsTemplate)()).appendTo(this.el); + this.$el.html(HtmlUtils.HTML(this.edit_view.render()).toString()); + this.$el.append(HtmlUtils.template(signatoryActionsTemplate)().toString()); this.edit_view.delegateEvents(); this.delegateEvents(); }, saveSignatoryData: function(event) { // Persist the data for this model - if (event && event.preventDefault) { event.preventDefault(); } var certificate = this.model.get('certificate'); + var self = this; + if (event && event.preventDefault) { event.preventDefault(); } if (!certificate.isValid()) { return; } - var self = this; ViewUtils.runOperationShowingMessage( gettext('Saving'), function() { @@ -94,7 +95,7 @@ function($, _, str, Backbone, gettext, TemplateUtils, ViewUtils, BaseView, Signa var attributes = $.extend({}, this.model.attributes, { signatory_number: this.model.collection.indexOf(this.model) + 1 }); - return $(this.el).html(_.template(signatoryDetailsTemplate)(attributes)); + return HtmlUtils.setHtml(this.$el, HtmlUtils.template(signatoryDetailsTemplate)(attributes)); } }); return SignatoryDetailsView; diff --git a/cms/static/js/certificates/views/signatory_editor.js b/cms/static/js/certificates/views/signatory_editor.js index 21d53f7f20b806bf7ca9876e55aa684d3407466a..9c70e68a4439b72c5bd95c9366bb7752595d36d4 100644 --- a/cms/static/js/certificates/views/signatory_editor.js +++ b/cms/static/js/certificates/views/signatory_editor.js @@ -11,11 +11,12 @@ define([ 'common/js/components/views/feedback_notification', 'js/models/uploads', 'js/views/uploads', - 'text!templates/signatory-editor.underscore' + 'text!templates/signatory-editor.underscore', + 'edx-ui-toolkit/js/utils/html-utils' ], function($, _, Backbone, gettext, TemplateUtils, ViewUtils, PromptView, NotificationView, FileUploadModel, FileUploadDialog, - signatoryEditorTemplate) { + signatoryEditorTemplate, HtmlUtils) { 'use strict'; var SignatoryEditorView = Backbone.View.extend({ tagName: 'div', @@ -78,7 +79,7 @@ function($, _, Backbone, gettext, is_editing_all_collections: this.isEditingAllCollections, total_saved_signatories: this.getTotalSignatoriesOnServer() }); - return $(this.el).html(_.template(signatoryEditorTemplate)(attributes)); + return HtmlUtils.setHtml(this.$el, HtmlUtils.template(signatoryEditorTemplate)(attributes)); }, setSignatoryName: function(event) { @@ -127,10 +128,9 @@ function($, _, Backbone, gettext, deleteItem: function(event) { // Remove the specified model from the collection - if (event && event.preventDefault) { event.preventDefault(); } var model = this.model; var self = this; - var titleTextTemplate = _.template(gettext('Delete "<%= signatoryName %>" from the list of signatories?')); + var titleTextTemplate = _.template(gettext('Delete "<%- signatoryName %>" from the list of signatories?')); var confirm = new PromptView.Warning({ title: titleTextTemplate({signatoryName: model.get('name')}), message: gettext('This action cannot be undone.'), @@ -148,9 +148,9 @@ function($, _, Backbone, gettext, deleting.show(); model.destroy({ wait: true, - success: function(model) { + success: function(model2) { deleting.hide(); - self.eventAgg.trigger('onSignatoryRemoved', model); + self.eventAgg.trigger('onSignatoryRemoved', model2); } }); } @@ -165,18 +165,20 @@ function($, _, Backbone, gettext, } } }); + if (event && event.preventDefault) { event.preventDefault(); } confirm.show(); }, uploadSignatureImage: function(event) { + var upload, self, modal; event.preventDefault(); - var upload = new FileUploadModel({ + upload = new FileUploadModel({ title: gettext('Upload signature image.'), message: gettext('Image must be in PNG format.'), mimeTypes: ['image/png'] }); - var self = this; - var modal = new FileUploadDialog({ + self = this; + modal = new FileUploadDialog({ model: upload, onSuccess: function(response) { self.model.set('signature_image_path', response.asset.url); @@ -192,12 +194,13 @@ function($, _, Backbone, gettext, */ toggleValidationErrorMessage: function(modelAttribute) { var selector = 'div.add-signatory-' + modelAttribute; + var errorMessage; if (!this.model.isValid() && _.has(this.model.validationError, modelAttribute)) { // Show the error message if it is not exist before. if (!$(selector).hasClass('error')) { - var errorMessage = this.model.validationError[modelAttribute]; + errorMessage = this.model.validationError[modelAttribute]; $(selector).addClass('error'); - $(selector).append("<span class='message-error'>" + errorMessage + '</span>'); + $(selector).append(HtmlUtils.joinHtml(HtmlUtils.HTML("<span class='message-error'>"), errorMessage, HtmlUtils.HTML('</span>')).toString()); // eslint-disable-line max-len } } else { // Remove the error message. diff --git a/cms/static/js/factories/edit_tabs.js b/cms/static/js/factories/edit_tabs.js index 9f2912fc912dd233f27d5c6f7fa346f1441632cb..51688bf6a1979d977b9da421c531c83117ae5884 100644 --- a/cms/static/js/factories/edit_tabs.js +++ b/cms/static/js/factories/edit_tabs.js @@ -4,6 +4,7 @@ import * as xmoduleLoader from 'xmodule'; import './base'; import 'cms/js/main'; import 'xblock/cms.runtime.v1'; +import 'xmodule/js/src/xmodule'; // Force the XBlockToXModuleShim to load for Static Tabs 'use strict'; export default function EditTabsFactory(courseLocation, explicitUrl) { diff --git a/cms/static/js/i18n/am/djangojs.js b/cms/static/js/i18n/am/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/cms/static/js/i18n/am/djangojs.js +++ b/cms/static/js/i18n/am/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/ar/djangojs.js b/cms/static/js/i18n/ar/djangojs.js index 54175c3ad3e73370ce03f0c5a08ae14896b53e40..a45f7bdba901fde7e0b001b06d1c01a6798775d6 100644 --- a/cms/static/js/i18n/ar/djangojs.js +++ b/cms/static/js/i18n/ar/djangojs.js @@ -1674,7 +1674,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1738,9 +1738,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "d\u200f/m\u200f/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/az/djangojs.js b/cms/static/js/i18n/az/djangojs.js index f659651f1bde4c7d76a607caf0e369bebdedbd58..21e2b8b0a6f66b5d800200a713f29dd3d03eddf0 100644 --- a/cms/static/js/i18n/az/djangojs.js +++ b/cms/static/js/i18n/az/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -157,9 +157,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/bg-bg/djangojs.js b/cms/static/js/i18n/bg-bg/djangojs.js index 846386a8dc94b4e5fd49323b533e7111f1702e12..4957525842b0502f4540407c4142de3c2154852a 100644 --- a/cms/static/js/i18n/bg-bg/djangojs.js +++ b/cms/static/js/i18n/bg-bg/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -165,9 +165,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/bn-bd/djangojs.js b/cms/static/js/i18n/bn-bd/djangojs.js index 48275730fbad40c445dacecf723441dfcd59619c..93c75995021e16ad78d612d8e6d2a1709ac59bec 100644 --- a/cms/static/js/i18n/bn-bd/djangojs.js +++ b/cms/static/js/i18n/bn-bd/djangojs.js @@ -68,7 +68,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -120,9 +120,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "6", + "FIRST_DAY_OF_WEEK": 6, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M, Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/bn-in/djangojs.js b/cms/static/js/i18n/bn-in/djangojs.js index 48275730fbad40c445dacecf723441dfcd59619c..93c75995021e16ad78d612d8e6d2a1709ac59bec 100644 --- a/cms/static/js/i18n/bn-in/djangojs.js +++ b/cms/static/js/i18n/bn-in/djangojs.js @@ -68,7 +68,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -120,9 +120,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "6", + "FIRST_DAY_OF_WEEK": 6, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M, Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/bs/djangojs.js b/cms/static/js/i18n/bs/djangojs.js index 65b677c3e9642faebc318bd6f2ab17558b7dd3c1..e891be783fb01879c30e9b066eda87fd0de230cc 100644 --- a/cms/static/js/i18n/bs/djangojs.js +++ b/cms/static/js/i18n/bs/djangojs.js @@ -53,7 +53,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -117,9 +117,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "Y M j", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/ca/djangojs.js b/cms/static/js/i18n/ca/djangojs.js index 516431f9f4a641e17cd4fc7ceed68c710161b112..7f4e006f5d8ead95d6189af13355fb36bf363fbd 100644 --- a/cms/static/js/i18n/ca/djangojs.js +++ b/cms/static/js/i18n/ca/djangojs.js @@ -1345,7 +1345,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1399,9 +1399,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y G:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/ca@valencia/djangojs.js b/cms/static/js/i18n/ca@valencia/djangojs.js index 8da83a3094bdc2b97fa8ff0b3d6ae7d85ef5505f..0dcde6cbfb4a657fb75b9bcb0aae70e94ec5b41c 100644 --- a/cms/static/js/i18n/ca@valencia/djangojs.js +++ b/cms/static/js/i18n/ca@valencia/djangojs.js @@ -1345,7 +1345,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1409,9 +1409,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/cs/djangojs.js b/cms/static/js/i18n/cs/djangojs.js index f42e092c9af37584f8f0a9e7a56c594628631dae..d7c010ffa892e4b1dc765f422365607f96d0e0c1 100644 --- a/cms/static/js/i18n/cs/djangojs.js +++ b/cms/static/js/i18n/cs/djangojs.js @@ -6,7 +6,7 @@ django.pluralidx = function(n) { - var v=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2; + var v=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3; if (typeof(v) == 'boolean') { return v ? 1 : 0; } else { @@ -23,6 +23,7 @@ "%(sel)s of %(cnt)s selected": [ "Vybr\u00e1na je %(sel)s polo\u017eka z celkem %(cnt)s.", "Vybr\u00e1ny jsou %(sel)s polo\u017eky z celkem %(cnt)s.", + "Vybran\u00fdch je %(sel)s polo\u017eek z celkem %(cnt)s.", "Vybran\u00fdch je %(sel)s polo\u017eek z celkem %(cnt)s." ], "6 a.m.": "6h r\u00e1no", @@ -53,11 +54,13 @@ "Note: You are %s hour ahead of server time.": [ "Pozn\u00e1mka: V\u00e1\u0161 \u010das o %s hodinu p\u0159edstihuje \u010das na serveru.", "Pozn\u00e1mka: V\u00e1\u0161 \u010das o %s hodiny p\u0159edstihuje \u010das na serveru.", + "Pozn\u00e1mka: V\u00e1\u0161 \u010das o %s hodin p\u0159edstihuje \u010das na serveru.", "Pozn\u00e1mka: V\u00e1\u0161 \u010das o %s hodin p\u0159edstihuje \u010das na serveru." ], "Note: You are %s hour behind server time.": [ "Pozn\u00e1mka: V\u00e1\u0161 \u010das se o %s hodinu zpo\u017e\u010fuje za \u010dasem na serveru.", "Pozn\u00e1mka: V\u00e1\u0161 \u010das se o %s hodiny zpo\u017e\u010fuje za \u010dasem na serveru.", + "Pozn\u00e1mka: V\u00e1\u0161 \u010das se o %s hodin zpo\u017e\u010fuje za \u010dasem na serveru.", "Pozn\u00e1mka: V\u00e1\u0161 \u010das se o %s hodin zpo\u017e\u010fuje za \u010dasem na serveru." ], "November": "listopad", @@ -104,7 +107,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -165,9 +168,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y G:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/cy/djangojs.js b/cms/static/js/i18n/cy/djangojs.js index ef5365ad7560a94d66988f9901b68485fdefa178..4ca4e208fe5fd6530a19458d792030fa6e582723 100644 --- a/cms/static/js/i18n/cy/djangojs.js +++ b/cms/static/js/i18n/cy/djangojs.js @@ -85,7 +85,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -141,9 +141,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y P", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/da/djangojs.js b/cms/static/js/i18n/da/djangojs.js index f68db68a6d30234b94e006d5335cea16bcc199b3..fdd09ee464bd7f14df17b1dd4a9341dfa2df9d1d 100644 --- a/cms/static/js/i18n/da/djangojs.js +++ b/cms/static/js/i18n/da/djangojs.js @@ -50,12 +50,12 @@ "Midnight": "Midnat", "Noon": "Middag", "Note: You are %s hour ahead of server time.": [ - "Obs: Du er %s time forud i forhold servertiden.", - "Obs: Du er %s timer forud i forhold servertiden." + "Obs: Du er %s time forud i forhold til servertiden.", + "Obs: Du er %s timer forud i forhold til servertiden." ], "Note: You are %s hour behind server time.": [ - "Obs: Du er %s time bagud i forhold servertiden.", - "Obs: Du er %s timer forud i forhold servertiden." + "Obs: Du er %s time bagud i forhold til servertiden.", + "Obs: Du er %s timer bagud i forhold til servertiden." ], "November": "November", "Now": "Nu", @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -151,9 +151,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/de-de/djangojs.js b/cms/static/js/i18n/de-de/djangojs.js index 6ce6baf54cba45fcab5fa4f5d1984d6b3d0c3a29..0a063ff19091133493cb91aba5d75e870666b48d 100644 --- a/cms/static/js/i18n/de-de/djangojs.js +++ b/cms/static/js/i18n/de-de/djangojs.js @@ -324,6 +324,7 @@ "Are you having trouble finding a team to join?": "Hast Du Probleme ein Team zum Beitreten zu finden?", "Are you sure that you want to leave this session?": "Sind Sie sicher, dass Sie diese Sitzung verlassen m\u00f6chten?", "Are you sure you want to change to a different session?": "Sind Sie sicher, dass Sie zu einer anderen Sitzung wechseln m\u00f6chten?", + "Are you sure you want to delete the following file? It cannot be restored.\nFile: ": "Wollen Sie die folgende Datei wirklich l\u00f6schen? Sie kann nicht wiederhergestellt werden.", "Are you sure you want to delete this comment?": "Bist du dir sicher, dass du diesen Kommentar l\u00f6schen m\u00f6chtest?", "Are you sure you want to delete this page? This action cannot be undone.": "Sind Sie sicher, dass Sie diese Seite l\u00f6schen wollen? Dies kann nicht r\u00fcckg\u00e4ngig gemacht werden.", "Are you sure you want to delete this post?": "Bist du dir sicher, dass du diesen Beitrag l\u00f6schen m\u00f6chtest?", @@ -623,7 +624,6 @@ "Default (Local Time Zone)": "Standard (Lokale Zeitzone)", "Default Timed Transcript": "Standard, zeitbehaftetes Transkript", "Delete": "L\u00f6schen", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "L\u00f6sche \"<%= signatoryName %>\" von der Liste der Unterzeichner?", "Delete File Confirmation": "Dateibest\u00e4tigung l\u00f6schen", "Delete My Account": "Meinen Account l\u00f6schen", "Delete Page Confirmation": "Seitenbest\u00e4tigung l\u00f6schen", @@ -668,7 +668,6 @@ "Do you want to upload your file before submitting?": "M\u00f6chten Sie die Datei hochladen, bevor Sie Ihre Antwort einreichen?", "Document properties": "Dokumenteneigenschaften", "Does the name on your ID match your account name: %(fullName)s?": "Passt der Name auf ihr Ausweis zu ihr Kontoname: %(fullName)s?", - "Does the photo of you match your ID photo?": "Passt das Foto zu das Foto auf ihr Ausweis?", "Does the photo of you show your whole face?": "Zeiget das Foto ihr vollst\u00e4ndiges Gesicht?", "Doing so means that you are no longer eligible for academic credit.": "Die Konsequenz hieraus ist, dass Sie nicht l\u00e4nger zum Erwerb akademische Kreditpunkte berechtigt sind.", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Wir sehen dein Bild nicht? Vergewissere dich, deinem Browser die Nutzung der Kamera zu erlauben, wenn er nach der Genehmigung fragt.", @@ -842,7 +841,6 @@ "Fill browser": "Vollbild im Browser", "Filter": "Filter", "Filter and sort topics": "Filter und sortiere Themen", - "Final Grade": "Finale Auswertung", "Final Grade Received": "Erhaltene Endnote", "Financial Aid": "Finanzielle Unterst\u00fctzung", "Financial Assistance": "Finanzielle Unterst\u00fctzung", @@ -876,7 +874,6 @@ "Generate": "Erstellen", "Generate Exception Certificates": "Ausnahmezertifikate erstellen", "Generate the user's certificate": "Zertifikat f\u00fcr den Nutzer erstellen", - "Get Credit": "Credit bekommen", "Go Back": "Gehe zur\u00fcck", "Go to Dashboard": "Zu \"Meine Kurse\"", "Go to my Dashboard": "Zu \"Meine Kurse\"", @@ -957,10 +954,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "Wenn der Unterabschnitt kein F\u00e4lligkeitsdatum hat, sehen die Lernenden immer ihre Ergebnisse, wenn sie Antworten zur Bewertung abgeben.", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "Wenn die Lerneinheit zuvor ver\u00f6ffentlicht und an die Lernenden freigegeben wurde, sind alle \u00c4nderungen, die Sie an der Lerneinheit vorgenommen haben, als sie noch ausgeblendet war, nun f\u00fcr alle Lernenden sichtbar.", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "Falls die Lerneinheit bereits vorher ver\u00f6ffentlicht und f\u00fcr die Teilnehmer freigeben war, werden jetzt alle Anderungen, die du w\u00e4hrend die Einheit versteckt war, vorgenommen hast, f\u00fcr die Teilnehmer sichtbar. M\u00f6chtest du fortfahren?", - "If you are unable to access your account contact us via email using {email}.": "Wenn Sie keinen Zugang zu Ihrem Account haben, kontaktieren Sie uns via E-Mail {email}.", "If you do not yet have an account, use the button below to register.": "Wenn Sie noch kein Account haben, nutzen Sie den unteren Button, um sich zu registrieren.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "Wenn Sie Ihre Identit\u00e4t jetzt nicht \u00fcberpr\u00fcfen k\u00f6nnen Sie immer noch Ihren Kurs erkunden von Ihrem Armaturenbrett. Sie werden regelm\u00e4\u00dfigen Erinnerungen von %(platformName)s erhalten um Ihre Identit\u00e4t zu \u00fcberpr\u00fcfen.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "Wenn Sie Ihre Identit\u00e4t jetzt nicht verifizieren, k\u00f6nnen Sie Ihren Kurs trotzdem \u00fcber 'Meine Kurse' erkunden. Sie erhalten von {platformName} regelm\u00e4\u00dfig Erinnerungen, um Ihre Identit\u00e4t zu \u00fcberpr\u00fcfen.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "Wenn Sie diese Seite ohne vorheriges Speichern oder Einreichen der Antwort verlassen, geht die Arbeit an dieser Antwort verloren.", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "Wenn Sie diese Seite verlassen ohne Ihre Partnerbewertung zu \u00fcbermitteln, werden Sie alle Ihre bis jetzt erledigte Arbeit verlieren.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "Wenn Sie diese Seite ohne vorheriges Speichern oder Einreichen der Antwort verlassen, geht die Arbeit an dieser Antwort verloren.", @@ -1165,7 +1160,6 @@ "Name of the signatory": "Name des Unterzeichners", "Name or short description of the configuration": "Name oder Kurzbeschreibung des Aufbaus", "Navigate up": "Aufw\u00e4rts navigieren", - "Need help logging in?": "Brauchen Sie Hilfe beim anmelden?", "Needs verified certificate ": "Ben\u00f6tigt ein verifiziertes Zertifikat", "Never published": "Bisher unver\u00f6ffentlicht", "Never show assessment results": "Auswertungen nie zeigen", @@ -1247,7 +1241,6 @@ "Once your account is deleted, you cannot use it to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "Sobald Ihr Konto gel\u00f6scht ist, k\u00f6nnen Sie es nicht mehr verwenden, um Kurse \u00fcber die App {platformName}, {siteName} oder eine andere von {platformName} gehostete Website zu besuchen.", "One or more rescheduling tasks failed.": "Eine oder mehrere Neuterminierungsaufgaben sind fehlgeschlagen.", "Only ": "Nur", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "Nur <%= fileTypes %> Dateien k\u00f6nnen hochgeladen werden. Bitte w\u00e4hlen Sie eine Datei mit der Dateiendung <%= fileExtensions %> zum hochladen aus.", "Only properly formatted .csv files will be accepted.": "Nur korrekt formatierte .csv Dateien werden hier akzeptiert.", "Only the parent course staff of a CCX can create content groups.": "Nur die \u00fcbergeordneten Kursleiter eines CCX k\u00f6nnen Inhaltsgruppen erstellen.", "Open Calculator": "Taschenrechner \u00f6ffnen", @@ -1524,7 +1517,6 @@ "Select a prerequisite subsection and enter a minimum score percentage and minimum completion percentage to limit access to this subsection. Allowed values are 0-100": "W\u00e4hlen Sie einen vorausgesetzten Unterabschnitt aus und geben Sie einen Mindestpunktzahlanteil und einen Mindestprozentsatz der Vollst\u00e4ndigkeit ein, um den Zugang zu diesem Unterabschnitt einzuschr\u00e4nken. Erlaubte Werte sind 0-100", "Select a section or problem": "W\u00e4hlen Sie einen Abschnitt oder eine Aufgabe", "Select a session:": "W\u00e4hlen Sie eine Sitzung aus:", - "Select a subject for your support request.": "W\u00e4hlen Sie ein Thema f\u00fcr Ihre Supportanfrage aus.", "Select a time allotment for the exam. If it is over 24 hours, type in the amount of time. You can grant individual learners extra time to complete the exam through the Instructor Dashboard.": "W\u00e4hlen Sie eine Zeitzuteilung f\u00fcr die Pr\u00fcfung aus. Wenn es mehr als 24 Stunden sind, geben Sie die Zeitspanne ein. Sie k\u00f6nnen einzelnen Lernenden \u00fcber das Lehrer-Dashboard zus\u00e4tzliche Zeit geben, um die Pr\u00fcfung abzuschlie\u00dfen.", "Select all": "Alles ausw\u00e4hlen", "Select fidelity": "Treue ausw\u00e4hlen", @@ -1726,9 +1718,7 @@ "Textbook Name": "Lehrbuch Name", "Textbook information": "Lehrbuch Information", "Textbook name is required": "Name f\u00fcr das Textbook wird ben\u00f6tigt", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Viele Dank %(full_name)s! Wir haben Ihre Zahlung f\u00fcr %(course_name)s erhalten.", "Thank you for setting your course goal to {goal}!": "Danke, f\u00fcr das definieren eines Kursziels zu {goal}!", - "Thank you for submitting a request! We will contact you within 24 hours.": "Vielen Dank f\u00fcr Ihre Anfrage! Wir werden Sie innerhalb von 24 Stunden kontaktieren.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Vielen Dank, dass Sie Ihren Antrag auf finanzielle Unterst\u00fctzung f\u00fcr {course_name} gestellt haben! Sie k\u00f6nnen mit einer Antwort in 2-4 Werktagen rechnen.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Danke f\u00fcr das Einsenden ihre Fotos. Wir werden diese zeitnah pr\u00fcfen. Sie k\u00f6nnen sich jetzt f\u00fcr jeden von %(platformName)s Kurse mit gepr\u00fcftem Zertifikat anmelden. Ihre \u00dcberpr\u00fcfung ist g\u00fcltig f\u00fcr ein Jahr. Nach einem Jahr m\u00fcssen Sie ihre Fotos wieder zur \u00dcberpr\u00fcfungeinsenden. ", "Thank you! We have received your payment for {courseName}.": "Dankesch\u00f6n! Wir haben Ihre Zahlung f\u00fcr {courseName} bekommen", @@ -1740,8 +1730,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Das Zertifikat f\u00fcr diesen Lerner wurde erneut validiert und das System f\u00fchrt die Note f\u00fcr diesen Lerner erneut durch.", "The cohort cannot be added": "Der Kohort kann nicht hinzugef\u00fcgt werden", "The cohort cannot be saved": "Dieser Kohort kann nicht gespeichert werden", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "Die Gesamtl\u00e4nge der Codefelder Organisation und Bibliothek darf nicht mehr als <%=limit%> Zeichen betragen.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "Die Gesamtl\u00e4nge der Felder Organisation, Kursnummer und Kursablauf darf nicht mehr als <%=limit%> Zeichen betragen.", "The country or region where you live.": "Das Land oder die Stadt in der Sie leben.", "The country that team members primarily identify with.": "Das Land mit dem sich die Teammitglieder prim\u00e4r identifizieren", "The course end date must be later than the course start date.": "Das Datum des Kursendes kann nicht vor dem Einschreibedatum des Kurses liegen.", @@ -1757,7 +1745,6 @@ "The following email addresses and/or usernames are invalid:": "Die folgenden E-Mail-Adressen und/oder Nutzernamen sind ung\u00fcltig:", "The following errors were generated:": "Folgende Fehler wurden generiert:", "The following file types are not allowed: ": "Die folgenden Dateitypen sind nicht erlaubt:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "Die folgende Information ist bereits in Ihrem {platform} Profil. Wir haben dies hier eingef\u00fcgt.", "The following message will be displayed at the bottom of the courseware pages within your course:": "Die folgende Nachricht wird im unteren Bereich Ihrers Kurses angezeigt. ", "The following options are available for the {license_name} license.": "Die folgenden Optionen sind f\u00fcr die {license_name} Lizenz verf\u00fcgbar.", "The following users are no longer enrolled in the course:": "Die folgenden Nutzer sind nicht l\u00e4nger in den Kurs eingeschrieben:", @@ -1769,7 +1756,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "Die der Prozentsatz der minimalen Fertigstellung der Aufgaben muss eine ganze Nummer zwischen 0 und 100 ergeben.", "The minimum grade for course credit is not set.": "Es ist keine Mindestbenotung definiert.", "The minimum score percentage must be a whole number between 0 and 100.": "Die minimale Punktzahl bei der Benotung muss eine ganze Zahl zwischen 0 und 100 sein.", - "The more you tell us, the more quickly and helpfully we can respond!": "Je mehr Sie uns von Ihrem Anliegen berichten, desto genauer und schneller k\u00f6nnen wir Ihnen helfen!", "The name of this signatory as it should appear on certificates.": "Der Name des Unterzeichners soll auf dem Zertifikat erscheinen.", "The name that identifies you on {platform_name}. You cannot change your username.": "Dies ist Ihr Benutzername auf der {platform_name}. Diesen k\u00f6nnen Sie nicht mehr \u00e4ndern.", "The name that is used for ID verification and that appears on your certificates.": "Dieser Name erscheint auf all Ihren Zertifikaten.", @@ -1777,7 +1763,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Anzahl der Unterabschnitte im Kurs, die Aufgaben dieses typs enthalten.", "The organization that this signatory belongs to, as it should appear on certificates.": "Die Organisation, zu welcher der Unterzeichner geh\u00f6rt, soll auf dem Zertifikat erscheinen.", "The page \"{route}\" could not be found.": "Die Seite \"{route}\" konnte nicht gefunden werden.", - "The photo of your face matches the photo on your ID.": "Das Foto von deinem Gesicht muss mit dem Foto in deinem Identit\u00e4tsnachweis \u00fcbereinstimmen", "The post you selected has been deleted.": "Der Beitrag, den Sie ausgew\u00e4hlt haben, wurde bereits gel\u00f6scht.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "Die ver\u00f6ffentlichte Branch-Version, {published}, wurde auf den Entwurf der Branch-Version, {draft}, zur\u00fcckgesetzt.", "The raw error message is:": "Die urspr\u00fcngliche Fehlermeldung ist:", @@ -1918,7 +1903,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "Um sicherzustellen, dass alle Teilnehmer auf das Video zugreifen k\u00f6nnen, empfehlen wir Ihnen, sowohl eine .mp4- als auch eine .webm Version Ihres Videos bereitzustellen. Klicken Sie unten, um eine URL f\u00fcr eine andere Version hinzuzuf\u00fcgen. Diese URLs k\u00f6nnen keine YouTube-URLs sein. Das erste aufgelistete Video, das mit dem Computer des Teilnehmers kompatibel ist, wird abgespielt.", "To complete the program, you must earn a verified certificate for each course.": "Um das Programm abzuschlie\u00dfen, m\u00fcssen Sie f\u00fcr jeden Kurs ein verifiziertes Zertifikat erwerben.", "To continue learning with this account, sign in below.": "Um mit diesem Konto weiter zu lernen, melden Sie sich unten an.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "Um den Credit-Prozess abzuschlie\u00dfen, %(display_name)s m\u00fcssen die Lernenden von %(platform_name)s einen Kreditantrag stellen.", "To invalidate a certificate for a particular learner, add the username or email address below.": "F\u00fcgen Sie \u00fcber die untenstehenden Eingabefelder den Benutzername oder die E-Mail Adresse des Teilnehmers hinzu, f\u00fcr welchen Sie die Zertifikate ung\u00fcltig machen m\u00f6chten.", "To pass this exam, you must complete the problems in the time allowed.": "Um diese Pr\u00fcfung zu bestehen, m\u00fcssen Sie die Probleme in der vorgegebenen Zeit l\u00f6sen.", "To receive a certificate, you must also verify your identity before {date}.": "Um ein Zertifikat zu erhalten, m\u00fcssen Sie auch Ihre Identit\u00e4t verifizieren vor dem {date}.", @@ -1927,7 +1911,6 @@ "To review learner cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on the {link_start}Data Download{link_end} page.": "Um die Kohortenzuordnungen der Lernenden zu \u00fcberpr\u00fcfen oder die Ergebnisse des Hochladens einer CSV-Datei zu sehen, laden Sie Kursprofilinformationen oder Kohortenergebnisse auf der Seite {link_start}Daten-Download{link_end} herunter.", "To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.": "Um Ihr Zertifikat auf Mozilla Backpack zu teilen, m\u00fcssen Sie zuerst ein Backpack-Konto haben. F\u00fchren Sie die folgenden Schritte aus, um Ihr Zertifikat zum Backpack hinzuzuf\u00fcgen.", "To take a successful photo, make sure that:": "Um ein erfolgreiches Bild zu machen, stell sicher dass:", - "To use the current photo, select the Take Photo button {icon}. To take another photo, select the Retake Photo button {icon}.": "Um das aktuelle Foto zu verwenden, w\u00e4hlen Sie die Kamerataste {icon}. Um ein weiteres Foto aufzunehmen, w\u00e4hlen Sie die Wiederholungs-Taste {icon}.", "To verify your identity, you need a webcam and a government-issued photo ID.": "Um Ihre Identit\u00e4t zu verifizieren, ben\u00f6tigen Sie eine Webcam und einen staatlich ausgestellten Lichtbildausweis.", "Today": "Heute", "Toggle Account Password (Usable/Unusable)": "Passwort des Benutzerkontos einblenden (Verwendbar/nicht verwendbar)", @@ -2008,7 +1991,6 @@ "Upload Videos": "Videos hochladen", "Upload a CSV file": "Hochladen einer CSV-Datei", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "Hochladen einer (.csv) Datei, in welcher die E-Mail Adressen oder der Benutzername der jeweiligen Teilnehmer, welche Sie zu der Ausnahmeliste hinzuf\u00fcgen m\u00f6chten, eingetragen sind. Bitte beachten Sie hierbei, dass die Eintr\u00e4ge durch Komma separiert werden. ", - "Upload a new PDF to \u201c<%= name %>\u201d": "Neues PDf unter \u201c<%= name %>\u201d hochgeladen", "Upload an image": "Ein Bild hochladen", "Upload an image or capture one with your web or phone camera.": "Bitte laden Sie ein Bild hoch oder nehmen Sie ein Foto mit ihr webcam oder Handy.", "Upload completed": "Hochladen fertiggestellt", @@ -2041,7 +2023,6 @@ "Use my university info": "Meine Universit\u00e4tsinformationen verwenden", "Use the All Topics menu to find specific topics.": "Benutzen Sie das Men\u00fc \"Alle Diskussionen\" um bestimmte Themen zu finden. ", "Use the Retake Photo button if you are not pleased with your photo": "Nutzen Sie den Wiederholungsknopf, wenn Sie unzufrieden mit Ihrer Aufnahme sind.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Benutzen Sie ihre webcam um ein Foto von ihr Ausweis zu nehmen. Wir werden dieses Foto mit das Foto von ihr Gesicht und der Name auf ihr Konto vergleichen.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Benutze ihre Webcam um ein Foto von ihren Gesicht aufzunehmen damit wir dieses mit dem Foto ihres Ausweises abgleichen k\u00f6nnen.", "Used": "benutzt", "Used in {count} location": [ @@ -2066,7 +2047,6 @@ "Verified Certificate upgrade": "Upgrade verifizierter Zertifikate", "Verified Status": "Gepr\u00fcfter Status", "Verified mode price": "Kosten der verifizierten Teilnahmeart", - "Verify Now": "Verifiziere Jetzt", "Version": "Version", "Vertical space": "Vertikaler Abstand", "Very loud": "Sehr Laut", @@ -2113,7 +2093,6 @@ "We couldn't find any results for \"%s\".": "Wir konnten leider keine Suchergebnisse f\u00fcr \"%s\" finden. ", "We couldn't sign you in.": "Wir konnten Sie leider nicht einloggen.", "We have encountered an error. Refresh your browser and then try again.": "Wir haben einen Fehler gefunden. Aktualisieren Sie Ihren Browser und versuchen Sie es dann erneut.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Wir haben Ihre Informationen erhalten und verifizieren Ihre Identit\u00e4t. Sie werden eine Meldung auf Ihrer 'Meine Kurse' \u00dcbersicht sehen, wenn der Verifikationsprozess abgeschlossen ist (normalerweise innerhalb von 1-2 Tagen). In der Zwischenzeit k\u00f6nnen Sie noch auf alle verf\u00fcgbaren Kursinhalte zugreifen.", "We just need a little more information before you start learning with %(platformName)s.": "Wir brauchen noch einige weitere Informationen, bevor Sie mit %(platformName)s lernen k\u00f6nnen.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Wir verwenden die h\u00f6chste Sicherheit zur Verf\u00fcgung um das Foto zu verschl\u00fcsseln und senden es an unsere Autorisierungsdienst f\u00fcr Kritik. Ihre Fotos und Daten sind nicht gespeichert und auch nicht sichtbar auf %(platformName)s nach das \u00dcberpr\u00fcfung Prozess.", "We're sorry to see you go! Your account will be deleted shortly.": "Es tut uns leid, dass Sie Ihren Account l\u00f6schen m\u00f6chten!", @@ -2221,14 +2200,10 @@ "You must specify a name": "Sie m\u00fcssen einen Namen auff\u00fchren", "You must specify a name for the cohort": "Sie m\u00fcssen einen Namen f\u00fcr die Gro\u00dfgruppe angeben", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "Sie m\u00fcssen Ihr Geburtsjahr eintragen, bevor Sie Ihr volles Profil teilen k\u00f6nnen. Gehen Sie zur {account_settings_page_link}, um Ihr Geburtsjahr einzutragen.", - "You need a computer or cell phone that has a webcam. When you receive a browser prompt, make sure that you allow access to the camera.": "Sie ben\u00f6tigen ein Computer oder Handy mit integrierter Webcam. Wenn Sie eine Anfrage \u00fcber Ihren Browser bekommen, stellen Sie sicher, dass der Zugriff auf die Kamera aktiviert ist.", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Sie ben\u00f6tigen einen F\u00fchrerschein, Reisepass oder einen anderen staatlich ausgestellten Lichtbildausweis mit Ihrem Namen und Foto.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Sie brauchen ein Ausweis mit ihr Name und Foto. Akzeptierte Identit\u00e4tsnachweise sind F\u00fchrerscheine, Reisep\u00e4sse oder andere Bildausweise mit amtlichen Licht.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Sie m\u00fcssen ihren Konto aktivieren vor Sie sich an ein Kurs anmelden k\u00f6nnen. Bitte kontrollieren Sie Ihr Posteingang f\u00fcr das Aktivierungsmail. ", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Vor Sie sich in Kurse eingeladen k\u00f6nnen, m\u00fcssen Sie ihr Konto aktivieren. Kontrollieren Sie ihr Posteingang f\u00fcr das Aktivierungsmail. Nach Sie ihre Aktivierung best\u00e4tigen, k\u00f6nnen Sie diese Seite neuladen.", "You receive messages from {platform_name} and course teams at this address.": "Auf diese E-Mail Adresse werden Sie alle Benachrichtigungen und Neuigkeiten der {platform_name} zugesandt bekommen.", "You reserve all rights for your work": "Sie behalten sich alle Rechte f\u00fcr Ihre Arbeit vor", - "You still need to visit the %(display_name)s website to complete the credit process.": "Sie m\u00fcssen noch die Website %(display_name)s besuchen, um den Credit-Prozess abzuschlie\u00dfen.", "You submitted {filename}; only {allowedFiles} are allowed.": "Ihre Einreichung {filename}; Es sind nur {allowedFiles} erlaubt.", "You waive some rights for your work, such that others can use it too": "Sie verzichten auf einige Rechte f\u00fcr Ihre Arbeit, so dass auch andere diese nutzen k\u00f6nnen", "You will be refunded the amount you paid.": "Sie werden eine R\u00fcckerstattung f\u00fcr Ihren gezahlten Betrag erhalten. ", @@ -2323,7 +2298,6 @@ "enter code here": "Code hier eingeben", "enter link description here": "Linkbeschreibung hier eingeben", "for": "f\u00fcr", - "for {courseName}": "f\u00fcr {courseName}", "group configuration": "Gruppenkonfiguration", "image omitted": "Bild weggelassen", "incorrect": "falsch", @@ -2500,7 +2474,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2552,9 +2526,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/el/djangojs.js b/cms/static/js/i18n/el/djangojs.js index bff79aa6a61ac0f5cc7cb1ea65bed76de1b6b205..38f03ea55b97cfc60421b5fb6f0060c9673ca909 100644 --- a/cms/static/js/i18n/el/djangojs.js +++ b/cms/static/js/i18n/el/djangojs.js @@ -434,7 +434,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -490,9 +490,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y P", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/en-uk/djangojs.js b/cms/static/js/i18n/en-uk/djangojs.js index 39914281913c92df4d92a324b5a7c9efbb65a380..10c4681968976135c7d32c6632950a5cbe9387a3 100644 --- a/cms/static/js/i18n/en-uk/djangojs.js +++ b/cms/static/js/i18n/en-uk/djangojs.js @@ -71,7 +71,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -127,9 +127,9 @@ "%m/%d/%y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/en/djangojs.js b/cms/static/js/i18n/en/djangojs.js index 46e07902835a61859de1f9ced1ae4c8594db6505..f6ad253896852559d1fd34e602401499533dabac 100644 --- a/cms/static/js/i18n/en/djangojs.js +++ b/cms/static/js/i18n/en/djangojs.js @@ -35,7 +35,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -91,9 +91,9 @@ "%m/%d/%y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/en@lolcat/djangojs.js b/cms/static/js/i18n/en@lolcat/djangojs.js index 09ab0ad1017c413c3bafcb7fa641bef68644a979..f099ebfc1d7e1fb0cc02eda8cbc11276c49368c9 100644 --- a/cms/static/js/i18n/en@lolcat/djangojs.js +++ b/cms/static/js/i18n/en@lolcat/djangojs.js @@ -35,7 +35,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -99,9 +99,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/en@pirate/djangojs.js b/cms/static/js/i18n/en@pirate/djangojs.js index 09ab0ad1017c413c3bafcb7fa641bef68644a979..f099ebfc1d7e1fb0cc02eda8cbc11276c49368c9 100644 --- a/cms/static/js/i18n/en@pirate/djangojs.js +++ b/cms/static/js/i18n/en@pirate/djangojs.js @@ -35,7 +35,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -99,9 +99,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/eo/djangojs.js b/cms/static/js/i18n/eo/djangojs.js index ef77c7b8c7af2fe847507d455e17174130c50e98..074af17a32b3e3f97f740dd1190c807a16e95463 100644 --- a/cms/static/js/i18n/eo/djangojs.js +++ b/cms/static/js/i18n/eo/djangojs.js @@ -27,6 +27,7 @@ " M\u00e9m\u00df\u00e9rs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#" ], " and ": " \u00e4nd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", + " as many questions may have already been answered.": " \u00e4s m\u00e4n\u00fd q\u00fc\u00e9st\u00ef\u00f6ns m\u00e4\u00fd h\u00e4v\u00e9 \u00e4lr\u00e9\u00e4d\u00fd \u00df\u00e9\u00e9n \u00e4nsw\u00e9r\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", " learner does not exist in LMS and not added to the exception list": " l\u00e9\u00e4rn\u00e9r d\u00f6\u00e9s n\u00f6t \u00e9x\u00efst \u00efn LMS \u00e4nd n\u00f6t \u00e4dd\u00e9d t\u00f6 th\u00e9 \u00e9x\u00e7\u00e9pt\u00ef\u00f6n l\u00efst \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", " learner is already white listed and not added to the exception list": " l\u00e9\u00e4rn\u00e9r \u00efs \u00e4lr\u00e9\u00e4d\u00fd wh\u00eft\u00e9 l\u00efst\u00e9d \u00e4nd n\u00f6t \u00e4dd\u00e9d t\u00f6 th\u00e9 \u00e9x\u00e7\u00e9pt\u00ef\u00f6n l\u00efst \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", " learner is not enrolled in course and not added to the exception list": " l\u00e9\u00e4rn\u00e9r \u00efs n\u00f6t \u00e9nr\u00f6ll\u00e9d \u00efn \u00e7\u00f6\u00fcrs\u00e9 \u00e4nd n\u00f6t \u00e4dd\u00e9d t\u00f6 th\u00e9 \u00e9x\u00e7\u00e9pt\u00ef\u00f6n l\u00efst \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", @@ -39,6 +40,8 @@ " records are not in correct format and not added to the exception list": " r\u00e9\u00e7\u00f6rds \u00e4r\u00e9 n\u00f6t \u00efn \u00e7\u00f6rr\u00e9\u00e7t f\u00f6rm\u00e4t \u00e4nd n\u00f6t \u00e4dd\u00e9d t\u00f6 th\u00e9 \u00e9x\u00e7\u00e9pt\u00ef\u00f6n l\u00efst \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "${listPrice}": "${listPrice} \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "%(cohort_name)s (%(user_count)s)": "%(cohort_name)s (%(user_count)s) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", + "%(comments_count)s %(span_sr_open)scomments %(span_close)s": "%(comments_count)s %(span_sr_open)s\u00e7\u00f6mm\u00e9nts %(span_close)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", + "%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s unread comments)%(span_close)s": "%(comments_count)s %(span_sr_open)s\u00e7\u00f6mm\u00e9nts (%(unread_comments_count)s \u00fcnr\u00e9\u00e4d \u00e7\u00f6mm\u00e9nts)%(span_close)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "%(errorCount)s error found in form.": [ "%(errorCount)s \u00e9rr\u00f6r f\u00f6\u00fcnd \u00efn f\u00f6rm. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "%(errorCount)s \u00e9rr\u00f6rs f\u00f6\u00fcnd \u00efn f\u00f6rm. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#" @@ -84,6 +87,7 @@ "%s from now": "%s fr\u00f6m n\u00f6w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "(Add signatories for a certificate)": "(\u00c0dd s\u00efgn\u00e4t\u00f6r\u00ef\u00e9s f\u00f6r \u00e4 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "(Caption will be displayed when you start playing the video.)": "(\u00c7\u00e4pt\u00ef\u00f6n w\u00efll \u00df\u00e9 d\u00efspl\u00e4\u00fd\u00e9d wh\u00e9n \u00fd\u00f6\u00fc st\u00e4rt pl\u00e4\u00fd\u00efng th\u00e9 v\u00efd\u00e9\u00f6.) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "(Community TA)": "(\u00c7\u00f6mm\u00fcn\u00eft\u00fd T\u00c0) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "(Optional)": "(\u00d6pt\u00ef\u00f6n\u00e4l) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "(Read-only)": "(R\u00e9\u00e4d-\u00f6nl\u00fd) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "(Required Field)": "(R\u00e9q\u00fc\u00efr\u00e9d F\u00ef\u00e9ld) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", @@ -91,6 +95,7 @@ "(Self-paced) Ends {end}": "(S\u00e9lf-p\u00e4\u00e7\u00e9d) \u00c9nds {end} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "(Self-paced) Started {start}": "(S\u00e9lf-p\u00e4\u00e7\u00e9d) St\u00e4rt\u00e9d {start} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "(Self-paced) Starts {start}": "(S\u00e9lf-p\u00e4\u00e7\u00e9d) St\u00e4rts {start} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", + "(Staff)": "(St\u00e4ff) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "(contains %(student_count)s student)": [ "(\u00e7\u00f6nt\u00e4\u00efns %(student_count)s st\u00fcd\u00e9nt) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "(\u00e7\u00f6nt\u00e4\u00efns %(student_count)s st\u00fcd\u00e9nts) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#" @@ -152,7 +157,12 @@ "Add URLs for additional versions": "\u00c0dd \u00dbRLs f\u00f6r \u00e4dd\u00eft\u00ef\u00f6n\u00e4l v\u00e9rs\u00ef\u00f6ns \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "Add a Chapter": "\u00c0dd \u00e4 \u00c7h\u00e4pt\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Add a New Cohort": "\u00c0dd \u00e4 N\u00e9w \u00c7\u00f6h\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "Add a Post": "\u00c0dd \u00e4 P\u00f6st \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", + "Add a Response": "\u00c0dd \u00e4 R\u00e9sp\u00f6ns\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", + "Add a clear and descriptive title to encourage participation. (Required)": "\u00c0dd \u00e4 \u00e7l\u00e9\u00e4r \u00e4nd d\u00e9s\u00e7r\u00efpt\u00efv\u00e9 t\u00eftl\u00e9 t\u00f6 \u00e9n\u00e7\u00f6\u00fcr\u00e4g\u00e9 p\u00e4rt\u00ef\u00e7\u00efp\u00e4t\u00ef\u00f6n. (R\u00e9q\u00fc\u00efr\u00e9d) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", + "Add a comment": "\u00c0dd \u00e4 \u00e7\u00f6mm\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Add a learning outcome here": "\u00c0dd \u00e4 l\u00e9\u00e4rn\u00efng \u00f6\u00fct\u00e7\u00f6m\u00e9 h\u00e9r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", + "Add a response:": "\u00c0dd \u00e4 r\u00e9sp\u00f6ns\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Add another group": "\u00c0dd \u00e4n\u00f6th\u00e9r gr\u00f6\u00fcp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Add language": "\u00c0dd l\u00e4ng\u00fc\u00e4g\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Add learners to this cohort": "\u00c0dd l\u00e9\u00e4rn\u00e9rs t\u00f6 th\u00efs \u00e7\u00f6h\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", @@ -162,6 +172,7 @@ "Add your first content group": "\u00c0dd \u00fd\u00f6\u00fcr f\u00efrst \u00e7\u00f6nt\u00e9nt gr\u00f6\u00fcp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Add your first group configuration": "\u00c0dd \u00fd\u00f6\u00fcr f\u00efrst gr\u00f6\u00fcp \u00e7\u00f6nf\u00efg\u00fcr\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "Add your first textbook": "\u00c0dd \u00fd\u00f6\u00fcr f\u00efrst t\u00e9xt\u00df\u00f6\u00f6k \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", + "Add your post to a relevant topic to help others find it. (Required)": "\u00c0dd \u00fd\u00f6\u00fcr p\u00f6st t\u00f6 \u00e4 r\u00e9l\u00e9v\u00e4nt t\u00f6p\u00ef\u00e7 t\u00f6 h\u00e9lp \u00f6th\u00e9rs f\u00efnd \u00eft. (R\u00e9q\u00fc\u00efr\u00e9d) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Add {role} Access": "\u00c0dd {role} \u00c0\u00e7\u00e7\u00e9ss \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Adding": "\u00c0dd\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Adding the selected course to your cart": "\u00c0dd\u00efng th\u00e9 s\u00e9l\u00e9\u00e7t\u00e9d \u00e7\u00f6\u00fcrs\u00e9 t\u00f6 \u00fd\u00f6\u00fcr \u00e7\u00e4rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", @@ -182,6 +193,7 @@ "Align left": "\u00c0l\u00efgn l\u00e9ft \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Align right": "\u00c0l\u00efgn r\u00efght \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Alignment": "\u00c0l\u00efgnm\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", + "All Groups": "\u00c0ll Gr\u00f6\u00fcps \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "All Learners and Staff": "\u00c0ll L\u00e9\u00e4rn\u00e9rs \u00e4nd St\u00e4ff \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "All Posts": "\u00c0ll P\u00f6sts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "All Rights Reserved": "\u00c0ll R\u00efghts R\u00e9s\u00e9rv\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", @@ -267,6 +279,7 @@ "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "\u00c0r\u00e9 \u00fd\u00f6\u00fc s\u00fcr\u00e9 \u00fd\u00f6\u00fc w\u00efsh t\u00f6 d\u00e9l\u00e9t\u00e9 th\u00efs \u00eft\u00e9m. \u00cct \u00e7\u00e4nn\u00f6t \u00df\u00e9 r\u00e9v\u00e9rs\u00e9d!\n\n\u00c0ls\u00f6 \u00e4n\u00fd \u00e7\u00f6nt\u00e9nt th\u00e4t l\u00efnks/r\u00e9f\u00e9rs t\u00f6 th\u00efs \u00eft\u00e9m w\u00efll n\u00f6 l\u00f6ng\u00e9r w\u00f6rk (\u00e9.g. \u00dfr\u00f6k\u00e9n \u00efm\u00e4g\u00e9s \u00e4nd/\u00f6r l\u00efnks) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192#", "Are you sure?": "\u00c0r\u00e9 \u00fd\u00f6\u00fc s\u00fcr\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "As part of the verification process, you take a photo of both your face and a government-issued photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u00c0s p\u00e4rt \u00f6f th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss, \u00fd\u00f6\u00fc t\u00e4k\u00e9 \u00e4 ph\u00f6t\u00f6 \u00f6f \u00df\u00f6th \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9 \u00e4nd \u00e4 g\u00f6v\u00e9rnm\u00e9nt-\u00efss\u00fc\u00e9d ph\u00f6t\u00f6 \u00ccD. \u00d6\u00fcr \u00e4\u00fcth\u00f6r\u00efz\u00e4t\u00ef\u00f6n s\u00e9rv\u00ef\u00e7\u00e9 \u00e7\u00f6nf\u00efrms \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd \u00df\u00fd \u00e7\u00f6mp\u00e4r\u00efng th\u00e9 ph\u00f6t\u00f6 \u00fd\u00f6\u00fc t\u00e4k\u00e9 w\u00efth th\u00e9 ph\u00f6t\u00f6 \u00f6n \u00fd\u00f6\u00fcr \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7#", + "As part of the verification process, you take a photo of both your face and a photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u00c0s p\u00e4rt \u00f6f th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss, \u00fd\u00f6\u00fc t\u00e4k\u00e9 \u00e4 ph\u00f6t\u00f6 \u00f6f \u00df\u00f6th \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9 \u00e4nd \u00e4 ph\u00f6t\u00f6 \u00ccD. \u00d6\u00fcr \u00e4\u00fcth\u00f6r\u00efz\u00e4t\u00ef\u00f6n s\u00e9rv\u00ef\u00e7\u00e9 \u00e7\u00f6nf\u00efrms \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd \u00df\u00fd \u00e7\u00f6mp\u00e4r\u00efng th\u00e9 ph\u00f6t\u00f6 \u00fd\u00f6\u00fc t\u00e4k\u00e9 w\u00efth th\u00e9 ph\u00f6t\u00f6 \u00f6n \u00fd\u00f6\u00fcr \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442#", "As you complete courses, you will see them listed here.": "\u00c0s \u00fd\u00f6\u00fc \u00e7\u00f6mpl\u00e9t\u00e9 \u00e7\u00f6\u00fcrs\u00e9s, \u00fd\u00f6\u00fc w\u00efll s\u00e9\u00e9 th\u00e9m l\u00efst\u00e9d h\u00e9r\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Assessment": "\u00c0ss\u00e9ssm\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Assessment Results Visibility": "\u00c0ss\u00e9ssm\u00e9nt R\u00e9s\u00fclts V\u00efs\u00ef\u00df\u00efl\u00eft\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", @@ -409,6 +422,7 @@ "Click to remove all chosen %s at once.": "Klaku por tuj forigi \u0109iujn %s elektitajn.", "Close": "\u00c7l\u00f6s\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "Close Calculator": "\u00c7l\u00f6s\u00e9 \u00c7\u00e4l\u00e7\u00fcl\u00e4t\u00f6r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "Closed": "\u00c7l\u00f6s\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Code": "\u00c7\u00f6d\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Code Sample (Ctrl+K)": "\u00c7\u00f6d\u00e9 S\u00e4mpl\u00e9 (\u00c7trl+K) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Code block": "\u00c7\u00f6d\u00e9 \u00dfl\u00f6\u00e7k \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", @@ -427,6 +441,7 @@ "Coming Soon": "\u00c7\u00f6m\u00efng S\u00f6\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Commentary": "\u00c7\u00f6mm\u00e9nt\u00e4r\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Common Problem Types": "\u00c7\u00f6mm\u00f6n Pr\u00f6\u00dfl\u00e9m T\u00fdp\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", + "Community TA": "\u00c7\u00f6mm\u00fcn\u00eft\u00fd T\u00c0 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Complete courses on your schedule to ensure you stand out in your field!": "\u00c7\u00f6mpl\u00e9t\u00e9 \u00e7\u00f6\u00fcrs\u00e9s \u00f6n \u00fd\u00f6\u00fcr s\u00e7h\u00e9d\u00fcl\u00e9 t\u00f6 \u00e9ns\u00fcr\u00e9 \u00fd\u00f6\u00fc st\u00e4nd \u00f6\u00fct \u00efn \u00fd\u00f6\u00fcr f\u00ef\u00e9ld! \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "Completed": "\u00c7\u00f6mpl\u00e9t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Component": "\u00c7\u00f6mp\u00f6n\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", @@ -477,6 +492,7 @@ ], "Course Content": "\u00c7\u00f6\u00fcrs\u00e9 \u00c7\u00f6nt\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Course Credit Requirements": "\u00c7\u00f6\u00fcrs\u00e9 \u00c7r\u00e9d\u00eft R\u00e9q\u00fc\u00efr\u00e9m\u00e9nts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", + "Course Discussion Forum": "\u00c7\u00f6\u00fcrs\u00e9 D\u00efs\u00e7\u00fcss\u00ef\u00f6n F\u00f6r\u00fcm \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "Course End": "\u00c7\u00f6\u00fcrs\u00e9 \u00c9nd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Course Handouts": "\u00c7\u00f6\u00fcrs\u00e9 H\u00e4nd\u00f6\u00fcts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Course ID": "\u00c7\u00f6\u00fcrs\u00e9 \u00ccD \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", @@ -499,6 +515,7 @@ "Create": "\u00c7r\u00e9\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Create Account": "\u00c7r\u00e9\u00e4t\u00e9 \u00c0\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Create Re-run": "\u00c7r\u00e9\u00e4t\u00e9 R\u00e9-r\u00fcn \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", + "Create Support Ticket": "\u00c7r\u00e9\u00e4t\u00e9 S\u00fcpp\u00f6rt T\u00ef\u00e7k\u00e9t \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Create a New Team": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4 N\u00e9w T\u00e9\u00e4m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Create a content group": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4 \u00e7\u00f6nt\u00e9nt gr\u00f6\u00fcp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "Create a new team if you can't find an existing team to join, or if you would like to learn with friends you know.": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4 n\u00e9w t\u00e9\u00e4m \u00eff \u00fd\u00f6\u00fc \u00e7\u00e4n't f\u00efnd \u00e4n \u00e9x\u00efst\u00efng t\u00e9\u00e4m t\u00f6 j\u00f6\u00efn, \u00f6r \u00eff \u00fd\u00f6\u00fc w\u00f6\u00fcld l\u00efk\u00e9 t\u00f6 l\u00e9\u00e4rn w\u00efth fr\u00ef\u00e9nds \u00fd\u00f6\u00fc kn\u00f6w. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", @@ -506,6 +523,7 @@ "Create account using %(providerName)s.": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00fcs\u00efng %(providerName)s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "Create an Account": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4n \u00c0\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Create an Account.": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4n \u00c0\u00e7\u00e7\u00f6\u00fcnt. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "Create an account": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4n \u00e4\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Create an account using": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4n \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00fcs\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "Create team.": "\u00c7r\u00e9\u00e4t\u00e9 t\u00e9\u00e4m. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Created": "\u00c7r\u00e9\u00e4t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", @@ -531,6 +549,7 @@ "Date Placed": "D\u00e4t\u00e9 Pl\u00e4\u00e7\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Date added": "D\u00e4t\u00e9 \u00e4dd\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Deactivate": "D\u00e9\u00e4\u00e7t\u00efv\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", + "Deactivating": "D\u00e9\u00e4\u00e7t\u00efv\u00e4t\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Deadlines": "D\u00e9\u00e4dl\u00efn\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "December": "decembro", "Declined": "D\u00e9\u00e7l\u00efn\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", @@ -539,7 +558,7 @@ "Default (Local Time Zone)": "D\u00e9f\u00e4\u00fclt (L\u00f6\u00e7\u00e4l T\u00efm\u00e9 Z\u00f6n\u00e9) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "Default Timed Transcript": "D\u00e9f\u00e4\u00fclt T\u00efm\u00e9d Tr\u00e4ns\u00e7r\u00efpt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "Delete": "D\u00e9l\u00e9t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "D\u00e9l\u00e9t\u00e9 \"<%= signatoryName %>\" fr\u00f6m th\u00e9 l\u00efst \u00f6f s\u00efgn\u00e4t\u00f6r\u00ef\u00e9s? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", + "Delete \"<%- signatoryName %>\" from the list of signatories?": "D\u00e9l\u00e9t\u00e9 \"<%- signatoryName %>\" fr\u00f6m th\u00e9 l\u00efst \u00f6f s\u00efgn\u00e4t\u00f6r\u00ef\u00e9s? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Delete File Confirmation": "D\u00e9l\u00e9t\u00e9 F\u00efl\u00e9 \u00c7\u00f6nf\u00efrm\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "Delete My Account": "D\u00e9l\u00e9t\u00e9 M\u00fd \u00c0\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Delete Page Confirmation": "D\u00e9l\u00e9t\u00e9 P\u00e4g\u00e9 \u00c7\u00f6nf\u00efrm\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", @@ -567,11 +586,14 @@ "Description": "D\u00e9s\u00e7r\u00efpt\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Description of the certificate": "D\u00e9s\u00e7r\u00efpt\u00ef\u00f6n \u00f6f th\u00e9 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", "Details": "D\u00e9t\u00e4\u00efls \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", + "Device with Camera": "D\u00e9v\u00ef\u00e7\u00e9 w\u00efth \u00c7\u00e4m\u00e9r\u00e4 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Dimensions": "D\u00efm\u00e9ns\u00ef\u00f6ns \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Disc": "D\u00efs\u00e7 \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Discard Changes": "D\u00efs\u00e7\u00e4rd \u00c7h\u00e4ng\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Discarding Changes": "D\u00efs\u00e7\u00e4rd\u00efng \u00c7h\u00e4ng\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "Discussion": "D\u00efs\u00e7\u00fcss\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Discussion Home": "D\u00efs\u00e7\u00fcss\u00ef\u00f6n H\u00f6m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", + "Discussion admins, moderators, and TAs can make their posts visible to all students or specify a single group.": "D\u00efs\u00e7\u00fcss\u00ef\u00f6n \u00e4dm\u00efns, m\u00f6d\u00e9r\u00e4t\u00f6rs, \u00e4nd T\u00c0s \u00e7\u00e4n m\u00e4k\u00e9 th\u00e9\u00efr p\u00f6sts v\u00efs\u00ef\u00dfl\u00e9 t\u00f6 \u00e4ll st\u00fcd\u00e9nts \u00f6r sp\u00e9\u00e7\u00eff\u00fd \u00e4 s\u00efngl\u00e9 gr\u00f6\u00fcp. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Discussion topics in the course are not divided.": "D\u00efs\u00e7\u00fcss\u00ef\u00f6n t\u00f6p\u00ef\u00e7s \u00efn th\u00e9 \u00e7\u00f6\u00fcrs\u00e9 \u00e4r\u00e9 n\u00f6t d\u00efv\u00efd\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Discussions are unified; all learners interact with posts from other learners, regardless of the group they are in.": "D\u00efs\u00e7\u00fcss\u00ef\u00f6ns \u00e4r\u00e9 \u00fcn\u00eff\u00ef\u00e9d; \u00e4ll l\u00e9\u00e4rn\u00e9rs \u00efnt\u00e9r\u00e4\u00e7t w\u00efth p\u00f6sts fr\u00f6m \u00f6th\u00e9r l\u00e9\u00e4rn\u00e9rs, r\u00e9g\u00e4rdl\u00e9ss \u00f6f th\u00e9 gr\u00f6\u00fcp th\u00e9\u00fd \u00e4r\u00e9 \u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Display Name": "D\u00efspl\u00e4\u00fd N\u00e4m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", @@ -584,7 +606,6 @@ "Do you want to upload your file before submitting?": "D\u00f6 \u00fd\u00f6\u00fc w\u00e4nt t\u00f6 \u00fcpl\u00f6\u00e4d \u00fd\u00f6\u00fcr f\u00efl\u00e9 \u00df\u00e9f\u00f6r\u00e9 s\u00fc\u00dfm\u00eftt\u00efng? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Document properties": "D\u00f6\u00e7\u00fcm\u00e9nt pr\u00f6p\u00e9rt\u00ef\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Does the name on your ID match your account name: %(fullName)s?": "D\u00f6\u00e9s th\u00e9 n\u00e4m\u00e9 \u00f6n \u00fd\u00f6\u00fcr \u00ccD m\u00e4t\u00e7h \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt n\u00e4m\u00e9: %(fullName)s? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", - "Does the photo of you match your ID photo?": "D\u00f6\u00e9s th\u00e9 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fc m\u00e4t\u00e7h \u00fd\u00f6\u00fcr \u00ccD ph\u00f6t\u00f6? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Does the photo of you show your whole face?": "D\u00f6\u00e9s th\u00e9 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fc sh\u00f6w \u00fd\u00f6\u00fcr wh\u00f6l\u00e9 f\u00e4\u00e7\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "D\u00f6n't s\u00e9\u00e9 \u00fd\u00f6\u00fcr p\u00ef\u00e7t\u00fcr\u00e9? M\u00e4k\u00e9 s\u00fcr\u00e9 t\u00f6 \u00e4ll\u00f6w \u00fd\u00f6\u00fcr \u00dfr\u00f6ws\u00e9r t\u00f6 \u00fcs\u00e9 \u00fd\u00f6\u00fcr \u00e7\u00e4m\u00e9r\u00e4 wh\u00e9n \u00eft \u00e4sks f\u00f6r p\u00e9rm\u00efss\u00ef\u00f6n. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Donate": "D\u00f6n\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", @@ -606,6 +627,7 @@ "Due Date:": "D\u00fc\u00e9 D\u00e4t\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Due Time in UTC:": "D\u00fc\u00e9 T\u00efm\u00e9 \u00efn \u00dbT\u00c7: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Due date cannot be before start date.": "D\u00fc\u00e9 d\u00e4t\u00e9 \u00e7\u00e4nn\u00f6t \u00df\u00e9 \u00df\u00e9f\u00f6r\u00e9 st\u00e4rt d\u00e4t\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", + "Due to the recent increase in interest in online education and edX, we are currently experiencing an unusually high volume of support requests. We appreciate your patience as we work to review each request. Please check the ": "D\u00fc\u00e9 t\u00f6 th\u00e9 r\u00e9\u00e7\u00e9nt \u00efn\u00e7r\u00e9\u00e4s\u00e9 \u00efn \u00efnt\u00e9r\u00e9st \u00efn \u00f6nl\u00efn\u00e9 \u00e9d\u00fc\u00e7\u00e4t\u00ef\u00f6n \u00e4nd \u00e9dX, w\u00e9 \u00e4r\u00e9 \u00e7\u00fcrr\u00e9ntl\u00fd \u00e9xp\u00e9r\u00ef\u00e9n\u00e7\u00efng \u00e4n \u00fcn\u00fcs\u00fc\u00e4ll\u00fd h\u00efgh v\u00f6l\u00fcm\u00e9 \u00f6f s\u00fcpp\u00f6rt r\u00e9q\u00fc\u00e9sts. W\u00e9 \u00e4ppr\u00e9\u00e7\u00ef\u00e4t\u00e9 \u00fd\u00f6\u00fcr p\u00e4t\u00ef\u00e9n\u00e7\u00e9 \u00e4s w\u00e9 w\u00f6rk t\u00f6 r\u00e9v\u00ef\u00e9w \u00e9\u00e4\u00e7h r\u00e9q\u00fc\u00e9st. Pl\u00e9\u00e4s\u00e9 \u00e7h\u00e9\u00e7k th\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 #", "Due:": "D\u00fc\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Duplicate": "D\u00fcpl\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Duplicating": "D\u00fcpl\u00ef\u00e7\u00e4t\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", @@ -625,8 +647,12 @@ "Edit Title": "\u00c9d\u00eft T\u00eftl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Edit Your Name": "\u00c9d\u00eft \u00dd\u00f6\u00fcr N\u00e4m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Edit this certificate?": "\u00c9d\u00eft th\u00efs \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", + "Edit your post below.": "\u00c9d\u00eft \u00fd\u00f6\u00fcr p\u00f6st \u00df\u00e9l\u00f6w. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Editable": "\u00c9d\u00eft\u00e4\u00dfl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Editing access for: {title}": "\u00c9d\u00eft\u00efng \u00e4\u00e7\u00e7\u00e9ss f\u00f6r: {title} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", + "Editing comment": "\u00c9d\u00eft\u00efng \u00e7\u00f6mm\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", + "Editing post": "\u00c9d\u00eft\u00efng p\u00f6st \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", + "Editing response": "\u00c9d\u00eft\u00efng r\u00e9sp\u00f6ns\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Editing: {title}": "\u00c9d\u00eft\u00efng: {title} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Editor": "\u00c9d\u00eft\u00f6r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Education Completed": "\u00c9d\u00fc\u00e7\u00e4t\u00ef\u00f6n \u00c7\u00f6mpl\u00e9t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", @@ -645,6 +671,7 @@ "Encoding": "\u00c9n\u00e7\u00f6d\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "End My Exam": "\u00c9nd M\u00fd \u00c9x\u00e4m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "End of transcript. Skip to the start.": "\u00c9nd \u00f6f tr\u00e4ns\u00e7r\u00efpt. Sk\u00efp t\u00f6 th\u00e9 st\u00e4rt. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", + "Endorse": "\u00c9nd\u00f6rs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "Ends {end}": "\u00c9nds {end} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Engage with posts": "\u00c9ng\u00e4g\u00e9 w\u00efth p\u00f6sts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Enroll Now": "\u00c9nr\u00f6ll N\u00f6w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", @@ -700,6 +727,7 @@ "Error getting the number of ungraded responses": "\u00c9rr\u00f6r g\u00e9tt\u00efng th\u00e9 n\u00fcm\u00df\u00e9r \u00f6f \u00fcngr\u00e4d\u00e9d r\u00e9sp\u00f6ns\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Error importing course": "\u00c9rr\u00f6r \u00efmp\u00f6rt\u00efng \u00e7\u00f6\u00fcrs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "Error listing task history for this student and problem.": "\u00c9rr\u00f6r l\u00efst\u00efng t\u00e4sk h\u00efst\u00f6r\u00fd f\u00f6r th\u00efs st\u00fcd\u00e9nt \u00e4nd pr\u00f6\u00dfl\u00e9m. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "Error posting your message.": "\u00c9rr\u00f6r p\u00f6st\u00efng \u00fd\u00f6\u00fcr m\u00e9ss\u00e4g\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "Error removing user": "\u00c9rr\u00f6r r\u00e9m\u00f6v\u00efng \u00fcs\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Error resetting entrance exam attempts for student '{student_id}'. Make sure student identifier is correct.": "\u00c9rr\u00f6r r\u00e9s\u00e9tt\u00efng \u00e9ntr\u00e4n\u00e7\u00e9 \u00e9x\u00e4m \u00e4tt\u00e9mpts f\u00f6r st\u00fcd\u00e9nt '{student_id}'. M\u00e4k\u00e9 s\u00fcr\u00e9 st\u00fcd\u00e9nt \u00efd\u00e9nt\u00eff\u00ef\u00e9r \u00efs \u00e7\u00f6rr\u00e9\u00e7t. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Error resetting problem attempts for problem '<%= problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "\u00c9rr\u00f6r r\u00e9s\u00e9tt\u00efng pr\u00f6\u00dfl\u00e9m \u00e4tt\u00e9mpts f\u00f6r pr\u00f6\u00dfl\u00e9m '<%= problem_id %>' \u00e4nd st\u00fcd\u00e9nt '<%- student_id %>'. M\u00e4k\u00e9 s\u00fcr\u00e9 th\u00e4t th\u00e9 pr\u00f6\u00dfl\u00e9m \u00e4nd st\u00fcd\u00e9nt \u00efd\u00e9nt\u00eff\u00ef\u00e9rs \u00e4r\u00e9 \u00e7\u00f6mpl\u00e9t\u00e9 \u00e4nd \u00e7\u00f6rr\u00e9\u00e7t. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442 \u03b1\u03b7\u03b9\u043c \u03b9#", @@ -757,7 +785,6 @@ "Fill browser": "F\u00efll \u00dfr\u00f6ws\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Filter": "Filtru", "Filter and sort topics": "F\u00eflt\u00e9r \u00e4nd s\u00f6rt t\u00f6p\u00ef\u00e7s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", - "Final Grade": "F\u00efn\u00e4l Gr\u00e4d\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Final Grade Received": "F\u00efn\u00e4l Gr\u00e4d\u00e9 R\u00e9\u00e7\u00e9\u00efv\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Financial Aid": "F\u00efn\u00e4n\u00e7\u00ef\u00e4l \u00c0\u00efd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Financial Assistance": "F\u00efn\u00e4n\u00e7\u00ef\u00e4l \u00c0ss\u00efst\u00e4n\u00e7\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", @@ -771,12 +798,15 @@ "Find previous": "F\u00efnd pr\u00e9v\u00ef\u00f6\u00fcs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Finish": "F\u00efn\u00efsh \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "First time here?": "F\u00efrst t\u00efm\u00e9 h\u00e9r\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "Follow": "F\u00f6ll\u00f6w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Follow or unfollow posts": "F\u00f6ll\u00f6w \u00f6r \u00fcnf\u00f6ll\u00f6w p\u00f6sts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", + "Following": "F\u00f6ll\u00f6w\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Font Family": "F\u00f6nt F\u00e4m\u00efl\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Font Sizes": "F\u00f6nt S\u00efz\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Footer": "F\u00f6\u00f6t\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "For grading to work, you must change all {oldName} subsections to {newName}.": "F\u00f6r gr\u00e4d\u00efng t\u00f6 w\u00f6rk, \u00fd\u00f6\u00fc m\u00fcst \u00e7h\u00e4ng\u00e9 \u00e4ll {oldName} s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6ns t\u00f6 {newName}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "For inquiries regarding assignments, grades, or structure of a specific course, please post in the discussion forums for that course directly.": "F\u00f6r \u00efnq\u00fc\u00efr\u00ef\u00e9s r\u00e9g\u00e4rd\u00efng \u00e4ss\u00efgnm\u00e9nts, gr\u00e4d\u00e9s, \u00f6r str\u00fc\u00e7t\u00fcr\u00e9 \u00f6f \u00e4 sp\u00e9\u00e7\u00eff\u00ef\u00e7 \u00e7\u00f6\u00fcrs\u00e9, pl\u00e9\u00e4s\u00e9 p\u00f6st \u00efn th\u00e9 d\u00efs\u00e7\u00fcss\u00ef\u00f6n f\u00f6r\u00fcms f\u00f6r th\u00e4t \u00e7\u00f6\u00fcrs\u00e9 d\u00efr\u00e9\u00e7tl\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442 \u03b1\u03b7\u03b9\u043c \u03b9\u2202 \u0454\u0455\u0442#", + "Forgot my password": "F\u00f6rg\u00f6t m\u00fd p\u00e4ssw\u00f6rd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Format": "F\u00f6rm\u00e4t \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Formats": "F\u00f6rm\u00e4ts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "Free text notes": "Fr\u00e9\u00e9 t\u00e9xt n\u00f6t\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", @@ -791,7 +821,6 @@ "Generate": "G\u00e9n\u00e9r\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Generate Exception Certificates": "G\u00e9n\u00e9r\u00e4t\u00e9 \u00c9x\u00e7\u00e9pt\u00ef\u00f6n \u00c7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", "Generate the user's certificate": "G\u00e9n\u00e9r\u00e4t\u00e9 th\u00e9 \u00fcs\u00e9r's \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", - "Get Credit": "G\u00e9t \u00c7r\u00e9d\u00eft \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Go to Dashboard": "G\u00f6 t\u00f6 D\u00e4sh\u00df\u00f6\u00e4rd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Go to my Dashboard": "G\u00f6 t\u00f6 m\u00fd D\u00e4sh\u00df\u00f6\u00e4rd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Go to your Dashboard": "G\u00f6 t\u00f6 \u00fd\u00f6\u00fcr D\u00e4sh\u00df\u00f6\u00e4rd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", @@ -873,10 +902,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "\u00ccf th\u00e9 s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6n d\u00f6\u00e9s n\u00f6t h\u00e4v\u00e9 \u00e4 d\u00fc\u00e9 d\u00e4t\u00e9, l\u00e9\u00e4rn\u00e9rs \u00e4lw\u00e4\u00fds s\u00e9\u00e9 th\u00e9\u00efr s\u00e7\u00f6r\u00e9s wh\u00e9n th\u00e9\u00fd s\u00fc\u00dfm\u00eft \u00e4nsw\u00e9rs t\u00f6 \u00e4ss\u00e9ssm\u00e9nts. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u00ccf th\u00e9 \u00fcn\u00eft w\u00e4s pr\u00e9v\u00ef\u00f6\u00fcsl\u00fd p\u00fc\u00dfl\u00efsh\u00e9d \u00e4nd r\u00e9l\u00e9\u00e4s\u00e9d t\u00f6 l\u00e9\u00e4rn\u00e9rs, \u00e4n\u00fd \u00e7h\u00e4ng\u00e9s \u00fd\u00f6\u00fc m\u00e4d\u00e9 t\u00f6 th\u00e9 \u00fcn\u00eft wh\u00e9n \u00eft w\u00e4s h\u00efdd\u00e9n w\u00efll n\u00f6w \u00df\u00e9 v\u00efs\u00ef\u00dfl\u00e9 t\u00f6 l\u00e9\u00e4rn\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442 \u03b1\u03b7\u03b9\u043c #", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "\u00ccf th\u00e9 \u00fcn\u00eft w\u00e4s pr\u00e9v\u00ef\u00f6\u00fcsl\u00fd p\u00fc\u00dfl\u00efsh\u00e9d \u00e4nd r\u00e9l\u00e9\u00e4s\u00e9d t\u00f6 st\u00fcd\u00e9nts, \u00e4n\u00fd \u00e7h\u00e4ng\u00e9s \u00fd\u00f6\u00fc m\u00e4d\u00e9 t\u00f6 th\u00e9 \u00fcn\u00eft wh\u00e9n \u00eft w\u00e4s h\u00efdd\u00e9n w\u00efll n\u00f6w \u00df\u00e9 v\u00efs\u00ef\u00dfl\u00e9 t\u00f6 st\u00fcd\u00e9nts. D\u00f6 \u00fd\u00f6\u00fc w\u00e4nt t\u00f6 pr\u00f6\u00e7\u00e9\u00e9d? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9#", - "If you are unable to access your account contact us via email using {email}.": "\u00ccf \u00fd\u00f6\u00fc \u00e4r\u00e9 \u00fcn\u00e4\u00dfl\u00e9 t\u00f6 \u00e4\u00e7\u00e7\u00e9ss \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00e7\u00f6nt\u00e4\u00e7t \u00fcs v\u00ef\u00e4 \u00e9m\u00e4\u00efl \u00fcs\u00efng {email}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "If you do not yet have an account, use the button below to register.": "\u00ccf \u00fd\u00f6\u00fc d\u00f6 n\u00f6t \u00fd\u00e9t h\u00e4v\u00e9 \u00e4n \u00e4\u00e7\u00e7\u00f6\u00fcnt, \u00fcs\u00e9 th\u00e9 \u00df\u00fctt\u00f6n \u00df\u00e9l\u00f6w t\u00f6 r\u00e9g\u00efst\u00e9r. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u00ccf \u00fd\u00f6\u00fc d\u00f6n't v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd n\u00f6w, \u00fd\u00f6\u00fc \u00e7\u00e4n st\u00efll \u00e9xpl\u00f6r\u00e9 \u00fd\u00f6\u00fcr \u00e7\u00f6\u00fcrs\u00e9 fr\u00f6m \u00fd\u00f6\u00fcr d\u00e4sh\u00df\u00f6\u00e4rd. \u00dd\u00f6\u00fc w\u00efll r\u00e9\u00e7\u00e9\u00efv\u00e9 p\u00e9r\u00ef\u00f6d\u00ef\u00e7 r\u00e9m\u00efnd\u00e9rs fr\u00f6m %(platformName)s t\u00f6 v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454#", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u00ccf \u00fd\u00f6\u00fc d\u00f6n't v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd n\u00f6w, \u00fd\u00f6\u00fc \u00e7\u00e4n st\u00efll \u00e9xpl\u00f6r\u00e9 \u00fd\u00f6\u00fcr \u00e7\u00f6\u00fcrs\u00e9 fr\u00f6m \u00fd\u00f6\u00fcr d\u00e4sh\u00df\u00f6\u00e4rd. \u00dd\u00f6\u00fc w\u00efll r\u00e9\u00e7\u00e9\u00efv\u00e9 p\u00e9r\u00ef\u00f6d\u00ef\u00e7 r\u00e9m\u00efnd\u00e9rs fr\u00f6m {platformName} t\u00f6 v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454#", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "\u00ccf \u00fd\u00f6\u00fc l\u00e9\u00e4v\u00e9 th\u00efs p\u00e4g\u00e9 w\u00efth\u00f6\u00fct s\u00e4v\u00efng \u00f6r s\u00fc\u00dfm\u00eftt\u00efng \u00fd\u00f6\u00fcr r\u00e9sp\u00f6ns\u00e9, \u00fd\u00f6\u00fc w\u00efll l\u00f6s\u00e9 \u00e4n\u00fd w\u00f6rk \u00fd\u00f6\u00fc h\u00e4v\u00e9 d\u00f6n\u00e9 \u00f6n th\u00e9 r\u00e9sp\u00f6ns\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "\u00ccf \u00fd\u00f6\u00fc l\u00e9\u00e4v\u00e9 th\u00efs p\u00e4g\u00e9 w\u00efth\u00f6\u00fct s\u00fc\u00dfm\u00eftt\u00efng \u00fd\u00f6\u00fcr p\u00e9\u00e9r \u00e4ss\u00e9ssm\u00e9nt, \u00fd\u00f6\u00fc w\u00efll l\u00f6s\u00e9 \u00e4n\u00fd w\u00f6rk \u00fd\u00f6\u00fc h\u00e4v\u00e9 d\u00f6n\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "\u00ccf \u00fd\u00f6\u00fc l\u00e9\u00e4v\u00e9 th\u00efs p\u00e4g\u00e9 w\u00efth\u00f6\u00fct s\u00fc\u00dfm\u00eftt\u00efng \u00fd\u00f6\u00fcr s\u00e9lf \u00e4ss\u00e9ssm\u00e9nt, \u00fd\u00f6\u00fc w\u00efll l\u00f6s\u00e9 \u00e4n\u00fd w\u00f6rk \u00fd\u00f6\u00fc h\u00e4v\u00e9 d\u00f6n\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", @@ -1007,6 +1034,7 @@ "Live view of webcam": "L\u00efv\u00e9 v\u00ef\u00e9w \u00f6f w\u00e9\u00df\u00e7\u00e4m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Load Another File": "L\u00f6\u00e4d \u00c0n\u00f6th\u00e9r F\u00efl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Load all responses": "L\u00f6\u00e4d \u00e4ll r\u00e9sp\u00f6ns\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "Load more": "L\u00f6\u00e4d m\u00f6r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Load next {numResponses} responses": "L\u00f6\u00e4d n\u00e9xt {numResponses} r\u00e9sp\u00f6ns\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "Load next {num_items} result": [ "L\u00f6\u00e4d n\u00e9xt {num_items} r\u00e9s\u00fclt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", @@ -1040,6 +1068,7 @@ "Manual": "M\u00e4n\u00fc\u00e4l \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "March": "marto", "Mark Exam As Completed": "M\u00e4rk \u00c9x\u00e4m \u00c0s \u00c7\u00f6mpl\u00e9t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", + "Mark as Answer": "M\u00e4rk \u00e4s \u00c0nsw\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Mark enrollment code as unused": "M\u00e4rk \u00e9nr\u00f6llm\u00e9nt \u00e7\u00f6d\u00e9 \u00e4s \u00fcn\u00fcs\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", "Markdown Editing Help": "M\u00e4rkd\u00f6wn \u00c9d\u00eft\u00efng H\u00e9lp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Masters": "M\u00e4st\u00e9rs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", @@ -1081,6 +1110,8 @@ "Name or short description of the configuration": "N\u00e4m\u00e9 \u00f6r sh\u00f6rt d\u00e9s\u00e7r\u00efpt\u00ef\u00f6n \u00f6f th\u00e9 \u00e7\u00f6nf\u00efg\u00fcr\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Navigate up": "N\u00e4v\u00efg\u00e4t\u00e9 \u00fcp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Need help logging in?": "N\u00e9\u00e9d h\u00e9lp l\u00f6gg\u00efng \u00efn? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", + "Need help signing in?": "N\u00e9\u00e9d h\u00e9lp s\u00efgn\u00efng \u00efn? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", + "Need other help signing in?": "N\u00e9\u00e9d \u00f6th\u00e9r h\u00e9lp s\u00efgn\u00efng \u00efn? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "Needs verified certificate ": "N\u00e9\u00e9ds v\u00e9r\u00eff\u00ef\u00e9d \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "Never published": "N\u00e9v\u00e9r p\u00fc\u00dfl\u00efsh\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Never show assessment results": "N\u00e9v\u00e9r sh\u00f6w \u00e4ss\u00e9ssm\u00e9nt r\u00e9s\u00fclts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", @@ -1100,6 +1131,7 @@ "No Flash Detected": "N\u00f6 Fl\u00e4sh D\u00e9t\u00e9\u00e7t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "No Timed Transcript": "N\u00f6 T\u00efm\u00e9d Tr\u00e4ns\u00e7r\u00efpt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "No Webcam Detected": "N\u00f6 W\u00e9\u00df\u00e7\u00e4m D\u00e9t\u00e9\u00e7t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "No assignments for team": "N\u00f6 \u00e4ss\u00efgnm\u00e9nts f\u00f6r t\u00e9\u00e4m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "No color": "N\u00f6 \u00e7\u00f6l\u00f6r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "No content-specific discussion topics exist.": "N\u00f6 \u00e7\u00f6nt\u00e9nt-sp\u00e9\u00e7\u00eff\u00ef\u00e7 d\u00efs\u00e7\u00fcss\u00ef\u00f6n t\u00f6p\u00ef\u00e7s \u00e9x\u00efst. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "No description available": "N\u00f6 d\u00e9s\u00e7r\u00efpt\u00ef\u00f6n \u00e4v\u00e4\u00efl\u00e4\u00dfl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", @@ -1163,9 +1195,10 @@ "Once your account is deleted, you cannot use it to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "\u00d6n\u00e7\u00e9 \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00efs d\u00e9l\u00e9t\u00e9d, \u00fd\u00f6\u00fc \u00e7\u00e4nn\u00f6t \u00fcs\u00e9 \u00eft t\u00f6 t\u00e4k\u00e9 \u00e7\u00f6\u00fcrs\u00e9s \u00f6n th\u00e9 {platformName} \u00e4pp, {siteName}, \u00f6r \u00e4n\u00fd \u00f6th\u00e9r s\u00eft\u00e9 h\u00f6st\u00e9d \u00df\u00fd {platformName}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "One or more rescheduling tasks failed.": "\u00d6n\u00e9 \u00f6r m\u00f6r\u00e9 r\u00e9s\u00e7h\u00e9d\u00fcl\u00efng t\u00e4sks f\u00e4\u00efl\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "Only ": "\u00d6nl\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u00d6nl\u00fd <%= fileTypes %> f\u00efl\u00e9s \u00e7\u00e4n \u00df\u00e9 \u00fcpl\u00f6\u00e4d\u00e9d. Pl\u00e9\u00e4s\u00e9 s\u00e9l\u00e9\u00e7t \u00e4 f\u00efl\u00e9 \u00e9nd\u00efng \u00efn <%= fileExtensions %> t\u00f6 \u00fcpl\u00f6\u00e4d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", + "Only <%- fileTypes %> files can be uploaded. Please select a file ending in <%- (fileExtensions) %> to upload.": "\u00d6nl\u00fd <%- fileTypes %> f\u00efl\u00e9s \u00e7\u00e4n \u00df\u00e9 \u00fcpl\u00f6\u00e4d\u00e9d. Pl\u00e9\u00e4s\u00e9 s\u00e9l\u00e9\u00e7t \u00e4 f\u00efl\u00e9 \u00e9nd\u00efng \u00efn <%- (fileExtensions) %> t\u00f6 \u00fcpl\u00f6\u00e4d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "Only properly formatted .csv files will be accepted.": "\u00d6nl\u00fd pr\u00f6p\u00e9rl\u00fd f\u00f6rm\u00e4tt\u00e9d .\u00e7sv f\u00efl\u00e9s w\u00efll \u00df\u00e9 \u00e4\u00e7\u00e7\u00e9pt\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Only the parent course staff of a CCX can create content groups.": "\u00d6nl\u00fd th\u00e9 p\u00e4r\u00e9nt \u00e7\u00f6\u00fcrs\u00e9 st\u00e4ff \u00f6f \u00e4 \u00c7\u00c7X \u00e7\u00e4n \u00e7r\u00e9\u00e4t\u00e9 \u00e7\u00f6nt\u00e9nt gr\u00f6\u00fcps. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "Open": "\u00d6p\u00e9n \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Open Calculator": "\u00d6p\u00e9n \u00c7\u00e4l\u00e7\u00fcl\u00e4t\u00f6r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Open language menu": "\u00d6p\u00e9n l\u00e4ng\u00fc\u00e4g\u00e9 m\u00e9n\u00fc \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Open the certificate you earned for the %(title)s program.": "\u00d6p\u00e9n th\u00e9 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u00fd\u00f6\u00fc \u00e9\u00e4rn\u00e9d f\u00f6r th\u00e9 %(title)s pr\u00f6gr\u00e4m. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -1186,6 +1219,7 @@ "Organization of the signatory": "\u00d6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n \u00f6f th\u00e9 s\u00efgn\u00e4t\u00f6r\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Organization:": "\u00d6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Other": "\u00d6th\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", + "Other sign-in issues": "\u00d6th\u00e9r s\u00efgn-\u00efn \u00efss\u00fc\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Overall Score": "\u00d6v\u00e9r\u00e4ll S\u00e7\u00f6r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "PDF Chapters": "PDF \u00c7h\u00e4pt\u00e9rs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Page break": "P\u00e4g\u00e9 \u00dfr\u00e9\u00e4k \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", @@ -1215,6 +1249,8 @@ "Photo of %(fullName)s's ID": "Ph\u00f6t\u00f6 \u00f6f %(fullName)s's \u00ccD \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Photo requirements:": "Ph\u00f6t\u00f6 r\u00e9q\u00fc\u00efr\u00e9m\u00e9nts: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Photos don't meet the requirements?": "Ph\u00f6t\u00f6s d\u00f6n't m\u00e9\u00e9t th\u00e9 r\u00e9q\u00fc\u00efr\u00e9m\u00e9nts? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", + "Pin": "P\u00efn \u2c60'\u03c3\u044f\u0454\u043c#", + "Pinned": "P\u00efnn\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Placeholder": "Pl\u00e4\u00e7\u00e9h\u00f6ld\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Play": "Pl\u00e4\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Play video": "Pl\u00e4\u00fd v\u00efd\u00e9\u00f6 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", @@ -1259,6 +1295,7 @@ "Please wait": "Pl\u00e9\u00e4s\u00e9 w\u00e4\u00eft \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Plugins": "Pl\u00fcg\u00efns \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "Post": "P\u00f6st \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", + "Post type": "P\u00f6st t\u00fdp\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Poster": "P\u00f6st\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Practice": "Pr\u00e4\u00e7t\u00ef\u00e7\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Practice Exam": "Pr\u00e4\u00e7t\u00ef\u00e7\u00e9 \u00c9x\u00e4m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", @@ -1315,6 +1352,8 @@ "Published and Live": "P\u00fc\u00dfl\u00efsh\u00e9d \u00e4nd L\u00efv\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Publishing": "P\u00fc\u00dfl\u00efsh\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Publishing Status": "P\u00fc\u00dfl\u00efsh\u00efng St\u00e4t\u00fcs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", + "Question": "Q\u00fc\u00e9st\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", + "Questions raise issues that need answers. Discussions share ideas and start conversations. (Required)": "Q\u00fc\u00e9st\u00ef\u00f6ns r\u00e4\u00efs\u00e9 \u00efss\u00fc\u00e9s th\u00e4t n\u00e9\u00e9d \u00e4nsw\u00e9rs. D\u00efs\u00e7\u00fcss\u00ef\u00f6ns sh\u00e4r\u00e9 \u00efd\u00e9\u00e4s \u00e4nd st\u00e4rt \u00e7\u00f6nv\u00e9rs\u00e4t\u00ef\u00f6ns. (R\u00e9q\u00fc\u00efr\u00e9d) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Queued": "Q\u00fc\u00e9\u00fc\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "REMAINING COURSES": "R\u00c9M\u00c0\u00ccN\u00ccNG \u00c7\u00d6\u00dbRS\u00c9S \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Re-run Course": "R\u00e9-r\u00fcn \u00c7\u00f6\u00fcrs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", @@ -1337,6 +1376,7 @@ "Regenerate the user's certificate": "R\u00e9g\u00e9n\u00e9r\u00e4t\u00e9 th\u00e9 \u00fcs\u00e9r's \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "Register with Institution/Campus Credentials": "R\u00e9g\u00efst\u00e9r w\u00efth \u00ccnst\u00eft\u00fct\u00ef\u00f6n/\u00c7\u00e4mp\u00fcs \u00c7r\u00e9d\u00e9nt\u00ef\u00e4ls \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Rejected": "R\u00e9j\u00e9\u00e7t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", + "Related to: %(courseware_title_linked)s": "R\u00e9l\u00e4t\u00e9d t\u00f6: %(courseware_title_linked)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Release Date and Time": "R\u00e9l\u00e9\u00e4s\u00e9 D\u00e4t\u00e9 \u00e4nd T\u00efm\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Release Date:": "R\u00e9l\u00e9\u00e4s\u00e9 D\u00e4t\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Release Status:": "R\u00e9l\u00e9\u00e4s\u00e9 St\u00e4t\u00fcs: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", @@ -1365,7 +1405,10 @@ "Replace all": "R\u00e9pl\u00e4\u00e7\u00e9 \u00e4ll \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Replace with": "R\u00e9pl\u00e4\u00e7\u00e9 w\u00efth \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Reply to Annotation": "R\u00e9pl\u00fd t\u00f6 \u00c0nn\u00f6t\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", + "Report": "R\u00e9p\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", + "Report abuse": "R\u00e9p\u00f6rt \u00e4\u00df\u00fcs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Report abuse, topics, and responses": "R\u00e9p\u00f6rt \u00e4\u00df\u00fcs\u00e9, t\u00f6p\u00ef\u00e7s, \u00e4nd r\u00e9sp\u00f6ns\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", + "Reported": "R\u00e9p\u00f6rt\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Requester": "R\u00e9q\u00fc\u00e9st\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Required": "R\u00e9q\u00fc\u00efr\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Required field": "R\u00e9q\u00fc\u00efr\u00e9d f\u00ef\u00e9ld \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", @@ -1385,6 +1428,7 @@ "Return and add email address": "R\u00e9t\u00fcrn \u00e4nd \u00e4dd \u00e9m\u00e4\u00efl \u00e4ddr\u00e9ss \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Return to Export": "R\u00e9t\u00fcrn t\u00f6 \u00c9xp\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Return to Your Dashboard": "R\u00e9t\u00fcrn t\u00f6 \u00dd\u00f6\u00fcr D\u00e4sh\u00df\u00f6\u00e4rd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", + "Return to all posts": "R\u00e9t\u00fcrn t\u00f6 \u00e4ll p\u00f6sts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Return to team listing": "R\u00e9t\u00fcrn t\u00f6 t\u00e9\u00e4m l\u00efst\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "Review Policy Exception": "R\u00e9v\u00ef\u00e9w P\u00f6l\u00ef\u00e7\u00fd \u00c9x\u00e7\u00e9pt\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "Review Rules": "R\u00e9v\u00ef\u00e9w R\u00fcl\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", @@ -1469,6 +1513,10 @@ "Show": "Montru", "Show All": "Sh\u00f6w \u00c0ll \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Show Annotations": "Sh\u00f6w \u00c0nn\u00f6t\u00e4t\u00ef\u00f6ns \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "Show Comment (%(num_comments)s)": [ + "Sh\u00f6w \u00c7\u00f6mm\u00e9nt (%(num_comments)s) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "Sh\u00f6w \u00c7\u00f6mm\u00e9nts (%(num_comments)s) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#" + ], "Show Deprecated Settings": "Sh\u00f6w D\u00e9pr\u00e9\u00e7\u00e4t\u00e9d S\u00e9tt\u00efngs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "Show Discussion": "Sh\u00f6w D\u00efs\u00e7\u00fcss\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Show Less": "Sh\u00f6w L\u00e9ss \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", @@ -1505,6 +1553,7 @@ "Sign in using %(providerName)s": "S\u00efgn \u00efn \u00fcs\u00efng %(providerName)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Sign in with %(providerName)s": "S\u00efgn \u00efn w\u00efth %(providerName)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Sign in with Institution/Campus Credentials": "S\u00efgn \u00efn w\u00efth \u00ccnst\u00eft\u00fct\u00ef\u00f6n/\u00c7\u00e4mp\u00fcs \u00c7r\u00e9d\u00e9nt\u00ef\u00e4ls \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", + "Sign in with your company or school": "S\u00efgn \u00efn w\u00efth \u00fd\u00f6\u00fcr \u00e7\u00f6mp\u00e4n\u00fd \u00f6r s\u00e7h\u00f6\u00f6l \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "Sign in.": "S\u00efgn \u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Signatory": "S\u00efgn\u00e4t\u00f6r\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Signatory field(s) has invalid data.": "S\u00efgn\u00e4t\u00f6r\u00fd f\u00ef\u00e9ld(s) h\u00e4s \u00efnv\u00e4l\u00efd d\u00e4t\u00e4. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", @@ -1613,6 +1662,7 @@ "Task inputs": "T\u00e4sk \u00efnp\u00fcts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Teaching Assistant": "T\u00e9\u00e4\u00e7h\u00efng \u00c0ss\u00efst\u00e4nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Team \"{team}\" successfully deleted.": "T\u00e9\u00e4m \"{team}\" s\u00fc\u00e7\u00e7\u00e9ssf\u00fcll\u00fd d\u00e9l\u00e9t\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", + "Team Assignments": "T\u00e9\u00e4m \u00c0ss\u00efgnm\u00e9nts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Team Description (Required) *": "T\u00e9\u00e4m D\u00e9s\u00e7r\u00efpt\u00ef\u00f6n (R\u00e9q\u00fc\u00efr\u00e9d) * \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Team Details": "T\u00e9\u00e4m D\u00e9t\u00e4\u00efls \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Team Name (Required) *": "T\u00e9\u00e4m N\u00e4m\u00e9 (R\u00e9q\u00fc\u00efr\u00e9d) * \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", @@ -1631,9 +1681,8 @@ "Textbook Name": "T\u00e9xt\u00df\u00f6\u00f6k N\u00e4m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Textbook information": "T\u00e9xt\u00df\u00f6\u00f6k \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Textbook name is required": "T\u00e9xt\u00df\u00f6\u00f6k n\u00e4m\u00e9 \u00efs r\u00e9q\u00fc\u00efr\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Th\u00e4nk \u00fd\u00f6\u00fc %(full_name)s! W\u00e9 h\u00e4v\u00e9 r\u00e9\u00e7\u00e9\u00efv\u00e9d \u00fd\u00f6\u00fcr p\u00e4\u00fdm\u00e9nt f\u00f6r %(course_name)s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Thank you for setting your course goal to {goal}!": "Th\u00e4nk \u00fd\u00f6\u00fc f\u00f6r s\u00e9tt\u00efng \u00fd\u00f6\u00fcr \u00e7\u00f6\u00fcrs\u00e9 g\u00f6\u00e4l t\u00f6 {goal}! \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", - "Thank you for submitting a request! We will contact you within 24 hours.": "Th\u00e4nk \u00fd\u00f6\u00fc f\u00f6r s\u00fc\u00dfm\u00eftt\u00efng \u00e4 r\u00e9q\u00fc\u00e9st! W\u00e9 w\u00efll \u00e7\u00f6nt\u00e4\u00e7t \u00fd\u00f6\u00fc w\u00efth\u00efn 24 h\u00f6\u00fcrs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", + "Thank you for submitting a request! We appreciate your patience while we work to review your request.": "Th\u00e4nk \u00fd\u00f6\u00fc f\u00f6r s\u00fc\u00dfm\u00eftt\u00efng \u00e4 r\u00e9q\u00fc\u00e9st! W\u00e9 \u00e4ppr\u00e9\u00e7\u00ef\u00e4t\u00e9 \u00fd\u00f6\u00fcr p\u00e4t\u00ef\u00e9n\u00e7\u00e9 wh\u00efl\u00e9 w\u00e9 w\u00f6rk t\u00f6 r\u00e9v\u00ef\u00e9w \u00fd\u00f6\u00fcr r\u00e9q\u00fc\u00e9st. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Th\u00e4nk \u00fd\u00f6\u00fc f\u00f6r s\u00fc\u00dfm\u00eftt\u00efng \u00fd\u00f6\u00fcr f\u00efn\u00e4n\u00e7\u00ef\u00e4l \u00e4ss\u00efst\u00e4n\u00e7\u00e9 \u00e4ppl\u00ef\u00e7\u00e4t\u00ef\u00f6n f\u00f6r {course_name}! \u00dd\u00f6\u00fc \u00e7\u00e4n \u00e9xp\u00e9\u00e7t \u00e4 r\u00e9sp\u00f6ns\u00e9 \u00efn 2-4 \u00df\u00fcs\u00efn\u00e9ss d\u00e4\u00fds. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c#", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Th\u00e4nk \u00fd\u00f6\u00fc f\u00f6r s\u00fc\u00dfm\u00eftt\u00efng \u00fd\u00f6\u00fcr ph\u00f6t\u00f6s. W\u00e9 w\u00efll r\u00e9v\u00ef\u00e9w th\u00e9m sh\u00f6rtl\u00fd. \u00dd\u00f6\u00fc \u00e7\u00e4n n\u00f6w s\u00efgn \u00fcp f\u00f6r \u00e4n\u00fd %(platformName)s \u00e7\u00f6\u00fcrs\u00e9 th\u00e4t \u00f6ff\u00e9rs v\u00e9r\u00eff\u00ef\u00e9d \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9s. V\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n \u00efs g\u00f6\u00f6d f\u00f6r \u00f6n\u00e9 \u00fd\u00e9\u00e4r. \u00c0ft\u00e9r \u00f6n\u00e9 \u00fd\u00e9\u00e4r, \u00fd\u00f6\u00fc m\u00fcst s\u00fc\u00dfm\u00eft ph\u00f6t\u00f6s f\u00f6r v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454#", "Thank you! We have received your payment for {courseName}.": "Th\u00e4nk \u00fd\u00f6\u00fc! W\u00e9 h\u00e4v\u00e9 r\u00e9\u00e7\u00e9\u00efv\u00e9d \u00fd\u00f6\u00fcr p\u00e4\u00fdm\u00e9nt f\u00f6r {courseName}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -1645,8 +1694,8 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Th\u00e9 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 f\u00f6r th\u00efs l\u00e9\u00e4rn\u00e9r h\u00e4s \u00df\u00e9\u00e9n r\u00e9-v\u00e4l\u00efd\u00e4t\u00e9d \u00e4nd th\u00e9 s\u00fdst\u00e9m \u00efs r\u00e9-r\u00fcnn\u00efng th\u00e9 gr\u00e4d\u00e9 f\u00f6r th\u00efs l\u00e9\u00e4rn\u00e9r. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "The cohort cannot be added": "Th\u00e9 \u00e7\u00f6h\u00f6rt \u00e7\u00e4nn\u00f6t \u00df\u00e9 \u00e4dd\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "The cohort cannot be saved": "Th\u00e9 \u00e7\u00f6h\u00f6rt \u00e7\u00e4nn\u00f6t \u00df\u00e9 s\u00e4v\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "Th\u00e9 \u00e7\u00f6m\u00df\u00efn\u00e9d l\u00e9ngth \u00f6f th\u00e9 \u00f6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n \u00e4nd l\u00ef\u00dfr\u00e4r\u00fd \u00e7\u00f6d\u00e9 f\u00ef\u00e9lds \u00e7\u00e4nn\u00f6t \u00df\u00e9 m\u00f6r\u00e9 th\u00e4n <%=limit%> \u00e7h\u00e4r\u00e4\u00e7t\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "Th\u00e9 \u00e7\u00f6m\u00df\u00efn\u00e9d l\u00e9ngth \u00f6f th\u00e9 \u00f6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n, \u00e7\u00f6\u00fcrs\u00e9 n\u00fcm\u00df\u00e9r, \u00e4nd \u00e7\u00f6\u00fcrs\u00e9 r\u00fcn f\u00ef\u00e9lds \u00e7\u00e4nn\u00f6t \u00df\u00e9 m\u00f6r\u00e9 th\u00e4n <%=limit%> \u00e7h\u00e4r\u00e4\u00e7t\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", + "The combined length of the organization and library code fields cannot be more than <%- limit %> characters.": "Th\u00e9 \u00e7\u00f6m\u00df\u00efn\u00e9d l\u00e9ngth \u00f6f th\u00e9 \u00f6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n \u00e4nd l\u00ef\u00dfr\u00e4r\u00fd \u00e7\u00f6d\u00e9 f\u00ef\u00e9lds \u00e7\u00e4nn\u00f6t \u00df\u00e9 m\u00f6r\u00e9 th\u00e4n <%- limit %> \u00e7h\u00e4r\u00e4\u00e7t\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "The combined length of the organization, course number, and course run fields cannot be more than <%- limit %> characters.": "Th\u00e9 \u00e7\u00f6m\u00df\u00efn\u00e9d l\u00e9ngth \u00f6f th\u00e9 \u00f6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n, \u00e7\u00f6\u00fcrs\u00e9 n\u00fcm\u00df\u00e9r, \u00e4nd \u00e7\u00f6\u00fcrs\u00e9 r\u00fcn f\u00ef\u00e9lds \u00e7\u00e4nn\u00f6t \u00df\u00e9 m\u00f6r\u00e9 th\u00e4n <%- limit %> \u00e7h\u00e4r\u00e4\u00e7t\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "The country or region where you live.": "Th\u00e9 \u00e7\u00f6\u00fcntr\u00fd \u00f6r r\u00e9g\u00ef\u00f6n wh\u00e9r\u00e9 \u00fd\u00f6\u00fc l\u00efv\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "The country that team members primarily identify with.": "Th\u00e9 \u00e7\u00f6\u00fcntr\u00fd th\u00e4t t\u00e9\u00e4m m\u00e9m\u00df\u00e9rs pr\u00efm\u00e4r\u00efl\u00fd \u00efd\u00e9nt\u00eff\u00fd w\u00efth. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The course end date must be later than the course start date.": "Th\u00e9 \u00e7\u00f6\u00fcrs\u00e9 \u00e9nd d\u00e4t\u00e9 m\u00fcst \u00df\u00e9 l\u00e4t\u00e9r th\u00e4n th\u00e9 \u00e7\u00f6\u00fcrs\u00e9 st\u00e4rt d\u00e4t\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -1663,7 +1712,7 @@ "The following email addresses and/or usernames are invalid:": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00e9m\u00e4\u00efl \u00e4ddr\u00e9ss\u00e9s \u00e4nd/\u00f6r \u00fcs\u00e9rn\u00e4m\u00e9s \u00e4r\u00e9 \u00efnv\u00e4l\u00efd: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The following errors were generated:": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00e9rr\u00f6rs w\u00e9r\u00e9 g\u00e9n\u00e9r\u00e4t\u00e9d: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "The following file types are not allowed: ": "Th\u00e9 f\u00f6ll\u00f6w\u00efng f\u00efl\u00e9 t\u00fdp\u00e9s \u00e4r\u00e9 n\u00f6t \u00e4ll\u00f6w\u00e9d: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00efs \u00e4lr\u00e9\u00e4d\u00fd \u00e4 p\u00e4rt \u00f6f \u00fd\u00f6\u00fcr {platform} pr\u00f6f\u00efl\u00e9. W\u00e9\\'v\u00e9 \u00efn\u00e7l\u00fcd\u00e9d \u00eft h\u00e9r\u00e9 f\u00f6r \u00fd\u00f6\u00fcr \u00e4ppl\u00ef\u00e7\u00e4t\u00ef\u00f6n. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", + "The following information is already a part of your {platform} profile. We've included it here for your application.": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00efs \u00e4lr\u00e9\u00e4d\u00fd \u00e4 p\u00e4rt \u00f6f \u00fd\u00f6\u00fcr {platform} pr\u00f6f\u00efl\u00e9. W\u00e9'v\u00e9 \u00efn\u00e7l\u00fcd\u00e9d \u00eft h\u00e9r\u00e9 f\u00f6r \u00fd\u00f6\u00fcr \u00e4ppl\u00ef\u00e7\u00e4t\u00ef\u00f6n. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "The following message will be displayed at the bottom of the courseware pages within your course:": "Th\u00e9 f\u00f6ll\u00f6w\u00efng m\u00e9ss\u00e4g\u00e9 w\u00efll \u00df\u00e9 d\u00efspl\u00e4\u00fd\u00e9d \u00e4t th\u00e9 \u00df\u00f6tt\u00f6m \u00f6f th\u00e9 \u00e7\u00f6\u00fcrs\u00e9w\u00e4r\u00e9 p\u00e4g\u00e9s w\u00efth\u00efn \u00fd\u00f6\u00fcr \u00e7\u00f6\u00fcrs\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "The following options are available for the {license_name} license.": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00f6pt\u00ef\u00f6ns \u00e4r\u00e9 \u00e4v\u00e4\u00efl\u00e4\u00dfl\u00e9 f\u00f6r th\u00e9 {license_name} l\u00ef\u00e7\u00e9ns\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The following users are no longer enrolled in the course:": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00fcs\u00e9rs \u00e4r\u00e9 n\u00f6 l\u00f6ng\u00e9r \u00e9nr\u00f6ll\u00e9d \u00efn th\u00e9 \u00e7\u00f6\u00fcrs\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -1675,7 +1724,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "Th\u00e9 m\u00efn\u00efm\u00fcm \u00e7\u00f6mpl\u00e9t\u00ef\u00f6n p\u00e9r\u00e7\u00e9nt\u00e4g\u00e9 m\u00fcst \u00df\u00e9 \u00e4 wh\u00f6l\u00e9 n\u00fcm\u00df\u00e9r \u00df\u00e9tw\u00e9\u00e9n 0 \u00e4nd 100. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "The minimum grade for course credit is not set.": "Th\u00e9 m\u00efn\u00efm\u00fcm gr\u00e4d\u00e9 f\u00f6r \u00e7\u00f6\u00fcrs\u00e9 \u00e7r\u00e9d\u00eft \u00efs n\u00f6t s\u00e9t. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The minimum score percentage must be a whole number between 0 and 100.": "Th\u00e9 m\u00efn\u00efm\u00fcm s\u00e7\u00f6r\u00e9 p\u00e9r\u00e7\u00e9nt\u00e4g\u00e9 m\u00fcst \u00df\u00e9 \u00e4 wh\u00f6l\u00e9 n\u00fcm\u00df\u00e9r \u00df\u00e9tw\u00e9\u00e9n 0 \u00e4nd 100. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", - "The more you tell us, the more quickly and helpfully we can respond!": "Th\u00e9 m\u00f6r\u00e9 \u00fd\u00f6\u00fc t\u00e9ll \u00fcs, th\u00e9 m\u00f6r\u00e9 q\u00fc\u00ef\u00e7kl\u00fd \u00e4nd h\u00e9lpf\u00fcll\u00fd w\u00e9 \u00e7\u00e4n r\u00e9sp\u00f6nd! \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "The name of this signatory as it should appear on certificates.": "Th\u00e9 n\u00e4m\u00e9 \u00f6f th\u00efs s\u00efgn\u00e4t\u00f6r\u00fd \u00e4s \u00eft sh\u00f6\u00fcld \u00e4pp\u00e9\u00e4r \u00f6n \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The name that identifies you on {platform_name}. You cannot change your username.": "Th\u00e9 n\u00e4m\u00e9 th\u00e4t \u00efd\u00e9nt\u00eff\u00ef\u00e9s \u00fd\u00f6\u00fc \u00f6n {platform_name}. \u00dd\u00f6\u00fc \u00e7\u00e4nn\u00f6t \u00e7h\u00e4ng\u00e9 \u00fd\u00f6\u00fcr \u00fcs\u00e9rn\u00e4m\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "The name that is used for ID verification and that appears on your certificates.": "Th\u00e9 n\u00e4m\u00e9 th\u00e4t \u00efs \u00fcs\u00e9d f\u00f6r \u00ccD v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n \u00e4nd th\u00e4t \u00e4pp\u00e9\u00e4rs \u00f6n \u00fd\u00f6\u00fcr \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", @@ -1683,7 +1731,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Th\u00e9 n\u00fcm\u00df\u00e9r \u00f6f s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6ns \u00efn th\u00e9 \u00e7\u00f6\u00fcrs\u00e9 th\u00e4t \u00e7\u00f6nt\u00e4\u00efn pr\u00f6\u00dfl\u00e9ms \u00f6f th\u00efs \u00e4ss\u00efgnm\u00e9nt t\u00fdp\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "The organization that this signatory belongs to, as it should appear on certificates.": "Th\u00e9 \u00f6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n th\u00e4t th\u00efs s\u00efgn\u00e4t\u00f6r\u00fd \u00df\u00e9l\u00f6ngs t\u00f6, \u00e4s \u00eft sh\u00f6\u00fcld \u00e4pp\u00e9\u00e4r \u00f6n \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "The page \"{route}\" could not be found.": "Th\u00e9 p\u00e4g\u00e9 \"{route}\" \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 f\u00f6\u00fcnd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", - "The photo of your face matches the photo on your ID.": "Th\u00e9 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9 m\u00e4t\u00e7h\u00e9s th\u00e9 ph\u00f6t\u00f6 \u00f6n \u00fd\u00f6\u00fcr \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The post you selected has been deleted.": "Th\u00e9 p\u00f6st \u00fd\u00f6\u00fc s\u00e9l\u00e9\u00e7t\u00e9d h\u00e4s \u00df\u00e9\u00e9n d\u00e9l\u00e9t\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "Th\u00e9 p\u00fc\u00dfl\u00efsh\u00e9d \u00dfr\u00e4n\u00e7h v\u00e9rs\u00ef\u00f6n, {published}, w\u00e4s r\u00e9s\u00e9t t\u00f6 th\u00e9 dr\u00e4ft \u00dfr\u00e4n\u00e7h v\u00e9rs\u00ef\u00f6n, {draft}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "The raw error message is:": "Th\u00e9 r\u00e4w \u00e9rr\u00f6r m\u00e9ss\u00e4g\u00e9 \u00efs: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", @@ -1760,6 +1807,7 @@ "This feature is currently in testing. Course teams can enter highlights, but learners will not receive email messages.": "Th\u00efs f\u00e9\u00e4t\u00fcr\u00e9 \u00efs \u00e7\u00fcrr\u00e9ntl\u00fd \u00efn t\u00e9st\u00efng. \u00c7\u00f6\u00fcrs\u00e9 t\u00e9\u00e4ms \u00e7\u00e4n \u00e9nt\u00e9r h\u00efghl\u00efghts, \u00df\u00fct l\u00e9\u00e4rn\u00e9rs w\u00efll n\u00f6t r\u00e9\u00e7\u00e9\u00efv\u00e9 \u00e9m\u00e4\u00efl m\u00e9ss\u00e4g\u00e9s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "This feedback could not be submitted.": "Th\u00efs f\u00e9\u00e9d\u00df\u00e4\u00e7k \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 s\u00fc\u00dfm\u00eftt\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "This file type is not supported. Supported file type is {supportedFileFormat}.": "Th\u00efs f\u00efl\u00e9 t\u00fdp\u00e9 \u00efs n\u00f6t s\u00fcpp\u00f6rt\u00e9d. S\u00fcpp\u00f6rt\u00e9d f\u00efl\u00e9 t\u00fdp\u00e9 \u00efs {supportedFileFormat}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "This grade will be applied to all members of the team. Do you want to continue?": "Th\u00efs gr\u00e4d\u00e9 w\u00efll \u00df\u00e9 \u00e4ppl\u00ef\u00e9d t\u00f6 \u00e4ll m\u00e9m\u00df\u00e9rs \u00f6f th\u00e9 t\u00e9\u00e4m. D\u00f6 \u00fd\u00f6\u00fc w\u00e4nt t\u00f6 \u00e7\u00f6nt\u00efn\u00fc\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "This group controls access to:": "Th\u00efs gr\u00f6\u00fcp \u00e7\u00f6ntr\u00f6ls \u00e4\u00e7\u00e7\u00e9ss t\u00f6: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", "This group no longer exists. Choose another group or do not restrict access to this unit.": "Th\u00efs gr\u00f6\u00fcp n\u00f6 l\u00f6ng\u00e9r \u00e9x\u00efsts. \u00c7h\u00f6\u00f6s\u00e9 \u00e4n\u00f6th\u00e9r gr\u00f6\u00fcp \u00f6r d\u00f6 n\u00f6t r\u00e9str\u00ef\u00e7t \u00e4\u00e7\u00e7\u00e9ss t\u00f6 th\u00efs \u00fcn\u00eft. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "This image file type is not supported. Supported file types are {supportedFileFormats}.": "Th\u00efs \u00efm\u00e4g\u00e9 f\u00efl\u00e9 t\u00fdp\u00e9 \u00efs n\u00f6t s\u00fcpp\u00f6rt\u00e9d. S\u00fcpp\u00f6rt\u00e9d f\u00efl\u00e9 t\u00fdp\u00e9s \u00e4r\u00e9 {supportedFileFormats}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", @@ -1782,6 +1830,10 @@ "This post could not be reopened. Refresh the page and try again.": "Th\u00efs p\u00f6st \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 r\u00e9\u00f6p\u00e9n\u00e9d. R\u00e9fr\u00e9sh th\u00e9 p\u00e4g\u00e9 \u00e4nd tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "This post could not be unflagged for abuse. Refresh the page and try again.": "Th\u00efs p\u00f6st \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 \u00fcnfl\u00e4gg\u00e9d f\u00f6r \u00e4\u00df\u00fcs\u00e9. R\u00e9fr\u00e9sh th\u00e9 p\u00e4g\u00e9 \u00e4nd tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "This post could not be unpinned. Refresh the page and try again.": "Th\u00efs p\u00f6st \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 \u00fcnp\u00efnn\u00e9d. R\u00e9fr\u00e9sh th\u00e9 p\u00e4g\u00e9 \u00e4nd tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "This post is visible only to %(group_name)s.": "Th\u00efs p\u00f6st \u00efs v\u00efs\u00ef\u00dfl\u00e9 \u00f6nl\u00fd t\u00f6 %(group_name)s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", + "This post is visible to everyone.": "Th\u00efs p\u00f6st \u00efs v\u00efs\u00ef\u00dfl\u00e9 t\u00f6 \u00e9v\u00e9r\u00fd\u00f6n\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", + "This post will be visible only to %(group_name)s.": "Th\u00efs p\u00f6st w\u00efll \u00df\u00e9 v\u00efs\u00ef\u00dfl\u00e9 \u00f6nl\u00fd t\u00f6 %(group_name)s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", + "This post will be visible to everyone.": "Th\u00efs p\u00f6st w\u00efll \u00df\u00e9 v\u00efs\u00ef\u00dfl\u00e9 t\u00f6 \u00e9v\u00e9r\u00fd\u00f6n\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "This problem could not be saved.": "Th\u00efs pr\u00f6\u00dfl\u00e9m \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 s\u00e4v\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "This problem has already been released. Any changes will apply only to future assessments.": "Th\u00efs pr\u00f6\u00dfl\u00e9m h\u00e4s \u00e4lr\u00e9\u00e4d\u00fd \u00df\u00e9\u00e9n r\u00e9l\u00e9\u00e4s\u00e9d. \u00c0n\u00fd \u00e7h\u00e4ng\u00e9s w\u00efll \u00e4ppl\u00fd \u00f6nl\u00fd t\u00f6 f\u00fct\u00fcr\u00e9 \u00e4ss\u00e9ssm\u00e9nts. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "This problem has been reset.": "Th\u00efs pr\u00f6\u00dfl\u00e9m h\u00e4s \u00df\u00e9\u00e9n r\u00e9s\u00e9t. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", @@ -1796,8 +1848,11 @@ "This role requires a divided discussions scheme.": "Th\u00efs r\u00f6l\u00e9 r\u00e9q\u00fc\u00efr\u00e9s \u00e4 d\u00efv\u00efd\u00e9d d\u00efs\u00e7\u00fcss\u00ef\u00f6ns s\u00e7h\u00e9m\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "This section could not be loaded.": "Th\u00efs s\u00e9\u00e7t\u00ef\u00f6n \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 l\u00f6\u00e4d\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.": "Th\u00efs sh\u00f6rt n\u00e4m\u00e9 f\u00f6r th\u00e9 \u00e4ss\u00efgnm\u00e9nt t\u00fdp\u00e9 (f\u00f6r \u00e9x\u00e4mpl\u00e9, HW \u00f6r M\u00efdt\u00e9rm) \u00e4pp\u00e9\u00e4rs n\u00e9xt t\u00f6 \u00e4ss\u00efgnm\u00e9nts \u00f6n \u00e4 l\u00e9\u00e4rn\u00e9r's Pr\u00f6gr\u00e9ss p\u00e4g\u00e9. \u2c60'\u03c3\u044f\u0454\u043c#", + "This special exam has been released to learners. You may not convert it to another type of special exam. You may revert this subsection back to being a basic exam by selecting 'None', but you will NOT be able to configure it as a special exam in the future.": "Th\u00efs sp\u00e9\u00e7\u00ef\u00e4l \u00e9x\u00e4m h\u00e4s \u00df\u00e9\u00e9n r\u00e9l\u00e9\u00e4s\u00e9d t\u00f6 l\u00e9\u00e4rn\u00e9rs. \u00dd\u00f6\u00fc m\u00e4\u00fd n\u00f6t \u00e7\u00f6nv\u00e9rt \u00eft t\u00f6 \u00e4n\u00f6th\u00e9r t\u00fdp\u00e9 \u00f6f sp\u00e9\u00e7\u00ef\u00e4l \u00e9x\u00e4m. \u00dd\u00f6\u00fc m\u00e4\u00fd r\u00e9v\u00e9rt th\u00efs s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6n \u00df\u00e4\u00e7k t\u00f6 \u00df\u00e9\u00efng \u00e4 \u00df\u00e4s\u00ef\u00e7 \u00e9x\u00e4m \u00df\u00fd s\u00e9l\u00e9\u00e7t\u00efng 'N\u00f6n\u00e9', \u00df\u00fct \u00fd\u00f6\u00fc w\u00efll N\u00d6T \u00df\u00e9 \u00e4\u00dfl\u00e9 t\u00f6 \u00e7\u00f6nf\u00efg\u00fcr\u00e9 \u00eft \u00e4s \u00e4 sp\u00e9\u00e7\u00ef\u00e4l \u00e9x\u00e4m \u00efn th\u00e9 f\u00fct\u00fcr\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f#", + "This subsection was released to learners as a special exam, but was reverted back to a basic exam. You may not configure it as a special exam now. Contact edX Support for assistance.": "Th\u00efs s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6n w\u00e4s r\u00e9l\u00e9\u00e4s\u00e9d t\u00f6 l\u00e9\u00e4rn\u00e9rs \u00e4s \u00e4 sp\u00e9\u00e7\u00ef\u00e4l \u00e9x\u00e4m, \u00df\u00fct w\u00e4s r\u00e9v\u00e9rt\u00e9d \u00df\u00e4\u00e7k t\u00f6 \u00e4 \u00df\u00e4s\u00ef\u00e7 \u00e9x\u00e4m. \u00dd\u00f6\u00fc m\u00e4\u00fd n\u00f6t \u00e7\u00f6nf\u00efg\u00fcr\u00e9 \u00eft \u00e4s \u00e4 sp\u00e9\u00e7\u00ef\u00e4l \u00e9x\u00e4m n\u00f6w. \u00c7\u00f6nt\u00e4\u00e7t \u00e9dX S\u00fcpp\u00f6rt f\u00f6r \u00e4ss\u00efst\u00e4n\u00e7\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5#", "This team does not have any members.": "Th\u00efs t\u00e9\u00e4m d\u00f6\u00e9s n\u00f6t h\u00e4v\u00e9 \u00e4n\u00fd m\u00e9m\u00df\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "This team is full.": "Th\u00efs t\u00e9\u00e4m \u00efs f\u00fcll. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "This thread is closed.": "Th\u00efs thr\u00e9\u00e4d \u00efs \u00e7l\u00f6s\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "This unit has validation issues.": "Th\u00efs \u00fcn\u00eft h\u00e4s v\u00e4l\u00efd\u00e4t\u00ef\u00f6n \u00efss\u00fc\u00e9s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "This vote could not be processed. Refresh the page and try again.": "Th\u00efs v\u00f6t\u00e9 \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 pr\u00f6\u00e7\u00e9ss\u00e9d. R\u00e9fr\u00e9sh th\u00e9 p\u00e4g\u00e9 \u00e4nd tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "This {parentCategory} has no {childCategory}": "Th\u00efs {parentCategory} h\u00e4s n\u00f6 {childCategory} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", @@ -1824,7 +1879,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "T\u00f6 \u00df\u00e9 s\u00fcr\u00e9 \u00e4ll st\u00fcd\u00e9nts \u00e7\u00e4n \u00e4\u00e7\u00e7\u00e9ss th\u00e9 v\u00efd\u00e9\u00f6, w\u00e9 r\u00e9\u00e7\u00f6mm\u00e9nd pr\u00f6v\u00efd\u00efng \u00df\u00f6th \u00e4n .mp4 \u00e4nd \u00e4 .w\u00e9\u00dfm v\u00e9rs\u00ef\u00f6n \u00f6f \u00fd\u00f6\u00fcr v\u00efd\u00e9\u00f6. \u00c7l\u00ef\u00e7k \u00df\u00e9l\u00f6w t\u00f6 \u00e4dd \u00e4 \u00dbRL f\u00f6r \u00e4n\u00f6th\u00e9r v\u00e9rs\u00ef\u00f6n. Th\u00e9s\u00e9 \u00dbRLs \u00e7\u00e4nn\u00f6t \u00df\u00e9 \u00dd\u00f6\u00fcT\u00fc\u00df\u00e9 \u00dbRLs. Th\u00e9 f\u00efrst l\u00efst\u00e9d v\u00efd\u00e9\u00f6 th\u00e4t's \u00e7\u00f6mp\u00e4t\u00ef\u00dfl\u00e9 w\u00efth th\u00e9 st\u00fcd\u00e9nt's \u00e7\u00f6mp\u00fct\u00e9r w\u00efll pl\u00e4\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202#", "To complete the program, you must earn a verified certificate for each course.": "T\u00f6 \u00e7\u00f6mpl\u00e9t\u00e9 th\u00e9 pr\u00f6gr\u00e4m, \u00fd\u00f6\u00fc m\u00fcst \u00e9\u00e4rn \u00e4 v\u00e9r\u00eff\u00ef\u00e9d \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 f\u00f6r \u00e9\u00e4\u00e7h \u00e7\u00f6\u00fcrs\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "To continue learning with this account, sign in below.": "T\u00f6 \u00e7\u00f6nt\u00efn\u00fc\u00e9 l\u00e9\u00e4rn\u00efng w\u00efth th\u00efs \u00e4\u00e7\u00e7\u00f6\u00fcnt, s\u00efgn \u00efn \u00df\u00e9l\u00f6w. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "T\u00f6 f\u00efn\u00e4l\u00efz\u00e9 \u00e7\u00f6\u00fcrs\u00e9 \u00e7r\u00e9d\u00eft, %(display_name)s r\u00e9q\u00fc\u00efr\u00e9s %(platform_name)s l\u00e9\u00e4rn\u00e9rs t\u00f6 s\u00fc\u00dfm\u00eft \u00e4 \u00e7r\u00e9d\u00eft r\u00e9q\u00fc\u00e9st. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "To invalidate a certificate for a particular learner, add the username or email address below.": "T\u00f6 \u00efnv\u00e4l\u00efd\u00e4t\u00e9 \u00e4 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 f\u00f6r \u00e4 p\u00e4rt\u00ef\u00e7\u00fcl\u00e4r l\u00e9\u00e4rn\u00e9r, \u00e4dd th\u00e9 \u00fcs\u00e9rn\u00e4m\u00e9 \u00f6r \u00e9m\u00e4\u00efl \u00e4ddr\u00e9ss \u00df\u00e9l\u00f6w. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "To receive a certificate, you must also verify your identity before {date}.": "T\u00f6 r\u00e9\u00e7\u00e9\u00efv\u00e9 \u00e4 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9, \u00fd\u00f6\u00fc m\u00fcst \u00e4ls\u00f6 v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd \u00df\u00e9f\u00f6r\u00e9 {date}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "To receive a certificate, you must also verify your identity.": "T\u00f6 r\u00e9\u00e7\u00e9\u00efv\u00e9 \u00e4 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9, \u00fd\u00f6\u00fc m\u00fcst \u00e4ls\u00f6 v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -1832,7 +1886,7 @@ "To review learner cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on the {link_start}Data Download{link_end} page.": "T\u00f6 r\u00e9v\u00ef\u00e9w l\u00e9\u00e4rn\u00e9r \u00e7\u00f6h\u00f6rt \u00e4ss\u00efgnm\u00e9nts \u00f6r s\u00e9\u00e9 th\u00e9 r\u00e9s\u00fclts \u00f6f \u00fcpl\u00f6\u00e4d\u00efng \u00e4 \u00c7SV f\u00efl\u00e9, d\u00f6wnl\u00f6\u00e4d \u00e7\u00f6\u00fcrs\u00e9 pr\u00f6f\u00efl\u00e9 \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00f6r \u00e7\u00f6h\u00f6rt r\u00e9s\u00fclts \u00f6n th\u00e9 {link_start}D\u00e4t\u00e4 D\u00f6wnl\u00f6\u00e4d{link_end} p\u00e4g\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2#", "To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.": "T\u00f6 sh\u00e4r\u00e9 \u00fd\u00f6\u00fcr \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u00f6n M\u00f6z\u00efll\u00e4 B\u00e4\u00e7kp\u00e4\u00e7k, \u00fd\u00f6\u00fc m\u00fcst f\u00efrst h\u00e4v\u00e9 \u00e4 B\u00e4\u00e7kp\u00e4\u00e7k \u00e4\u00e7\u00e7\u00f6\u00fcnt. \u00c7\u00f6mpl\u00e9t\u00e9 th\u00e9 f\u00f6ll\u00f6w\u00efng st\u00e9ps t\u00f6 \u00e4dd \u00fd\u00f6\u00fcr \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 t\u00f6 B\u00e4\u00e7kp\u00e4\u00e7k. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442#", "To take a successful photo, make sure that:": "T\u00f6 t\u00e4k\u00e9 \u00e4 s\u00fc\u00e7\u00e7\u00e9ssf\u00fcl ph\u00f6t\u00f6, m\u00e4k\u00e9 s\u00fcr\u00e9 th\u00e4t: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", - "To use the current photo, select the Take Photo button {icon}. To take another photo, select the Retake Photo button {icon}.": "T\u00f6 \u00fcs\u00e9 th\u00e9 \u00e7\u00fcrr\u00e9nt ph\u00f6t\u00f6, s\u00e9l\u00e9\u00e7t th\u00e9 T\u00e4k\u00e9 Ph\u00f6t\u00f6 \u00df\u00fctt\u00f6n {icon}. T\u00f6 t\u00e4k\u00e9 \u00e4n\u00f6th\u00e9r ph\u00f6t\u00f6, s\u00e9l\u00e9\u00e7t th\u00e9 R\u00e9t\u00e4k\u00e9 Ph\u00f6t\u00f6 \u00df\u00fctt\u00f6n {icon}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", + "To take the photo of your face, click on the camera button {icon}. If you need to try again, click 'Retake Photo'.": "T\u00f6 t\u00e4k\u00e9 th\u00e9 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9, \u00e7l\u00ef\u00e7k \u00f6n th\u00e9 \u00e7\u00e4m\u00e9r\u00e4 \u00df\u00fctt\u00f6n {icon}. \u00ccf \u00fd\u00f6\u00fc n\u00e9\u00e9d t\u00f6 tr\u00fd \u00e4g\u00e4\u00efn, \u00e7l\u00ef\u00e7k 'R\u00e9t\u00e4k\u00e9 Ph\u00f6t\u00f6'. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "To verify your identity, you need a webcam and a government-issued photo ID.": "T\u00f6 v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd, \u00fd\u00f6\u00fc n\u00e9\u00e9d \u00e4 w\u00e9\u00df\u00e7\u00e4m \u00e4nd \u00e4 g\u00f6v\u00e9rnm\u00e9nt-\u00efss\u00fc\u00e9d ph\u00f6t\u00f6 \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "Today": "Hodia\u016d", "Toggle Account Password (Usable/Unusable)": "T\u00f6ggl\u00e9 \u00c0\u00e7\u00e7\u00f6\u00fcnt P\u00e4ssw\u00f6rd (\u00dbs\u00e4\u00dfl\u00e9/\u00dbn\u00fcs\u00e4\u00dfl\u00e9) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", @@ -1841,6 +1895,7 @@ "Tools": "T\u00f6\u00f6ls \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "Top": "T\u00f6p \u2c60'\u03c3\u044f\u0454\u043c#", "Topic": "T\u00f6p\u00ef\u00e7 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", + "Topic area": "T\u00f6p\u00ef\u00e7 \u00e4r\u00e9\u00e4 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Topics": "T\u00f6p\u00ef\u00e7s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Total": "T\u00f6t\u00e4l \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "Total Number": "T\u00f6t\u00e4l N\u00fcm\u00df\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", @@ -1871,7 +1926,9 @@ "Undo Changes": "\u00dbnd\u00f6 \u00c7h\u00e4ng\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Undo move": "\u00dbnd\u00f6 m\u00f6v\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Undo moving": "\u00dbnd\u00f6 m\u00f6v\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", + "Unendorse": "\u00dbn\u00e9nd\u00f6rs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Unexpected server error.": "\u00dbn\u00e9xp\u00e9\u00e7t\u00e9d s\u00e9rv\u00e9r \u00e9rr\u00f6r. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", + "Unfollow": "\u00dbnf\u00f6ll\u00f6w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Ungraded": "\u00dbngr\u00e4d\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Unit": "\u00dbn\u00eft \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Unit Access": "\u00dbn\u00eft \u00c0\u00e7\u00e7\u00e9ss \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", @@ -1883,14 +1940,20 @@ "Unlink This Account": "\u00dbnl\u00efnk Th\u00efs \u00c0\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Unlink your {accountName} account": "\u00dbnl\u00efnk \u00fd\u00f6\u00fcr {accountName} \u00e4\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "Unlinking": "\u00dbnl\u00efnk\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", + "Unmark as Answer": "\u00dbnm\u00e4rk \u00e4s \u00c0nsw\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Unmute": "\u00dbnm\u00fct\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Unnamed Option": "\u00dbnn\u00e4m\u00e9d \u00d6pt\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", + "Unpin": "\u00dbnp\u00efn \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "Unpublished changes to content that will release in the future": "\u00dbnp\u00fc\u00dfl\u00efsh\u00e9d \u00e7h\u00e4ng\u00e9s t\u00f6 \u00e7\u00f6nt\u00e9nt th\u00e4t w\u00efll r\u00e9l\u00e9\u00e4s\u00e9 \u00efn th\u00e9 f\u00fct\u00fcr\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Unpublished changes to live content": "\u00dbnp\u00fc\u00dfl\u00efsh\u00e9d \u00e7h\u00e4ng\u00e9s t\u00f6 l\u00efv\u00e9 \u00e7\u00f6nt\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "Unpublished units will not be released": "\u00dbnp\u00fc\u00dfl\u00efsh\u00e9d \u00fcn\u00efts w\u00efll n\u00f6t \u00df\u00e9 r\u00e9l\u00e9\u00e4s\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", + "Unreport": "\u00dbnr\u00e9p\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Unscheduled": "\u00dbns\u00e7h\u00e9d\u00fcl\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Update": "\u00dbpd\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Update Settings": "\u00dbpd\u00e4t\u00e9 S\u00e9tt\u00efngs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", + "Update comment": "\u00dbpd\u00e4t\u00e9 \u00e7\u00f6mm\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", + "Update post": "\u00dbpd\u00e4t\u00e9 p\u00f6st \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", + "Update response": "\u00dbpd\u00e4t\u00e9 r\u00e9sp\u00f6ns\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Update team.": "\u00dbpd\u00e4t\u00e9 t\u00e9\u00e4m. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Updating Tags": "\u00dbpd\u00e4t\u00efng T\u00e4gs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Updating with latest library content": "\u00dbpd\u00e4t\u00efng w\u00efth l\u00e4t\u00e9st l\u00ef\u00dfr\u00e4r\u00fd \u00e7\u00f6nt\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", @@ -1912,7 +1975,7 @@ "Upload Videos": "\u00dbpl\u00f6\u00e4d V\u00efd\u00e9\u00f6s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Upload a CSV file": "\u00dbpl\u00f6\u00e4d \u00e4 \u00c7SV f\u00efl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u00dbpl\u00f6\u00e4d \u00e4 \u00e7\u00f6mm\u00e4 s\u00e9p\u00e4r\u00e4t\u00e9d v\u00e4l\u00fc\u00e9s (.\u00e7sv) f\u00efl\u00e9 th\u00e4t \u00e7\u00f6nt\u00e4\u00efns th\u00e9 \u00fcs\u00e9rn\u00e4m\u00e9s \u00f6r \u00e9m\u00e4\u00efl \u00e4ddr\u00e9ss\u00e9s \u00f6f l\u00e9\u00e4rn\u00e9rs wh\u00f6 h\u00e4v\u00e9 \u00df\u00e9\u00e9n g\u00efv\u00e9n \u00e9x\u00e7\u00e9pt\u00ef\u00f6ns. \u00ccn\u00e7l\u00fcd\u00e9 th\u00e9 \u00fcs\u00e9rn\u00e4m\u00e9 \u00f6r \u00e9m\u00e4\u00efl \u00e4ddr\u00e9ss \u00efn th\u00e9 f\u00efrst \u00e7\u00f6mm\u00e4 s\u00e9p\u00e4r\u00e4t\u00e9d f\u00ef\u00e9ld. \u00dd\u00f6\u00fc \u00e7\u00e4n \u00efn\u00e7l\u00fcd\u00e9 \u00e4n \u00f6pt\u00ef\u00f6n\u00e4l n\u00f6t\u00e9 d\u00e9s\u00e7r\u00ef\u00df\u00efng th\u00e9 r\u00e9\u00e4s\u00f6n f\u00f6r th\u00e9 \u00e9x\u00e7\u00e9pt\u00ef\u00f6n \u00efn th\u00e9 s\u00e9\u00e7\u00f6nd \u00e7\u00f6mm\u00e4 s\u00e9p\u00e4r\u00e4t\u00e9d f\u00ef\u00e9ld. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9#", - "Upload a new PDF to \u201c<%= name %>\u201d": "\u00dbpl\u00f6\u00e4d \u00e4 n\u00e9w PDF t\u00f6 \u201c<%= name %>\u201d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", + "Upload a new PDF to \u201c<%- name %>\u201d": "\u00dbpl\u00f6\u00e4d \u00e4 n\u00e9w PDF t\u00f6 \u201c<%- name %>\u201d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "Upload an image": "\u00dbpl\u00f6\u00e4d \u00e4n \u00efm\u00e4g\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Upload an image or capture one with your web or phone camera.": "\u00dbpl\u00f6\u00e4d \u00e4n \u00efm\u00e4g\u00e9 \u00f6r \u00e7\u00e4pt\u00fcr\u00e9 \u00f6n\u00e9 w\u00efth \u00fd\u00f6\u00fcr w\u00e9\u00df \u00f6r ph\u00f6n\u00e9 \u00e7\u00e4m\u00e9r\u00e4. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Upload completed": "\u00dbpl\u00f6\u00e4d \u00e7\u00f6mpl\u00e9t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", @@ -1947,7 +2010,7 @@ "Use my university info": "\u00dbs\u00e9 m\u00fd \u00fcn\u00efv\u00e9rs\u00eft\u00fd \u00efnf\u00f6 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "Use the All Topics menu to find specific topics.": "\u00dbs\u00e9 th\u00e9 \u00c0ll T\u00f6p\u00ef\u00e7s m\u00e9n\u00fc t\u00f6 f\u00efnd sp\u00e9\u00e7\u00eff\u00ef\u00e7 t\u00f6p\u00ef\u00e7s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Use the Retake Photo button if you are not pleased with your photo": "\u00dbs\u00e9 th\u00e9 R\u00e9t\u00e4k\u00e9 Ph\u00f6t\u00f6 \u00df\u00fctt\u00f6n \u00eff \u00fd\u00f6\u00fc \u00e4r\u00e9 n\u00f6t pl\u00e9\u00e4s\u00e9d w\u00efth \u00fd\u00f6\u00fcr ph\u00f6t\u00f6 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u00dbs\u00e9 \u00fd\u00f6\u00fcr w\u00e9\u00df\u00e7\u00e4m t\u00f6 t\u00e4k\u00e9 \u00e4 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr \u00ccD. W\u00e9 w\u00efll m\u00e4t\u00e7h th\u00efs ph\u00f6t\u00f6 w\u00efth th\u00e9 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9 \u00e4nd th\u00e9 n\u00e4m\u00e9 \u00f6n \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt. \u2c60'\u03c3\u044f\u0454\u043c#", + "Use your webcam to take a photo of your ID.": "\u00dbs\u00e9 \u00fd\u00f6\u00fcr w\u00e9\u00df\u00e7\u00e4m t\u00f6 t\u00e4k\u00e9 \u00e4 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u00dbs\u00e9 \u00fd\u00f6\u00fcr w\u00e9\u00df\u00e7\u00e4m t\u00f6 t\u00e4k\u00e9 \u00e4 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9. W\u00e9 w\u00efll m\u00e4t\u00e7h th\u00efs ph\u00f6t\u00f6 w\u00efth th\u00e9 ph\u00f6t\u00f6 \u00f6n \u00fd\u00f6\u00fcr \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Used": "\u00dbs\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Used in {count} location": [ @@ -1973,7 +2036,6 @@ "Verified Certificate upgrade": "V\u00e9r\u00eff\u00ef\u00e9d \u00c7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u00fcpgr\u00e4d\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Verified Status": "V\u00e9r\u00eff\u00ef\u00e9d St\u00e4t\u00fcs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Verified mode price": "V\u00e9r\u00eff\u00ef\u00e9d m\u00f6d\u00e9 pr\u00ef\u00e7\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", - "Verify Now": "V\u00e9r\u00eff\u00fd N\u00f6w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Version": "V\u00e9rs\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "Vertical space": "V\u00e9rt\u00ef\u00e7\u00e4l sp\u00e4\u00e7\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Very loud": "V\u00e9r\u00fd l\u00f6\u00fcd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", @@ -2000,16 +2062,19 @@ "View Teams in the {topic_name} Topic": "V\u00ef\u00e9w T\u00e9\u00e4ms \u00efn th\u00e9 {topic_name} T\u00f6p\u00ef\u00e7 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "View all errors": "V\u00ef\u00e9w \u00e4ll \u00e9rr\u00f6rs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "View child items": "V\u00ef\u00e9w \u00e7h\u00efld \u00eft\u00e9ms \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "View discussion": "V\u00ef\u00e9w d\u00efs\u00e7\u00fcss\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "View {span_start} {team_name} {span_end}": "V\u00ef\u00e9w {span_start} {team_name} {span_end} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Viewing %s course": [ "V\u00ef\u00e9w\u00efng %s \u00e7\u00f6\u00fcrs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "V\u00ef\u00e9w\u00efng %s \u00e7\u00f6\u00fcrs\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#" ], "Visibility": "V\u00efs\u00ef\u00df\u00efl\u00eft\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", + "Visible to": "V\u00efs\u00ef\u00dfl\u00e9 t\u00f6 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Visible to Staff Only": "V\u00efs\u00ef\u00dfl\u00e9 t\u00f6 St\u00e4ff \u00d6nl\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Visual aids": "V\u00efs\u00fc\u00e4l \u00e4\u00efds \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Volume": "V\u00f6l\u00fcm\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Vote for good posts and responses": "V\u00f6t\u00e9 f\u00f6r g\u00f6\u00f6d p\u00f6sts \u00e4nd r\u00e9sp\u00f6ns\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", + "Vote for this post,": "V\u00f6t\u00e9 f\u00f6r th\u00efs p\u00f6st, \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Waiting": "W\u00e4\u00eft\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "Want to confirm your identity later?": "W\u00e4nt t\u00f6 \u00e7\u00f6nf\u00efrm \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd l\u00e4t\u00e9r? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "Warning": "W\u00e4rn\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", @@ -2019,9 +2084,11 @@ "We couldn't find any results for \"%s\".": "W\u00e9 \u00e7\u00f6\u00fcldn't f\u00efnd \u00e4n\u00fd r\u00e9s\u00fclts f\u00f6r \"%s\". \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "We couldn't sign you in.": "W\u00e9 \u00e7\u00f6\u00fcldn't s\u00efgn \u00fd\u00f6\u00fc \u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "We have encountered an error. Refresh your browser and then try again.": "W\u00e9 h\u00e4v\u00e9 \u00e9n\u00e7\u00f6\u00fcnt\u00e9r\u00e9d \u00e4n \u00e9rr\u00f6r. R\u00e9fr\u00e9sh \u00fd\u00f6\u00fcr \u00dfr\u00f6ws\u00e9r \u00e4nd th\u00e9n tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "W\u00e9 h\u00e4v\u00e9 r\u00e9\u00e7\u00e9\u00efv\u00e9d \u00fd\u00f6\u00fcr \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00e4nd \u00e4r\u00e9 v\u00e9r\u00eff\u00fd\u00efng \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd. \u00dd\u00f6\u00fc w\u00efll s\u00e9\u00e9 \u00e4 m\u00e9ss\u00e4g\u00e9 \u00f6n \u00fd\u00f6\u00fcr d\u00e4sh\u00df\u00f6\u00e4rd wh\u00e9n th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss \u00efs \u00e7\u00f6mpl\u00e9t\u00e9 (\u00fcs\u00fc\u00e4ll\u00fd w\u00efth\u00efn 1-2 d\u00e4\u00fds). \u00ccn th\u00e9 m\u00e9\u00e4nt\u00efm\u00e9, \u00fd\u00f6\u00fc \u00e7\u00e4n st\u00efll \u00e4\u00e7\u00e7\u00e9ss \u00e4ll \u00e4v\u00e4\u00efl\u00e4\u00dfl\u00e9 \u00e7\u00f6\u00fcrs\u00e9 \u00e7\u00f6nt\u00e9nt. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454#", + "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days). In the meantime, you can still access all available course content.": "W\u00e9 h\u00e4v\u00e9 r\u00e9\u00e7\u00e9\u00efv\u00e9d \u00fd\u00f6\u00fcr \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00e4nd \u00e4r\u00e9 v\u00e9r\u00eff\u00fd\u00efng \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd. \u00dd\u00f6\u00fc w\u00efll s\u00e9\u00e9 \u00e4 m\u00e9ss\u00e4g\u00e9 \u00f6n \u00fd\u00f6\u00fcr d\u00e4sh\u00df\u00f6\u00e4rd wh\u00e9n th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss \u00efs \u00e7\u00f6mpl\u00e9t\u00e9 (\u00fcs\u00fc\u00e4ll\u00fd w\u00efth\u00efn 5-7 d\u00e4\u00fds). \u00ccn th\u00e9 m\u00e9\u00e4nt\u00efm\u00e9, \u00fd\u00f6\u00fc \u00e7\u00e4n st\u00efll \u00e4\u00e7\u00e7\u00e9ss \u00e4ll \u00e4v\u00e4\u00efl\u00e4\u00dfl\u00e9 \u00e7\u00f6\u00fcrs\u00e9 \u00e7\u00f6nt\u00e9nt. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454#", "We just need a little more information before you start learning with %(platformName)s.": "W\u00e9 j\u00fcst n\u00e9\u00e9d \u00e4 l\u00efttl\u00e9 m\u00f6r\u00e9 \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00df\u00e9f\u00f6r\u00e9 \u00fd\u00f6\u00fc st\u00e4rt l\u00e9\u00e4rn\u00efng w\u00efth %(platformName)s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", + "We securely encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "W\u00e9 s\u00e9\u00e7\u00fcr\u00e9l\u00fd \u00e9n\u00e7r\u00fdpt \u00fd\u00f6\u00fcr ph\u00f6t\u00f6 \u00e4nd s\u00e9nd \u00eft t\u00f6 \u00f6\u00fcr \u00e4\u00fcth\u00f6r\u00efz\u00e4t\u00ef\u00f6n s\u00e9rv\u00ef\u00e7\u00e9 f\u00f6r r\u00e9v\u00ef\u00e9w. \u00dd\u00f6\u00fcr ph\u00f6t\u00f6 \u00e4nd \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00e4r\u00e9 n\u00f6t s\u00e4v\u00e9d \u00f6r v\u00efs\u00ef\u00dfl\u00e9 \u00e4n\u00fdwh\u00e9r\u00e9 \u00f6n %(platformName)s \u00e4ft\u00e9r th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss \u00efs \u00e7\u00f6mpl\u00e9t\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442#", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "W\u00e9 \u00fcs\u00e9 th\u00e9 h\u00efgh\u00e9st l\u00e9v\u00e9ls \u00f6f s\u00e9\u00e7\u00fcr\u00eft\u00fd \u00e4v\u00e4\u00efl\u00e4\u00dfl\u00e9 t\u00f6 \u00e9n\u00e7r\u00fdpt \u00fd\u00f6\u00fcr ph\u00f6t\u00f6 \u00e4nd s\u00e9nd \u00eft t\u00f6 \u00f6\u00fcr \u00e4\u00fcth\u00f6r\u00efz\u00e4t\u00ef\u00f6n s\u00e9rv\u00ef\u00e7\u00e9 f\u00f6r r\u00e9v\u00ef\u00e9w. \u00dd\u00f6\u00fcr ph\u00f6t\u00f6 \u00e4nd \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00e4r\u00e9 n\u00f6t s\u00e4v\u00e9d \u00f6r v\u00efs\u00ef\u00dfl\u00e9 \u00e4n\u00fdwh\u00e9r\u00e9 \u00f6n %(platformName)s \u00e4ft\u00e9r th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss \u00efs \u00e7\u00f6mpl\u00e9t\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c#", + "We use your verification photos to confirm your identity and ensure the validity of your certificate.": "W\u00e9 \u00fcs\u00e9 \u00fd\u00f6\u00fcr v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n ph\u00f6t\u00f6s t\u00f6 \u00e7\u00f6nf\u00efrm \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd \u00e4nd \u00e9ns\u00fcr\u00e9 th\u00e9 v\u00e4l\u00efd\u00eft\u00fd \u00f6f \u00fd\u00f6\u00fcr \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "We're sorry to see you go! Your account will be deleted shortly.": "W\u00e9'r\u00e9 s\u00f6rr\u00fd t\u00f6 s\u00e9\u00e9 \u00fd\u00f6\u00fc g\u00f6! \u00dd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt w\u00efll \u00df\u00e9 d\u00e9l\u00e9t\u00e9d sh\u00f6rtl\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "We're sorry, there was an error": "W\u00e9'r\u00e9 s\u00f6rr\u00fd, th\u00e9r\u00e9 w\u00e4s \u00e4n \u00e9rr\u00f6r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", "We've encountered an error. Refresh your browser and then try again.": "W\u00e9'v\u00e9 \u00e9n\u00e7\u00f6\u00fcnt\u00e9r\u00e9d \u00e4n \u00e9rr\u00f6r. R\u00e9fr\u00e9sh \u00fd\u00f6\u00fcr \u00dfr\u00f6ws\u00e9r \u00e4nd th\u00e9n tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", @@ -2044,6 +2111,7 @@ "When learners submit an answer to an assessment, they immediately see whether the answer is correct or incorrect, and the score received.": "Wh\u00e9n l\u00e9\u00e4rn\u00e9rs s\u00fc\u00dfm\u00eft \u00e4n \u00e4nsw\u00e9r t\u00f6 \u00e4n \u00e4ss\u00e9ssm\u00e9nt, th\u00e9\u00fd \u00efmm\u00e9d\u00ef\u00e4t\u00e9l\u00fd s\u00e9\u00e9 wh\u00e9th\u00e9r th\u00e9 \u00e4nsw\u00e9r \u00efs \u00e7\u00f6rr\u00e9\u00e7t \u00f6r \u00efn\u00e7\u00f6rr\u00e9\u00e7t, \u00e4nd th\u00e9 s\u00e7\u00f6r\u00e9 r\u00e9\u00e7\u00e9\u00efv\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442 \u03b1\u03b7\u03b9\u043c \u03b9\u2202 \u0454\u0455\u0442 \u0142\u03b1\u0432\u03c3#", "When your face is in position, use the Take Photo button {icon} below to take your photo.": "Wh\u00e9n \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9 \u00efs \u00efn p\u00f6s\u00eft\u00ef\u00f6n, \u00fcs\u00e9 th\u00e9 T\u00e4k\u00e9 Ph\u00f6t\u00f6 \u00df\u00fctt\u00f6n {icon} \u00df\u00e9l\u00f6w t\u00f6 t\u00e4k\u00e9 \u00fd\u00f6\u00fcr ph\u00f6t\u00f6. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Which timed transcript would you like to use?": "Wh\u00ef\u00e7h t\u00efm\u00e9d tr\u00e4ns\u00e7r\u00efpt w\u00f6\u00fcld \u00fd\u00f6\u00fc l\u00efk\u00e9 t\u00f6 \u00fcs\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", + "While our support team is happy to assist with the edX platform, the course staff has the expertise for specific assignment questions, grading or the proper procedures in each course. Please post all course related questions within the Discussion Forum where the Course Staff can directly respond.": "Wh\u00efl\u00e9 \u00f6\u00fcr s\u00fcpp\u00f6rt t\u00e9\u00e4m \u00efs h\u00e4pp\u00fd t\u00f6 \u00e4ss\u00efst w\u00efth th\u00e9 \u00e9dX pl\u00e4tf\u00f6rm, th\u00e9 \u00e7\u00f6\u00fcrs\u00e9 st\u00e4ff h\u00e4s th\u00e9 \u00e9xp\u00e9rt\u00efs\u00e9 f\u00f6r sp\u00e9\u00e7\u00eff\u00ef\u00e7 \u00e4ss\u00efgnm\u00e9nt q\u00fc\u00e9st\u00ef\u00f6ns, gr\u00e4d\u00efng \u00f6r th\u00e9 pr\u00f6p\u00e9r pr\u00f6\u00e7\u00e9d\u00fcr\u00e9s \u00efn \u00e9\u00e4\u00e7h \u00e7\u00f6\u00fcrs\u00e9. Pl\u00e9\u00e4s\u00e9 p\u00f6st \u00e4ll \u00e7\u00f6\u00fcrs\u00e9 r\u00e9l\u00e4t\u00e9d q\u00fc\u00e9st\u00ef\u00f6ns w\u00efth\u00efn th\u00e9 D\u00efs\u00e7\u00fcss\u00ef\u00f6n F\u00f6r\u00fcm wh\u00e9r\u00e9 th\u00e9 \u00c7\u00f6\u00fcrs\u00e9 St\u00e4ff \u00e7\u00e4n d\u00efr\u00e9\u00e7tl\u00fd r\u00e9sp\u00f6nd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142#", "Whole words": "Wh\u00f6l\u00e9 w\u00f6rds \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Why activate?": "Wh\u00fd \u00e4\u00e7t\u00efv\u00e4t\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Why does %(platformName)s need my photo?": "Wh\u00fd d\u00f6\u00e9s %(platformName)s n\u00e9\u00e9d m\u00fd ph\u00f6t\u00f6? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", @@ -2126,14 +2194,13 @@ "You must specify a name": "\u00dd\u00f6\u00fc m\u00fcst sp\u00e9\u00e7\u00eff\u00fd \u00e4 n\u00e4m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "You must specify a name for the cohort": "\u00dd\u00f6\u00fc m\u00fcst sp\u00e9\u00e7\u00eff\u00fd \u00e4 n\u00e4m\u00e9 f\u00f6r th\u00e9 \u00e7\u00f6h\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u00dd\u00f6\u00fc m\u00fcst sp\u00e9\u00e7\u00eff\u00fd \u00fd\u00f6\u00fcr \u00df\u00efrth \u00fd\u00e9\u00e4r \u00df\u00e9f\u00f6r\u00e9 \u00fd\u00f6\u00fc \u00e7\u00e4n sh\u00e4r\u00e9 \u00fd\u00f6\u00fcr f\u00fcll pr\u00f6f\u00efl\u00e9. T\u00f6 sp\u00e9\u00e7\u00eff\u00fd \u00fd\u00f6\u00fcr \u00df\u00efrth \u00fd\u00e9\u00e4r, g\u00f6 t\u00f6 th\u00e9 {account_settings_page_link} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", - "You need a computer or cell phone that has a webcam. When you receive a browser prompt, make sure that you allow access to the camera.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4 \u00e7\u00f6mp\u00fct\u00e9r \u00f6r \u00e7\u00e9ll ph\u00f6n\u00e9 th\u00e4t h\u00e4s \u00e4 w\u00e9\u00df\u00e7\u00e4m. Wh\u00e9n \u00fd\u00f6\u00fc r\u00e9\u00e7\u00e9\u00efv\u00e9 \u00e4 \u00dfr\u00f6ws\u00e9r pr\u00f6mpt, m\u00e4k\u00e9 s\u00fcr\u00e9 th\u00e4t \u00fd\u00f6\u00fc \u00e4ll\u00f6w \u00e4\u00e7\u00e7\u00e9ss t\u00f6 th\u00e9 \u00e7\u00e4m\u00e9r\u00e4. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442 \u03b1\u03b7\u03b9\u043c \u03b9\u2202 \u0454\u0455\u0442 \u0142\u03b1\u0432\u03c3\u044f\u03c5\u043c#", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4 dr\u00efv\u00e9r's l\u00ef\u00e7\u00e9ns\u00e9, p\u00e4ssp\u00f6rt, \u00f6r \u00f6th\u00e9r g\u00f6v\u00e9rnm\u00e9nt-\u00efss\u00fc\u00e9d \u00ccD th\u00e4t h\u00e4s \u00fd\u00f6\u00fcr n\u00e4m\u00e9 \u00e4nd ph\u00f6t\u00f6. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4n \u00ccD w\u00efth \u00fd\u00f6\u00fcr n\u00e4m\u00e9 \u00e4nd ph\u00f6t\u00f6. \u00c0 dr\u00efv\u00e9r's l\u00ef\u00e7\u00e9ns\u00e9, p\u00e4ssp\u00f6rt, \u00f6r \u00f6th\u00e9r g\u00f6v\u00e9rnm\u00e9nt-\u00efss\u00fc\u00e9d \u00ccDs \u00e4r\u00e9 \u00e4ll \u00e4\u00e7\u00e7\u00e9pt\u00e4\u00dfl\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", + "You need a device that has a webcam. If you receive a browser prompt for access to your camera, please make sure to click 'Allow'.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4 d\u00e9v\u00ef\u00e7\u00e9 th\u00e4t h\u00e4s \u00e4 w\u00e9\u00df\u00e7\u00e4m. \u00ccf \u00fd\u00f6\u00fc r\u00e9\u00e7\u00e9\u00efv\u00e9 \u00e4 \u00dfr\u00f6ws\u00e9r pr\u00f6mpt f\u00f6r \u00e4\u00e7\u00e7\u00e9ss t\u00f6 \u00fd\u00f6\u00fcr \u00e7\u00e4m\u00e9r\u00e4, pl\u00e9\u00e4s\u00e9 m\u00e4k\u00e9 s\u00fcr\u00e9 t\u00f6 \u00e7l\u00ef\u00e7k '\u00c0ll\u00f6w'. \u2c60'#", + "You need a valid ID that contains your full name and photo.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4 v\u00e4l\u00efd \u00ccD th\u00e4t \u00e7\u00f6nt\u00e4\u00efns \u00fd\u00f6\u00fcr f\u00fcll n\u00e4m\u00e9 \u00e4nd ph\u00f6t\u00f6. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "You need an ID with your name and photo. A driver's license, passport, or ID are all acceptable.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4n \u00ccD w\u00efth \u00fd\u00f6\u00fcr n\u00e4m\u00e9 \u00e4nd ph\u00f6t\u00f6. \u00c0 dr\u00efv\u00e9r's l\u00ef\u00e7\u00e9ns\u00e9, p\u00e4ssp\u00f6rt, \u00f6r \u00ccD \u00e4r\u00e9 \u00e4ll \u00e4\u00e7\u00e7\u00e9pt\u00e4\u00dfl\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d t\u00f6 \u00e4\u00e7t\u00efv\u00e4t\u00e9 \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00df\u00e9f\u00f6r\u00e9 \u00fd\u00f6\u00fc \u00e7\u00e4n \u00e9nr\u00f6ll \u00efn \u00e7\u00f6\u00fcrs\u00e9s. \u00c7h\u00e9\u00e7k \u00fd\u00f6\u00fcr \u00efn\u00df\u00f6x f\u00f6r \u00e4n \u00e4\u00e7t\u00efv\u00e4t\u00ef\u00f6n \u00e9m\u00e4\u00efl. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d t\u00f6 \u00e4\u00e7t\u00efv\u00e4t\u00e9 \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00df\u00e9f\u00f6r\u00e9 \u00fd\u00f6\u00fc \u00e7\u00e4n \u00e9nr\u00f6ll \u00efn \u00e7\u00f6\u00fcrs\u00e9s. \u00c7h\u00e9\u00e7k \u00fd\u00f6\u00fcr \u00efn\u00df\u00f6x f\u00f6r \u00e4n \u00e4\u00e7t\u00efv\u00e4t\u00ef\u00f6n \u00e9m\u00e4\u00efl. \u00c0ft\u00e9r \u00fd\u00f6\u00fc \u00e7\u00f6mpl\u00e9t\u00e9 \u00e4\u00e7t\u00efv\u00e4t\u00ef\u00f6n \u00fd\u00f6\u00fc \u00e7\u00e4n r\u00e9t\u00fcrn \u00e4nd r\u00e9fr\u00e9sh th\u00efs p\u00e4g\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2#", "You receive messages from {platform_name} and course teams at this address.": "\u00dd\u00f6\u00fc r\u00e9\u00e7\u00e9\u00efv\u00e9 m\u00e9ss\u00e4g\u00e9s fr\u00f6m {platform_name} \u00e4nd \u00e7\u00f6\u00fcrs\u00e9 t\u00e9\u00e4ms \u00e4t th\u00efs \u00e4ddr\u00e9ss. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "You reserve all rights for your work": "\u00dd\u00f6\u00fc r\u00e9s\u00e9rv\u00e9 \u00e4ll r\u00efghts f\u00f6r \u00fd\u00f6\u00fcr w\u00f6rk \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u00dd\u00f6\u00fc st\u00efll n\u00e9\u00e9d t\u00f6 v\u00efs\u00eft th\u00e9 %(display_name)s w\u00e9\u00dfs\u00eft\u00e9 t\u00f6 \u00e7\u00f6mpl\u00e9t\u00e9 th\u00e9 \u00e7r\u00e9d\u00eft pr\u00f6\u00e7\u00e9ss. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "You submitted {filename}; only {allowedFiles} are allowed.": "\u00dd\u00f6\u00fc s\u00fc\u00dfm\u00eftt\u00e9d {filename}; \u00f6nl\u00fd {allowedFiles} \u00e4r\u00e9 \u00e4ll\u00f6w\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "You waive some rights for your work, such that others can use it too": "\u00dd\u00f6\u00fc w\u00e4\u00efv\u00e9 s\u00f6m\u00e9 r\u00efghts f\u00f6r \u00fd\u00f6\u00fcr w\u00f6rk, s\u00fc\u00e7h th\u00e4t \u00f6th\u00e9rs \u00e7\u00e4n \u00fcs\u00e9 \u00eft t\u00f6\u00f6 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "You will be refunded the amount you paid.": "\u00dd\u00f6\u00fc w\u00efll \u00df\u00e9 r\u00e9f\u00fcnd\u00e9d th\u00e9 \u00e4m\u00f6\u00fcnt \u00fd\u00f6\u00fc p\u00e4\u00efd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", @@ -2202,6 +2269,7 @@ "and others": "\u00e4nd \u00f6th\u00e9rs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "anonymous": "\u00e4n\u00f6n\u00fdm\u00f6\u00fcs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "answer": "\u00e4nsw\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", + "answered question": "\u00e4nsw\u00e9r\u00e9d q\u00fc\u00e9st\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "asset_path is required": "\u00e4ss\u00e9t_p\u00e4th \u00efs r\u00e9q\u00fc\u00efr\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "bytes": "\u00df\u00fdt\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "certificate": "\u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", @@ -2213,6 +2281,8 @@ "delete chapter": "d\u00e9l\u00e9t\u00e9 \u00e7h\u00e4pt\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "delete group": "d\u00e9l\u00e9t\u00e9 gr\u00f6\u00fcp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "details about the failure": "d\u00e9t\u00e4\u00efls \u00e4\u00df\u00f6\u00fct th\u00e9 f\u00e4\u00efl\u00fcr\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", + "discussion": "d\u00efs\u00e7\u00fcss\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", + "discussion posted %(time_ago)s by %(author)s": "d\u00efs\u00e7\u00fcss\u00ef\u00f6n p\u00f6st\u00e9d %(time_ago)s \u00df\u00fd %(author)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "dragging": "dr\u00e4gg\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "dragging out of slider": "dr\u00e4gg\u00efng \u00f6\u00fct \u00f6f sl\u00efd\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "dropped in slider": "dr\u00f6pp\u00e9d \u00efn sl\u00efd\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", @@ -2222,15 +2292,19 @@ "e.g. 'http://google.com'": "\u00e9.g. 'http://g\u00f6\u00f6gl\u00e9.\u00e7\u00f6m' \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "e.g. johndoe@example.com, JaneDoe, joeydoe@example.com": "\u00e9.g. j\u00f6hnd\u00f6\u00e9@\u00e9x\u00e4mpl\u00e9.\u00e7\u00f6m, J\u00e4n\u00e9D\u00f6\u00e9, j\u00f6\u00e9\u00fdd\u00f6\u00e9@\u00e9x\u00e4mpl\u00e9.\u00e7\u00f6m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "emphasized text": "\u00e9mph\u00e4s\u00efz\u00e9d t\u00e9xt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", + "endorsed %(time_ago)s": "\u00e9nd\u00f6rs\u00e9d %(time_ago)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", + "endorsed %(time_ago)s by %(user)s": "\u00e9nd\u00f6rs\u00e9d %(time_ago)s \u00df\u00fd %(user)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "enter code here": "\u00e9nt\u00e9r \u00e7\u00f6d\u00e9 h\u00e9r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "enter link description here": "\u00e9nt\u00e9r l\u00efnk d\u00e9s\u00e7r\u00efpt\u00ef\u00f6n h\u00e9r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", + "follow this post": "f\u00f6ll\u00f6w th\u00efs p\u00f6st \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "for": "f\u00f6r \u2c60'\u03c3\u044f\u0454\u043c#", - "for {courseName}": "f\u00f6r {courseName} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "group configuration": "gr\u00f6\u00fcp \u00e7\u00f6nf\u00efg\u00fcr\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "image omitted": "\u00efm\u00e4g\u00e9 \u00f6m\u00eftt\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "incorrect": "\u00efn\u00e7\u00f6rr\u00e9\u00e7t \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "last activity": "l\u00e4st \u00e4\u00e7t\u00efv\u00eft\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "less than a minute": "l\u00e9ss th\u00e4n \u00e4 m\u00efn\u00fct\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "marked as answer %(time_ago)s": "m\u00e4rk\u00e9d \u00e4s \u00e4nsw\u00e9r %(time_ago)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", + "marked as answer %(time_ago)s by %(user)s": "m\u00e4rk\u00e9d \u00e4s \u00e4nsw\u00e9r %(time_ago)s \u00df\u00fd %(user)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "minute": "m\u00efn\u00fct\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "minutes": "m\u00efn\u00fct\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "name": "n\u00e4m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", @@ -2248,9 +2322,13 @@ "or create a new one here": "\u00f6r \u00e7r\u00e9\u00e4t\u00e9 \u00e4 n\u00e9w \u00f6n\u00e9 h\u00e9r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "or sign in with": "\u00f6r s\u00efgn \u00efn w\u00efth \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "path/to/introductionToCookieBaking-CH{order}.pdf": "p\u00e4th/t\u00f6/\u00efntr\u00f6d\u00fc\u00e7t\u00ef\u00f6nT\u00f6\u00c7\u00f6\u00f6k\u00ef\u00e9B\u00e4k\u00efng-\u00c7H{order}.pdf \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", + "post anonymously": "p\u00f6st \u00e4n\u00f6n\u00fdm\u00f6\u00fcsl\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "post anonymously to classmates": "p\u00f6st \u00e4n\u00f6n\u00fdm\u00f6\u00fcsl\u00fd t\u00f6 \u00e7l\u00e4ssm\u00e4t\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", + "posted %(time_ago)s by %(author)s": "p\u00f6st\u00e9d %(time_ago)s \u00df\u00fd %(author)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "price": "pr\u00ef\u00e7\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "provide the title/name of the chapter that will be used in navigating": "pr\u00f6v\u00efd\u00e9 th\u00e9 t\u00eftl\u00e9/n\u00e4m\u00e9 \u00f6f th\u00e9 \u00e7h\u00e4pt\u00e9r th\u00e4t w\u00efll \u00df\u00e9 \u00fcs\u00e9d \u00efn n\u00e4v\u00efg\u00e4t\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "provide the title/name of the text book as you would like your students to see it": "pr\u00f6v\u00efd\u00e9 th\u00e9 t\u00eftl\u00e9/n\u00e4m\u00e9 \u00f6f th\u00e9 t\u00e9xt \u00df\u00f6\u00f6k \u00e4s \u00fd\u00f6\u00fc w\u00f6\u00fcld l\u00efk\u00e9 \u00fd\u00f6\u00fcr st\u00fcd\u00e9nts t\u00f6 s\u00e9\u00e9 \u00eft \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", + "question posted %(time_ago)s by %(author)s": "q\u00fc\u00e9st\u00ef\u00f6n p\u00f6st\u00e9d %(time_ago)s \u00df\u00fd %(author)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "remove": "r\u00e9m\u00f6v\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "remove all": "r\u00e9m\u00f6v\u00e9 \u00e4ll \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "second": "s\u00e9\u00e7\u00f6nd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", @@ -2262,6 +2340,7 @@ "team count": "t\u00e9\u00e4m \u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "text_word_{uniqueId}": "t\u00e9xt_w\u00f6rd_{uniqueId} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "text_word_{uniqueId} title_word_{uniqueId}": "t\u00e9xt_w\u00f6rd_{uniqueId} t\u00eftl\u00e9_w\u00f6rd_{uniqueId} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", + "the more quickly and helpfully we can respond!": "th\u00e9 m\u00f6r\u00e9 q\u00fc\u00ef\u00e7kl\u00fd \u00e4nd h\u00e9lpf\u00fcll\u00fd w\u00e9 \u00e7\u00e4n r\u00e9sp\u00f6nd! \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "there is currently {numVotes} vote": [ "th\u00e9r\u00e9 \u00efs \u00e7\u00fcrr\u00e9ntl\u00fd {numVotes} v\u00f6t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "th\u00e9r\u00e9 \u00e4r\u00e9 \u00e7\u00fcrr\u00e9ntl\u00fd {numVotes} v\u00f6t\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#" @@ -2269,6 +2348,7 @@ "title_word_{uniqueId}": "t\u00eftl\u00e9_w\u00f6rd_{uniqueId} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "toggle chapter %(displayName)s": "t\u00f6ggl\u00e9 \u00e7h\u00e4pt\u00e9r %(displayName)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "toggle subsection %(displayName)s": "t\u00f6ggl\u00e9 s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6n %(displayName)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", + "unanswered question": "\u00fcn\u00e4nsw\u00e9r\u00e9d q\u00fc\u00e9st\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "unit": "\u00fcn\u00eft \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "unsubmitted": "\u00fcns\u00fc\u00dfm\u00eftt\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "upload a PDF file or provide the path to a Studio asset file": "\u00fcpl\u00f6\u00e4d \u00e4 PDF f\u00efl\u00e9 \u00f6r pr\u00f6v\u00efd\u00e9 th\u00e9 p\u00e4th t\u00f6 \u00e4 St\u00fcd\u00ef\u00f6 \u00e4ss\u00e9t f\u00efl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -2365,6 +2445,7 @@ ], "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}": "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "{type} Progress": "{type} Pr\u00f6gr\u00e9ss \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", + "{unread_comments_count} new": "{unread_comments_count} n\u00e9w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "\u2026": "\u2026 \u2c60#" }; for (var key in newcatalog) { @@ -2387,7 +2468,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2449,9 +2530,9 @@ "%d %m %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j\\-\\a \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "Y-m-d H:i", "SHORT_DATE_FORMAT": "Y-m-d", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/es-419/djangojs.js b/cms/static/js/i18n/es-419/djangojs.js index e0708b61b6b15a2fe399db50686b8dc9bab33b85..ef7c05993bdf67c3672eb14e9e8ba3c1ee614ec0 100644 --- a/cms/static/js/i18n/es-419/djangojs.js +++ b/cms/static/js/i18n/es-419/djangojs.js @@ -96,10 +96,15 @@ " ${price} {currency} )": " ${price} {currency} )", " From this point in time, you must follow the <a href=\"%(link_urls.online_proctoring_rules)s\" target=\"_blank\">online proctoring rules</a> to pass the proctoring review for your exam. ": "A partir de este momento, debe seguir las <a href=\"%(link_urls.online_proctoring_rules)s\" target=\"_blank\">reglas de supervisi\u00f3n online</a> para aprobar la revisi\u00f3n de la supervisi\u00f3n para su examen.", " Link": "Enlace", + " Member": [ + "Miembro", + "Miembros" + ], " Your Proctoring Session Has Started ": "Su Sesi\u00f3n Supervisada Ha Comenzado", " and ": "y", " and {num_of_minutes} minute": "y {num_of_minutes} minuto", " and {num_of_minutes} minutes": "y {num_of_minutes} minutos", + " as many questions may have already been answered.": "ya que muchas preguntas comunes pueden ya haber sido respondidas.", " learner does not exist in LMS and not added to the exception list": "estudiante no existe en el LMS y no se a\u00f1adi\u00f3 a la lista de excepciones", " learner is already white listed and not added to the exception list": "el estudiante ya est\u00e1 en la lista blanca y no se a\u00f1adi\u00f3 a las excepciones", " learner is not enrolled in course and not added to the exception list": "el estudiante no est\u00e1 inscrito en el curso y no se a\u00f1adi\u00f3 a la lista de excepciones", @@ -113,6 +118,8 @@ " to complete and submit the exam.": "para completar y enviar el examen.", "${listPrice}": "${listPrice}", "%(cohort_name)s (%(user_count)s)": "%(cohort_name)s (%(user_count)s)", + "%(comments_count)s %(span_sr_open)scomments %(span_close)s": "%(comments_count)s %(span_sr_open)s comentarios %(span_close)s", + "%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s unread comments)%(span_close)s": "%(comments_count)s %(span_sr_open)s comentarios (%(unread_comments_count)s comentarios no le\u00eddos)%(span_close)s", "%(errorCount)s error found in form.": [ "%(errorCount)s error en el formulario.", "%(errorCount)s errores en el formulario." @@ -158,6 +165,7 @@ "%s from now": "%s a partir de ahora", "(Add signatories for a certificate)": "(A\u00f1adir signatarios para el certificado)", "(Caption will be displayed when you start playing the video.)": "(Los subt\u00edtulos ser\u00e1n mostrados al iniciar la reproducci\u00f3n del video.)", + "(Community TA)": "(Profesor ayudante de la comunidad)", "(Optional)": "(Opcional)", "(Read-only)": "(Solo-lectura)", "(Required Field)": "(Campo requerido)", @@ -165,6 +173,7 @@ "(Self-paced) Ends {end}": "(A ritmo propio)Termina{end}", "(Self-paced) Started {start}": "(A ritmo propio) Empezado {start}", "(Self-paced) Starts {start}": "(A su propio ritmo) Empieza {start}", + "(Staff)": "(Equipo del curso)", "(contains %(student_count)s student)": [ "(contiene %(student_count)s estudiante)", "(contiene %(student_count)s estudiantes)" @@ -226,7 +235,12 @@ "Add URLs for additional versions": "A\u00f1ada URLs para las versiones adicionales", "Add a Chapter": "A\u00f1adir cap\u00edtulo", "Add a New Cohort": "A\u00f1adir NuevaCohorte", + "Add a Post": "A\u00f1ade una publicaci\u00f3n", + "Add a Response": "A\u00f1ade una respuesta", + "Add a clear and descriptive title to encourage participation. (Required)": "Agrega un t\u00edtulo claro y descriptivo para fomentar la participaci\u00f3n. (Requerido)", + "Add a comment": "A\u00f1ade un comentario", "Add a learning outcome here": "Agregar Resultado de aprendizaje", + "Add a response:": "A\u00f1ade tu respuesta:", "Add another group": "A\u00f1adir nuevo grupo", "Add language": "A\u00f1adir idioma", "Add learners to this cohort": "Agregar estudiantes a este cohorte", @@ -236,6 +250,7 @@ "Add your first content group": "Agrege su primer grupo de contenido", "Add your first group configuration": "Agregue su primera configuraci\u00f3n de grupo", "Add your first textbook": "A\u00f1ada su primer libro de texto", + "Add your post to a relevant topic to help others find it. (Required)": "A\u00f1ade tu publicaci\u00f3n a un tema relevante para que los dem\u00e1s la puedan encontrar. (Requerido)", "Add {role} Access": "A\u00f1adir permisos de {role}", "Adding": "A\u00f1adiendo", "Adding the selected course to your cart": "A\u00f1adiendo el curso seleccionado a tu carrito de compras", @@ -256,6 +271,7 @@ "Align left": "Alienar a la izquierda", "Align right": "Alinear a la derecha", "Alignment": "Alinear a la", + "All Groups": "Todos los grupos", "All Learners and Staff": "Todos los estudiantes y equipo del curso", "All Posts": "Todas las publicaciones", "All Rights Reserved": "Todos los derechos reservados", @@ -308,6 +324,7 @@ "An error occurred. Please reload the page.": "Ocurri\u00f3 un error. Por favor recargue la p\u00e1gina.", "An error occurred. Please try again.": "Ocurri\u00f3 un error. Por favor, intenta nuevamente.", "An error occurred. Try again.": "Ocurri\u00f3 un error. Intenta nuevamente.", + "An unexpected error has occurred.": "Ha ocurrido un error inesperado.", "An unexpected error occurred. Please try again.": "Se produjo un error inesperado. Por favor, int\u00e9ntalo nuevamente.", "Anchor": "Ancla", "Anchors": "Anclas", @@ -319,6 +336,7 @@ "Are you having trouble finding a team to join?": "\u00bfTiene problemas para encontrar un equipo al cual unirse?", "Are you sure that you want to leave this session?": "\u00bf Est\u00e1 seguro de que quiere salir de esta sesi\u00f3n?", "Are you sure you want to change to a different session?": "\u00bfEst\u00e1 seguro de que quiere cambiar a una sesi\u00f3n diferente?", + "Are you sure you want to delete the following file? It cannot be restored.\nFile: ": "\u00bfEst\u00e1s seguro de que desea eliminar el siguiente archivo? No puede ser restaurado.\nArchivo:", "Are you sure you want to delete this comment?": "\u00bfEst\u00e1s seguro de que deseas borrar este comentario?", "Are you sure you want to delete this page? This action cannot be undone.": "\u00bfEst\u00e1s seguro de que deseas borrar esta p\u00e1gina? Esta acci\u00f3n no se puede deshacer.", "Are you sure you want to delete this post?": "\u00bfEst\u00e1s seguro de que deseas borrar esta publicaci\u00f3n?", @@ -339,10 +357,12 @@ "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "\u00bfEst\u00e1 seguro de que desea borrar este \u00edtem?. \u00a1Esta acci\u00f3n no puede revertirse!\n\nCualquier contenido que haga referencia a este \u00edtem dejar\u00e1 de funcionar (im\u00e1genes o v\u00ednculos)", "Are you sure?": "\u00bfEst\u00e1 seguro?", "As part of the verification process, you take a photo of both your face and a government-issued photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "Como parte del proceso de verificaci\u00f3n, usted debe tomar una foto de su cara y de su documento de identidad. Nuestro servicio de autorizaci\u00f3n confirmar\u00e1 su identidad comparando la foto que usted se toma con la foto en su documento.", + "As part of the verification process, you take a photo of both your face and a photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "Como parte del proceso de verificaci\u00f3n, usted tomar\u00e1 una foto de su cara y de su documento de identificaci\u00f3n con foto. Nuestro servicio de autorizaci\u00f3n confirma su identidad comparando la foto que toma con la foto en su identificaci\u00f3n.", "As you complete courses, you will see them listed here.": "Mientras completas cursos, los ver\u00e1s enumerados aqu\u00ed.", "Assessment": "Evaluaci\u00f3n", "Assessment Results Visibility": "Visibilidad de los resultados de la evaluaci\u00f3n", "Assessments": "Evaluaciones", + "Assign Team Memberships": "Asignar membres\u00edas de equipo", "Assign learners to cohorts by uploading a CSV file": "Asignar estudiantes a cohortes subiendo un archivo CSV", "Assign students to cohorts by uploading a CSV file.": "Asignar estudiantes al cohorte cargando un archivo CSV.", "Assignment Type Name": "Nombre del tipo de tarea", @@ -402,6 +422,7 @@ "Cannot delete when in use by a unit": "No puede borrar cuando esta en uso por una unidad", "Cannot delete when in use by an experiment": "No se puede borrar mientras est\u00e9 en uso por un experimento", "Cannot drop more <%= types %> assignments than are assigned.": "No se pueden borrar m\u00e1s asignaciones de <%= types %> de los que son asignados.", + "Cannot join instructor managed team": "No se puede unir al equipo administrado por el instructor", "Caption": "Leyenda", "Caution: The last published version of this unit is live. By publishing changes you will change the student experience.": "Atenci\u00f3n: La \u00faltima versi\u00f3n publicada de esta unidad est\u00e1 en vivo. Al publicar los cambios, cambiar\u00e1 la experiencia de los estudiantes.", "Cell": "Celda", @@ -481,6 +502,7 @@ "Click to remove all chosen %s at once.": "Haz clic para eliminar todos los %s elegidos", "Close": "Cerrar", "Close Calculator": "Cerrar Calculadora", + "Closed": "Cerrado", "Code": "C\u00f3digo", "Code Sample (Ctrl+K)": "C\u00f3digo (Ctrl+K)", "Code block": "Bloque de c\u00f3digo", @@ -499,6 +521,7 @@ "Coming Soon": "Pr\u00f3ximamente", "Commentary": "Comentario", "Common Problem Types": "Tipos de problemas comunes", + "Community TA": "Profesor asistente de la comunidad", "Complete courses on your schedule to ensure you stand out in your field!": "\u00a1Complete cursos seg\u00fan tu horario para asegurar que sobresalgas en tu disciplina!", "Completed": "Finalizado", "Component": "Componente", @@ -524,6 +547,7 @@ "Continue to my practice exam": "Continuar a mi examen de pr\u00e1ctica", "Continue to my proctored exam. I want to be eligible for credit.": "Continuar a mi examen supervisado. Quiero ser elegible para cr\u00e9dito.", "Copy": "Copiar", + "Copy Component Location": "Copiar la ubicaci\u00f3n del Componente", "Copy Email To Editor": "Copiar el correo al editor", "Copy row": "Copiar la fila", "Correct failed component": "Corregir componente fallido", @@ -534,6 +558,7 @@ "Could not find the specified string.": "No se encontr\u00f3 la cadena especificada.", "Could not find users associated with the following identifiers:": "No se puede encontrar el usuario asociado al siguiente identificador:", "Could not grade your answer. The submission was aborted.": "No se ha podido calificar tu respuesta. El registro fue cancelado.", + "Could not load teams information.": "No se pudo cargar la informaci\u00f3n de los equipos.", "Could not override problem score for {user}.": "No fue posible sobreescribir el puntaje del problema para el usuario {user}.", "Could not retrieve download url.": "No se pudo recuperar la url de descarga.", "Could not retrieve payment information": "No se pudo conseguir la informaci\u00f3n del pago", @@ -551,6 +576,7 @@ ], "Course Content": "Contenidos del curso", "Course Credit Requirements": "Requerimientos de cr\u00e9ditos para el curso", + "Course Discussion Forum": "Foro de discusi\u00f3n del curso", "Course End": "Finalizaci\u00f3n del curso", "Course Handouts": "Materiales del curso", "Course ID": "Id de Curso", @@ -562,6 +588,7 @@ "Course Number Override": "Reemplazo para el n\u00famero de curso", "Course Number:": "N\u00famero del curso:", "Course Outline": "Estructura del curso", + "Course Run:": "Edici\u00f3n del Curso:", "Course Start": "Inicio del Curso", "Course Title": "T\u00edtulo del curso", "Course Title Override": "Reemplazo para el t\u00edtulo del curso", @@ -573,9 +600,11 @@ "Create": "Crear", "Create Account": "Crear cuenta", "Create Re-run": "Crear reapertura", + "Create Support Ticket": "Crear caso de soporte", "Create a New Team": "Crear un nuevo equipo", "Create a content group": "Crear contenido de grupo", "Create a new team if you can't find an existing team to join, or if you would like to learn with friends you know.": "Crea un nuevo equipo si no puedes encontrar uno existente para unirte o si deseas aprender con personas que ya conoces.", + "Create a {link_start}Mozilla Backpack{link_end} account, or log in to your existing account": "Crear una {link_start}cuenta en Mozilla Backpack{link_end} o iniciar sesi\u00f3n en una cuenta existente.", "Create account using %(providerName)s.": "Crear una cuenta usando %(providerName)s", "Create an Account": "Crear una cuenta", "Create an Account.": "Crear una cuenta.", @@ -612,7 +641,6 @@ "Default (Local Time Zone)": "Por defecto (Zona horaria local)", "Default Timed Transcript": "Transcripci\u00f3n con tiempos por defecto", "Delete": "Borrar", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u00bfDesea borrar \"<%= signatoryName %>\" de la lista de signatarios?", "Delete File Confirmation": "Confirmaci\u00f3n de borrado de archivo", "Delete My Account": "Eliminar mi cuenta", "Delete Page Confirmation": "Confirmaci\u00f3n de eliminaci\u00f3n de p\u00e1gina", @@ -627,9 +655,11 @@ "Delete this team?": "\u00bfBorrar este equipo?", "Delete this {xblock_type} (and prerequisite)?": "\u00bfEliminar este {xblock_type} (y prerrequisitos)?", "Delete this {xblock_type}?": "\u00bfEliminar este {xblock_type}?", + "Delete \u201c<%- name %>\u201d?": "Eliminar \u201c<%- name %>\u201d?", "Deleted Content Group": "Contenido de grupo eliminado", "Deleted Group": "Grupo eliminado", "Deleting": "Borrando", + "Deleting a team is permanent and cannot be undone.All members are removed from the team, and team discussions can no longer be accessed.": "Borrar un equipo es una acci\u00f3n permanente y no puede ser revertida. Todos los miembros son removidos del equipo, y las discusiones creadas en el equipo no pueden ser accedidas de nuevo.", "Deleting a textbook cannot be undone and once deleted any reference to it in your courseware's navigation will also be removed.": "El borrado de un libro de texto no se puede deshacer y una vez borrado, cualquier referencia al mismo en la navegaci\u00f3n del curso ser\u00e1 eliminada.", "Deleting this %(item_display_name)s is permanent and cannot be undone.": "Eliminar %(item_display_name)s is permanente y no puede deshacerse", "Deleting this {xblock_type} is permanent and cannot be undone.": "Eliminar este {xblock_type} es una acci\u00f3n permanente y no se puede revertir.", @@ -638,11 +668,14 @@ "Description": "Descripci\u00f3n", "Description of the certificate": "Descripci\u00f3n del certificado", "Details": "Detalles", + "Device with Camera": "Dispositivo con c\u00e1mara", "Dimensions": "Dimensiones", "Disc": "Disco", "Discard Changes": "Descartar cambios", "Discarding Changes": "Descartando cambios", + "Discussion": "Discusi\u00f3n", "Discussion Home": "Inicio de la discusi\u00f3n", + "Discussion admins, moderators, and TAs can make their posts visible to all students or specify a single group.": "Los administradores de la discusi\u00f3n, moderadores, y profesores asociados pueden hacer sus publicaciones visibles a todos los estudiantes o especificar un grupo en particular.", "Discussion topics in the course are not divided.": "Temas de discusi\u00f3n en el curso no son divididos.", "Discussions are unified; all learners interact with posts from other learners, regardless of the group they are in.": "Las discusiones son unificadas; todos los estudiantes interact\u00faan con publicaciones de otros estudiantes, sin considerar su grupo.", "Display Name": "Nombre para mostrar:", @@ -655,13 +688,13 @@ "Do you want to upload your file before submitting?": "Quieres subir tu archivo antes de enviarlo ?", "Document properties": "Propiedades del documento", "Does the name on your ID match your account name: %(fullName)s?": "\u00bfCorresponde el nombre en su identificaci\u00f3n con el nombre es su cuenta: %(fullName)s?", - "Does the photo of you match your ID photo?": "\u00bfSu foto corresponde a la foto en su identificaci\u00f3n?", "Does the photo of you show your whole face?": "\u00bfMuestra la foto su cara completa?", "Doing so means that you are no longer eligible for academic credit.": "Hacer esto significa que ya no ser\u00e1 elegible para cr\u00e9dito acad\u00e9mico.", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u00bfNo puede ver su foto? Aseg\u00farese de permitir a su navegador que utilice la c\u00e1mara web cuando este le solicite tal autorizaci\u00f3n.", "Donate": "Donar", "Double-check that your webcam is connected and working to continue.": "Verifica que tu c\u00e1mara web est\u00e9 conectada y funcionando para continuar.", "Download": "Descargar", + "Download Memberships": "Descargar membres\u00edas", "Download Software Clicked": "'Descargar aplicaci\u00f3n' seleccionado", "Download Transcript for Editing": "Descargar Transcripci\u00f3n para editar", "Download URL": "URL de descarga", @@ -677,6 +710,7 @@ "Due Date:": "Fecha l\u00edmite:", "Due Time in UTC:": "Hora l\u00edmite en UTC:", "Due date cannot be before start date.": "Fecha l\u00edmite no puede ser menor al a fecha de inicio.", + "Due to the recent increase in interest in online education and edX, we are currently experiencing an unusually high volume of support requests. We appreciate your patience as we work to review each request. Please check the ": "Debido al reciente aumento en el inter\u00e9s en la educaci\u00f3n en l\u00ednea y en edX, actualmente estamos experimentando un volumen inusualmente alto de solicitudes de soporte. Agradecemos su paciencia mientras trabajamos para revisar cada solicitud. Por favor, consulte el", "Due:": "Fecha de entrega:", "Duplicate": "Duplicar", "Duplicating": "Duplicando", @@ -693,9 +727,15 @@ "Edit Membership": "Editar membres\u00eda", "Edit Team": "Editar Equipo", "Edit Thumbnail": "Editar imagen miniatura", + "Edit Title": "Editar t\u00edtulo", "Edit Your Name": "Edite su nombre", "Edit this certificate?": "\u00bfEditar este certificado?", + "Edit your post below.": "Edita tu publicaci\u00f3n a continuaci\u00f3n.", "Editable": "Editable", + "Editing access for: {title}": "Editando acceso para: {title}", + "Editing comment": "Editando comentario", + "Editing post": "Editando publicaci\u00f3n", + "Editing response": "Editando respuesta", "Editing: {title}": "Edici\u00f3n: {title}", "Editor": "Editor", "Education Completed": "Educaci\u00f3n completada", @@ -713,6 +753,7 @@ "Encoding": "Codificaci\u00f3n", "End My Exam": "Finalizar mi examen", "End of transcript. Skip to the start.": "Fin de la transcripci\u00f3n. Saltar al inicio.", + "Endorse": "Validar", "Ends {end}": "Termina {end}", "Engage with posts": "Trabajar con las publicaciones", "Enroll Now": "Incr\u00edbase ahora", @@ -747,6 +788,7 @@ "Error adding learners.": "Error para agregar estudiantes.", "Error adding user": "Error al a\u00f1adir el usuario.", "Error adding/removing users as beta testers.": "Error a\u00f1adiendo o eliminando usuarios de pruebas.", + "Error assigning team memberships": "Error al asignar membres\u00edas de equipo", "Error changing user's permissions.": "Error al cambiar los permisos del usuario.", "Error deleting entrance exam state for student '{student_id}'. Make sure student identifier is correct.": "Error borrando el estado del examen de ingreso para el estudiante '{student_id}'. Aseg\u00farate que el identificador del estudiante es correcto.", "Error deleting student '<%- student_id %>'s state on problem '<%- problem_id %>'. Make sure that the problem and student identifiers are complete and correct.": "Error al borrar el estado del estudiante '<%- student_id %>' para el problema '<%- problem_id %>'. Verifica que el problema y el estudiante est\u00e9n identificados correctamente.", @@ -767,6 +809,7 @@ "Error getting the number of ungraded responses": "Error al obtener el n\u00famero de respuestas no calificadas.", "Error importing course": "Error al importar el curso", "Error listing task history for this student and problem.": "Error listando el historial de tareas para este estudiante y problema.", + "Error posting your message.": "Error al publicar tu mensaje.", "Error removing user": "Error al remover el usuario.", "Error resetting entrance exam attempts for student '{student_id}'. Make sure student identifier is correct.": "Error reiniciando los intentos de examen de ingreso para el estudiante '{student_id}'. Aseg\u00farate que el identificador es correcto.", "Error resetting problem attempts for problem '<%= problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "Error al reiniciar los env\u00edos para el problema '<%= problem_id %>' y estudiante '<%- student_id %>'. Aseg\u00farate de que los identificadores del problema y el estudiante est\u00e9n completos y correctos.", @@ -777,6 +820,7 @@ "Error starting a task to rescore problem '<%- problem_id %>' for student '<%- student_id %>'. Make sure that the the problem and student identifiers are complete and correct.": "Error al iniciar el proceso de re puntuaci\u00f3n del problema '<%- problem_id %>' para el estudiante '<%- student_id %>'. Verifica que el problema y el estudiante est\u00e9n identificados correctamente.", "Error starting a task to rescore problem '<%- problem_id %>'. Make sure that the problem identifier is complete and correct.": "Error al iniciar la tarea para re puntuar el problema '<%- problem_id %>'. Verifica que el problema est\u00e9 identificado correctamente.", "Error starting a task to reset attempts for all students on problem '<%- problem_id %>'. Make sure that the problem identifier is complete and correct.": "Error en el proceso de reinicio de env\u00edos para todos los estudiantes para el problema '<%- problem_id %>'. Verifica que el problema est\u00e9 identificado correctamente.", + "Error when looking up username": "Error al buscar el nombre de usuario", "Error while generating certificates. Please try again.": "Error al generar los certificados. Por favor intenta nuevamente.", "Error while regenerating certificates. Please try again.": "Error al regenerar los certificados. Por favor int\u00e9ntalo nuevamente.", "Error.": "Error.", @@ -824,7 +868,6 @@ "Fill browser": "Ir a pantalla completa", "Filter": "Filtro", "Filter and sort topics": "Filtrar y ordenar los temas", - "Final Grade": "Calificaci\u00f3n Final", "Final Grade Received": "Calificaci\u00f3n final recibida", "Financial Aid": "Ayuda financiera", "Financial Assistance": "Asistencia financiera", @@ -838,7 +881,9 @@ "Find previous": "Encontrar el anterior", "Finish": "Finalizar", "First time here?": "Primera vez aqu\u00ed?", + "Follow": "Seguir", "Follow or unfollow posts": "Seguir o dejar de seguir publicaciones", + "Following": "Siguiendo", "Font Family": "Tipo de fuente", "Font Sizes": "Tama\u00f1o de fuente", "Footer": "Pie de p\u00e1gina", @@ -858,7 +903,6 @@ "Generate": "Generar", "Generate Exception Certificates": "Generar excepciones de certificados", "Generate the user's certificate": "Generar el certificado del usuario", - "Get Credit": "Obtenga cr\u00e9ditos", "Go Back": "Volver Atr\u00e1s", "Go to Dashboard": "Ir al panel de control", "Go to my Dashboard": "Ir a mi Panel De Control", @@ -935,21 +979,23 @@ "ID-Verification is not required for this Professional Education course.": "La verification de ID no se requiere para este curso de Educaci\u00f3n Profesional", "Identity Verification In Progress": "Verificaci\u00f3n de identidad en progreso", "If the course does not have an end date, learners always see their scores when they submit answers to assessments.": "Si el curso no tiene fecha de caducidad, los estudiantes siempre ven sus puntajes cuando env\u00edan las respuestas de las evaluaciones.", + "If the photos you submit are rejected, try moving the computer or camera orientation to change the lighting angle. The most common reason for rejection is inability to read the text on the ID card.": "Si las fotos que env\u00eda son rechazadas, intente mover la computadora o la orientaci\u00f3n de la c\u00e1mara para cambiar el \u00e1ngulo de iluminaci\u00f3n. La raz\u00f3n m\u00e1s com\u00fan para el rechazo es la imposibilidad de leer el texto en la tarjeta de identificaci\u00f3n.", "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "Si la subsecci\u00f3n no tiene fecha de caducidad, los estudiantes siempre pueden ver sus puntajes cuando env\u00edan las respuestas a la evaluaci\u00f3n.", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "Si la unidad fue publicada anteriormente y liberada a los estudiantes, cualquier cambio que haya realizado cuando estaba oculta ser\u00e1 ahora visible para los estudiantes.", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "Si la unidad fue publicada anteriormente y liberada a los estudiantes, cualquier cambio realizado cuando estaba oculta ser\u00e1 ahora visible para los estudiantes. \u00bfDeseas proceder?", - "If you are unable to access your account contact us via email using {email}.": "Si no puedes acceder a tu cuenta, cont\u00e1ctanos por correo electr\u00f3nico a {email}.", "If you do not yet have an account, use the button below to register.": "Si todav\u00eda no tienes una cuenta, puedes utilizar el bot\u00f3n abajo para registrarte ", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "Si no verifica su identidad ahora, de todas formas podr\u00e1 explorar el curso desde su Panel de Control. Recibir\u00e1 recordatorios peri\u00f3dicos de %(platformName)s para realizar la verificaci\u00f3n de identidad.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "Si no verifica su identidad ahora, de todas formas podr\u00e1 explorar el curso desde su Panel de Control. Recibir\u00e1 recordatorios peri\u00f3dicos de {platformName} para realizar la verificaci\u00f3n de identidad.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "Si abandona esta p\u00e1gina sin guardar o enviar su respuesta, perder\u00e1 todo el trabajo realizado en la respuesta.", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "Si abandona esta p\u00e1gina sin enviar su trabajo, perder\u00e1 todos los cambios realizados.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "Si abandona esta p\u00e1gina sin enviar su auto evaluaci\u00f3n, perder\u00e1 todos los cambios realizados.", "If you leave this page without submitting your staff assessment, you will lose any work you have done.": "Si abandona esta p\u00e1gina sin enviar su evaluaci\u00f3n, se perder\u00e1n todos los cambios realizados.", + "If you leave, you can no longer post in this team's discussions.Your place will be available to another learner.": "Si deja el equipo, no puede volver a publicar discusiones dentro del equipo. Su lugar en el quipo estar\u00e1 disponible para otro estudiante.", "If you make significant changes, make sure you notify members of the team before making these changes.": "Si haces cambios significativos, aseg\u00farate de avisarle a los miembros del equipos antes de realizar estos cambios.", "If you make this %(xblockType)s visible to learners, learners will be able to see its content after the release date has passed and you have published the unit. Only units that are explicitly hidden from learners will remain hidden after you clear this option for the %(xblockType)s.": "Si hace este %(xblockType)s visible a los estudiantes, podr\u00e1n ver su contenido a partir de la fecha de liberaci\u00f3n siempre que haya publicado la unidad. S\u00f3lo las unidades que est\u00e1n ocultos expl\u00edcitamente permanecer\u00e1n ocultas despu\u00e9s de quitar esta opci\u00f3n para %(xblockType)s.", + "If you proceed, you will be unable to use this account to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "Si procedes, no podr\u00e1s usarla ni tomar cursos en la app {platformName}, {siteName}, ni en cualquier otro sitio de {platformName}.", "If you remove this transcript, the transcript will not be available for any components that use this video.": "Si elimina esta transcripci\u00f3n, la transcripci\u00f3n no estar\u00e1 disponible para ning\u00fan componente que use este v\u00eddeo.", "If you remove this transcript, the transcript will not be available for this component.": "Si elimina esta transcripci\u00f3n, la transcripci\u00f3n no estar\u00e1 disponible para este componente.", + "If you require assistance with taking either photo for submission, contact %(platformName)s support for additional suggestions.": "Si requiere asistencia tomando cualquiera de las fotos para enviarlas, contacte soporte%(platformName)s para sugerencias adicionales.", "If you select an option other than \"%(hide_label)s\", published units in this subsection become available to learners unless they are explicitly hidden.": "Si selecciona esta opci\u00f3n distinta a \"%(hide_label)s\", \nlas unidades publicadas en este subsecci\u00f3n pasar\u00e1n a estar disponible para los estudiantes a menos que est\u00e1n expl\u00edcitamente ocultas.", "If you still wish to continue and delete your account, please enter your account password:": "Si deseas continuar y eliminar tu cuenta, por favor introduce la contrase\u00f1a de tu cuenta:", "If you use the Advanced Editor, this problem will be converted to XML and you will not be able to return to the Simple Editor Interface.\n\nProceed to the Advanced Editor and convert this problem to XML?": "Si utiliza el Editor Avanzado, este problema ser\u00e1 convertido a formato XML y no podr\u00e1 volver a la pantalla del Editor Simple.\n\n\u00bfPasar al Editor avanzado y convertir este problema al formato XML?", @@ -970,6 +1016,7 @@ "Incorrect url format.": "Formato incorrecto de URL.", "Increase indent": "Aumentar Sangr\u00eda", "Individual Exceptions": "Excepciones individuales", + "Individual file size must be {max_files_mb}MB or less.": "El tama\u00f1o del archivo debe ser de aproximadamente {max_files_mb}MB o menos.", "Inheriting Student Visibility": "Heredando la Visibilidad a estudiantes.", "Inline": "Dentro de la l\u00ednea", "Insert": "Insertar", @@ -1025,6 +1072,7 @@ "Last Activity %(date)s": "\u00daltima Actividad %(date)s", "Last Edited:": "\u00daltima modificaci\u00f3n:", "Last Updated": "\u00daltima Actualizaci\u00f3n", + "Last activity {date}": "\u00daltima actividad {date}", "Last modified by": "\u00daltima modificaci\u00f3n por", "Last published %(last_published_date)s by %(publish_username)s": "Publicado por \u00faltima vez el %(last_published_date)s por %(publish_username)s", "Last published {lastPublishedStart}{publishedOn}{lastPublishedEnd} by {publishedByStart}{publishedBy}{publishedByEnd}": "Last published {lastPublishedStart}{publishedOn}{lastPublishedEnd} por {publishedByStart}{publishedBy}{publishedByEnd}", @@ -1068,6 +1116,7 @@ "Live view of webcam": "Se\u00f1al en vivo de la webcam", "Load Another File": "Cargar otro archivo", "Load all responses": "Cargando todas las respuestas", + "Load more": "Cargar m\u00e1s", "Load next {numResponses} responses": "Cargar las siguientes {numResponses} respuestas", "Load next {num_items} result": [ "Cargar el siguiente {num_items} resultado", @@ -1096,10 +1145,12 @@ "Make sure your face is well-lit": "Asegurese de que su rostro est\u00e9 bien iluminado", "Make this subsection available as a prerequisite to other content": "Deje disponible esta secci\u00f3n como prerrequisito de otro contenido", "Making Visible to Students": "Haciendo visible a los estudiantes", + "Manage": "Administrar", "Manage Learners": "Manejar Estudiantes", "Manual": "Manual", "March": "Marzo", "Mark Exam As Completed": "Marcar el examen como completado", + "Mark as Answer": "Marcar como respuesta", "Mark enrollment code as unused": "Marcar c\u00f3digo de inscripci\u00f3n como no utilizado", "Markdown Editing Help": "Ayuda para la edici\u00f3n con marcadores Markdown", "Masters": "Maestr\u00edas", @@ -1111,6 +1162,8 @@ "Membership": "Afiliaci\u00f3n", "Merge cells": "Fusionar celdas", "Message:": "Mensaje:", + "MicroBachelors": "MicroBachelors", + "MicroMasters": "MicroMasters", "Middle": "Educaci\u00f3n media", "Midnight": "Medianoche", "Minimum Completion:": "Valor m\u00ednimo a completar:", @@ -1123,11 +1176,13 @@ "Move cancelled. \"{sourceDisplayName}\" has been moved back to its original location.": "Movimiento cancelado. \"{sourceDisplayName}\" ha sido movido a su ubicaci\u00f3n original.", "Move: {displayName}": "Mover: {displayName}", "Moving": "Moviendo", + "Multiple teams returned for course": "Varios equipos encontrados para el curso", "Must be a Staff User to Perform this request.": "Hay que ser un usuario del equipo para cumplir esta petici\u00f3n.", "Must complete verification checkpoint": "Debe completar el punto de verificaci\u00f3n", "Mute": "Silenciar", "Muted": "En silencio", "My Orders": "Mis Pedidos", + "My Teams": "Mis equipos", "N/A": "N/D", "Name": "Nombre", "Name ": "Nombre", @@ -1212,11 +1267,16 @@ "Ok": "Aceptar", "Onboarding": "Integraci\u00f3n", "Onboarding Exam": "Examen de Integraci\u00f3n", + "Once in position, use the Take Photo button {icon} to capture your ID": "Una vez en posici\u00f3n, use el bot\u00f3n Tomar foto {icon} para captura su ID", + "Once in position, use the Take Photo button {icon} to capture your photo": "Una vez en posici\u00f3n, use el bot\u00f3n Tomar foto {icon} para captura su foto", "Once you complete one of the program requirements you have a program record. This record is marked complete once you meet all program requirements. A program record can be used to continue your learning journey and demonstrate your learning to others.": "Una vez complete uno de los requisitos de programa, usted tendr\u00e1 un registro de programa. Este registro es marcado como completo una vez cumpla con todos los requisitos del programa. Un registro del programa puede ser usado para continuar su registro diario de aprendizaje y demostrar su aprendizaje a otros.", + "Once your account is deleted, you cannot use it to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "Una vez tu cuenta es borrada, no podr\u00e1s usarla ni tomar cursos en la app {platformName}, {siteName}, ni en cualquier otro sitio de {platformName}.", "One or more rescheduling tasks failed.": "Una o m\u00e1s tareas de re-programaci\u00f3n fall\u00f3.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "S\u00f3lo pueden cargarse archivos de tipo <%= fileTypes %>. Por favor selecciona un archivo que termine en <%= fileExtensions %> para ser cargado.", + "Only ": "Solo", + "Only <%- fileTypes %> files can be uploaded. Please select a file ending in <%- (fileExtensions) %> to upload.": "Solo archivos <%- fileTypes %> pueden ser cargados. Por favor seleccione un archivo que finalice en <%- (fileExtensions) %> para cargarlo.", "Only properly formatted .csv files will be accepted.": "Solo archivos .csv correctamente formateados pueden ser utilizados.", "Only the parent course staff of a CCX can create content groups.": "S\u00f3lo el personal del curso principal de un CCX puede crear grupos de contenido.", + "Open": "Abrir", "Open Calculator": "Abrir Calculadora", "Open language menu": "Abrir men\u00fa de idioma", "Open the certificate you earned for the %(title)s program.": "Abrir el certificado que ganaste en el programa %(title)s.", @@ -1235,6 +1295,7 @@ "Organization ": "Organizaci\u00f3n", "Organization Name": "Nombre de la organizaci\u00f3n", "Organization of the signatory": "Organizaci\u00f3n del signatario", + "Organization:": "Organizaci\u00f3n:", "Other": "Otro", "Overall Score": "Puntaje general", "PDF Chapters": "Cap\u00edtulos de PDF", @@ -1267,6 +1328,8 @@ "Photo of %(fullName)s's ID": "Foto de la identificaci\u00f3n de %(fullName)s", "Photo requirements:": "Requerimientos para las fotos:", "Photos don't meet the requirements?": "\u00bfSus fotos no cumplen los requerimientos?", + "Pin": "Marcar", + "Pinned": "Marcado", "Placeholder": "Marcador de posici\u00f3n", "Play": "Reproducir", "Play video": "Reproducir video", @@ -1298,6 +1361,7 @@ "Please enter your log-in or recovery email address below and we will send you an email with instructions.": "Por favor ingrese su direcci\u00f3n de correo electr\u00f3nico de inicio de sesi\u00f3n o de recuperaci\u00f3n a continuaci\u00f3n , y le enviaremos un correo electr\u00f3nico con instrucciones.", "Please fix the following errors:": "Por favor corrija los siguientes errores:", "Please follow the instructions here to upload a file elsewhere and link to it: {maxFileSizeRedirectUrl}": "Por favor siga las instrucciones aqui para cargar un archivo en otro parte y enlazelo: {maxFileSizeRedirectUrl}", + "Please note: Deletion of your account and personal data is permanent and cannot be undone. {platformName} will not be able to recover your account or the data that is deleted.": "Cuidado: la eliminaci\u00f3n de su cuenta y datos personales es permanente e irreversible. {platformName} no podr\u00e1 recuperar ni su cuenta ni los datos eliminados.", "Please print this page for your records; it serves as your receipt. You will also receive an email with the same information.": "Por favor imprima esta p\u00e1gina para sus registros; la misma es v\u00e1lida como su recibo. Tambi\u00e9n recibir\u00e1 un correo electr\u00f3nico con la esta informaci\u00f3n.", "Please provide a description of the link destination.": "Por favor, provee una descripci\u00f3n de la destinaci\u00f3n del v\u00ednculo.", "Please provide a valid URL.": "Por favor, provee un URL v\u00e1lido.", @@ -1310,6 +1374,7 @@ "Please wait": "Por favor espere", "Plugins": "Plug-ins", "Post": "Publicaci\u00f3n", + "Post type": "Tipo de publicaci\u00f3n", "Poster": "Poster", "Practice Exam Completed": "Examen de pr\u00e1ctica completado", "Practice Exam Failed": "Examen de pr\u00e1ctica no aprobado", @@ -1369,8 +1434,11 @@ "Published and Live": "Publicado y en vivo", "Publishing": "Publicando", "Publishing Status": "Estado de publicaci\u00f3n", + "Question": "Pregunta", + "Questions raise issues that need answers. Discussions share ideas and start conversations. (Required)": "Utiliza Pregunta para plantear temas que necesitan respuestas. Utiliza Discusi\u00f3n para compartir tus ideas y comenzar conversaciones. (Requerido)", "Queued": "En cola", "REMAINING COURSES": "CURSOS RESTANTES", + "Re-run Course": "Relanzar Curso", "Read More": "Leer mas", "Read more": "Leer m\u00e1s", "Ready To Start": "Listo para comenzar", @@ -1390,6 +1458,7 @@ "Regenerate the user's certificate": "Regenerar el certificado del usuario", "Register with Institution/Campus Credentials": "Registrarse con las credenciales de la instituci\u00f3n o el Campus", "Rejected": "Rechazado", + "Related to: %(courseware_title_linked)s": "Relacionado con: %(courseware_title_linked)s", "Release Date and Time": "Fecha y hora de liberaci\u00f3n", "Release Date:": "Fecha de liberaci\u00f3n:", "Release Status:": "Estado de liberaci\u00f3n:", @@ -1418,7 +1487,10 @@ "Replace all": "Reemplazar todo", "Replace with": "Reemplazar con", "Reply to Annotation": "Responder a la anotaci\u00f3n", + "Report": "Denunciar", + "Report abuse": "Denunciar un abuso", "Report abuse, topics, and responses": "Denunciar abusos, temas, y respuestas", + "Reported": "Denunciado", "Requester": "Solicitante", "Required": "Requerido", "Required field.": "Campo requerido.", @@ -1438,6 +1510,7 @@ "Return and add email address": "Volver y introduir un correo electr\u00f3nico. ", "Return to Export": "Regresar a exportar", "Return to Your Dashboard": "Volver al panel principal", + "Return to all posts": "Volver a todas las publicaciones", "Return to team listing": "Volver a la lista del equipo", "Review Policy Exception": "Revisar excepci\u00f3n a la pol\u00edtica", "Review Rules": "Revisar las reglas", @@ -1473,6 +1546,10 @@ "Section Highlights": "Destacados de la secci\u00f3n", "Section Visibility": "Visibilidad de la secci\u00f3n", "Sections": "Secciones", + "Security": "Seguridad", + "See all teams you belong to and all public teams in your course, organized by topic.": "Vea todos los equipos a los que pertenece y todos los equipos p\u00fablicos en su curso, organizados por tema.", + "See all teams you belong to and all public teams in your course, organized by topic. Join an open public team to collaborate with other learners who are interested in the same topic as you are.": "Vea todos los equipos a los que pertenece y todos los equipos p\u00fablicos en su curso, organizados por tema. \u00danase a un equipo p\u00fablico abierto para colaborar con otros estudiantes interesados en el mismo tema que usted.", + "See all teams you belong to.": "Ver todos los equipos a los que usted pertenece.", "Select": "Seleccionar", "Select Session": "Seleccione la sesi\u00f3n.", "Select a Content Group": "seleccionar contenido de grupo", @@ -1518,6 +1595,10 @@ "Show": "Mostrar", "Show All": "Mostrar todo", "Show Annotations": "Mostrar anotaciones", + "Show Comment (%(num_comments)s)": [ + "Mostrar comentario (%(num_comments)s)", + "Mostrar comentarios (%(num_comments)s)" + ], "Show Deprecated Settings": "Mostrar configuraciones descartadas", "Show Discussion": "Mostrar Discusi\u00f3n", "Show Less": "Mostrar menos", @@ -1686,9 +1767,8 @@ "Textbook Name": "Nombre", "Textbook information": "Informaci\u00f3n del libro de texto", "Textbook name is required": "Se requiere el nombre del libro de texto", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Gracias %(full_name)s! Hemos recibido su pago para el curso %(course_name)s.", "Thank you for setting your course goal to {goal}!": "\u00a1 Gracias por establecer su objetivo para este curso en {goal}!", - "Thank you for submitting a request! We will contact you within 24 hours.": "Gracias por mandarnos un mensaje. Te contactaremos dentro de las siguientes 24 horas.", + "Thank you for submitting a request! We appreciate your patience while we work to review your request.": "\u00a1Gracias por su env\u00edo! Agradecemos su paciencia mientras trabajamos para revisar su solicitud.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Gracias por enviar tu aplicaci\u00f3n de financiamiento para {course_name}!. Espera una respuesta de 2-4 dias h\u00e1biles.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Gracias por enviar sus fotos. Las revisaremos pronto. Ahora puede registrarse para cualquier curso de %(platformName)s que ofrezca Certficados Verificados. La verificaci\u00f3n es v\u00e1lida por un a\u00f1o. Despu\u00e9s de este periodo, deber\u00e1 volver a enviar fotograf\u00edas para una nueva verificaci\u00f3n.", "Thank you! We have received your payment for {courseName}.": "\u00a1Gracias! Hemos recibido tu pago para {courseName}.", @@ -1700,8 +1780,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "El certificado para este estudiante ha sido revalidado y el sistema est\u00e1 computando nuevamente la calificaci\u00f3n.", "The cohort cannot be added": "El cohorte no puede ser a\u00f1adido", "The cohort cannot be saved": "El cohorte debe ser grabado", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "La longitud combinada de los campos para la organizaci\u00f3n y c\u00f3digo de la librer\u00eda no puede superar los <%=limit%> caracteres.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "La longitud combinada de los campos para la organizaci\u00f3n, n\u00famero de curso y grupo no puede superar los <%=limit%> caracteres.", "The country or region where you live.": "El pa\u00eds o la regi\u00f3n donde t\u00fa vives. ", "The country that team members primarily identify with.": "El pa\u00eds que identifica de forma primaria a los miembros del equipo.", "The course end date must be later than the course start date.": "La fecha de finalizaci\u00f3n del curso debe ser posterior a la fecha de inicio.", @@ -1717,7 +1795,7 @@ "The following email addresses and/or usernames are invalid:": "El correo electr\u00f3nico y/o el nombre de usuario no son v\u00e1lidos:", "The following errors were generated:": "Se generaron los siguientes errores:", "The following file types are not allowed: ": "Los siguientes tipos de archivos son soportados:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "La siguiente informaci\u00f3n ya es parte de su perfil en {platform} . La hemos incluido aqu\u00ed para su aplicaci\u00f3n.", + "The following information is already a part of your {platform} profile. We've included it here for your application.": "La siguiente informaci\u00f3n ya es parte de su perfil en {platform} . La hemos incluido aqu\u00ed para su aplicaci\u00f3n", "The following message will be displayed at the bottom of the courseware pages within your course:": "El siguiente mensaje ser\u00e1 mostrado al final de las p\u00e1ginas de los cursos. ", "The following options are available for the {license_name} license.": "Las siguientes opciones est\u00e1n disponibles para {license_name} licencia", "The following users are no longer enrolled in the course:": "Los siguientes usuarios ya no est\u00e1n inscritos en el curso:", @@ -1729,7 +1807,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "El porcentaje m\u00ednimo a completar debe ser un n\u00famero entero entre 0 y 100. ", "The minimum grade for course credit is not set.": "La calificaci\u00f3n m\u00ednima para obtener cr\u00e9ditos por el curso no est\u00e1 definida.", "The minimum score percentage must be a whole number between 0 and 100.": "La nota m\u00ednima para aprobar debe ser un n\u00famero entero entre 0 y 100.", - "The more you tell us, the more quickly and helpfully we can respond!": "Cuanto m\u00e1s nos digas, antes y mejor podremos ayudarte.", "The name of this signatory as it should appear on certificates.": "El nombre de este signatario como debe aparecer en los certificados.", "The name that identifies you on {platform_name}. You cannot change your username.": "El nombre que lo identifica en {platform_name}. No puede cambiar el nombre de usuario.", "The name that is used for ID verification and that appears on your certificates.": "El nombre que es usado para la verificaci\u00f3n de identidad y aparece en sus certificados.", @@ -1737,7 +1814,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "El n\u00famero de subdivisiones del curso que contiene problemas de este tipo de asignaci\u00f3n.", "The organization that this signatory belongs to, as it should appear on certificates.": "La organizaci\u00f3n a la que pertenece el firmante, como debe aparecer en los certificados. ", "The page \"{route}\" could not be found.": "La p\u00e1gina \"{route}\" no pudo ser encontrada.", - "The photo of your face matches the photo on your ID.": "La foto de su documento coincide con la foto de su cara.", "The post you selected has been deleted.": "La publicaci\u00f3n que seleccion\u00f3 ha sido borrada.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "La versi\u00f3n publicada, {published}, fue restablecida a la versi\u00f3n borrador, {draft}.", "The raw error message is:": "El error crudo es:", @@ -1814,16 +1890,19 @@ "This feature is currently in testing. Course teams can enter highlights, but learners will not receive email messages.": "Esta caracter\u00edstica est\u00e1 en prueba actualmente. Equipos del curso pueden ingresar destacados, pero los estudiantes no recibir\u00e1n mensajes de correo electr\u00f3nico.", "This feedback could not be submitted.": "Este comentario no pudo ser enviado.", "This file type is not supported. Supported file type is {supportedFileFormat}.": "Este tipo de archivo no es soportado. El tipo de archivo soportado es {supportedFileFormat}.", + "This grade will be applied to all members of the team. Do you want to continue?": "Esta calificaci\u00f3n se aplicar\u00e1 a todos los miembros del equipo. \u00bfDesea continuar?", "This group controls access to:": "Este grupo controla el acceso a:", "This group no longer exists. Choose another group or do not restrict access to this unit.": "Este grupo ya no existe. Seleccione otro grupo o no restrinja el acceso a esta unidad.", "This image file type is not supported. Supported file types are {supportedFileFormats}.": "El tipo de archivo no es soportado. Los tipos de archivo soportados son {supportedFileFormats}.", "This image is for decorative purposes only and does not require a description.": "Esta imagen es decorativa solamente y no requiere descripci\u00f3n.", + "This includes access to {siteName} from your employer\u2019s or university\u2019s system{additionalSiteSpecificDeletionText}.": "Esto incluye acceso a {siteName} desde el sistema de tu empleador o universidad{additionalSiteSpecificDeletionText}.", "This is the Description of the Group Configuration": "Esta es la descripci\u00f3n de configuraci\u00f3n del grupo", "This is the Name of the Group Configuration": "Este es el nombre de la Configuraci\u00f3n del Grupo", "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "Esta es la lista de %s disponibles. Puede elegir algunos seleccion\u00e1ndolos en la caja inferior y luego haciendo clic en la flecha \"Elegir\" que hay entre las dos cajas.", "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "Esta es la lista de los %s elegidos. Puede elmininar algunos seleccion\u00e1ndolos en la caja inferior y luego haciendo click en la flecha \"Eliminar\" que hay entre las dos cajas.", "This is the name of the group": "Este es el nombre del grupo", "This learner is currently sharing a limited profile.": "Este usuario est\u00e1 compartiendo un perfil limitado.", + "This learner will be removed from the team,allowing another learner to take the available spot.": "Este estudiante ser\u00e1 removido del equipo, permitiendo a otro estudiante tomar su lugar.", "This link will open in a modal window": "Este enlace se abrir\u00e1 en una ventana modal", "This link will open in a new browser window/tab": "Este enlace se abrir\u00e1 en una nueva ventana o pesta\u00f1a del navegador", "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.": "Esto puede estar sucediendo debido a un error con nuestros servidores o con tu conexi\u00f3n a Internet. Intenta refrescar la p\u00e1gina o verifica tu acceso a Internet.", @@ -1834,6 +1913,10 @@ "This post could not be reopened. Refresh the page and try again.": "No se pudo abrir esta publicaci\u00f3n de nuevo. Recarga la p\u00e1gina e intenta nuevamente.", "This post could not be unflagged for abuse. Refresh the page and try again.": "No se pudo desmarcar esta publicaci\u00f3n como abusiva. Recarga la p\u00e1gina e intenta nuevamente.", "This post could not be unpinned. Refresh the page and try again.": "No se pudo desmarcar esta publicaci\u00f3n. Recarga la p\u00e1gina e intente nuevamente.", + "This post is visible only to %(group_name)s.": "Este post es visible solo para %(group_name)s.", + "This post is visible to everyone.": "Esta publicaci\u00f3n es visible para todos.", + "This post will be visible only to %(group_name)s.": "Esta publicaci\u00f3n ser\u00e1 visible solo para %(group_name)s.", + "This post will be visible to everyone.": "Esta publicaci\u00f3n ser\u00e1 visible para todos.", "This problem could not be saved.": "Este problema no pudo ser guardado.", "This problem has already been released. Any changes will apply only to future assessments.": "Este problema ya ha sido liberado. Cualquier cambio en el mismo se aplicar\u00e1 solo a los env\u00edo futuros.", "This problem has been reset.": "Este problema ha sido restablecido.", @@ -1850,6 +1933,7 @@ "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.": "Estos nombres para los tipos de asignaciones (por ejemplo, Tareas o Examen trimestral) aparecen al lado de las asignaciones en la p\u00e1gina de Progreso del estudiante.", "This team does not have any members.": "Este equipo no tiene todav\u00eda ning\u00fan miembro.", "This team is full.": "Este equipo est\u00e1 lleno.", + "This thread is closed.": "Este hilo est\u00e1 cerrado.", "This unit has validation issues.": "Esta unidad tiene errores de validaci\u00f3n", "This vote could not be processed. Refresh the page and try again.": "Este voto no se pudo procesar. Recarga la p\u00e1gina e intenta nuevamente.", "This {parentCategory} has no {childCategory}": "Esta {parentCategory} no tiene {childCategory}", @@ -1876,7 +1960,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "Para asegurar que todos los estudiantes puedan ver el video, recomendamos suministrar tanto una versi\u00f3n .mp4 como una versi\u00f3n .webm del recurso. Haga clic a continuaci\u00f3n para a\u00f1adir la URL de una nueva versi\u00f3n. Estas URLs no pueden ser de Youtube. El primer video listado que sea compatible con la terminal del usuario ser\u00e1 el que se reproducir\u00e1.", "To complete the program, you must earn a verified certificate for each course.": "Para completar el programa, deber\u00e1s ganar un certificado verificado en cada curso.", "To continue learning with this account, sign in below.": "Para continuar aprendiendo con esta cuenta, reg\u00edstrese a continuaci\u00f3n.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "Para finalizar un cr\u00e9dito de curso, %(display_name)s requieres %(platform_name)s profesores para postular una solicitud de cr\u00e9dito.", "To invalidate a certificate for a particular learner, add the username or email address below.": "Para invalidar el certificado de un estudiante particular, a\u00f1ada el nombre de usuario o correo electr\u00f3nico a continuaci\u00f3n.", "To pass this exam, you must complete the problems in the time allowed.": "Para aprobar este examen, hay que completar los problemas durante el tiempo permitido.", "To receive a certificate, you must also verify your identity before {date}.": "Para recibir un certificado, tambi\u00e9n debe verificar su identidad antes del {date}.", @@ -1885,6 +1968,7 @@ "To review learner cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on the {link_start}Data Download{link_end} page.": "Para revisar asiginaciones de cohortes de los estudiantes o ver los resultados del archivo CVS que est\u00e1 subiendo, descargue la informaci\u00f3n del perfil del curso o los resultados del cohorte en la p\u00e1gina {link_start}Data Download{link_end}.", "To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.": "Para compartir tu certificado en Mozilla Backpack, debes tener una cuenta de Backpack primero. Completa los siguientes pasos para agregar tu certificado a Backpack.", "To take a successful photo, make sure that:": "Para tomar la foto correctamente, aseg\u00farese de: ", + "To take the photo of your face, click on the camera button {icon}. If you need to try again, click 'Retake Photo'.": "Para tomar la foto de su cara, haga clic en el bot\u00f3n de la c\u00e1mara {icon}. Si necesita volver a intentarlo, haga clic en 'Retomar foto'.", "To verify your identity, you need a webcam and a government-issued photo ID.": "Para verificar su identidad, necesitar\u00e1 una c\u00e1mara web, y un documento de identificaci\u00f3n oficial con foto.", "Today": "Hoy", "Toggle Account Password (Usable/Unusable)": "Cambiar Contrase\u00f1a de Cuenta (Usable/No-usable)", @@ -1893,6 +1977,7 @@ "Tools": "Herramientas", "Top": "Superior", "Topic": "Tema", + "Topic area": "\u00c1rea tem\u00e1tica", "Topics": "Temas", "Total": "Total", "Total Number": "N\u00famero total", @@ -1924,7 +2009,9 @@ "Undo Changes": "Deshacer Cambios", "Undo move": "Deshacer movimiento", "Undo moving": "Deshacer movimiento", + "Unendorse": "Invalidar", "Unexpected server error.": "Ocurri\u00f3 un error inesperado en el servidor.", + "Unfollow": "Dejar de seguir", "Ungraded": "No calificado", "Ungraded Practice Exam": "Examen de pr\u00e1ctica no calificado", "Unit": "Unidad", @@ -1937,14 +2024,20 @@ "Unlink This Account": "Desvincular esta cuenta", "Unlink your {accountName} account": "Desvincular tu cuenta de {accountName} ", "Unlinking": "Desvinculando", + "Unmark as Answer": "Desmarcar como respuesta", "Unmute": "Restablecer sonido", "Unnamed Option": "Opci\u00f3n sin nombre", + "Unpin": "Desmarcar", "Unpublished changes to content that will release in the future": "Cambios no publicados del contenido que ser\u00e1 liberado en el futuro", "Unpublished changes to live content": "Cambios no publicados en el contenido en vivo", "Unpublished units will not be released": "Las unidades no publicadas no ser\u00e1n liberadas", + "Unreport": "Dejar de denunciar", "Unscheduled": "No programado", "Update": "Actualizar", "Update Settings": "Actualizar ajustes", + "Update comment": "Actualizar comentario", + "Update post": "Actualiza publicaci\u00f3n", + "Update response": "Actualiza respuesta", "Update team.": "Actualizar el equipo.", "Updating Tags": "Actualizando Etiquetas", "Updating with latest library content": "Actualizando con el m\u00e1s reciente contenido de la librer\u00eda", @@ -1955,6 +2048,7 @@ "Upload": "Subir", "Upload File": "Subir archivo", "Upload File and Assign Students": "Cargar archivo y asignar estudiantes", + "Upload Memberships": "Subir membres\u00edas", "Upload New .srt Transcript": "Cargar nuevo archivo de transcripci\u00f3n .srt", "Upload New File": "Subir nuevo archivo", "Upload New Transcript": "Cargar nueva transcripci\u00f3n", @@ -1964,7 +2058,7 @@ "Upload Videos": "Cargar Videos", "Upload a CSV file": "Cargar un archivo CSV", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "Cargue un archivo separado por comas (.csv) que contenga los nombres de usuario o correos electr\u00f3nicos de los estudiantes a los que se le han otorgado excepciones. Incluya el nombre de usuario o correo electr\u00f3nico en el primer campo. Puede incluir adem\u00e1s en un segundo campo, una nota opcional describiendo la raz\u00f3n para otorgar la excepci\u00f3n.", - "Upload a new PDF to \u201c<%= name %>\u201d": "Subir un nuevo PDF a \u201c<%= name %>\u201d", + "Upload a new PDF to \u201c<%- name %>\u201d": "cargar un nuevo PDF a \u201c<%- name %>\u201d", "Upload an image": "Subir una imagen", "Upload an image or capture one with your web or phone camera.": "Subir una imagen o captura con tu camara web o del tel\u00e9fono", "Upload completed": "Carga terminada", @@ -1994,8 +2088,10 @@ "Use cohorts as the basis for dividing discussions. All learners, regardless of cohort, see the same discussion topics, but within divided topics, only members of the same cohort see and respond to each others\u2019 posts. ": "Usar cohortes como base de dividir las discusiones. Todos los estudiantes, sin considerar su cohorte, ven los mismos temas de discusi\u00f3n, pero dentro de temas divididos, los estudiantes solamente ven y responden a las publicaciones de otros estudiantes en el mismo cohorte como ellos.", "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "Usar rutas de inscripci\u00f3n como base de dividir las discusiones. Todos los estudiantes, sin considerar su ruta de inscripci\u00f3n, ven los mismos temas de discusi\u00f3n, pero dentro de temas divididos, los estudiantes solamente ven y responden a las publicaciones de otros estudiantes en la misma ruta de inscripci\u00f3n como ellos.", "Use my institution/campus credentials": "Usar mis credenciales de la instituci\u00f3n o el Campus", + "Use my university info": "Usar informaci\u00f3n de mi universidad", "Use the All Topics menu to find specific topics.": "Use el men\u00fa de todos los temas para encontrar temas espec\u00edficos.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Use su c\u00e1mara web para tomar una fotograf\u00eda de su documento de identidad. Usaremos esta foto para verificarla contra la fotograf\u00eda de su cara y el nombre de su cuenta.", + "Use the Retake Photo button if you are not pleased with your photo": "Use el bot\u00f3n Retomar foto si no est\u00e1 satisfecho con su foto", + "Use your webcam to take a photo of your ID.": "Use su c\u00e1mara web para tomar una fotograf\u00eda de su documento de identificaci\u00f3n.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Use su c\u00e1mara web para tomar una fotograf\u00eda de su cara. Usaremos esta foto para verificarla contra la fotograf\u00eda de su documento de identificaci\u00f3n.", "Used": "Utilizado", "Used in {count} location": [ @@ -2003,6 +2099,7 @@ "Usado en {count} ubicaciones" ], "User Email": "Correo electr\u00f3nico del usuario", + "User lookup failed": "Fall\u00f3 b\u00fasqueda del usuario", "Username": "Nombre de usuario", "Username or email address": "Nombre de usuario o correo electr\u00f3nico", "Users must create and activate their account before they can be promoted to beta tester.": "Los usuarios deben crear y activar su cuenta antes de que puedan ser promovidos a usuarios de prueba.", @@ -2019,7 +2116,6 @@ "Verified Certificate upgrade": "Optar por el Certificado Verificado", "Verified Status": "Verificaci\u00f3n", "Verified mode price": "Precio del modo verificado", - "Verify Now": "Verificar ahora", "Version": "Versi\u00f3n", "Vertical space": "Espacio vertical", "Very loud": "Muy alto", @@ -2040,32 +2136,40 @@ "View Archived Course": "Ver curso archivado", "View Cohort": "Ver Cohorte", "View Course": "Ver curso", + "View Current Team Memberships": "Ver las membres\u00edas actuales del equipo", "View Live": "Ver en vivo", "View Program Record": "Ver registros del programa", + "View Teams in the {topic_name} Topic": "Ver equipos en el tema {topic_name}", "View all errors": "Ver todos los errores", "View child items": "Ver items hijos", + "View discussion": "Ver discusi\u00f3n", "View my exam": "Ver mi examen", + "View {span_start} {team_name} {span_end}": "Ver {span_start} {team_name} {span_end}", "Viewing %s course": [ "Mostrando %s curso", "Mostrando %s cursos" ], "Visibility": "Visibilidad", + "Visible to": "Visible para", "Visible to Staff Only": "Visible solo para el equipo del curso", "Visual aids": "Ayudas visuales", "Volume": "Volumen", "Vote for good posts and responses": "Votar por las mejores publicaciones y respuestas", + "Vote for this post,": "Votar esta publicaci\u00f3n", "Waiting": "Esperando", "Want to confirm your identity later?": "\u00bfDesea confirmar su identidad despu\u00e9s?", - "Warning": "Atenci\u00f3n:", + "Warning": "Advertencia", "Warnings": "Advertencias", "We ask you to activate your account to ensure it is really you creating the account and to prevent fraud.": "Necesitamos que active su cuenta para asegurarnos que es usted realmente el que est\u00e1 creando la cuenta y para prevenir fraude.", "We couldn't create your account.": "No pudimos crear tu cuenta.", "We couldn't find any results for \"%s\".": "No se ha encontrado ninguna coincidencia para \"%s\".", "We couldn't sign you in.": "No se ha podido iniciar tu sesi\u00f3n.", "We have encountered an error. Refresh your browser and then try again.": "Hemos detectado un error. Por favor recarga la p\u00e1gina en el navegador e intenta nuevamente.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Hemos recibido la informaci\u00f3n enviada y estamos verificando su identidad. Recibir un mensaje en su Panel principal cuando el proceso de verificaci\u00f3n est\u00e9 completado (usualmente entre 1-2 d\u00edas). Durante este tiempo, igualmente tendr\u00e1 acceso a todo el contenido de su curso.", + "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days). In the meantime, you can still access all available course content.": "Hemos recibido su informaci\u00f3n y estamos verificando su identidad. Ver\u00e1 un mensaje en su tablero cuando se complete el proceso de verificaci\u00f3n (generalmente dentro de 5-7 d\u00edas). Mientras tanto, a\u00fan puede acceder a todo el contenido del curso disponible.", "We just need a little more information before you start learning with %(platformName)s.": "Necesitamos un poco mas de informaci\u00f3n antes de que comiences a aprender con %(platformName)s.", + "We securely encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Ciframos su foto de forma segura y la enviamos a nuestro servicio de autorizaci\u00f3n para su revisi\u00f3n. Su foto e informaci\u00f3n no se guardan ni son visibles en ning\u00fan lugar de %(platformName)s despu\u00e9s de que se complete el proceso de verificaci\u00f3n.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Usamos los m\u00e1s altos niveles de seguridad disponibles para encriptar su foto y enviarla a nuestro servicio de autorizaci\u00f3n para revisi\u00f3n. Su foto y su informaci\u00f3n no son guardadas ni quedan visibles en ninguna parte de %(platformName)s desp\u00faes de que el proceso de verificaci\u00f3n haya sido completado.", + "We use your verification photos to confirm your identity and ensure the validity of your certificate.": "Utilizamos sus fotos de verificaci\u00f3n para confirmar su identidad y garantizar la validez de su certificado.", "We're sorry to see you go! Your account will be deleted shortly.": "\u00a1Sentimos que te vayas! Tu cuenta ser\u00e1 eliminada en breve.", "We're sorry, there was an error": "Lo sentimos, ha habido un error", "We've encountered an error. Refresh your browser and then try again.": "Hemos detectado un error. Por favor recarga la p\u00e1gina en el navegador e intenta nuevamente.", @@ -2081,9 +2185,14 @@ "What can we help you with, {username}?": "\u00bfEn qu\u00e9 podemos ayudarte, {username}?", "What does %(platformName)s do with this photo?": "\u00bfQu\u00e9 hace %(platformName)s con esta imagen?", "What does this mean?": "\u00bfQu\u00e9 significa esto?", + "What if I can't see the camera image, or if I can't see my photo do determine which side is visible?": "\u00bfQu\u00e9 sucede si no puedo ver la imagen de la c\u00e1mara, o si no puedo ver mi foto para determinar qu\u00e9 lado es visible?", + "What if I have difficulty holding my ID in position relative to the camera?": "\u00bfQu\u00e9 sucede si tengo dificultades para mantener mi identificaci\u00f3n en posici\u00f3n con respecto a la c\u00e1mara?", + "What if I have difficulty holding my head in position relative to the camera?": "\u00bfQu\u00e9 sucede si tengo dificultades para mantener la cabeza en posici\u00f3n con respecto a la c\u00e1mara?", "What's Your Next Accomplishment?": "\u00bfQu\u00e9 ser\u00e1 tu pr\u00f3ximo logro?", "When learners submit an answer to an assessment, they immediately see whether the answer is correct or incorrect, and the score received.": "Cuando los estudiantes env\u00edan una respuesta para evaluaci\u00f3n, ven inmediatamente si la respuesta es correcta o incorrecta, y la calificaci\u00f3n recibida.", + "When your face is in position, use the Take Photo button {icon} below to take your photo.": "Cuando su cara est\u00e9 en posici\u00f3n, use el bot\u00f3n Tomar foto {icon} a continuaci\u00f3n para tomar su foto.", "Which timed transcript would you like to use?": "\u00bfCu\u00e1l de las transcripciones desea utilizar?", + "While our support team is happy to assist with the edX platform, the course staff has the expertise for specific assignment questions, grading or the proper procedures in each course. Please post all course related questions within the Discussion Forum where the Course Staff can directly respond.": "Si bien nuestro equipo de soporte est\u00e1 encantado de ayudar con la plataforma edX, el personal del curso tiene la experiencia para preguntas espec\u00edficas del curso, calificaci\u00f3n o los procedimientos adecuados en cada curso. Publique todas las preguntas relacionadas con el curso en el Foro de discusi\u00f3n donde el personal del curso pueda responder directamente.", "Whole words": "Palabras completas", "Why activate?": "Por qu\u00e9 activar?", "Why does %(platformName)s need my photo?": "Por qu\u00e9 %(platformName)s necesita mi foto ?", @@ -2097,6 +2206,7 @@ "Yes, delete this {xblock_type}": "Si, eliminar este {xblock_type}", "Yes, replace the edX transcript with the YouTube transcript": "Si, reemplazar la transcripci\u00f3n de edX con la de YouTube", "Yesterday": "Ayer", + "You already belong to another team in this team set.": "Usted ya pertenece a otro equipo en este conjunto.", "You already have an edX account with your {enterprise_name} email address.": "Ya tiene una cuenta edX con su direcci\u00f3n de correo electr\u00f3nico de {enterprise_name}", "You are a member of this team.": "Usted ya es miembro de este equipo.", "You are currently sharing a limited profile.": "Actualmente est\u00e1 compartiendo un perfil limitado.", @@ -2105,6 +2215,7 @@ "You are not enrolled in any programs yet.": "No se encuentra inscrito en ning\u00fan programa a\u00fan.", "You are now enrolled as a verified student for:": "Ahora estas inscrito como estudiante verificado para:", "You are sending an email message with the subject {subject} to the following recipients.": "Tu est\u00e1s enviando un correo electr\u00f3nico con asunto {subject} a los siguientes destinatarios.", + "You are taking \"{exam_link}\" as {exam_type}. ": "Est\u00e1s tomando \"{exam_link}\" como {exam_type}. ", "You are upgrading your enrollment for: {courseName}": "Est\u00e1s cambiando a la modalidad verificada para: {courseName}", "You can also retry this practice exam": "Tambi\u00e9n puede comenzar este examen de pr\u00e1ctica nuevamente", "You can change sessions until {expiration_date}.": "Puede cambiar ediciones hasta {expiration_date}.", @@ -2142,6 +2253,7 @@ "You have not created any group configurations yet.": "No ha creado ninguna configuraci\u00f3n de grupo.", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "Ha seleccionado una acci\u00f3n y no hs hecho ning\u00fan cambio en campos individuales. Probablemente est\u00e9 buscando el bot\u00f3n Ejecutar en lugar del bot\u00f3n Guardar.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "Ha seleccionado una acci\u00f3n, pero no ha guardado los cambios en los campos individuales todav\u00eda. Pulse OK para guardar. Tendr\u00e1 que volver a ejecutar la acci\u00f3n.", + "You have selected \u201cDelete my account.\u201d Deletion of your account and personal data is permanent and cannot be undone. {platformName} will not be able to recover your account or the data that is deleted.": "Ha seleccionado \u201cEliminar mi cuenta\u201d. La eliminaci\u00f3n de su cuenta y datos personales es permanente e irreversible. {platformName} no podr\u00e1 recuperar su cuenta o los datos que se hayan borrado.", "You have set your language to {beta_language}, which is currently not fully translated. You can help us translate this language fully by joining the Transifex community and adding translations from English for learners that speak {beta_language}.": "Ha establecido su idioma en {beta_language}, el cual no est\u00e1 traducido completamente. Puede ayudarnos a traducir este idioma totalmente uni\u00e9ndose la comunidad Transifex y adicionando traducciones desde el Ingl\u00e9s para los estudiantes que hablan {beta_language}.", "You have successfully signed into %(currentProvider)s, but your %(currentProvider)s account does not have a linked %(platformName)s account. To link your accounts, sign in now using your %(platformName)s password.": "Has iniciado sesi\u00f3n exitosamente en %(currentProvider)s, pero tu cuenta de %(currentProvider)s no est\u00e1 vinculada con una cuenta en %(platformName)s. Para vincular tus cuentas, ingresa con tu usuario y contrase\u00f1a de %(platformName)s.", "You have successfully updated your goal.": "Ha actualizado exitosamente su objetivo.", @@ -2153,6 +2265,8 @@ "You haven't added any textbooks to this course yet.": "No ha a\u00f1adido a\u00fan ning\u00fan libro de texto a este curso.", "You may access your account with this address if single-sign on or access to your primary email is not available.": "Puede acceder a su cuenta con esta direcci\u00f3n si no est\u00e1n disponibles el inicio de sesi\u00f3n \u00fanico -SSO- o el acceso a su correo electr\u00f3nico principal.", "You may also lose access to verified certificates and other program credentials like MicroMasters certificates. If you want to make a copy of these for your records before proceeding with deletion, follow the instructions for {htmlStart}printing or downloading a certificate{htmlEnd}.": "Puede que tambi\u00e9n pierdas el acceso a los certificados verificados y otros certificados de programas como los de los MicroMasters. Si quieres hacer una copia de dichos certificados para tus archivos antes de proceder a la eliminaci\u00f3n, sigue las instrucciones para {htmlStart}imprimir o descargar un certificado{htmlEnd}.", + "You may be able to complete the image capture procedure without assistance, but it may take a couple of submission attempts to get the camera positioning right. Optimal camera positioning varies with each computer, but generally the best position for a headshot is approximately 12-18 inches (30-45 centimeters) from the camera, with your head centered relative to the computer screen. ": "Es posible que pueda completar el procedimiento de captura de im\u00e1genes sin ayuda, pero puede tomar un par de intentos de env\u00edo para obtener la posici\u00f3n correcta de la c\u00e1mara. El posicionamiento \u00f3ptimo de la c\u00e1mara var\u00eda con cada computadora, pero generalmente la mejor posici\u00f3n para la doma de la cabeza es de aproximadamente 12-18 pulgadas (30-45 cent\u00edmetros) de la c\u00e1mara, con la cabeza centrada en relaci\u00f3n con la pantalla de la computadora.", + "You may be able to complete the image capture procedure without assistance, but it may take a couple of submission attempts to get the camera positioning right. Optimal camera positioning varies with each computer, but generally, the best position for a photo of an ID card is 8-12 inches (20-30 centimeters) from the camera, with the ID card centered relative to the camera. ": "Es posible que pueda completar el procedimiento de captura de im\u00e1genes sin ayuda, pero puede tomar un par de intentos de env\u00edo para obtener la posici\u00f3n correcta de la c\u00e1mara. El posicionamiento \u00f3ptimo de la c\u00e1mara var\u00eda con cada computadora, pero en general, la mejor posici\u00f3n para una foto de una tarjeta de identificaci\u00f3n es de 8 a 12 pulgadas (20-30 cent\u00edmetros) de la c\u00e1mara, con la tarjeta de identificaci\u00f3n centrada en relaci\u00f3n con la c\u00e1mara.", "You must be over 13 to share a full profile. If you are over 13, make sure that you have specified a birth year on the {account_settings_page_link}": "Debes tener 13 a\u00f1os o m\u00e1s para compartir un perfil completo. Si tienes m\u00e1s de esta edad, aseg\u00farate que has especificado un a\u00f1o de nacimiento en {account_settings_page_link}", "You must enter a valid email address in order to add a new team member": "Se debe introducir un email valido para adicionar un nuevo miembro en el equipo. ", "You must provide a learner name.": "Debe ingresar un nombre.", @@ -2162,13 +2276,13 @@ "You must specify a name": "Debes especificar un nombre", "You must specify a name for the cohort": "Debes especificar un nombre para el cohorte", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "Debes especificar un a\u00f1o de nacimiento antes de poder compartir tu perfil completo. Para definir un a\u00f1o de nacimiento, visita {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Necesita el documento de identidad, licencia de conducir, pasaporte u otra identificaci\u00f3n certificada por el gobierno, que contenga su foto y nombre.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Necesitas un ID con tu nombre y foto. Licencia, pasaporte, c\u00e9dula todos son aceptados.", + "You need a device that has a webcam. If you receive a browser prompt for access to your camera, please make sure to click 'Allow'.": "Necesita un dispositivo que tenga una c\u00e1mara web. Si recibe un mensaje del navegador para acceder a su c\u00e1mara, aseg\u00farese de hacer clic en \"Permitir\".", + "You need a valid ID that contains your full name and photo.": "Necesita un ID v\u00e1lida que contenga su nombre completo y foto.", + "You need an ID with your name and photo. A driver's license, passport, or ID are all acceptable.": "Necesita un documento de identificaci\u00f3n con su nombre y foto. Licencia de conducir, pasaporte o c\u00e9dula son aceptados.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Necesita activar la cuenta antes de que pueda registrarse para el curso. Revise su bandeja de entrada que un correo electr\u00f3nico de activaci\u00f3n fue enviado.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Necesita activar la cuenta antes de que pueda registrarse para el curso. Revise su bandeja de entrada que un correo electr\u00f3nico de activaci\u00f3n fue enviado. Una vez haya completado la activaci\u00f3n puede regresar y recargar esta p\u00e1gina.", "You receive messages from {platform_name} and course teams at this address.": "Recibe mensajes de {platform_name} y equipos del curso en esta direcci\u00f3n.", "You reserve all rights for your work": "Te reservas todos los derechos por tu trabajo", - "You still need to visit the %(display_name)s website to complete the credit process.": "Todav\u00eda debe visitar el sitio web de %(display_name)s para completar el proceso de cr\u00e9dito.", "You submitted {filename}; only {allowedFiles} are allowed.": "Tu enviaste {filename}; solamente se permiten {allowedFiles}.", "You waive some rights for your work, such that others can use it too": "Renuncias a algunos derechos de tu trabajo para que otros puedan usarlo tambi\u00e9n. ", "You will be refunded the amount you paid.": "Se le devolver\u00e1 el valor pagado.", @@ -2238,6 +2352,7 @@ "and others": "y otros", "anonymous": "an\u00f3nimo", "answer": "pregunta", + "answered question": "pregunta respondida", "asset_path is required": "Se requiere la ruta_del_recurso", "bytes": "bytes", "certificate": "certificado", @@ -2251,6 +2366,8 @@ "delete chapter": "borrar cap\u00edtulo", "delete group": "borrar grupo", "details about the failure": "detalles sobre la falla", + "discussion": "discusi\u00f3n", + "discussion posted %(time_ago)s by %(author)s": "discusi\u00f3n publicada hace %(time_ago)s por %(author)s", "dragging": "arrastrando", "dragging out of slider": "arrastrando fuera del carrusel", "dropped in slider": "soltada en el carrusel", @@ -2260,16 +2377,20 @@ "e.g. 'http://google.com'": "p.ej. 'https://google.com'", "e.g. johndoe@example.com, JaneDoe, joeydoe@example.com": "ej. johndoe@example.com, JaneDoe, joeydoe@example.com", "emphasized text": "texto enfatizado", + "endorsed %(time_ago)s": "Validado hace %(time_ago)s", + "endorsed %(time_ago)s by %(user)s": "Validado hace %(time_ago)s por %(user)s", "enter code here": "ingresa el c\u00f3digo aqu\u00ed", "enter link description here": "Ingresa la descripci\u00f3n del v\u00ednculo aqu\u00ed", + "follow this post": "sigue esta publicaci\u00f3n", "for": "para", - "for {courseName}": "Para {courseName}", "group configuration": "Configuraci\u00f3n de Grupo", "image omitted": "imagen omitida", "incorrect": "incorrecto", "internally reviewed": "revisado internamente", "last activity": "\u00faltima actividad", "less than a minute": "menos de un minuto", + "marked as answer %(time_ago)s": "marcado como respuesta hace %(time_ago)s", + "marked as answer %(time_ago)s by %(user)s": "marcado como respuesta hace %(time_ago)s por %(user)s", "minute": "minuto", "minutes": "minutos", "name": "nombre", @@ -2288,11 +2409,15 @@ "or sign in with": "o inicie sesi\u00f3n con", "path/to/introductionToCookieBaking-CH{order}.pdf": "path/to/introductionToCookieBaking-CH{order}.pdf", "pending": "pendiente", + "post anonymously": "Escribe una publicaci\u00f3n de forma an\u00f3nima", + "post anonymously to classmates": "publica an\u00f3nimamente a tus compa\u00f1eros de curso", + "posted %(time_ago)s by %(author)s": "publicado hace %(time_ago)s por %(author)s", "practice": "pr\u00e1ctica", "price": "precio", "proctored": "supervisado", "provide the title/name of the chapter that will be used in navigating": "Ingrese el t\u00edtulo / nombre del cap\u00edtulo que se usar\u00e1", "provide the title/name of the text book as you would like your students to see it": "ingrese el t\u00edtulo / nombre del libro de texto como ser\u00e1 visto por los estudiantes", + "question posted %(time_ago)s by %(author)s": "pregunta publicada hace %(time_ago)s por %(author)s", "remove": "eliminar", "remove all": "eliminar todo", "satisfactory": "adecuado", @@ -2305,6 +2430,7 @@ "team count": "Cantidad de equipos", "text_word_{uniqueId}": "text_word_{uniqueId}", "text_word_{uniqueId} title_word_{uniqueId}": "text_word_{uniqueId} title_word_{uniqueId}", + "the more quickly and helpfully we can respond!": "\u00a1lo m\u00e1s r\u00e1pido y servicial que podemos responder!", "there is currently {numVotes} vote": [ "actualmente hay {numVotes} voto", "actualmente hay {numVotes} votos" @@ -2313,6 +2439,7 @@ "title_word_{uniqueId}": "title_word_{uniqueId}", "toggle chapter %(displayName)s": "cambiar cap\u00edtulo %(displayName)s", "toggle subsection %(displayName)s": "cambiar subsecci\u00f3n %(displayName)s", + "unanswered question": "pregunta sin responder", "unit": "unidad", "unsatisfactory": "inadecuado", "unsubmitted": "No enviado", @@ -2330,6 +2457,15 @@ "{categoryText} in {parentDisplayname}": "{categoryText} en {parentDisplayname}", "{currentCountOpeningTag}{currentCharacterCount}{currentCountClosingTag} of {maxCharacters}": "{currentCountOpeningTag}{currentCharacterCount}{currentCountClosingTag} de {maxCharacters}", "{display_name} Settings": "Ajustes de configuraci\u00f3n para {display_name} ", + "{download_link_start}Download this image (right-click or option-click, save as){link_end} and then {upload_link_start}upload{link_end} it to your backpack.": "{download_link_start}descargar esta imagen (clic derecho, guardar como){link_end} y luego {upload_link_start} carguela {link_end} a su bolsa en Mozilla Backpack.", + "{earned}/{possible} point (graded)": [ + "{earned}/{possible} punto (calificado)", + "{earned}/{possible} puntos (calificado)" + ], + "{earned}/{possible} point (ungraded)": [ + "{earned}/{possible} punto (no calificado)", + "{earned}/{possible} puntos (no calificado)" + ], "{email}": "{email}", "{email} is already on the {container} team. Recheck the email address if you want to add a new member.": "{email} ya est\u00e1 en el equipo de {container}. Verifique nuevamente la direcic\u00f3n de correo si desea a\u00f1adir un nuevo miembro.", "{filename} exceeds maximum size of {maxFileSizeInGB} GB.": "El archivo {filename} excede el tama\u00f1o m\u00e1ximo de {maxFileSizeInGB} GB.", @@ -2371,8 +2507,25 @@ "{num_of_hours} hours": "{num_of_hours} horas", "{num_of_minutes} minute": "{num_of_minutes} minuto", "{num_of_minutes} minutes": "{num_of_minutes} minutos", + "{num_points} point possible (graded)": [ + "{num_points} punto posible (calificable)", + "{num_points} puntos posibles (calificables)" + ], + "{num_points} point possible (graded, results hidden)": [ + "{num_points} punto posible (calificable, resultado oculto)", + "{num_points} puntos posibles (calificables, resultados ocultos)" + ], + "{num_points} point possible (ungraded)": [ + "{num_points} punto posible (no calificable)", + "{num_points} puntos posibles (no calificables)" + ], + "{num_points} point possible (ungraded, results hidden)": [ + "{num_points} punto posible (no calificable, resultado oculto)", + "{num_points} puntos posibles (no calificables, resultados ocultos)" + ], "{organization}\\'s logo": "Logo de la {organization}", "{paragraphStart}You entered {boldStart}{email}{boldEnd}. If this email address is associated with your {platform_name} account, we will send a message with password recovery instructions to this email address.{paragraphEnd}{paragraphStart}If you do not receive a password reset message after 1 minute, verify that you entered the correct email address, or check your spam folder.{paragraphEnd}{paragraphStart}If you need further assistance, {anchorStart}contact technical support{anchorEnd}.{paragraphEnd}": "{paragraphStart}Has escrito {boldStart}{email}{boldEnd}. Si este correo electr\u00f3nico est\u00e1 asociado a tu cuenta {platform_name}, te enviaremos un correo con las instrucciones para recuperar tu contrase\u00f1a a este correo electr\u00f3nico. {paragraphEnd}{paragraphStart}Si no recibes el correo de restablecimiento de contrase\u00f1a despu\u00e9s de 1 minuto, verifica que escribiste la direcci\u00f3n de correo correcta o mira en tu carpeta de correo no deseado.{paragraphEnd}{paragraphStart}Si necesitas m\u00e1s ayuda, {anchorStart}contacta con soporte t\u00e9cnico{anchorEnd}.{paragraphEnd}", + "{paragraph}=p;{preformatted}=pre;{heading3}=h3;{heading4}=h4;{heading5}=h5;{heading6}=h6": "{paragraph}=p;{preformatted}=pre;{heading3}=h3;{heading4}=h4;{heading5}=h5;{heading6}=h6", "{screen_reader_start}Warning:{screen_reader_end} No content groups exist.": "{screen_reader_start}Advertencia:{screen_reader_end} No existe ning\u00fan grupo de contenido.", "{screen_reader_start}Warning:{screen_reader_end} The previously selected content group was deleted. Select another content group.": "{screen_reader_start}Advertencia:{screen_reader_end} El grupo de contenido previamente seleccionado ha sido borrado. Seleccione otro grupo de contenido.", "{seconds} {unit}": "{seconds} {unit}", @@ -2380,6 +2533,11 @@ "{sessionDates} (Open until {enrollmentEnd})": "{sessionDates} (Abierto hasta {enrollmentEnd})", "{sessionDates} - Currently Selected": "{sessionDates} - seleccionado actualmente", "{start_strong}{total}{end_strong} words submitted in total.": "{start_strong}{total}{end_strong} palabras enviadas en total.", + "{strongStart}Warning: Account deletion is permanent.{strongEnd} Please read the above carefully before proceeding. This is an irreversible action, and {strongStart}you will no longer be able to use the same email on {platformName}.{strongEnd}": "{strongStart}Advertencia: La eliminaci\u00f3n de la cuenta es permanente.{strongEnd} Por favor lea cuidadosamente la informaci\u00f3n en la parte superior antes de proceder. Esta es una acci\u00f3n irreversible, y {strongStart}no podr\u00e1 volver a usar el mismo correo electr\u00f3nico en {platformName}.{strongEnd}", + "{team_count} Team": [ + "{team_count} equipo", + "{team_count} Equipos" + ], "{totalItems} total": "{totalItems} total", "{total_results} result": [ "{total_results} resultado", @@ -2387,6 +2545,7 @@ ], "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}": "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}", "{type} Progress": "{type} Progreso", + "{unread_comments_count} new": "{unread_comments_count} nuevos", "\u2026": "..." }; for (var key in newcatalog) { @@ -2409,7 +2568,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2463,9 +2622,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/es-ar/djangojs.js b/cms/static/js/i18n/es-ar/djangojs.js index 9ebf997a285108aba512555183ed36b3a3c2d8b7..e10b8e4e89f4766582cc736ca4c419c4f313e7d3 100644 --- a/cms/static/js/i18n/es-ar/djangojs.js +++ b/cms/static/js/i18n/es-ar/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -155,9 +155,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/es-ec/djangojs.js b/cms/static/js/i18n/es-ec/djangojs.js index f8aa7d47094c0dce17243a2d17b7257bdfda827c..19d80dd5152e1887111e369d78a0eb31a2dc6e84 100644 --- a/cms/static/js/i18n/es-ec/djangojs.js +++ b/cms/static/js/i18n/es-ec/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -155,9 +155,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/es-es/djangojs.js b/cms/static/js/i18n/es-es/djangojs.js index ce63c1eab48eeeb03a266518a04d99080d74efcd..5bf397cb7ebabf587369b32f4c90dfb2e0a442a2 100644 --- a/cms/static/js/i18n/es-es/djangojs.js +++ b/cms/static/js/i18n/es-es/djangojs.js @@ -128,7 +128,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -182,9 +182,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/es-mx/djangojs.js b/cms/static/js/i18n/es-mx/djangojs.js index 89713b7e3b46201854ec85d2b137a832a09c8d5b..175107bba148f3d96f15c2df2f481be8838b5a04 100644 --- a/cms/static/js/i18n/es-mx/djangojs.js +++ b/cms/static/js/i18n/es-mx/djangojs.js @@ -25,21 +25,44 @@ "%(sel)s de %(cnt)s seleccionados/as" ], "6 a.m.": "6 a.m.", + "6 p.m.": "6 p.m.", + "April": "Abril", + "August": "Agosto", "Available %s": "Disponible %s", "Cancel": "Cancelar", "Choose": "Seleccionar", + "Choose a Date": "Elija una fecha", + "Choose a Time": "Elija una hora", "Choose a time": "Elija una hora", "Choose all": "Seleccionar todos", "Chosen %s": "%s seleccionados", "Click to choose all %s at once.": "Da click para seleccionar todos los %s de una vez.", "Click to remove all chosen %s at once.": "Da click para eliminar todos los %s seleccionados de una vez.", + "December": "Diciembre", + "February": "Febrero", "Filter": "Filtro", "Hide": "Ocultar", + "January": "Enero", + "July": "Julio", + "June": "Junio", + "March": "Marzo", + "May": "Mayo", "Midnight": "Medianoche", "Noon": "Mediod\u00eda", + "Note: You are %s hour ahead of server time.": [ + "Nota: Usted esta a %s horas por delante de la hora del servidor.", + "Nota: Usted va %s horas por delante de la hora del servidor." + ], + "Note: You are %s hour behind server time.": [ + "Nota: Usted esta a %s hora de retraso de tiempo de servidor.", + "Nota: Usted va %s horas por detr\u00e1s de la hora del servidor." + ], + "November": "Noviembre", "Now": "Ahora", + "October": "Octubre", "Remove": "Quitar", "Remove all": "Eliminar todos", + "September": "Septiembre", "Show": "Mostrar", "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "Esta es la lista de los %s disponibles. Usted puede elegir algunos seleccion\u00e1ndolos en el cuadro de abajo y haciendo click en la flecha \"Seleccionar\" entre las dos cajas.", "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "Esta es la lista de los %s elegidos. Usted puede eliminar algunos seleccion\u00e1ndolos en el cuadro de abajo y haciendo click en la flecha \"Eliminar\" entre las dos cajas.", @@ -49,7 +72,14 @@ "Yesterday": "Ayer", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "Ha seleccionado una acci\u00f3n pero no ha realizado ninguna modificaci\u00f3n en campos individuales. Es probable que lo que necesite usar en realidad sea el bot\u00f3n Ejecutar y no el bot\u00f3n Guardar.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "Ha seleccionado una acci\u00f3n, pero todav\u00eda no ha grabado las modificaciones que ha realizado en campos individuales. Por favor haga click en Aceptar para grabarlas. Necesitar\u00e1 ejecutar la acci\u00f3n nuevamente.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Tiene modificaciones sin guardar en campos modificables individuales. Si ejecuta una acci\u00f3n las mismas se perder\u00e1n." + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Tiene modificaciones sin guardar en campos modificables individuales. Si ejecuta una acci\u00f3n las mismas se perder\u00e1n.", + "one letter Friday\u0004F": "V", + "one letter Monday\u0004M": "L", + "one letter Saturday\u0004S": "S", + "one letter Sunday\u0004S": "D", + "one letter Thursday\u0004T": "J", + "one letter Tuesday\u0004T": "M", + "one letter Wednesday\u0004W": "M" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -71,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -126,12 +156,12 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", - "THOUSAND_SEPARATOR": "\u00a0", + "THOUSAND_SEPARATOR": ",", "TIME_FORMAT": "H:i", "TIME_INPUT_FORMATS": [ "%H:%M:%S", diff --git a/cms/static/js/i18n/es-pe/djangojs.js b/cms/static/js/i18n/es-pe/djangojs.js index f8aa7d47094c0dce17243a2d17b7257bdfda827c..19d80dd5152e1887111e369d78a0eb31a2dc6e84 100644 --- a/cms/static/js/i18n/es-pe/djangojs.js +++ b/cms/static/js/i18n/es-pe/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -155,9 +155,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/et-ee/djangojs.js b/cms/static/js/i18n/et-ee/djangojs.js index 00a1e6c73dd5d6f1780d13d38afc0140ff335b1f..04605d36fbd88aa7905b689f0f6724c52ea23444 100644 --- a/cms/static/js/i18n/et-ee/djangojs.js +++ b/cms/static/js/i18n/et-ee/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -165,9 +165,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/eu-es/djangojs.js b/cms/static/js/i18n/eu-es/djangojs.js index fb4b07de30088ea3ef1551fad65f629664c15b41..a981097ecd5ba507942499b239581de86af7b19e 100644 --- a/cms/static/js/i18n/eu-es/djangojs.js +++ b/cms/static/js/i18n/eu-es/djangojs.js @@ -377,7 +377,6 @@ "Default": "Berezkoa", "Default (Local Time Zone)": "Berezko (tokian tokiko ordu-eremua)", "Delete": "Ezabatu", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\"<%= signatoryName %>\" ezabatu nahi duzu sinatzaileen zerrendatik?", "Delete File Confirmation": "Fitxategia ezabatzeko konfirmazioa", "Delete My Account": "Ezabatu nire kontua", "Delete Page Confirmation": "Orria ezabatzeko konfirmazioa", @@ -505,7 +504,6 @@ "Fill browser": "Zabaldu nabigatzailea", "Filter": "Filtroa", "Filter and sort topics": "Iragazi eta ordenatu gaiak", - "Final Grade": "Azken kalifikazioa", "Financial Assistance Application": "Finantza-laguntzarako eskaria", "Find": "Bilatu", "Find a course": "Bilatu ikastaroa", @@ -529,7 +527,6 @@ "General": "Orokorra", "Generate": "Sortu", "Generate the user's certificate": "Sortu erabiltzailearen ziurtagiria", - "Get Credit": "Lortu kreditua", "Go Back": "Itzuli", "Go to Dashboard": "Joan aginte-panelera", "Go to my Dashboard": "Joan aginte-panelera", @@ -936,7 +933,6 @@ "Select a group type": "Aukeratu talde-mota", "Select a section or problem": "Aukeratu atala edo ariketa", "Select a session:": "Aukeratu saioa:", - "Select a subject for your support request.": "Aukeratu laguntza-eskaeraren gaia.", "Select all": "Aukeratu guztiak", "Select language": "Aukeratu hizkuntza", "Select one or more groups:": "Aukera talde bat edo gehiago:", @@ -1055,7 +1051,6 @@ "Textbook Name": "Testu-liburuaren izena", "Textbook information": "Testu-liburuaren informazioa", "Textbook name is required": "Testu-liburuaren izena beharrezkoa da", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Eskerrik asko %(full_name)s! Zure ordainketa jaso dugu %(course_name)s dela-eta.", "Thank you! We have received your payment for {courseName}.": "Eskerrik asko! Zure ordainketa jaso dugu {courseName} ikastarorako.", "The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "Badirudi sartu duzun URL-a e-posta helbidea dela. Nahi al duzu beharrrezko den mailto: aurrizkia gehitzea?", "The URL you entered seems to be an external link. Do you want to add the required http:// prefix?": "Badirudi sartu duzun URL-a kanporako esteka dela. Nahi al duzu beharrezko den http:// aurrizkia gehitzea?", @@ -1076,7 +1071,6 @@ "The grading process is still running. Refresh the page to see updates.": "Kalifikazio-prozesua abian da. Eguneratu orria azken emaitzak ikusteko.", "The language that team members primarily use to communicate with each other.": "Elkarrekin komunikatzeko taldeko partaideek erabiltzen duten hizkuntza nagusia.", "The language used throughout this site. This site is currently available in a limited number of languages. Changing the value of this field will cause the page to refresh.": "Gunean zehar erabilitako hizkuntza. Gune honetan hizkuntza kopuru mugatua dago eskura eskura. Eremu honetan balorea aldatzeak orria freskatuko du.", - "The more you tell us, the more quickly and helpfully we can respond!": "Zenbat eta gehiago esan, orduan eta azkarrago eta hobeto erantzungo dizugu!", "The name that identifies you on {platform_name}. You cannot change your username.": "{platform_name} plataforman identifikatzen zaituen izena. Ezin duzu erabiltzaile-izena aldatu.", "The selected content group does not exist": "Aukeratutako eduki-taldea ez da existitzen", "The server could not be contacted.": "Ezin izan da zerbitzariarekin konektatu.", @@ -1214,7 +1208,6 @@ "Verification Deadline": "Egiaztatzeko azken data", "Verified": "Egiaztatuta", "Verified Certificate": "Egiaztatutako ziurtagiria", - "Verify Now": "Egiaztatu orain!", "Version": "Bertsioa", "Vertical space": "Espazio bertikala", "Very loud": "Oso altu", @@ -1465,7 +1458,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1499,7 +1492,7 @@ /* formatting library */ django.formats = { - "DATETIME_FORMAT": "N j, Y, P", + "DATETIME_FORMAT": "Y\\k\\o N j\\a, H:i", "DATETIME_INPUT_FORMATS": [ "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", @@ -1529,11 +1522,11 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", - "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", - "SHORT_DATETIME_FORMAT": "m/d/Y P", - "SHORT_DATE_FORMAT": "Y M j", + "FIRST_DAY_OF_WEEK": 1, + "MONTH_DAY_FORMAT": "F\\r\\e\\n j\\a", + "NUMBER_GROUPING": 3, + "SHORT_DATETIME_FORMAT": "Y-m-d H:i", + "SHORT_DATE_FORMAT": "Y-m-d", "THOUSAND_SEPARATOR": ".", "TIME_FORMAT": "H:i", "TIME_INPUT_FORMATS": [ @@ -1541,7 +1534,7 @@ "%H:%M:%S.%f", "%H:%M" ], - "YEAR_MONTH_FORMAT": "F Y" + "YEAR_MONTH_FORMAT": "Y\\k\\o F" }; django.get_format = function(format_type) { diff --git a/cms/static/js/i18n/fa-ir/djangojs.js b/cms/static/js/i18n/fa-ir/djangojs.js index 34ca6f67a61fc264dfa84c62ee2e65c43158c74f..17e5f1e50af3a87bef785ebdc4f8329ec855287b 100644 --- a/cms/static/js/i18n/fa-ir/djangojs.js +++ b/cms/static/js/i18n/fa-ir/djangojs.js @@ -6,7 +6,7 @@ django.pluralidx = function(n) { - var v=0; + var v=(n > 1); if (typeof(v) == 'boolean') { return v ? 1 : 0; } else { @@ -21,6 +21,7 @@ var newcatalog = { "%(sel)s of %(cnt)s selected": [ + " %(sel)s \u0627\u0632 %(cnt)s \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647\u200c\u0627\u0646\u062f", " %(sel)s \u0627\u0632 %(cnt)s \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647\u200c\u0627\u0646\u062f" ], "6 a.m.": "\u06f6 \u0635\u0628\u062d", @@ -49,9 +50,11 @@ "Midnight": "\u0646\u06cc\u0645\u0647\u200c\u0634\u0628", "Noon": "\u0638\u0647\u0631", "Note: You are %s hour ahead of server time.": [ + "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u062c\u0644\u0648 \u0647\u0633\u062a\u06cc\u062f.", "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u062c\u0644\u0648 \u0647\u0633\u062a\u06cc\u062f." ], "Note: You are %s hour behind server time.": [ + "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u0639\u0642\u0628 \u0647\u0633\u062a\u06cc\u062f.", "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u0639\u0642\u0628 \u0647\u0633\u062a\u06cc\u062f." ], "November": "\u0646\u0648\u0627\u0645\u0628\u0631", @@ -98,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -162,9 +165,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "6", + "FIRST_DAY_OF_WEEK": 6, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "Y/n/j\u060c\u200f G:i", "SHORT_DATE_FORMAT": "Y/n/j", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/fa/djangojs.js b/cms/static/js/i18n/fa/djangojs.js index 34ca6f67a61fc264dfa84c62ee2e65c43158c74f..17e5f1e50af3a87bef785ebdc4f8329ec855287b 100644 --- a/cms/static/js/i18n/fa/djangojs.js +++ b/cms/static/js/i18n/fa/djangojs.js @@ -6,7 +6,7 @@ django.pluralidx = function(n) { - var v=0; + var v=(n > 1); if (typeof(v) == 'boolean') { return v ? 1 : 0; } else { @@ -21,6 +21,7 @@ var newcatalog = { "%(sel)s of %(cnt)s selected": [ + " %(sel)s \u0627\u0632 %(cnt)s \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647\u200c\u0627\u0646\u062f", " %(sel)s \u0627\u0632 %(cnt)s \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647\u200c\u0627\u0646\u062f" ], "6 a.m.": "\u06f6 \u0635\u0628\u062d", @@ -49,9 +50,11 @@ "Midnight": "\u0646\u06cc\u0645\u0647\u200c\u0634\u0628", "Noon": "\u0638\u0647\u0631", "Note: You are %s hour ahead of server time.": [ + "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u062c\u0644\u0648 \u0647\u0633\u062a\u06cc\u062f.", "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u062c\u0644\u0648 \u0647\u0633\u062a\u06cc\u062f." ], "Note: You are %s hour behind server time.": [ + "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u0639\u0642\u0628 \u0647\u0633\u062a\u06cc\u062f.", "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u0639\u0642\u0628 \u0647\u0633\u062a\u06cc\u062f." ], "November": "\u0646\u0648\u0627\u0645\u0628\u0631", @@ -98,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -162,9 +165,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "6", + "FIRST_DAY_OF_WEEK": 6, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "Y/n/j\u060c\u200f G:i", "SHORT_DATE_FORMAT": "Y/n/j", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/fake2/djangojs.js b/cms/static/js/i18n/fake2/djangojs.js index 0c2c86c25ab39e2ff087090c02f66ce2a7989bbc..30a4c73c2bef614dc4d7f138ffd260fce01859be 100644 --- a/cms/static/js/i18n/fake2/djangojs.js +++ b/cms/static/js/i18n/fake2/djangojs.js @@ -27,6 +27,7 @@ " M\u01dd\u026fb\u01dd\u0279s" ], " and ": " \u0250nd ", + " as many questions may have already been answered.": " \u0250s \u026f\u0250n\u028e bn\u01dds\u0287\u1d09\u00f8ns \u026f\u0250\u028e \u0265\u0250\u028c\u01dd \u0250l\u0279\u01dd\u0250d\u028e b\u01dd\u01ddn \u0250ns\u028d\u01dd\u0279\u01ddd.", " learner does not exist in LMS and not added to the exception list": " l\u01dd\u0250\u0279n\u01dd\u0279 d\u00f8\u01dds n\u00f8\u0287 \u01ddx\u1d09s\u0287 \u1d09n \u0141MS \u0250nd n\u00f8\u0287 \u0250dd\u01ddd \u0287\u00f8 \u0287\u0265\u01dd \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8n l\u1d09s\u0287", " learner is already white listed and not added to the exception list": " l\u01dd\u0250\u0279n\u01dd\u0279 \u1d09s \u0250l\u0279\u01dd\u0250d\u028e \u028d\u0265\u1d09\u0287\u01dd l\u1d09s\u0287\u01ddd \u0250nd n\u00f8\u0287 \u0250dd\u01ddd \u0287\u00f8 \u0287\u0265\u01dd \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8n l\u1d09s\u0287", " learner is not enrolled in course and not added to the exception list": " l\u01dd\u0250\u0279n\u01dd\u0279 \u1d09s n\u00f8\u0287 \u01ddn\u0279\u00f8ll\u01ddd \u1d09n \u0254\u00f8n\u0279s\u01dd \u0250nd n\u00f8\u0287 \u0250dd\u01ddd \u0287\u00f8 \u0287\u0265\u01dd \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8n l\u1d09s\u0287", @@ -39,6 +40,8 @@ " records are not in correct format and not added to the exception list": " \u0279\u01dd\u0254\u00f8\u0279ds \u0250\u0279\u01dd n\u00f8\u0287 \u1d09n \u0254\u00f8\u0279\u0279\u01dd\u0254\u0287 \u025f\u00f8\u0279\u026f\u0250\u0287 \u0250nd n\u00f8\u0287 \u0250dd\u01ddd \u0287\u00f8 \u0287\u0265\u01dd \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8n l\u1d09s\u0287", "${listPrice}": "${listPrice}", "%(cohort_name)s (%(user_count)s)": "%(cohort_name)s (%(user_count)s)", + "%(comments_count)s %(span_sr_open)scomments %(span_close)s": "%(comments_count)s %(span_sr_open)s\u0254\u00f8\u026f\u026f\u01ddn\u0287s %(span_close)s", + "%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s unread comments)%(span_close)s": "%(comments_count)s %(span_sr_open)s\u0254\u00f8\u026f\u026f\u01ddn\u0287s (%(unread_comments_count)s nn\u0279\u01dd\u0250d \u0254\u00f8\u026f\u026f\u01ddn\u0287s)%(span_close)s", "%(errorCount)s error found in form.": [ "%(errorCount)s \u01dd\u0279\u0279\u00f8\u0279 \u025f\u00f8nnd \u1d09n \u025f\u00f8\u0279\u026f.", "%(errorCount)s \u01dd\u0279\u0279\u00f8\u0279s \u025f\u00f8nnd \u1d09n \u025f\u00f8\u0279\u026f." @@ -80,6 +83,7 @@ "%s from now": "%s \u025f\u0279\u00f8\u026f n\u00f8\u028d", "(Add signatories for a certificate)": "(\u023add s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u1d09\u01dds \u025f\u00f8\u0279 \u0250 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd)", "(Caption will be displayed when you start playing the video.)": "(\u023b\u0250d\u0287\u1d09\u00f8n \u028d\u1d09ll b\u01dd d\u1d09sdl\u0250\u028e\u01ddd \u028d\u0265\u01ddn \u028e\u00f8n s\u0287\u0250\u0279\u0287 dl\u0250\u028e\u1d09n\u0183 \u0287\u0265\u01dd \u028c\u1d09d\u01dd\u00f8.)", + "(Community TA)": "(\u023b\u00f8\u026f\u026fnn\u1d09\u0287\u028e \u0166\u023a)", "(Optional)": "(\u00d8d\u0287\u1d09\u00f8n\u0250l)", "(Read-only)": "(\u024c\u01dd\u0250d-\u00f8nl\u028e)", "(Required Field)": "(\u024c\u01ddbn\u1d09\u0279\u01ddd F\u1d09\u01ddld)", @@ -87,6 +91,7 @@ "(Self-paced) Ends {end}": "(S\u01ddl\u025f-d\u0250\u0254\u01ddd) \u0246nds {end}", "(Self-paced) Started {start}": "(S\u01ddl\u025f-d\u0250\u0254\u01ddd) S\u0287\u0250\u0279\u0287\u01ddd {start}", "(Self-paced) Starts {start}": "(S\u01ddl\u025f-d\u0250\u0254\u01ddd) S\u0287\u0250\u0279\u0287s {start}", + "(Staff)": "(S\u0287\u0250\u025f\u025f)", "(contains %(student_count)s student)": [ "(\u0254\u00f8n\u0287\u0250\u1d09ns %(student_count)s s\u0287nd\u01ddn\u0287)", "(\u0254\u00f8n\u0287\u0250\u1d09ns %(student_count)s s\u0287nd\u01ddn\u0287s)" @@ -145,7 +150,12 @@ "Add URLs for additional versions": "\u023add \u0244\u024c\u0141s \u025f\u00f8\u0279 \u0250dd\u1d09\u0287\u1d09\u00f8n\u0250l \u028c\u01dd\u0279s\u1d09\u00f8ns", "Add a Chapter": "\u023add \u0250 \u023b\u0265\u0250d\u0287\u01dd\u0279", "Add a New Cohort": "\u023add \u0250 N\u01dd\u028d \u023b\u00f8\u0265\u00f8\u0279\u0287", + "Add a Post": "\u023add \u0250 \u2c63\u00f8s\u0287", + "Add a Response": "\u023add \u0250 \u024c\u01ddsd\u00f8ns\u01dd", + "Add a clear and descriptive title to encourage participation. (Required)": "\u023add \u0250 \u0254l\u01dd\u0250\u0279 \u0250nd d\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u028c\u01dd \u0287\u1d09\u0287l\u01dd \u0287\u00f8 \u01ddn\u0254\u00f8n\u0279\u0250\u0183\u01dd d\u0250\u0279\u0287\u1d09\u0254\u1d09d\u0250\u0287\u1d09\u00f8n. (\u024c\u01ddbn\u1d09\u0279\u01ddd)", + "Add a comment": "\u023add \u0250 \u0254\u00f8\u026f\u026f\u01ddn\u0287", "Add a learning outcome here": "\u023add \u0250 l\u01dd\u0250\u0279n\u1d09n\u0183 \u00f8n\u0287\u0254\u00f8\u026f\u01dd \u0265\u01dd\u0279\u01dd", + "Add a response:": "\u023add \u0250 \u0279\u01ddsd\u00f8ns\u01dd:", "Add another group": "\u023add \u0250n\u00f8\u0287\u0265\u01dd\u0279 \u0183\u0279\u00f8nd", "Add language": "\u023add l\u0250n\u0183n\u0250\u0183\u01dd", "Add learners to this cohort": "\u023add l\u01dd\u0250\u0279n\u01dd\u0279s \u0287\u00f8 \u0287\u0265\u1d09s \u0254\u00f8\u0265\u00f8\u0279\u0287", @@ -155,6 +165,7 @@ "Add your first content group": "\u023add \u028e\u00f8n\u0279 \u025f\u1d09\u0279s\u0287 \u0254\u00f8n\u0287\u01ddn\u0287 \u0183\u0279\u00f8nd", "Add your first group configuration": "\u023add \u028e\u00f8n\u0279 \u025f\u1d09\u0279s\u0287 \u0183\u0279\u00f8nd \u0254\u00f8n\u025f\u1d09\u0183n\u0279\u0250\u0287\u1d09\u00f8n", "Add your first textbook": "\u023add \u028e\u00f8n\u0279 \u025f\u1d09\u0279s\u0287 \u0287\u01ddx\u0287b\u00f8\u00f8\u029e", + "Add your post to a relevant topic to help others find it. (Required)": "\u023add \u028e\u00f8n\u0279 d\u00f8s\u0287 \u0287\u00f8 \u0250 \u0279\u01ddl\u01dd\u028c\u0250n\u0287 \u0287\u00f8d\u1d09\u0254 \u0287\u00f8 \u0265\u01ddld \u00f8\u0287\u0265\u01dd\u0279s \u025f\u1d09nd \u1d09\u0287. (\u024c\u01ddbn\u1d09\u0279\u01ddd)", "Add {role} Access": "\u023add {role} \u023a\u0254\u0254\u01ddss", "Adding": "\u023add\u1d09n\u0183", "Adding the selected course to your cart": "\u023add\u1d09n\u0183 \u0287\u0265\u01dd s\u01ddl\u01dd\u0254\u0287\u01ddd \u0254\u00f8n\u0279s\u01dd \u0287\u00f8 \u028e\u00f8n\u0279 \u0254\u0250\u0279\u0287", @@ -173,6 +184,7 @@ "Align left": "\u023al\u1d09\u0183n l\u01dd\u025f\u0287", "Align right": "\u023al\u1d09\u0183n \u0279\u1d09\u0183\u0265\u0287", "Alignment": "\u023al\u1d09\u0183n\u026f\u01ddn\u0287", + "All Groups": "\u023all \u01e4\u0279\u00f8nds", "All Learners and Staff": "\u023all \u0141\u01dd\u0250\u0279n\u01dd\u0279s \u0250nd S\u0287\u0250\u025f\u025f", "All Posts": "\u023all \u2c63\u00f8s\u0287s", "All Rights Reserved": "\u023all \u024c\u1d09\u0183\u0265\u0287s \u024c\u01dds\u01dd\u0279\u028c\u01ddd", @@ -254,6 +266,7 @@ "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "\u023a\u0279\u01dd \u028e\u00f8n sn\u0279\u01dd \u028e\u00f8n \u028d\u1d09s\u0265 \u0287\u00f8 d\u01ddl\u01dd\u0287\u01dd \u0287\u0265\u1d09s \u1d09\u0287\u01dd\u026f. \u0197\u0287 \u0254\u0250nn\u00f8\u0287 b\u01dd \u0279\u01dd\u028c\u01dd\u0279s\u01ddd!\n\n\u023als\u00f8 \u0250n\u028e \u0254\u00f8n\u0287\u01ddn\u0287 \u0287\u0265\u0250\u0287 l\u1d09n\u029es/\u0279\u01dd\u025f\u01dd\u0279s \u0287\u00f8 \u0287\u0265\u1d09s \u1d09\u0287\u01dd\u026f \u028d\u1d09ll n\u00f8 l\u00f8n\u0183\u01dd\u0279 \u028d\u00f8\u0279\u029e (\u01dd.\u0183. b\u0279\u00f8\u029e\u01ddn \u1d09\u026f\u0250\u0183\u01dds \u0250nd/\u00f8\u0279 l\u1d09n\u029es)", "Are you sure?": "\u023a\u0279\u01dd \u028e\u00f8n sn\u0279\u01dd?", "As part of the verification process, you take a photo of both your face and a government-issued photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u023as d\u0250\u0279\u0287 \u00f8\u025f \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss, \u028e\u00f8n \u0287\u0250\u029e\u01dd \u0250 d\u0265\u00f8\u0287\u00f8 \u00f8\u025f b\u00f8\u0287\u0265 \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd \u0250nd \u0250 \u0183\u00f8\u028c\u01dd\u0279n\u026f\u01ddn\u0287-\u1d09ssn\u01ddd d\u0265\u00f8\u0287\u00f8 \u0197\u0110. \u00d8n\u0279 \u0250n\u0287\u0265\u00f8\u0279\u1d09z\u0250\u0287\u1d09\u00f8n s\u01dd\u0279\u028c\u1d09\u0254\u01dd \u0254\u00f8n\u025f\u1d09\u0279\u026fs \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e b\u028e \u0254\u00f8\u026fd\u0250\u0279\u1d09n\u0183 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u028e\u00f8n \u0287\u0250\u029e\u01dd \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8n \u028e\u00f8n\u0279 \u0197\u0110.", + "As part of the verification process, you take a photo of both your face and a photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u023as d\u0250\u0279\u0287 \u00f8\u025f \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss, \u028e\u00f8n \u0287\u0250\u029e\u01dd \u0250 d\u0265\u00f8\u0287\u00f8 \u00f8\u025f b\u00f8\u0287\u0265 \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd \u0250nd \u0250 d\u0265\u00f8\u0287\u00f8 \u0197\u0110. \u00d8n\u0279 \u0250n\u0287\u0265\u00f8\u0279\u1d09z\u0250\u0287\u1d09\u00f8n s\u01dd\u0279\u028c\u1d09\u0254\u01dd \u0254\u00f8n\u025f\u1d09\u0279\u026fs \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e b\u028e \u0254\u00f8\u026fd\u0250\u0279\u1d09n\u0183 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u028e\u00f8n \u0287\u0250\u029e\u01dd \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8n \u028e\u00f8n\u0279 \u0197\u0110.", "As you complete courses, you will see them listed here.": "\u023as \u028e\u00f8n \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0254\u00f8n\u0279s\u01dds, \u028e\u00f8n \u028d\u1d09ll s\u01dd\u01dd \u0287\u0265\u01dd\u026f l\u1d09s\u0287\u01ddd \u0265\u01dd\u0279\u01dd.", "Assessment Results Visibility": "\u023ass\u01ddss\u026f\u01ddn\u0287 \u024c\u01ddsnl\u0287s V\u1d09s\u1d09b\u1d09l\u1d09\u0287\u028e", "Assign Team Memberships": "\u023ass\u1d09\u0183n \u0166\u01dd\u0250\u026f M\u01dd\u026fb\u01dd\u0279s\u0265\u1d09ds", @@ -381,6 +394,7 @@ "Click to edit": "\u023bl\u1d09\u0254\u029e \u0287\u00f8 \u01ddd\u1d09\u0287", "Close": "\u023bl\u00f8s\u01dd", "Close Calculator": "\u023bl\u00f8s\u01dd \u023b\u0250l\u0254nl\u0250\u0287\u00f8\u0279", + "Closed": "\u023bl\u00f8s\u01ddd", "Code": "\u023b\u00f8d\u01dd", "Code Sample (Ctrl+K)": "\u023b\u00f8d\u01dd S\u0250\u026fdl\u01dd (\u023b\u0287\u0279l+\ua740)", "Code block": "\u023b\u00f8d\u01dd bl\u00f8\u0254\u029e", @@ -399,6 +413,7 @@ "Coming Soon": "\u023b\u00f8\u026f\u1d09n\u0183 S\u00f8\u00f8n", "Commentary": "\u023b\u00f8\u026f\u026f\u01ddn\u0287\u0250\u0279\u028e", "Common Problem Types": "\u023b\u00f8\u026f\u026f\u00f8n \u2c63\u0279\u00f8bl\u01dd\u026f \u0166\u028ed\u01dds", + "Community TA": "\u023b\u00f8\u026f\u026fnn\u1d09\u0287\u028e \u0166\u023a", "Complete courses on your schedule to ensure you stand out in your field!": "\u023b\u00f8\u026fdl\u01dd\u0287\u01dd \u0254\u00f8n\u0279s\u01dds \u00f8n \u028e\u00f8n\u0279 s\u0254\u0265\u01dddnl\u01dd \u0287\u00f8 \u01ddnsn\u0279\u01dd \u028e\u00f8n s\u0287\u0250nd \u00f8n\u0287 \u1d09n \u028e\u00f8n\u0279 \u025f\u1d09\u01ddld!", "Completed": "\u023b\u00f8\u026fdl\u01dd\u0287\u01ddd", "Component": "\u023b\u00f8\u026fd\u00f8n\u01ddn\u0287", @@ -445,6 +460,7 @@ ], "Course Content": "\u023b\u00f8n\u0279s\u01dd \u023b\u00f8n\u0287\u01ddn\u0287", "Course Credit Requirements": "\u023b\u00f8n\u0279s\u01dd \u023b\u0279\u01ddd\u1d09\u0287 \u024c\u01ddbn\u1d09\u0279\u01dd\u026f\u01ddn\u0287s", + "Course Discussion Forum": "\u023b\u00f8n\u0279s\u01dd \u0110\u1d09s\u0254nss\u1d09\u00f8n F\u00f8\u0279n\u026f", "Course End": "\u023b\u00f8n\u0279s\u01dd \u0246nd", "Course Handouts": "\u023b\u00f8n\u0279s\u01dd \u0126\u0250nd\u00f8n\u0287s", "Course ID": "\u023b\u00f8n\u0279s\u01dd \u0197\u0110", @@ -467,6 +483,7 @@ "Create": "\u023b\u0279\u01dd\u0250\u0287\u01dd", "Create Account": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u023a\u0254\u0254\u00f8nn\u0287", "Create Re-run": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u024c\u01dd-\u0279nn", + "Create Support Ticket": "\u023b\u0279\u01dd\u0250\u0287\u01dd Sndd\u00f8\u0279\u0287 \u0166\u1d09\u0254\u029e\u01dd\u0287", "Create a New Team": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250 N\u01dd\u028d \u0166\u01dd\u0250\u026f", "Create a content group": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250 \u0254\u00f8n\u0287\u01ddn\u0287 \u0183\u0279\u00f8nd", "Create a new team if you can't find an existing team to join, or if you would like to learn with friends you know.": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250 n\u01dd\u028d \u0287\u01dd\u0250\u026f \u1d09\u025f \u028e\u00f8n \u0254\u0250n'\u0287 \u025f\u1d09nd \u0250n \u01ddx\u1d09s\u0287\u1d09n\u0183 \u0287\u01dd\u0250\u026f \u0287\u00f8 \u027e\u00f8\u1d09n, \u00f8\u0279 \u1d09\u025f \u028e\u00f8n \u028d\u00f8nld l\u1d09\u029e\u01dd \u0287\u00f8 l\u01dd\u0250\u0279n \u028d\u1d09\u0287\u0265 \u025f\u0279\u1d09\u01ddnds \u028e\u00f8n \u029en\u00f8\u028d.", @@ -474,6 +491,7 @@ "Create account using %(providerName)s.": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250\u0254\u0254\u00f8nn\u0287 ns\u1d09n\u0183 %(providerName)s.", "Create an Account": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250n \u023a\u0254\u0254\u00f8nn\u0287", "Create an Account.": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250n \u023a\u0254\u0254\u00f8nn\u0287.", + "Create an account": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250n \u0250\u0254\u0254\u00f8nn\u0287", "Create an account using": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250n \u0250\u0254\u0254\u00f8nn\u0287 ns\u1d09n\u0183", "Create team.": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0287\u01dd\u0250\u026f.", "Creating missing groups": "\u023b\u0279\u01dd\u0250\u0287\u1d09n\u0183 \u026f\u1d09ss\u1d09n\u0183 \u0183\u0279\u00f8nds", @@ -496,13 +514,14 @@ "Date Placed": "\u0110\u0250\u0287\u01dd \u2c63l\u0250\u0254\u01ddd", "Date added": "\u0110\u0250\u0287\u01dd \u0250dd\u01ddd", "Deactivate": "\u0110\u01dd\u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u01dd", + "Deactivating": "\u0110\u01dd\u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u1d09n\u0183", "Deadlines": "\u0110\u01dd\u0250dl\u1d09n\u01dds", "Decrease indent": "\u0110\u01dd\u0254\u0279\u01dd\u0250s\u01dd \u1d09nd\u01ddn\u0287", "Default": "\u0110\u01dd\u025f\u0250nl\u0287", "Default (Local Time Zone)": "\u0110\u01dd\u025f\u0250nl\u0287 (\u0141\u00f8\u0254\u0250l \u0166\u1d09\u026f\u01dd \u01b5\u00f8n\u01dd)", "Default Timed Transcript": "\u0110\u01dd\u025f\u0250nl\u0287 \u0166\u1d09\u026f\u01ddd \u0166\u0279\u0250ns\u0254\u0279\u1d09d\u0287", "Delete": "\u0110\u01ddl\u01dd\u0287\u01dd", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u0110\u01ddl\u01dd\u0287\u01dd \"<%= signatoryName %>\" \u025f\u0279\u00f8\u026f \u0287\u0265\u01dd l\u1d09s\u0287 \u00f8\u025f s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u1d09\u01dds?", + "Delete \"<%- signatoryName %>\" from the list of signatories?": "\u0110\u01ddl\u01dd\u0287\u01dd \"<%- signatoryName %>\" \u025f\u0279\u00f8\u026f \u0287\u0265\u01dd l\u1d09s\u0287 \u00f8\u025f s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u1d09\u01dds?", "Delete File Confirmation": "\u0110\u01ddl\u01dd\u0287\u01dd F\u1d09l\u01dd \u023b\u00f8n\u025f\u1d09\u0279\u026f\u0250\u0287\u1d09\u00f8n", "Delete My Account": "\u0110\u01ddl\u01dd\u0287\u01dd M\u028e \u023a\u0254\u0254\u00f8nn\u0287", "Delete Page Confirmation": "\u0110\u01ddl\u01dd\u0287\u01dd \u2c63\u0250\u0183\u01dd \u023b\u00f8n\u025f\u1d09\u0279\u026f\u0250\u0287\u1d09\u00f8n", @@ -529,11 +548,14 @@ "Description": "\u0110\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n", "Description of the certificate": "\u0110\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n \u00f8\u025f \u0287\u0265\u01dd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd", "Details": "\u0110\u01dd\u0287\u0250\u1d09ls", + "Device with Camera": "\u0110\u01dd\u028c\u1d09\u0254\u01dd \u028d\u1d09\u0287\u0265 \u023b\u0250\u026f\u01dd\u0279\u0250", "Dimensions": "\u0110\u1d09\u026f\u01ddns\u1d09\u00f8ns", "Disc": "\u0110\u1d09s\u0254", "Discard Changes": "\u0110\u1d09s\u0254\u0250\u0279d \u023b\u0265\u0250n\u0183\u01dds", "Discarding Changes": "\u0110\u1d09s\u0254\u0250\u0279d\u1d09n\u0183 \u023b\u0265\u0250n\u0183\u01dds", + "Discussion": "\u0110\u1d09s\u0254nss\u1d09\u00f8n", "Discussion Home": "\u0110\u1d09s\u0254nss\u1d09\u00f8n \u0126\u00f8\u026f\u01dd", + "Discussion admins, moderators, and TAs can make their posts visible to all students or specify a single group.": "\u0110\u1d09s\u0254nss\u1d09\u00f8n \u0250d\u026f\u1d09ns, \u026f\u00f8d\u01dd\u0279\u0250\u0287\u00f8\u0279s, \u0250nd \u0166\u023as \u0254\u0250n \u026f\u0250\u029e\u01dd \u0287\u0265\u01dd\u1d09\u0279 d\u00f8s\u0287s \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 \u0250ll s\u0287nd\u01ddn\u0287s \u00f8\u0279 sd\u01dd\u0254\u1d09\u025f\u028e \u0250 s\u1d09n\u0183l\u01dd \u0183\u0279\u00f8nd.", "Discussion topics in the course are not divided.": "\u0110\u1d09s\u0254nss\u1d09\u00f8n \u0287\u00f8d\u1d09\u0254s \u1d09n \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd \u0250\u0279\u01dd n\u00f8\u0287 d\u1d09\u028c\u1d09d\u01ddd.", "Discussions are unified; all learners interact with posts from other learners, regardless of the group they are in.": "\u0110\u1d09s\u0254nss\u1d09\u00f8ns \u0250\u0279\u01dd nn\u1d09\u025f\u1d09\u01ddd; \u0250ll l\u01dd\u0250\u0279n\u01dd\u0279s \u1d09n\u0287\u01dd\u0279\u0250\u0254\u0287 \u028d\u1d09\u0287\u0265 d\u00f8s\u0287s \u025f\u0279\u00f8\u026f \u00f8\u0287\u0265\u01dd\u0279 l\u01dd\u0250\u0279n\u01dd\u0279s, \u0279\u01dd\u0183\u0250\u0279dl\u01ddss \u00f8\u025f \u0287\u0265\u01dd \u0183\u0279\u00f8nd \u0287\u0265\u01dd\u028e \u0250\u0279\u01dd \u1d09n.", "Display Name": "\u0110\u1d09sdl\u0250\u028e N\u0250\u026f\u01dd", @@ -545,7 +567,6 @@ "Do you want to replace the edX transcript with the YouTube transcript?": "\u0110\u00f8 \u028e\u00f8n \u028d\u0250n\u0287 \u0287\u00f8 \u0279\u01dddl\u0250\u0254\u01dd \u0287\u0265\u01dd \u01dddX \u0287\u0279\u0250ns\u0254\u0279\u1d09d\u0287 \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd \u024e\u00f8n\u0166nb\u01dd \u0287\u0279\u0250ns\u0254\u0279\u1d09d\u0287?", "Document properties": "\u0110\u00f8\u0254n\u026f\u01ddn\u0287 d\u0279\u00f8d\u01dd\u0279\u0287\u1d09\u01dds", "Does the name on your ID match your account name: %(fullName)s?": "\u0110\u00f8\u01dds \u0287\u0265\u01dd n\u0250\u026f\u01dd \u00f8n \u028e\u00f8n\u0279 \u0197\u0110 \u026f\u0250\u0287\u0254\u0265 \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 n\u0250\u026f\u01dd: %(fullName)s?", - "Does the photo of you match your ID photo?": "\u0110\u00f8\u01dds \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n \u026f\u0250\u0287\u0254\u0265 \u028e\u00f8n\u0279 \u0197\u0110 d\u0265\u00f8\u0287\u00f8?", "Does the photo of you show your whole face?": "\u0110\u00f8\u01dds \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n s\u0265\u00f8\u028d \u028e\u00f8n\u0279 \u028d\u0265\u00f8l\u01dd \u025f\u0250\u0254\u01dd?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u0110\u00f8n'\u0287 s\u01dd\u01dd \u028e\u00f8n\u0279 d\u1d09\u0254\u0287n\u0279\u01dd? M\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u00f8 \u0250ll\u00f8\u028d \u028e\u00f8n\u0279 b\u0279\u00f8\u028ds\u01dd\u0279 \u0287\u00f8 ns\u01dd \u028e\u00f8n\u0279 \u0254\u0250\u026f\u01dd\u0279\u0250 \u028d\u0265\u01ddn \u1d09\u0287 \u0250s\u029es \u025f\u00f8\u0279 d\u01dd\u0279\u026f\u1d09ss\u1d09\u00f8n.", "Donate": "\u0110\u00f8n\u0250\u0287\u01dd", @@ -566,6 +587,7 @@ "Due Date:": "\u0110n\u01dd \u0110\u0250\u0287\u01dd:", "Due Time in UTC:": "\u0110n\u01dd \u0166\u1d09\u026f\u01dd \u1d09n \u0244\u0166\u023b:", "Due date cannot be before start date.": "\u0110n\u01dd d\u0250\u0287\u01dd \u0254\u0250nn\u00f8\u0287 b\u01dd b\u01dd\u025f\u00f8\u0279\u01dd s\u0287\u0250\u0279\u0287 d\u0250\u0287\u01dd.", + "Due to the recent increase in interest in online education and edX, we are currently experiencing an unusually high volume of support requests. We appreciate your patience as we work to review each request. Please check the ": "\u0110n\u01dd \u0287\u00f8 \u0287\u0265\u01dd \u0279\u01dd\u0254\u01ddn\u0287 \u1d09n\u0254\u0279\u01dd\u0250s\u01dd \u1d09n \u1d09n\u0287\u01dd\u0279\u01dds\u0287 \u1d09n \u00f8nl\u1d09n\u01dd \u01dddn\u0254\u0250\u0287\u1d09\u00f8n \u0250nd \u01dddX, \u028d\u01dd \u0250\u0279\u01dd \u0254n\u0279\u0279\u01ddn\u0287l\u028e \u01ddxd\u01dd\u0279\u1d09\u01ddn\u0254\u1d09n\u0183 \u0250n nnnsn\u0250ll\u028e \u0265\u1d09\u0183\u0265 \u028c\u00f8ln\u026f\u01dd \u00f8\u025f sndd\u00f8\u0279\u0287 \u0279\u01ddbn\u01dds\u0287s. W\u01dd \u0250dd\u0279\u01dd\u0254\u1d09\u0250\u0287\u01dd \u028e\u00f8n\u0279 d\u0250\u0287\u1d09\u01ddn\u0254\u01dd \u0250s \u028d\u01dd \u028d\u00f8\u0279\u029e \u0287\u00f8 \u0279\u01dd\u028c\u1d09\u01dd\u028d \u01dd\u0250\u0254\u0265 \u0279\u01ddbn\u01dds\u0287. \u2c63l\u01dd\u0250s\u01dd \u0254\u0265\u01dd\u0254\u029e \u0287\u0265\u01dd ", "Due:": "\u0110n\u01dd:", "Duplicate": "\u0110ndl\u1d09\u0254\u0250\u0287\u01dd", "Duplicating": "\u0110ndl\u1d09\u0254\u0250\u0287\u1d09n\u0183", @@ -585,8 +607,12 @@ "Edit Title": "\u0246d\u1d09\u0287 \u0166\u1d09\u0287l\u01dd", "Edit Your Name": "\u0246d\u1d09\u0287 \u024e\u00f8n\u0279 N\u0250\u026f\u01dd", "Edit this certificate?": "\u0246d\u1d09\u0287 \u0287\u0265\u1d09s \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd?", + "Edit your post below.": "\u0246d\u1d09\u0287 \u028e\u00f8n\u0279 d\u00f8s\u0287 b\u01ddl\u00f8\u028d.", "Editable": "\u0246d\u1d09\u0287\u0250bl\u01dd", "Editing access for: {title}": "\u0246d\u1d09\u0287\u1d09n\u0183 \u0250\u0254\u0254\u01ddss \u025f\u00f8\u0279: {title}", + "Editing comment": "\u0246d\u1d09\u0287\u1d09n\u0183 \u0254\u00f8\u026f\u026f\u01ddn\u0287", + "Editing post": "\u0246d\u1d09\u0287\u1d09n\u0183 d\u00f8s\u0287", + "Editing response": "\u0246d\u1d09\u0287\u1d09n\u0183 \u0279\u01ddsd\u00f8ns\u01dd", "Editing: {title}": "\u0246d\u1d09\u0287\u1d09n\u0183: {title}", "Editor": "\u0246d\u1d09\u0287\u00f8\u0279", "Education Completed": "\u0246dn\u0254\u0250\u0287\u1d09\u00f8n \u023b\u00f8\u026fdl\u01dd\u0287\u01ddd", @@ -604,6 +630,7 @@ "Encoding": "\u0246n\u0254\u00f8d\u1d09n\u0183", "End My Exam": "\u0246nd M\u028e \u0246x\u0250\u026f", "End of transcript. Skip to the start.": "\u0246nd \u00f8\u025f \u0287\u0279\u0250ns\u0254\u0279\u1d09d\u0287. S\u029e\u1d09d \u0287\u00f8 \u0287\u0265\u01dd s\u0287\u0250\u0279\u0287.", + "Endorse": "\u0246nd\u00f8\u0279s\u01dd", "Ends {end}": "\u0246nds {end}", "Engage with posts": "\u0246n\u0183\u0250\u0183\u01dd \u028d\u1d09\u0287\u0265 d\u00f8s\u0287s", "Enroll Now": "\u0246n\u0279\u00f8ll N\u00f8\u028d", @@ -658,6 +685,7 @@ "Error getting task history for problem '<%- problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "\u0246\u0279\u0279\u00f8\u0279 \u0183\u01dd\u0287\u0287\u1d09n\u0183 \u0287\u0250s\u029e \u0265\u1d09s\u0287\u00f8\u0279\u028e \u025f\u00f8\u0279 d\u0279\u00f8bl\u01dd\u026f '<%- problem_id %>' \u0250nd s\u0287nd\u01ddn\u0287 '<%- student_id %>'. M\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u0265\u0250\u0287 \u0287\u0265\u01dd d\u0279\u00f8bl\u01dd\u026f \u0250nd s\u0287nd\u01ddn\u0287 \u1d09d\u01ddn\u0287\u1d09\u025f\u1d09\u01dd\u0279s \u0250\u0279\u01dd \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0250nd \u0254\u00f8\u0279\u0279\u01dd\u0254\u0287.", "Error importing course": "\u0246\u0279\u0279\u00f8\u0279 \u1d09\u026fd\u00f8\u0279\u0287\u1d09n\u0183 \u0254\u00f8n\u0279s\u01dd", "Error listing task history for this student and problem.": "\u0246\u0279\u0279\u00f8\u0279 l\u1d09s\u0287\u1d09n\u0183 \u0287\u0250s\u029e \u0265\u1d09s\u0287\u00f8\u0279\u028e \u025f\u00f8\u0279 \u0287\u0265\u1d09s s\u0287nd\u01ddn\u0287 \u0250nd d\u0279\u00f8bl\u01dd\u026f.", + "Error posting your message.": "\u0246\u0279\u0279\u00f8\u0279 d\u00f8s\u0287\u1d09n\u0183 \u028e\u00f8n\u0279 \u026f\u01ddss\u0250\u0183\u01dd.", "Error removing user": "\u0246\u0279\u0279\u00f8\u0279 \u0279\u01dd\u026f\u00f8\u028c\u1d09n\u0183 ns\u01dd\u0279", "Error resetting entrance exam attempts for student '{student_id}'. Make sure student identifier is correct.": "\u0246\u0279\u0279\u00f8\u0279 \u0279\u01dds\u01dd\u0287\u0287\u1d09n\u0183 \u01ddn\u0287\u0279\u0250n\u0254\u01dd \u01ddx\u0250\u026f \u0250\u0287\u0287\u01dd\u026fd\u0287s \u025f\u00f8\u0279 s\u0287nd\u01ddn\u0287 '{student_id}'. M\u0250\u029e\u01dd sn\u0279\u01dd s\u0287nd\u01ddn\u0287 \u1d09d\u01ddn\u0287\u1d09\u025f\u1d09\u01dd\u0279 \u1d09s \u0254\u00f8\u0279\u0279\u01dd\u0254\u0287.", "Error resetting problem attempts for problem '<%= problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "\u0246\u0279\u0279\u00f8\u0279 \u0279\u01dds\u01dd\u0287\u0287\u1d09n\u0183 d\u0279\u00f8bl\u01dd\u026f \u0250\u0287\u0287\u01dd\u026fd\u0287s \u025f\u00f8\u0279 d\u0279\u00f8bl\u01dd\u026f '<%= problem_id %>' \u0250nd s\u0287nd\u01ddn\u0287 '<%- student_id %>'. M\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u0265\u0250\u0287 \u0287\u0265\u01dd d\u0279\u00f8bl\u01dd\u026f \u0250nd s\u0287nd\u01ddn\u0287 \u1d09d\u01ddn\u0287\u1d09\u025f\u1d09\u01dd\u0279s \u0250\u0279\u01dd \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0250nd \u0254\u00f8\u0279\u0279\u01dd\u0254\u0287.", @@ -709,7 +737,6 @@ "Files that you upload must be smaller than 5MB in size.": "F\u1d09l\u01dds \u0287\u0265\u0250\u0287 \u028e\u00f8n ndl\u00f8\u0250d \u026fns\u0287 b\u01dd s\u026f\u0250ll\u01dd\u0279 \u0287\u0265\u0250n 5M\u0243 \u1d09n s\u1d09z\u01dd.", "Fill browser": "F\u1d09ll b\u0279\u00f8\u028ds\u01dd\u0279", "Filter and sort topics": "F\u1d09l\u0287\u01dd\u0279 \u0250nd s\u00f8\u0279\u0287 \u0287\u00f8d\u1d09\u0254s", - "Final Grade": "F\u1d09n\u0250l \u01e4\u0279\u0250d\u01dd", "Financial Aid": "F\u1d09n\u0250n\u0254\u1d09\u0250l \u023a\u1d09d", "Financial Assistance": "F\u1d09n\u0250n\u0254\u1d09\u0250l \u023ass\u1d09s\u0287\u0250n\u0254\u01dd", "Financial Assistance Application": "F\u1d09n\u0250n\u0254\u1d09\u0250l \u023ass\u1d09s\u0287\u0250n\u0254\u01dd \u023addl\u1d09\u0254\u0250\u0287\u1d09\u00f8n", @@ -722,12 +749,15 @@ "Find previous": "F\u1d09nd d\u0279\u01dd\u028c\u1d09\u00f8ns", "Finish": "F\u1d09n\u1d09s\u0265", "First time here?": "F\u1d09\u0279s\u0287 \u0287\u1d09\u026f\u01dd \u0265\u01dd\u0279\u01dd?", + "Follow": "F\u00f8ll\u00f8\u028d", "Follow or unfollow posts": "F\u00f8ll\u00f8\u028d \u00f8\u0279 nn\u025f\u00f8ll\u00f8\u028d d\u00f8s\u0287s", + "Following": "F\u00f8ll\u00f8\u028d\u1d09n\u0183", "Font Family": "F\u00f8n\u0287 F\u0250\u026f\u1d09l\u028e", "Font Sizes": "F\u00f8n\u0287 S\u1d09z\u01dds", "Footer": "F\u00f8\u00f8\u0287\u01dd\u0279", "For grading to work, you must change all {oldName} subsections to {newName}.": "F\u00f8\u0279 \u0183\u0279\u0250d\u1d09n\u0183 \u0287\u00f8 \u028d\u00f8\u0279\u029e, \u028e\u00f8n \u026fns\u0287 \u0254\u0265\u0250n\u0183\u01dd \u0250ll {oldName} snbs\u01dd\u0254\u0287\u1d09\u00f8ns \u0287\u00f8 {newName}.", "For inquiries regarding assignments, grades, or structure of a specific course, please post in the discussion forums for that course directly.": "F\u00f8\u0279 \u1d09nbn\u1d09\u0279\u1d09\u01dds \u0279\u01dd\u0183\u0250\u0279d\u1d09n\u0183 \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287s, \u0183\u0279\u0250d\u01dds, \u00f8\u0279 s\u0287\u0279n\u0254\u0287n\u0279\u01dd \u00f8\u025f \u0250 sd\u01dd\u0254\u1d09\u025f\u1d09\u0254 \u0254\u00f8n\u0279s\u01dd, dl\u01dd\u0250s\u01dd d\u00f8s\u0287 \u1d09n \u0287\u0265\u01dd d\u1d09s\u0254nss\u1d09\u00f8n \u025f\u00f8\u0279n\u026fs \u025f\u00f8\u0279 \u0287\u0265\u0250\u0287 \u0254\u00f8n\u0279s\u01dd d\u1d09\u0279\u01dd\u0254\u0287l\u028e.", + "Forgot my password": "F\u00f8\u0279\u0183\u00f8\u0287 \u026f\u028e d\u0250ss\u028d\u00f8\u0279d", "Format": "F\u00f8\u0279\u026f\u0250\u0287", "Formats": "F\u00f8\u0279\u026f\u0250\u0287s", "Free text notes": "F\u0279\u01dd\u01dd \u0287\u01ddx\u0287 n\u00f8\u0287\u01dds", @@ -742,7 +772,6 @@ "Generate": "\u01e4\u01ddn\u01dd\u0279\u0250\u0287\u01dd", "Generate Exception Certificates": "\u01e4\u01ddn\u01dd\u0279\u0250\u0287\u01dd \u0246x\u0254\u01ddd\u0287\u1d09\u00f8n \u023b\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dds", "Generate the user's certificate": "\u01e4\u01ddn\u01dd\u0279\u0250\u0287\u01dd \u0287\u0265\u01dd ns\u01dd\u0279's \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd", - "Get Credit": "\u01e4\u01dd\u0287 \u023b\u0279\u01ddd\u1d09\u0287", "Go to Dashboard": "\u01e4\u00f8 \u0287\u00f8 \u0110\u0250s\u0265b\u00f8\u0250\u0279d", "Go to my Dashboard": "\u01e4\u00f8 \u0287\u00f8 \u026f\u028e \u0110\u0250s\u0265b\u00f8\u0250\u0279d", "Go to your Dashboard": "\u01e4\u00f8 \u0287\u00f8 \u028e\u00f8n\u0279 \u0110\u0250s\u0265b\u00f8\u0250\u0279d", @@ -823,10 +852,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "\u0197\u025f \u0287\u0265\u01dd snbs\u01dd\u0254\u0287\u1d09\u00f8n d\u00f8\u01dds n\u00f8\u0287 \u0265\u0250\u028c\u01dd \u0250 dn\u01dd d\u0250\u0287\u01dd, l\u01dd\u0250\u0279n\u01dd\u0279s \u0250l\u028d\u0250\u028es s\u01dd\u01dd \u0287\u0265\u01dd\u1d09\u0279 s\u0254\u00f8\u0279\u01dds \u028d\u0265\u01ddn \u0287\u0265\u01dd\u028e snb\u026f\u1d09\u0287 \u0250ns\u028d\u01dd\u0279s \u0287\u00f8 \u0250ss\u01ddss\u026f\u01ddn\u0287s.", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u0197\u025f \u0287\u0265\u01dd nn\u1d09\u0287 \u028d\u0250s d\u0279\u01dd\u028c\u1d09\u00f8nsl\u028e dnbl\u1d09s\u0265\u01ddd \u0250nd \u0279\u01ddl\u01dd\u0250s\u01ddd \u0287\u00f8 l\u01dd\u0250\u0279n\u01dd\u0279s, \u0250n\u028e \u0254\u0265\u0250n\u0183\u01dds \u028e\u00f8n \u026f\u0250d\u01dd \u0287\u00f8 \u0287\u0265\u01dd nn\u1d09\u0287 \u028d\u0265\u01ddn \u1d09\u0287 \u028d\u0250s \u0265\u1d09dd\u01ddn \u028d\u1d09ll n\u00f8\u028d b\u01dd \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 l\u01dd\u0250\u0279n\u01dd\u0279s.", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "\u0197\u025f \u0287\u0265\u01dd nn\u1d09\u0287 \u028d\u0250s d\u0279\u01dd\u028c\u1d09\u00f8nsl\u028e dnbl\u1d09s\u0265\u01ddd \u0250nd \u0279\u01ddl\u01dd\u0250s\u01ddd \u0287\u00f8 s\u0287nd\u01ddn\u0287s, \u0250n\u028e \u0254\u0265\u0250n\u0183\u01dds \u028e\u00f8n \u026f\u0250d\u01dd \u0287\u00f8 \u0287\u0265\u01dd nn\u1d09\u0287 \u028d\u0265\u01ddn \u1d09\u0287 \u028d\u0250s \u0265\u1d09dd\u01ddn \u028d\u1d09ll n\u00f8\u028d b\u01dd \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 s\u0287nd\u01ddn\u0287s. \u0110\u00f8 \u028e\u00f8n \u028d\u0250n\u0287 \u0287\u00f8 d\u0279\u00f8\u0254\u01dd\u01ddd?", - "If you are unable to access your account contact us via email using {email}.": "\u0197\u025f \u028e\u00f8n \u0250\u0279\u01dd nn\u0250bl\u01dd \u0287\u00f8 \u0250\u0254\u0254\u01ddss \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 \u0254\u00f8n\u0287\u0250\u0254\u0287 ns \u028c\u1d09\u0250 \u01dd\u026f\u0250\u1d09l ns\u1d09n\u0183 {email}.", "If you do not yet have an account, use the button below to register.": "\u0197\u025f \u028e\u00f8n d\u00f8 n\u00f8\u0287 \u028e\u01dd\u0287 \u0265\u0250\u028c\u01dd \u0250n \u0250\u0254\u0254\u00f8nn\u0287, ns\u01dd \u0287\u0265\u01dd bn\u0287\u0287\u00f8n b\u01ddl\u00f8\u028d \u0287\u00f8 \u0279\u01dd\u0183\u1d09s\u0287\u01dd\u0279.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u0197\u025f \u028e\u00f8n d\u00f8n'\u0287 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e n\u00f8\u028d, \u028e\u00f8n \u0254\u0250n s\u0287\u1d09ll \u01ddxdl\u00f8\u0279\u01dd \u028e\u00f8n\u0279 \u0254\u00f8n\u0279s\u01dd \u025f\u0279\u00f8\u026f \u028e\u00f8n\u0279 d\u0250s\u0265b\u00f8\u0250\u0279d. \u024e\u00f8n \u028d\u1d09ll \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd d\u01dd\u0279\u1d09\u00f8d\u1d09\u0254 \u0279\u01dd\u026f\u1d09nd\u01dd\u0279s \u025f\u0279\u00f8\u026f %(platformName)s \u0287\u00f8 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u0197\u025f \u028e\u00f8n d\u00f8n'\u0287 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e n\u00f8\u028d, \u028e\u00f8n \u0254\u0250n s\u0287\u1d09ll \u01ddxdl\u00f8\u0279\u01dd \u028e\u00f8n\u0279 \u0254\u00f8n\u0279s\u01dd \u025f\u0279\u00f8\u026f \u028e\u00f8n\u0279 d\u0250s\u0265b\u00f8\u0250\u0279d. \u024e\u00f8n \u028d\u1d09ll \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd d\u01dd\u0279\u1d09\u00f8d\u1d09\u0254 \u0279\u01dd\u026f\u1d09nd\u01dd\u0279s \u025f\u0279\u00f8\u026f {platformName} \u0287\u00f8 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e.", "If you leave, you can no longer post in this team's discussions.Your place will be available to another learner.": "\u0197\u025f \u028e\u00f8n l\u01dd\u0250\u028c\u01dd, \u028e\u00f8n \u0254\u0250n n\u00f8 l\u00f8n\u0183\u01dd\u0279 d\u00f8s\u0287 \u1d09n \u0287\u0265\u1d09s \u0287\u01dd\u0250\u026f's d\u1d09s\u0254nss\u1d09\u00f8ns.\u024e\u00f8n\u0279 dl\u0250\u0254\u01dd \u028d\u1d09ll b\u01dd \u0250\u028c\u0250\u1d09l\u0250bl\u01dd \u0287\u00f8 \u0250n\u00f8\u0287\u0265\u01dd\u0279 l\u01dd\u0250\u0279n\u01dd\u0279.", "If you make significant changes, make sure you notify members of the team before making these changes.": "\u0197\u025f \u028e\u00f8n \u026f\u0250\u029e\u01dd s\u1d09\u0183n\u1d09\u025f\u1d09\u0254\u0250n\u0287 \u0254\u0265\u0250n\u0183\u01dds, \u026f\u0250\u029e\u01dd sn\u0279\u01dd \u028e\u00f8n n\u00f8\u0287\u1d09\u025f\u028e \u026f\u01dd\u026fb\u01dd\u0279s \u00f8\u025f \u0287\u0265\u01dd \u0287\u01dd\u0250\u026f b\u01dd\u025f\u00f8\u0279\u01dd \u026f\u0250\u029e\u1d09n\u0183 \u0287\u0265\u01dds\u01dd \u0254\u0265\u0250n\u0183\u01dds.", "If you make this %(xblockType)s visible to learners, learners will be able to see its content after the release date has passed and you have published the unit. Only units that are explicitly hidden from learners will remain hidden after you clear this option for the %(xblockType)s.": "\u0197\u025f \u028e\u00f8n \u026f\u0250\u029e\u01dd \u0287\u0265\u1d09s %(xblockType)s \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 l\u01dd\u0250\u0279n\u01dd\u0279s, l\u01dd\u0250\u0279n\u01dd\u0279s \u028d\u1d09ll b\u01dd \u0250bl\u01dd \u0287\u00f8 s\u01dd\u01dd \u1d09\u0287s \u0254\u00f8n\u0287\u01ddn\u0287 \u0250\u025f\u0287\u01dd\u0279 \u0287\u0265\u01dd \u0279\u01ddl\u01dd\u0250s\u01dd d\u0250\u0287\u01dd \u0265\u0250s d\u0250ss\u01ddd \u0250nd \u028e\u00f8n \u0265\u0250\u028c\u01dd dnbl\u1d09s\u0265\u01ddd \u0287\u0265\u01dd nn\u1d09\u0287. \u00d8nl\u028e nn\u1d09\u0287s \u0287\u0265\u0250\u0287 \u0250\u0279\u01dd \u01ddxdl\u1d09\u0254\u1d09\u0287l\u028e \u0265\u1d09dd\u01ddn \u025f\u0279\u00f8\u026f l\u01dd\u0250\u0279n\u01dd\u0279s \u028d\u1d09ll \u0279\u01dd\u026f\u0250\u1d09n \u0265\u1d09dd\u01ddn \u0250\u025f\u0287\u01dd\u0279 \u028e\u00f8n \u0254l\u01dd\u0250\u0279 \u0287\u0265\u1d09s \u00f8d\u0287\u1d09\u00f8n \u025f\u00f8\u0279 \u0287\u0265\u01dd %(xblockType)s.", @@ -948,6 +975,7 @@ "Live view of webcam": "\u0141\u1d09\u028c\u01dd \u028c\u1d09\u01dd\u028d \u00f8\u025f \u028d\u01ddb\u0254\u0250\u026f", "Load Another File": "\u0141\u00f8\u0250d \u023an\u00f8\u0287\u0265\u01dd\u0279 F\u1d09l\u01dd", "Load all responses": "\u0141\u00f8\u0250d \u0250ll \u0279\u01ddsd\u00f8ns\u01dds", + "Load more": "\u0141\u00f8\u0250d \u026f\u00f8\u0279\u01dd", "Load next {numResponses} responses": "\u0141\u00f8\u0250d n\u01ddx\u0287 {numResponses} \u0279\u01ddsd\u00f8ns\u01dds", "Load next {num_items} result": [ "\u0141\u00f8\u0250d n\u01ddx\u0287 {num_items} \u0279\u01ddsnl\u0287", @@ -980,6 +1008,7 @@ "Manage Learners": "M\u0250n\u0250\u0183\u01dd \u0141\u01dd\u0250\u0279n\u01dd\u0279s", "Manual": "M\u0250nn\u0250l", "Mark Exam As Completed": "M\u0250\u0279\u029e \u0246x\u0250\u026f \u023as \u023b\u00f8\u026fdl\u01dd\u0287\u01ddd", + "Mark as Answer": "M\u0250\u0279\u029e \u0250s \u023ans\u028d\u01dd\u0279", "Mark enrollment code as unused": "M\u0250\u0279\u029e \u01ddn\u0279\u00f8ll\u026f\u01ddn\u0287 \u0254\u00f8d\u01dd \u0250s nnns\u01ddd", "Markdown Editing Help": "M\u0250\u0279\u029ed\u00f8\u028dn \u0246d\u1d09\u0287\u1d09n\u0183 \u0126\u01ddld", "Masters": "M\u0250s\u0287\u01dd\u0279s", @@ -1018,6 +1047,8 @@ "Name or short description of the configuration": "N\u0250\u026f\u01dd \u00f8\u0279 s\u0265\u00f8\u0279\u0287 d\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n \u00f8\u025f \u0287\u0265\u01dd \u0254\u00f8n\u025f\u1d09\u0183n\u0279\u0250\u0287\u1d09\u00f8n", "Navigate up": "N\u0250\u028c\u1d09\u0183\u0250\u0287\u01dd nd", "Need help logging in?": "N\u01dd\u01ddd \u0265\u01ddld l\u00f8\u0183\u0183\u1d09n\u0183 \u1d09n?", + "Need help signing in?": "N\u01dd\u01ddd \u0265\u01ddld s\u1d09\u0183n\u1d09n\u0183 \u1d09n?", + "Need other help signing in?": "N\u01dd\u01ddd \u00f8\u0287\u0265\u01dd\u0279 \u0265\u01ddld s\u1d09\u0183n\u1d09n\u0183 \u1d09n?", "Needs verified certificate ": "N\u01dd\u01ddds \u028c\u01dd\u0279\u1d09\u025f\u1d09\u01ddd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd ", "Never published": "N\u01dd\u028c\u01dd\u0279 dnbl\u1d09s\u0265\u01ddd", "Never show assessment results": "N\u01dd\u028c\u01dd\u0279 s\u0265\u00f8\u028d \u0250ss\u01ddss\u026f\u01ddn\u0287 \u0279\u01ddsnl\u0287s", @@ -1037,6 +1068,7 @@ "No Flash Detected": "N\u00f8 Fl\u0250s\u0265 \u0110\u01dd\u0287\u01dd\u0254\u0287\u01ddd", "No Timed Transcript": "N\u00f8 \u0166\u1d09\u026f\u01ddd \u0166\u0279\u0250ns\u0254\u0279\u1d09d\u0287", "No Webcam Detected": "N\u00f8 W\u01ddb\u0254\u0250\u026f \u0110\u01dd\u0287\u01dd\u0254\u0287\u01ddd", + "No assignments for team": "N\u00f8 \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287s \u025f\u00f8\u0279 \u0287\u01dd\u0250\u026f", "No color": "N\u00f8 \u0254\u00f8l\u00f8\u0279", "No content-specific discussion topics exist.": "N\u00f8 \u0254\u00f8n\u0287\u01ddn\u0287-sd\u01dd\u0254\u1d09\u025f\u1d09\u0254 d\u1d09s\u0254nss\u1d09\u00f8n \u0287\u00f8d\u1d09\u0254s \u01ddx\u1d09s\u0287.", "No description available": "N\u00f8 d\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n \u0250\u028c\u0250\u1d09l\u0250bl\u01dd", @@ -1085,9 +1117,10 @@ "Once in position, use the Take Photo button {icon} to capture your photo": "\u00d8n\u0254\u01dd \u1d09n d\u00f8s\u1d09\u0287\u1d09\u00f8n, ns\u01dd \u0287\u0265\u01dd \u0166\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8 bn\u0287\u0287\u00f8n {icon} \u0287\u00f8 \u0254\u0250d\u0287n\u0279\u01dd \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8", "Once you complete one of the program requirements you have a program record. This record is marked complete once you meet all program requirements. A program record can be used to continue your learning journey and demonstrate your learning to others.": "\u00d8n\u0254\u01dd \u028e\u00f8n \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u00f8n\u01dd \u00f8\u025f \u0287\u0265\u01dd d\u0279\u00f8\u0183\u0279\u0250\u026f \u0279\u01ddbn\u1d09\u0279\u01dd\u026f\u01ddn\u0287s \u028e\u00f8n \u0265\u0250\u028c\u01dd \u0250 d\u0279\u00f8\u0183\u0279\u0250\u026f \u0279\u01dd\u0254\u00f8\u0279d. \u0166\u0265\u1d09s \u0279\u01dd\u0254\u00f8\u0279d \u1d09s \u026f\u0250\u0279\u029e\u01ddd \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u00f8n\u0254\u01dd \u028e\u00f8n \u026f\u01dd\u01dd\u0287 \u0250ll d\u0279\u00f8\u0183\u0279\u0250\u026f \u0279\u01ddbn\u1d09\u0279\u01dd\u026f\u01ddn\u0287s. \u023a d\u0279\u00f8\u0183\u0279\u0250\u026f \u0279\u01dd\u0254\u00f8\u0279d \u0254\u0250n b\u01dd ns\u01ddd \u0287\u00f8 \u0254\u00f8n\u0287\u1d09nn\u01dd \u028e\u00f8n\u0279 l\u01dd\u0250\u0279n\u1d09n\u0183 \u027e\u00f8n\u0279n\u01dd\u028e \u0250nd d\u01dd\u026f\u00f8ns\u0287\u0279\u0250\u0287\u01dd \u028e\u00f8n\u0279 l\u01dd\u0250\u0279n\u1d09n\u0183 \u0287\u00f8 \u00f8\u0287\u0265\u01dd\u0279s.", "Once your account is deleted, you cannot use it to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "\u00d8n\u0254\u01dd \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 \u1d09s d\u01ddl\u01dd\u0287\u01ddd, \u028e\u00f8n \u0254\u0250nn\u00f8\u0287 ns\u01dd \u1d09\u0287 \u0287\u00f8 \u0287\u0250\u029e\u01dd \u0254\u00f8n\u0279s\u01dds \u00f8n \u0287\u0265\u01dd {platformName} \u0250dd, {siteName}, \u00f8\u0279 \u0250n\u028e \u00f8\u0287\u0265\u01dd\u0279 s\u1d09\u0287\u01dd \u0265\u00f8s\u0287\u01ddd b\u028e {platformName}.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u00d8nl\u028e <%= fileTypes %> \u025f\u1d09l\u01dds \u0254\u0250n b\u01dd ndl\u00f8\u0250d\u01ddd. \u2c63l\u01dd\u0250s\u01dd s\u01ddl\u01dd\u0254\u0287 \u0250 \u025f\u1d09l\u01dd \u01ddnd\u1d09n\u0183 \u1d09n <%= fileExtensions %> \u0287\u00f8 ndl\u00f8\u0250d.", + "Only <%- fileTypes %> files can be uploaded. Please select a file ending in <%- (fileExtensions) %> to upload.": "\u00d8nl\u028e <%- fileTypes %> \u025f\u1d09l\u01dds \u0254\u0250n b\u01dd ndl\u00f8\u0250d\u01ddd. \u2c63l\u01dd\u0250s\u01dd s\u01ddl\u01dd\u0254\u0287 \u0250 \u025f\u1d09l\u01dd \u01ddnd\u1d09n\u0183 \u1d09n <%- (fileExtensions) %> \u0287\u00f8 ndl\u00f8\u0250d.", "Only properly formatted .csv files will be accepted.": "\u00d8nl\u028e d\u0279\u00f8d\u01dd\u0279l\u028e \u025f\u00f8\u0279\u026f\u0250\u0287\u0287\u01ddd .\u0254s\u028c \u025f\u1d09l\u01dds \u028d\u1d09ll b\u01dd \u0250\u0254\u0254\u01ddd\u0287\u01ddd.", "Only the parent course staff of a CCX can create content groups.": "\u00d8nl\u028e \u0287\u0265\u01dd d\u0250\u0279\u01ddn\u0287 \u0254\u00f8n\u0279s\u01dd s\u0287\u0250\u025f\u025f \u00f8\u025f \u0250 \u023b\u023bX \u0254\u0250n \u0254\u0279\u01dd\u0250\u0287\u01dd \u0254\u00f8n\u0287\u01ddn\u0287 \u0183\u0279\u00f8nds.", + "Open": "\u00d8d\u01ddn", "Open Calculator": "\u00d8d\u01ddn \u023b\u0250l\u0254nl\u0250\u0287\u00f8\u0279", "Open language menu": "\u00d8d\u01ddn l\u0250n\u0183n\u0250\u0183\u01dd \u026f\u01ddnn", "Open the certificate you earned for the %(title)s program.": "\u00d8d\u01ddn \u0287\u0265\u01dd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u028e\u00f8n \u01dd\u0250\u0279n\u01ddd \u025f\u00f8\u0279 \u0287\u0265\u01dd %(title)s d\u0279\u00f8\u0183\u0279\u0250\u026f.", @@ -1107,6 +1140,7 @@ "Organization of the signatory": "\u00d8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n \u00f8\u025f \u0287\u0265\u01dd s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u028e", "Organization:": "\u00d8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n:", "Other": "\u00d8\u0287\u0265\u01dd\u0279", + "Other sign-in issues": "\u00d8\u0287\u0265\u01dd\u0279 s\u1d09\u0183n-\u1d09n \u1d09ssn\u01dds", "Overall Score": "\u00d8\u028c\u01dd\u0279\u0250ll S\u0254\u00f8\u0279\u01dd", "PDF Chapters": "\u2c63\u0110F \u023b\u0265\u0250d\u0287\u01dd\u0279s", "Page break": "\u2c63\u0250\u0183\u01dd b\u0279\u01dd\u0250\u029e", @@ -1135,6 +1169,8 @@ "Photo of %(fullName)s's ID": "\u2c63\u0265\u00f8\u0287\u00f8 \u00f8\u025f %(fullName)s's \u0197\u0110", "Photo requirements:": "\u2c63\u0265\u00f8\u0287\u00f8 \u0279\u01ddbn\u1d09\u0279\u01dd\u026f\u01ddn\u0287s:", "Photos don't meet the requirements?": "\u2c63\u0265\u00f8\u0287\u00f8s d\u00f8n'\u0287 \u026f\u01dd\u01dd\u0287 \u0287\u0265\u01dd \u0279\u01ddbn\u1d09\u0279\u01dd\u026f\u01ddn\u0287s?", + "Pin": "\u2c63\u1d09n", + "Pinned": "\u2c63\u1d09nn\u01ddd", "Placeholder": "\u2c63l\u0250\u0254\u01dd\u0265\u00f8ld\u01dd\u0279", "Play": "\u2c63l\u0250\u028e", "Play video": "\u2c63l\u0250\u028e \u028c\u1d09d\u01dd\u00f8", @@ -1177,6 +1213,7 @@ "Please verify that your webcam is connected and that you have allowed your browser to access it.": "\u2c63l\u01dd\u0250s\u01dd \u028c\u01dd\u0279\u1d09\u025f\u028e \u0287\u0265\u0250\u0287 \u028e\u00f8n\u0279 \u028d\u01ddb\u0254\u0250\u026f \u1d09s \u0254\u00f8nn\u01dd\u0254\u0287\u01ddd \u0250nd \u0287\u0265\u0250\u0287 \u028e\u00f8n \u0265\u0250\u028c\u01dd \u0250ll\u00f8\u028d\u01ddd \u028e\u00f8n\u0279 b\u0279\u00f8\u028ds\u01dd\u0279 \u0287\u00f8 \u0250\u0254\u0254\u01ddss \u1d09\u0287.", "Plugins": "\u2c63ln\u0183\u1d09ns", "Post": "\u2c63\u00f8s\u0287", + "Post type": "\u2c63\u00f8s\u0287 \u0287\u028ed\u01dd", "Poster": "\u2c63\u00f8s\u0287\u01dd\u0279", "Practice Proctored": "\u2c63\u0279\u0250\u0254\u0287\u1d09\u0254\u01dd \u2c63\u0279\u00f8\u0254\u0287\u00f8\u0279\u01ddd", "Practice proctored Exam": "\u2c63\u0279\u0250\u0254\u0287\u1d09\u0254\u01dd d\u0279\u00f8\u0254\u0287\u00f8\u0279\u01ddd \u0246x\u0250\u026f", @@ -1231,6 +1268,8 @@ "Published and Live": "\u2c63nbl\u1d09s\u0265\u01ddd \u0250nd \u0141\u1d09\u028c\u01dd", "Publishing": "\u2c63nbl\u1d09s\u0265\u1d09n\u0183", "Publishing Status": "\u2c63nbl\u1d09s\u0265\u1d09n\u0183 S\u0287\u0250\u0287ns", + "Question": "Qn\u01dds\u0287\u1d09\u00f8n", + "Questions raise issues that need answers. Discussions share ideas and start conversations. (Required)": "Qn\u01dds\u0287\u1d09\u00f8ns \u0279\u0250\u1d09s\u01dd \u1d09ssn\u01dds \u0287\u0265\u0250\u0287 n\u01dd\u01ddd \u0250ns\u028d\u01dd\u0279s. \u0110\u1d09s\u0254nss\u1d09\u00f8ns s\u0265\u0250\u0279\u01dd \u1d09d\u01dd\u0250s \u0250nd s\u0287\u0250\u0279\u0287 \u0254\u00f8n\u028c\u01dd\u0279s\u0250\u0287\u1d09\u00f8ns. (\u024c\u01ddbn\u1d09\u0279\u01ddd)", "Queued": "Qn\u01ddn\u01ddd", "REMAINING COURSES": "\u024c\u0246M\u023a\u0197N\u0197N\u01e4 \u023b\u00d8\u0244\u024cS\u0246S", "Re-run Course": "\u024c\u01dd-\u0279nn \u023b\u00f8n\u0279s\u01dd", @@ -1250,6 +1289,7 @@ "Regenerate": "\u024c\u01dd\u0183\u01ddn\u01dd\u0279\u0250\u0287\u01dd", "Regenerate the user's certificate": "\u024c\u01dd\u0183\u01ddn\u01dd\u0279\u0250\u0287\u01dd \u0287\u0265\u01dd ns\u01dd\u0279's \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd", "Register with Institution/Campus Credentials": "\u024c\u01dd\u0183\u1d09s\u0287\u01dd\u0279 \u028d\u1d09\u0287\u0265 \u0197ns\u0287\u1d09\u0287n\u0287\u1d09\u00f8n/\u023b\u0250\u026fdns \u023b\u0279\u01ddd\u01ddn\u0287\u1d09\u0250ls", + "Related to: %(courseware_title_linked)s": "\u024c\u01ddl\u0250\u0287\u01ddd \u0287\u00f8: %(courseware_title_linked)s", "Release Date and Time": "\u024c\u01ddl\u01dd\u0250s\u01dd \u0110\u0250\u0287\u01dd \u0250nd \u0166\u1d09\u026f\u01dd", "Release Date:": "\u024c\u01ddl\u01dd\u0250s\u01dd \u0110\u0250\u0287\u01dd:", "Release Status:": "\u024c\u01ddl\u01dd\u0250s\u01dd S\u0287\u0250\u0287ns:", @@ -1277,7 +1317,10 @@ "Replace all": "\u024c\u01dddl\u0250\u0254\u01dd \u0250ll", "Replace with": "\u024c\u01dddl\u0250\u0254\u01dd \u028d\u1d09\u0287\u0265", "Reply to Annotation": "\u024c\u01dddl\u028e \u0287\u00f8 \u023ann\u00f8\u0287\u0250\u0287\u1d09\u00f8n", + "Report": "\u024c\u01ddd\u00f8\u0279\u0287", + "Report abuse": "\u024c\u01ddd\u00f8\u0279\u0287 \u0250bns\u01dd", "Report abuse, topics, and responses": "\u024c\u01ddd\u00f8\u0279\u0287 \u0250bns\u01dd, \u0287\u00f8d\u1d09\u0254s, \u0250nd \u0279\u01ddsd\u00f8ns\u01dds", + "Reported": "\u024c\u01ddd\u00f8\u0279\u0287\u01ddd", "Requester": "\u024c\u01ddbn\u01dds\u0287\u01dd\u0279", "Required": "\u024c\u01ddbn\u1d09\u0279\u01ddd", "Required field.": "\u024c\u01ddbn\u1d09\u0279\u01ddd \u025f\u1d09\u01ddld.", @@ -1296,6 +1339,7 @@ "Return and add email address": "\u024c\u01dd\u0287n\u0279n \u0250nd \u0250dd \u01dd\u026f\u0250\u1d09l \u0250dd\u0279\u01ddss", "Return to Export": "\u024c\u01dd\u0287n\u0279n \u0287\u00f8 \u0246xd\u00f8\u0279\u0287", "Return to Your Dashboard": "\u024c\u01dd\u0287n\u0279n \u0287\u00f8 \u024e\u00f8n\u0279 \u0110\u0250s\u0265b\u00f8\u0250\u0279d", + "Return to all posts": "\u024c\u01dd\u0287n\u0279n \u0287\u00f8 \u0250ll d\u00f8s\u0287s", "Return to team listing": "\u024c\u01dd\u0287n\u0279n \u0287\u00f8 \u0287\u01dd\u0250\u026f l\u1d09s\u0287\u1d09n\u0183", "Review Rules": "\u024c\u01dd\u028c\u1d09\u01dd\u028d \u024cnl\u01dds", "Review Your Photos": "\u024c\u01dd\u028c\u1d09\u01dd\u028d \u024e\u00f8n\u0279 \u2c63\u0265\u00f8\u0287\u00f8s", @@ -1373,6 +1417,10 @@ "Short explanation": "S\u0265\u00f8\u0279\u0287 \u01ddxdl\u0250n\u0250\u0287\u1d09\u00f8n", "Show All": "S\u0265\u00f8\u028d \u023all", "Show Annotations": "S\u0265\u00f8\u028d \u023ann\u00f8\u0287\u0250\u0287\u1d09\u00f8ns", + "Show Comment (%(num_comments)s)": [ + "S\u0265\u00f8\u028d \u023b\u00f8\u026f\u026f\u01ddn\u0287 (%(num_comments)s)", + "S\u0265\u00f8\u028d \u023b\u00f8\u026f\u026f\u01ddn\u0287s (%(num_comments)s)" + ], "Show Deprecated Settings": "S\u0265\u00f8\u028d \u0110\u01ddd\u0279\u01dd\u0254\u0250\u0287\u01ddd S\u01dd\u0287\u0287\u1d09n\u0183s", "Show Discussion": "S\u0265\u00f8\u028d \u0110\u1d09s\u0254nss\u1d09\u00f8n", "Show Less": "S\u0265\u00f8\u028d \u0141\u01ddss", @@ -1409,6 +1457,7 @@ "Sign in using %(providerName)s": "S\u1d09\u0183n \u1d09n ns\u1d09n\u0183 %(providerName)s", "Sign in with %(providerName)s": "S\u1d09\u0183n \u1d09n \u028d\u1d09\u0287\u0265 %(providerName)s", "Sign in with Institution/Campus Credentials": "S\u1d09\u0183n \u1d09n \u028d\u1d09\u0287\u0265 \u0197ns\u0287\u1d09\u0287n\u0287\u1d09\u00f8n/\u023b\u0250\u026fdns \u023b\u0279\u01ddd\u01ddn\u0287\u1d09\u0250ls", + "Sign in with your company or school": "S\u1d09\u0183n \u1d09n \u028d\u1d09\u0287\u0265 \u028e\u00f8n\u0279 \u0254\u00f8\u026fd\u0250n\u028e \u00f8\u0279 s\u0254\u0265\u00f8\u00f8l", "Sign in.": "S\u1d09\u0183n \u1d09n.", "Signatory": "S\u1d09\u0183n\u0250\u0287\u00f8\u0279\u028e", "Signatory field(s) has invalid data.": "S\u1d09\u0183n\u0250\u0287\u00f8\u0279\u028e \u025f\u1d09\u01ddld(s) \u0265\u0250s \u1d09n\u028c\u0250l\u1d09d d\u0250\u0287\u0250.", @@ -1515,6 +1564,7 @@ "Task inputs": "\u0166\u0250s\u029e \u1d09ndn\u0287s", "Teaching Assistant": "\u0166\u01dd\u0250\u0254\u0265\u1d09n\u0183 \u023ass\u1d09s\u0287\u0250n\u0287", "Team \"{team}\" successfully deleted.": "\u0166\u01dd\u0250\u026f \"{team}\" sn\u0254\u0254\u01ddss\u025fnll\u028e d\u01ddl\u01dd\u0287\u01ddd.", + "Team Assignments": "\u0166\u01dd\u0250\u026f \u023ass\u1d09\u0183n\u026f\u01ddn\u0287s", "Team Description (Required) *": "\u0166\u01dd\u0250\u026f \u0110\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n (\u024c\u01ddbn\u1d09\u0279\u01ddd) *", "Team Details": "\u0166\u01dd\u0250\u026f \u0110\u01dd\u0287\u0250\u1d09ls", "Team Name (Required) *": "\u0166\u01dd\u0250\u026f N\u0250\u026f\u01dd (\u024c\u01ddbn\u1d09\u0279\u01ddd) *", @@ -1533,9 +1583,8 @@ "Textbook Name": "\u0166\u01ddx\u0287b\u00f8\u00f8\u029e N\u0250\u026f\u01dd", "Textbook information": "\u0166\u01ddx\u0287b\u00f8\u00f8\u029e \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n", "Textbook name is required": "\u0166\u01ddx\u0287b\u00f8\u00f8\u029e n\u0250\u026f\u01dd \u1d09s \u0279\u01ddbn\u1d09\u0279\u01ddd", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n %(full_name)s! W\u01dd \u0265\u0250\u028c\u01dd \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01ddd \u028e\u00f8n\u0279 d\u0250\u028e\u026f\u01ddn\u0287 \u025f\u00f8\u0279 %(course_name)s.", "Thank you for setting your course goal to {goal}!": "\u0166\u0265\u0250n\u029e \u028e\u00f8n \u025f\u00f8\u0279 s\u01dd\u0287\u0287\u1d09n\u0183 \u028e\u00f8n\u0279 \u0254\u00f8n\u0279s\u01dd \u0183\u00f8\u0250l \u0287\u00f8 {goal}!", - "Thank you for submitting a request! We will contact you within 24 hours.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n \u025f\u00f8\u0279 snb\u026f\u1d09\u0287\u0287\u1d09n\u0183 \u0250 \u0279\u01ddbn\u01dds\u0287! W\u01dd \u028d\u1d09ll \u0254\u00f8n\u0287\u0250\u0254\u0287 \u028e\u00f8n \u028d\u1d09\u0287\u0265\u1d09n 24 \u0265\u00f8n\u0279s.", + "Thank you for submitting a request! We appreciate your patience while we work to review your request.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n \u025f\u00f8\u0279 snb\u026f\u1d09\u0287\u0287\u1d09n\u0183 \u0250 \u0279\u01ddbn\u01dds\u0287! W\u01dd \u0250dd\u0279\u01dd\u0254\u1d09\u0250\u0287\u01dd \u028e\u00f8n\u0279 d\u0250\u0287\u1d09\u01ddn\u0254\u01dd \u028d\u0265\u1d09l\u01dd \u028d\u01dd \u028d\u00f8\u0279\u029e \u0287\u00f8 \u0279\u01dd\u028c\u1d09\u01dd\u028d \u028e\u00f8n\u0279 \u0279\u01ddbn\u01dds\u0287.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n \u025f\u00f8\u0279 snb\u026f\u1d09\u0287\u0287\u1d09n\u0183 \u028e\u00f8n\u0279 \u025f\u1d09n\u0250n\u0254\u1d09\u0250l \u0250ss\u1d09s\u0287\u0250n\u0254\u01dd \u0250ddl\u1d09\u0254\u0250\u0287\u1d09\u00f8n \u025f\u00f8\u0279 {course_name}! \u024e\u00f8n \u0254\u0250n \u01ddxd\u01dd\u0254\u0287 \u0250 \u0279\u01ddsd\u00f8ns\u01dd \u1d09n 2-4 bns\u1d09n\u01ddss d\u0250\u028es.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n \u025f\u00f8\u0279 snb\u026f\u1d09\u0287\u0287\u1d09n\u0183 \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8s. W\u01dd \u028d\u1d09ll \u0279\u01dd\u028c\u1d09\u01dd\u028d \u0287\u0265\u01dd\u026f s\u0265\u00f8\u0279\u0287l\u028e. \u024e\u00f8n \u0254\u0250n n\u00f8\u028d s\u1d09\u0183n nd \u025f\u00f8\u0279 \u0250n\u028e %(platformName)s \u0254\u00f8n\u0279s\u01dd \u0287\u0265\u0250\u0287 \u00f8\u025f\u025f\u01dd\u0279s \u028c\u01dd\u0279\u1d09\u025f\u1d09\u01ddd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dds. V\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n \u1d09s \u0183\u00f8\u00f8d \u025f\u00f8\u0279 \u00f8n\u01dd \u028e\u01dd\u0250\u0279. \u023a\u025f\u0287\u01dd\u0279 \u00f8n\u01dd \u028e\u01dd\u0250\u0279, \u028e\u00f8n \u026fns\u0287 snb\u026f\u1d09\u0287 d\u0265\u00f8\u0287\u00f8s \u025f\u00f8\u0279 \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n \u0250\u0183\u0250\u1d09n.", "Thank you! We have received your payment for {courseName}.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n! W\u01dd \u0265\u0250\u028c\u01dd \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01ddd \u028e\u00f8n\u0279 d\u0250\u028e\u026f\u01ddn\u0287 \u025f\u00f8\u0279 {courseName}.", @@ -1547,8 +1596,8 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u0166\u0265\u01dd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u025f\u00f8\u0279 \u0287\u0265\u1d09s l\u01dd\u0250\u0279n\u01dd\u0279 \u0265\u0250s b\u01dd\u01ddn \u0279\u01dd-\u028c\u0250l\u1d09d\u0250\u0287\u01ddd \u0250nd \u0287\u0265\u01dd s\u028es\u0287\u01dd\u026f \u1d09s \u0279\u01dd-\u0279nnn\u1d09n\u0183 \u0287\u0265\u01dd \u0183\u0279\u0250d\u01dd \u025f\u00f8\u0279 \u0287\u0265\u1d09s l\u01dd\u0250\u0279n\u01dd\u0279.", "The cohort cannot be added": "\u0166\u0265\u01dd \u0254\u00f8\u0265\u00f8\u0279\u0287 \u0254\u0250nn\u00f8\u0287 b\u01dd \u0250dd\u01ddd", "The cohort cannot be saved": "\u0166\u0265\u01dd \u0254\u00f8\u0265\u00f8\u0279\u0287 \u0254\u0250nn\u00f8\u0287 b\u01dd s\u0250\u028c\u01ddd", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u0166\u0265\u01dd \u0254\u00f8\u026fb\u1d09n\u01ddd l\u01ddn\u0183\u0287\u0265 \u00f8\u025f \u0287\u0265\u01dd \u00f8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n \u0250nd l\u1d09b\u0279\u0250\u0279\u028e \u0254\u00f8d\u01dd \u025f\u1d09\u01ddlds \u0254\u0250nn\u00f8\u0287 b\u01dd \u026f\u00f8\u0279\u01dd \u0287\u0265\u0250n <%=limit%> \u0254\u0265\u0250\u0279\u0250\u0254\u0287\u01dd\u0279s.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u0166\u0265\u01dd \u0254\u00f8\u026fb\u1d09n\u01ddd l\u01ddn\u0183\u0287\u0265 \u00f8\u025f \u0287\u0265\u01dd \u00f8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n, \u0254\u00f8n\u0279s\u01dd nn\u026fb\u01dd\u0279, \u0250nd \u0254\u00f8n\u0279s\u01dd \u0279nn \u025f\u1d09\u01ddlds \u0254\u0250nn\u00f8\u0287 b\u01dd \u026f\u00f8\u0279\u01dd \u0287\u0265\u0250n <%=limit%> \u0254\u0265\u0250\u0279\u0250\u0254\u0287\u01dd\u0279s.", + "The combined length of the organization and library code fields cannot be more than <%- limit %> characters.": "\u0166\u0265\u01dd \u0254\u00f8\u026fb\u1d09n\u01ddd l\u01ddn\u0183\u0287\u0265 \u00f8\u025f \u0287\u0265\u01dd \u00f8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n \u0250nd l\u1d09b\u0279\u0250\u0279\u028e \u0254\u00f8d\u01dd \u025f\u1d09\u01ddlds \u0254\u0250nn\u00f8\u0287 b\u01dd \u026f\u00f8\u0279\u01dd \u0287\u0265\u0250n <%- limit %> \u0254\u0265\u0250\u0279\u0250\u0254\u0287\u01dd\u0279s.", + "The combined length of the organization, course number, and course run fields cannot be more than <%- limit %> characters.": "\u0166\u0265\u01dd \u0254\u00f8\u026fb\u1d09n\u01ddd l\u01ddn\u0183\u0287\u0265 \u00f8\u025f \u0287\u0265\u01dd \u00f8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n, \u0254\u00f8n\u0279s\u01dd nn\u026fb\u01dd\u0279, \u0250nd \u0254\u00f8n\u0279s\u01dd \u0279nn \u025f\u1d09\u01ddlds \u0254\u0250nn\u00f8\u0287 b\u01dd \u026f\u00f8\u0279\u01dd \u0287\u0265\u0250n <%- limit %> \u0254\u0265\u0250\u0279\u0250\u0254\u0287\u01dd\u0279s.", "The country or region where you live.": "\u0166\u0265\u01dd \u0254\u00f8nn\u0287\u0279\u028e \u00f8\u0279 \u0279\u01dd\u0183\u1d09\u00f8n \u028d\u0265\u01dd\u0279\u01dd \u028e\u00f8n l\u1d09\u028c\u01dd.", "The country that team members primarily identify with.": "\u0166\u0265\u01dd \u0254\u00f8nn\u0287\u0279\u028e \u0287\u0265\u0250\u0287 \u0287\u01dd\u0250\u026f \u026f\u01dd\u026fb\u01dd\u0279s d\u0279\u1d09\u026f\u0250\u0279\u1d09l\u028e \u1d09d\u01ddn\u0287\u1d09\u025f\u028e \u028d\u1d09\u0287\u0265.", "The course end date must be later than the course start date.": "\u0166\u0265\u01dd \u0254\u00f8n\u0279s\u01dd \u01ddnd d\u0250\u0287\u01dd \u026fns\u0287 b\u01dd l\u0250\u0287\u01dd\u0279 \u0287\u0265\u0250n \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd s\u0287\u0250\u0279\u0287 d\u0250\u0287\u01dd.", @@ -1563,7 +1612,7 @@ "The file you are trying to upload is too large.": "\u0166\u0265\u01dd \u025f\u1d09l\u01dd \u028e\u00f8n \u0250\u0279\u01dd \u0287\u0279\u028e\u1d09n\u0183 \u0287\u00f8 ndl\u00f8\u0250d \u1d09s \u0287\u00f8\u00f8 l\u0250\u0279\u0183\u01dd.", "The following email addresses and/or usernames are invalid:": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u01dd\u026f\u0250\u1d09l \u0250dd\u0279\u01ddss\u01dds \u0250nd/\u00f8\u0279 ns\u01dd\u0279n\u0250\u026f\u01dds \u0250\u0279\u01dd \u1d09n\u028c\u0250l\u1d09d:", "The following errors were generated:": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u01dd\u0279\u0279\u00f8\u0279s \u028d\u01dd\u0279\u01dd \u0183\u01ddn\u01dd\u0279\u0250\u0287\u01ddd:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u1d09s \u0250l\u0279\u01dd\u0250d\u028e \u0250 d\u0250\u0279\u0287 \u00f8\u025f \u028e\u00f8n\u0279 {platform} d\u0279\u00f8\u025f\u1d09l\u01dd. W\u01dd\\'\u028c\u01dd \u1d09n\u0254lnd\u01ddd \u1d09\u0287 \u0265\u01dd\u0279\u01dd \u025f\u00f8\u0279 \u028e\u00f8n\u0279 \u0250ddl\u1d09\u0254\u0250\u0287\u1d09\u00f8n.", + "The following information is already a part of your {platform} profile. We've included it here for your application.": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u1d09s \u0250l\u0279\u01dd\u0250d\u028e \u0250 d\u0250\u0279\u0287 \u00f8\u025f \u028e\u00f8n\u0279 {platform} d\u0279\u00f8\u025f\u1d09l\u01dd. W\u01dd'\u028c\u01dd \u1d09n\u0254lnd\u01ddd \u1d09\u0287 \u0265\u01dd\u0279\u01dd \u025f\u00f8\u0279 \u028e\u00f8n\u0279 \u0250ddl\u1d09\u0254\u0250\u0287\u1d09\u00f8n.", "The following message will be displayed at the bottom of the courseware pages within your course:": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u026f\u01ddss\u0250\u0183\u01dd \u028d\u1d09ll b\u01dd d\u1d09sdl\u0250\u028e\u01ddd \u0250\u0287 \u0287\u0265\u01dd b\u00f8\u0287\u0287\u00f8\u026f \u00f8\u025f \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd\u028d\u0250\u0279\u01dd d\u0250\u0183\u01dds \u028d\u1d09\u0287\u0265\u1d09n \u028e\u00f8n\u0279 \u0254\u00f8n\u0279s\u01dd:", "The following options are available for the {license_name} license.": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u00f8d\u0287\u1d09\u00f8ns \u0250\u0279\u01dd \u0250\u028c\u0250\u1d09l\u0250bl\u01dd \u025f\u00f8\u0279 \u0287\u0265\u01dd {license_name} l\u1d09\u0254\u01ddns\u01dd.", "The following users are no longer enrolled in the course:": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 ns\u01dd\u0279s \u0250\u0279\u01dd n\u00f8 l\u00f8n\u0183\u01dd\u0279 \u01ddn\u0279\u00f8ll\u01ddd \u1d09n \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd:", @@ -1575,7 +1624,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "\u0166\u0265\u01dd \u026f\u1d09n\u1d09\u026fn\u026f \u0254\u00f8\u026fdl\u01dd\u0287\u1d09\u00f8n d\u01dd\u0279\u0254\u01ddn\u0287\u0250\u0183\u01dd \u026fns\u0287 b\u01dd \u0250 \u028d\u0265\u00f8l\u01dd nn\u026fb\u01dd\u0279 b\u01dd\u0287\u028d\u01dd\u01ddn 0 \u0250nd 100.", "The minimum grade for course credit is not set.": "\u0166\u0265\u01dd \u026f\u1d09n\u1d09\u026fn\u026f \u0183\u0279\u0250d\u01dd \u025f\u00f8\u0279 \u0254\u00f8n\u0279s\u01dd \u0254\u0279\u01ddd\u1d09\u0287 \u1d09s n\u00f8\u0287 s\u01dd\u0287.", "The minimum score percentage must be a whole number between 0 and 100.": "\u0166\u0265\u01dd \u026f\u1d09n\u1d09\u026fn\u026f s\u0254\u00f8\u0279\u01dd d\u01dd\u0279\u0254\u01ddn\u0287\u0250\u0183\u01dd \u026fns\u0287 b\u01dd \u0250 \u028d\u0265\u00f8l\u01dd nn\u026fb\u01dd\u0279 b\u01dd\u0287\u028d\u01dd\u01ddn 0 \u0250nd 100.", - "The more you tell us, the more quickly and helpfully we can respond!": "\u0166\u0265\u01dd \u026f\u00f8\u0279\u01dd \u028e\u00f8n \u0287\u01ddll ns, \u0287\u0265\u01dd \u026f\u00f8\u0279\u01dd bn\u1d09\u0254\u029el\u028e \u0250nd \u0265\u01ddld\u025fnll\u028e \u028d\u01dd \u0254\u0250n \u0279\u01ddsd\u00f8nd!", "The name of this signatory as it should appear on certificates.": "\u0166\u0265\u01dd n\u0250\u026f\u01dd \u00f8\u025f \u0287\u0265\u1d09s s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u028e \u0250s \u1d09\u0287 s\u0265\u00f8nld \u0250dd\u01dd\u0250\u0279 \u00f8n \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dds.", "The name that identifies you on {platform_name}. You cannot change your username.": "\u0166\u0265\u01dd n\u0250\u026f\u01dd \u0287\u0265\u0250\u0287 \u1d09d\u01ddn\u0287\u1d09\u025f\u1d09\u01dds \u028e\u00f8n \u00f8n {platform_name}. \u024e\u00f8n \u0254\u0250nn\u00f8\u0287 \u0254\u0265\u0250n\u0183\u01dd \u028e\u00f8n\u0279 ns\u01dd\u0279n\u0250\u026f\u01dd.", "The name that is used for ID verification and that appears on your certificates.": "\u0166\u0265\u01dd n\u0250\u026f\u01dd \u0287\u0265\u0250\u0287 \u1d09s ns\u01ddd \u025f\u00f8\u0279 \u0197\u0110 \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n \u0250nd \u0287\u0265\u0250\u0287 \u0250dd\u01dd\u0250\u0279s \u00f8n \u028e\u00f8n\u0279 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dds.", @@ -1583,7 +1631,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "\u0166\u0265\u01dd nn\u026fb\u01dd\u0279 \u00f8\u025f snbs\u01dd\u0254\u0287\u1d09\u00f8ns \u1d09n \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd \u0287\u0265\u0250\u0287 \u0254\u00f8n\u0287\u0250\u1d09n d\u0279\u00f8bl\u01dd\u026fs \u00f8\u025f \u0287\u0265\u1d09s \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287 \u0287\u028ed\u01dd.", "The organization that this signatory belongs to, as it should appear on certificates.": "\u0166\u0265\u01dd \u00f8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n \u0287\u0265\u0250\u0287 \u0287\u0265\u1d09s s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u028e b\u01ddl\u00f8n\u0183s \u0287\u00f8, \u0250s \u1d09\u0287 s\u0265\u00f8nld \u0250dd\u01dd\u0250\u0279 \u00f8n \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dds.", "The page \"{route}\" could not be found.": "\u0166\u0265\u01dd d\u0250\u0183\u01dd \"{route}\" \u0254\u00f8nld n\u00f8\u0287 b\u01dd \u025f\u00f8nnd.", - "The photo of your face matches the photo on your ID.": "\u0166\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd \u026f\u0250\u0287\u0254\u0265\u01dds \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8n \u028e\u00f8n\u0279 \u0197\u0110.", "The post you selected has been deleted.": "\u0166\u0265\u01dd d\u00f8s\u0287 \u028e\u00f8n s\u01ddl\u01dd\u0254\u0287\u01ddd \u0265\u0250s b\u01dd\u01ddn d\u01ddl\u01dd\u0287\u01ddd.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "\u0166\u0265\u01dd dnbl\u1d09s\u0265\u01ddd b\u0279\u0250n\u0254\u0265 \u028c\u01dd\u0279s\u1d09\u00f8n, {published}, \u028d\u0250s \u0279\u01dds\u01dd\u0287 \u0287\u00f8 \u0287\u0265\u01dd d\u0279\u0250\u025f\u0287 b\u0279\u0250n\u0254\u0265 \u028c\u01dd\u0279s\u1d09\u00f8n, {draft}.", "The raw error message is:": "\u0166\u0265\u01dd \u0279\u0250\u028d \u01dd\u0279\u0279\u00f8\u0279 \u026f\u01ddss\u0250\u0183\u01dd \u1d09s:", @@ -1675,6 +1722,10 @@ "This post could not be reopened. Refresh the page and try again.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u0254\u00f8nld n\u00f8\u0287 b\u01dd \u0279\u01dd\u00f8d\u01ddn\u01ddd. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", "This post could not be unflagged for abuse. Refresh the page and try again.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u0254\u00f8nld n\u00f8\u0287 b\u01dd nn\u025fl\u0250\u0183\u0183\u01ddd \u025f\u00f8\u0279 \u0250bns\u01dd. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", "This post could not be unpinned. Refresh the page and try again.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u0254\u00f8nld n\u00f8\u0287 b\u01dd nnd\u1d09nn\u01ddd. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", + "This post is visible only to %(group_name)s.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u1d09s \u028c\u1d09s\u1d09bl\u01dd \u00f8nl\u028e \u0287\u00f8 %(group_name)s.", + "This post is visible to everyone.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u1d09s \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 \u01dd\u028c\u01dd\u0279\u028e\u00f8n\u01dd.", + "This post will be visible only to %(group_name)s.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u028d\u1d09ll b\u01dd \u028c\u1d09s\u1d09bl\u01dd \u00f8nl\u028e \u0287\u00f8 %(group_name)s.", + "This post will be visible to everyone.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u028d\u1d09ll b\u01dd \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 \u01dd\u028c\u01dd\u0279\u028e\u00f8n\u01dd.", "This problem has been reset.": "\u0166\u0265\u1d09s d\u0279\u00f8bl\u01dd\u026f \u0265\u0250s b\u01dd\u01ddn \u0279\u01dds\u01dd\u0287.", "This response could not be marked as an answer. Refresh the page and try again.": "\u0166\u0265\u1d09s \u0279\u01ddsd\u00f8ns\u01dd \u0254\u00f8nld n\u00f8\u0287 b\u01dd \u026f\u0250\u0279\u029e\u01ddd \u0250s \u0250n \u0250ns\u028d\u01dd\u0279. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", "This response could not be marked as endorsed. Refresh the page and try again.": "\u0166\u0265\u1d09s \u0279\u01ddsd\u00f8ns\u01dd \u0254\u00f8nld n\u00f8\u0287 b\u01dd \u026f\u0250\u0279\u029e\u01ddd \u0250s \u01ddnd\u00f8\u0279s\u01ddd. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", @@ -1682,8 +1733,11 @@ "This response could not be unmarked as an answer. Refresh the page and try again.": "\u0166\u0265\u1d09s \u0279\u01ddsd\u00f8ns\u01dd \u0254\u00f8nld n\u00f8\u0287 b\u01dd nn\u026f\u0250\u0279\u029e\u01ddd \u0250s \u0250n \u0250ns\u028d\u01dd\u0279. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", "This role requires a divided discussions scheme.": "\u0166\u0265\u1d09s \u0279\u00f8l\u01dd \u0279\u01ddbn\u1d09\u0279\u01dds \u0250 d\u1d09\u028c\u1d09d\u01ddd d\u1d09s\u0254nss\u1d09\u00f8ns s\u0254\u0265\u01dd\u026f\u01dd.", "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.": "\u0166\u0265\u1d09s s\u0265\u00f8\u0279\u0287 n\u0250\u026f\u01dd \u025f\u00f8\u0279 \u0287\u0265\u01dd \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287 \u0287\u028ed\u01dd (\u025f\u00f8\u0279 \u01ddx\u0250\u026fdl\u01dd, \u0126W \u00f8\u0279 M\u1d09d\u0287\u01dd\u0279\u026f) \u0250dd\u01dd\u0250\u0279s n\u01ddx\u0287 \u0287\u00f8 \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287s \u00f8n \u0250 l\u01dd\u0250\u0279n\u01dd\u0279's \u2c63\u0279\u00f8\u0183\u0279\u01ddss d\u0250\u0183\u01dd.", + "This special exam has been released to learners. You may not convert it to another type of special exam. You may revert this subsection back to being a basic exam by selecting 'None', but you will NOT be able to configure it as a special exam in the future.": "\u0166\u0265\u1d09s sd\u01dd\u0254\u1d09\u0250l \u01ddx\u0250\u026f \u0265\u0250s b\u01dd\u01ddn \u0279\u01ddl\u01dd\u0250s\u01ddd \u0287\u00f8 l\u01dd\u0250\u0279n\u01dd\u0279s. \u024e\u00f8n \u026f\u0250\u028e n\u00f8\u0287 \u0254\u00f8n\u028c\u01dd\u0279\u0287 \u1d09\u0287 \u0287\u00f8 \u0250n\u00f8\u0287\u0265\u01dd\u0279 \u0287\u028ed\u01dd \u00f8\u025f sd\u01dd\u0254\u1d09\u0250l \u01ddx\u0250\u026f. \u024e\u00f8n \u026f\u0250\u028e \u0279\u01dd\u028c\u01dd\u0279\u0287 \u0287\u0265\u1d09s snbs\u01dd\u0254\u0287\u1d09\u00f8n b\u0250\u0254\u029e \u0287\u00f8 b\u01dd\u1d09n\u0183 \u0250 b\u0250s\u1d09\u0254 \u01ddx\u0250\u026f b\u028e s\u01ddl\u01dd\u0254\u0287\u1d09n\u0183 'N\u00f8n\u01dd', bn\u0287 \u028e\u00f8n \u028d\u1d09ll N\u00d8\u0166 b\u01dd \u0250bl\u01dd \u0287\u00f8 \u0254\u00f8n\u025f\u1d09\u0183n\u0279\u01dd \u1d09\u0287 \u0250s \u0250 sd\u01dd\u0254\u1d09\u0250l \u01ddx\u0250\u026f \u1d09n \u0287\u0265\u01dd \u025fn\u0287n\u0279\u01dd.", + "This subsection was released to learners as a special exam, but was reverted back to a basic exam. You may not configure it as a special exam now. Contact edX Support for assistance.": "\u0166\u0265\u1d09s snbs\u01dd\u0254\u0287\u1d09\u00f8n \u028d\u0250s \u0279\u01ddl\u01dd\u0250s\u01ddd \u0287\u00f8 l\u01dd\u0250\u0279n\u01dd\u0279s \u0250s \u0250 sd\u01dd\u0254\u1d09\u0250l \u01ddx\u0250\u026f, bn\u0287 \u028d\u0250s \u0279\u01dd\u028c\u01dd\u0279\u0287\u01ddd b\u0250\u0254\u029e \u0287\u00f8 \u0250 b\u0250s\u1d09\u0254 \u01ddx\u0250\u026f. \u024e\u00f8n \u026f\u0250\u028e n\u00f8\u0287 \u0254\u00f8n\u025f\u1d09\u0183n\u0279\u01dd \u1d09\u0287 \u0250s \u0250 sd\u01dd\u0254\u1d09\u0250l \u01ddx\u0250\u026f n\u00f8\u028d. \u023b\u00f8n\u0287\u0250\u0254\u0287 \u01dddX Sndd\u00f8\u0279\u0287 \u025f\u00f8\u0279 \u0250ss\u1d09s\u0287\u0250n\u0254\u01dd.", "This team does not have any members.": "\u0166\u0265\u1d09s \u0287\u01dd\u0250\u026f d\u00f8\u01dds n\u00f8\u0287 \u0265\u0250\u028c\u01dd \u0250n\u028e \u026f\u01dd\u026fb\u01dd\u0279s.", "This team is full.": "\u0166\u0265\u1d09s \u0287\u01dd\u0250\u026f \u1d09s \u025fnll.", + "This thread is closed.": "\u0166\u0265\u1d09s \u0287\u0265\u0279\u01dd\u0250d \u1d09s \u0254l\u00f8s\u01ddd.", "This unit has validation issues.": "\u0166\u0265\u1d09s nn\u1d09\u0287 \u0265\u0250s \u028c\u0250l\u1d09d\u0250\u0287\u1d09\u00f8n \u1d09ssn\u01dds.", "This vote could not be processed. Refresh the page and try again.": "\u0166\u0265\u1d09s \u028c\u00f8\u0287\u01dd \u0254\u00f8nld n\u00f8\u0287 b\u01dd d\u0279\u00f8\u0254\u01ddss\u01ddd. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", "This {parentCategory} has no {childCategory}": "\u0166\u0265\u1d09s {parentCategory} \u0265\u0250s n\u00f8 {childCategory}", @@ -1708,7 +1762,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "\u0166\u00f8 b\u01dd sn\u0279\u01dd \u0250ll s\u0287nd\u01ddn\u0287s \u0254\u0250n \u0250\u0254\u0254\u01ddss \u0287\u0265\u01dd \u028c\u1d09d\u01dd\u00f8, \u028d\u01dd \u0279\u01dd\u0254\u00f8\u026f\u026f\u01ddnd d\u0279\u00f8\u028c\u1d09d\u1d09n\u0183 b\u00f8\u0287\u0265 \u0250n .\u026fd4 \u0250nd \u0250 .\u028d\u01ddb\u026f \u028c\u01dd\u0279s\u1d09\u00f8n \u00f8\u025f \u028e\u00f8n\u0279 \u028c\u1d09d\u01dd\u00f8. \u023bl\u1d09\u0254\u029e b\u01ddl\u00f8\u028d \u0287\u00f8 \u0250dd \u0250 \u0244\u024c\u0141 \u025f\u00f8\u0279 \u0250n\u00f8\u0287\u0265\u01dd\u0279 \u028c\u01dd\u0279s\u1d09\u00f8n. \u0166\u0265\u01dds\u01dd \u0244\u024c\u0141s \u0254\u0250nn\u00f8\u0287 b\u01dd \u024e\u00f8n\u0166nb\u01dd \u0244\u024c\u0141s. \u0166\u0265\u01dd \u025f\u1d09\u0279s\u0287 l\u1d09s\u0287\u01ddd \u028c\u1d09d\u01dd\u00f8 \u0287\u0265\u0250\u0287's \u0254\u00f8\u026fd\u0250\u0287\u1d09bl\u01dd \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd s\u0287nd\u01ddn\u0287's \u0254\u00f8\u026fdn\u0287\u01dd\u0279 \u028d\u1d09ll dl\u0250\u028e.", "To complete the program, you must earn a verified certificate for each course.": "\u0166\u00f8 \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0287\u0265\u01dd d\u0279\u00f8\u0183\u0279\u0250\u026f, \u028e\u00f8n \u026fns\u0287 \u01dd\u0250\u0279n \u0250 \u028c\u01dd\u0279\u1d09\u025f\u1d09\u01ddd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u025f\u00f8\u0279 \u01dd\u0250\u0254\u0265 \u0254\u00f8n\u0279s\u01dd.", "To continue learning with this account, sign in below.": "\u0166\u00f8 \u0254\u00f8n\u0287\u1d09nn\u01dd l\u01dd\u0250\u0279n\u1d09n\u0183 \u028d\u1d09\u0287\u0265 \u0287\u0265\u1d09s \u0250\u0254\u0254\u00f8nn\u0287, s\u1d09\u0183n \u1d09n b\u01ddl\u00f8\u028d.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "\u0166\u00f8 \u025f\u1d09n\u0250l\u1d09z\u01dd \u0254\u00f8n\u0279s\u01dd \u0254\u0279\u01ddd\u1d09\u0287, %(display_name)s \u0279\u01ddbn\u1d09\u0279\u01dds %(platform_name)s l\u01dd\u0250\u0279n\u01dd\u0279s \u0287\u00f8 snb\u026f\u1d09\u0287 \u0250 \u0254\u0279\u01ddd\u1d09\u0287 \u0279\u01ddbn\u01dds\u0287.", "To invalidate a certificate for a particular learner, add the username or email address below.": "\u0166\u00f8 \u1d09n\u028c\u0250l\u1d09d\u0250\u0287\u01dd \u0250 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u025f\u00f8\u0279 \u0250 d\u0250\u0279\u0287\u1d09\u0254nl\u0250\u0279 l\u01dd\u0250\u0279n\u01dd\u0279, \u0250dd \u0287\u0265\u01dd ns\u01dd\u0279n\u0250\u026f\u01dd \u00f8\u0279 \u01dd\u026f\u0250\u1d09l \u0250dd\u0279\u01ddss b\u01ddl\u00f8\u028d.", "To receive a certificate, you must also verify your identity before {date}.": "\u0166\u00f8 \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd \u0250 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd, \u028e\u00f8n \u026fns\u0287 \u0250ls\u00f8 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e b\u01dd\u025f\u00f8\u0279\u01dd {date}.", "To receive a certificate, you must also verify your identity.": "\u0166\u00f8 \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd \u0250 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd, \u028e\u00f8n \u026fns\u0287 \u0250ls\u00f8 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e.", @@ -1716,13 +1769,14 @@ "To review learner cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on the {link_start}Data Download{link_end} page.": "\u0166\u00f8 \u0279\u01dd\u028c\u1d09\u01dd\u028d l\u01dd\u0250\u0279n\u01dd\u0279 \u0254\u00f8\u0265\u00f8\u0279\u0287 \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287s \u00f8\u0279 s\u01dd\u01dd \u0287\u0265\u01dd \u0279\u01ddsnl\u0287s \u00f8\u025f ndl\u00f8\u0250d\u1d09n\u0183 \u0250 \u023bSV \u025f\u1d09l\u01dd, d\u00f8\u028dnl\u00f8\u0250d \u0254\u00f8n\u0279s\u01dd d\u0279\u00f8\u025f\u1d09l\u01dd \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u00f8\u0279 \u0254\u00f8\u0265\u00f8\u0279\u0287 \u0279\u01ddsnl\u0287s \u00f8n \u0287\u0265\u01dd {link_start}\u0110\u0250\u0287\u0250 \u0110\u00f8\u028dnl\u00f8\u0250d{link_end} d\u0250\u0183\u01dd.", "To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.": "\u0166\u00f8 s\u0265\u0250\u0279\u01dd \u028e\u00f8n\u0279 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u00f8n M\u00f8z\u1d09ll\u0250 \u0243\u0250\u0254\u029ed\u0250\u0254\u029e, \u028e\u00f8n \u026fns\u0287 \u025f\u1d09\u0279s\u0287 \u0265\u0250\u028c\u01dd \u0250 \u0243\u0250\u0254\u029ed\u0250\u0254\u029e \u0250\u0254\u0254\u00f8nn\u0287. \u023b\u00f8\u026fdl\u01dd\u0287\u01dd \u0287\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 s\u0287\u01ddds \u0287\u00f8 \u0250dd \u028e\u00f8n\u0279 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u0287\u00f8 \u0243\u0250\u0254\u029ed\u0250\u0254\u029e.", "To take a successful photo, make sure that:": "\u0166\u00f8 \u0287\u0250\u029e\u01dd \u0250 sn\u0254\u0254\u01ddss\u025fnl d\u0265\u00f8\u0287\u00f8, \u026f\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u0265\u0250\u0287:", - "To use the current photo, select the Take Photo button {icon}. To take another photo, select the Retake Photo button {icon}.": "\u0166\u00f8 ns\u01dd \u0287\u0265\u01dd \u0254n\u0279\u0279\u01ddn\u0287 d\u0265\u00f8\u0287\u00f8, s\u01ddl\u01dd\u0254\u0287 \u0287\u0265\u01dd \u0166\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8 bn\u0287\u0287\u00f8n {icon}. \u0166\u00f8 \u0287\u0250\u029e\u01dd \u0250n\u00f8\u0287\u0265\u01dd\u0279 d\u0265\u00f8\u0287\u00f8, s\u01ddl\u01dd\u0254\u0287 \u0287\u0265\u01dd \u024c\u01dd\u0287\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8 bn\u0287\u0287\u00f8n {icon}.", + "To take the photo of your face, click on the camera button {icon}. If you need to try again, click 'Retake Photo'.": "\u0166\u00f8 \u0287\u0250\u029e\u01dd \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd, \u0254l\u1d09\u0254\u029e \u00f8n \u0287\u0265\u01dd \u0254\u0250\u026f\u01dd\u0279\u0250 bn\u0287\u0287\u00f8n {icon}. \u0197\u025f \u028e\u00f8n n\u01dd\u01ddd \u0287\u00f8 \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n, \u0254l\u1d09\u0254\u029e '\u024c\u01dd\u0287\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8'.", "To verify your identity, you need a webcam and a government-issued photo ID.": "\u0166\u00f8 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e, \u028e\u00f8n n\u01dd\u01ddd \u0250 \u028d\u01ddb\u0254\u0250\u026f \u0250nd \u0250 \u0183\u00f8\u028c\u01dd\u0279n\u026f\u01ddn\u0287-\u1d09ssn\u01ddd d\u0265\u00f8\u0287\u00f8 \u0197\u0110.", "Toggle Account Password (Usable/Unusable)": "\u0166\u00f8\u0183\u0183l\u01dd \u023a\u0254\u0254\u00f8nn\u0287 \u2c63\u0250ss\u028d\u00f8\u0279d (\u0244s\u0250bl\u01dd/\u0244nns\u0250bl\u01dd)", "Toggle Notifications Setting": "\u0166\u00f8\u0183\u0183l\u01dd N\u00f8\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8ns S\u01dd\u0287\u0287\u1d09n\u0183", "Tools": "\u0166\u00f8\u00f8ls", "Top": "\u0166\u00f8d", "Topic": "\u0166\u00f8d\u1d09\u0254", + "Topic area": "\u0166\u00f8d\u1d09\u0254 \u0250\u0279\u01dd\u0250", "Topics": "\u0166\u00f8d\u1d09\u0254s", "Total": "\u0166\u00f8\u0287\u0250l", "Total Number": "\u0166\u00f8\u0287\u0250l Nn\u026fb\u01dd\u0279", @@ -1749,6 +1803,8 @@ "Undo Changes": "\u0244nd\u00f8 \u023b\u0265\u0250n\u0183\u01dds", "Undo move": "\u0244nd\u00f8 \u026f\u00f8\u028c\u01dd", "Undo moving": "\u0244nd\u00f8 \u026f\u00f8\u028c\u1d09n\u0183", + "Unendorse": "\u0244n\u01ddnd\u00f8\u0279s\u01dd", + "Unfollow": "\u0244n\u025f\u00f8ll\u00f8\u028d", "Ungraded": "\u0244n\u0183\u0279\u0250d\u01ddd", "Unit": "\u0244n\u1d09\u0287", "Unit Access": "\u0244n\u1d09\u0287 \u023a\u0254\u0254\u01ddss", @@ -1759,13 +1815,19 @@ "Unlink This Account": "\u0244nl\u1d09n\u029e \u0166\u0265\u1d09s \u023a\u0254\u0254\u00f8nn\u0287", "Unlink your {accountName} account": "\u0244nl\u1d09n\u029e \u028e\u00f8n\u0279 {accountName} \u0250\u0254\u0254\u00f8nn\u0287", "Unlinking": "\u0244nl\u1d09n\u029e\u1d09n\u0183", + "Unmark as Answer": "\u0244n\u026f\u0250\u0279\u029e \u0250s \u023ans\u028d\u01dd\u0279", "Unmute": "\u0244n\u026fn\u0287\u01dd", + "Unpin": "\u0244nd\u1d09n", "Unpublished changes to content that will release in the future": "\u0244ndnbl\u1d09s\u0265\u01ddd \u0254\u0265\u0250n\u0183\u01dds \u0287\u00f8 \u0254\u00f8n\u0287\u01ddn\u0287 \u0287\u0265\u0250\u0287 \u028d\u1d09ll \u0279\u01ddl\u01dd\u0250s\u01dd \u1d09n \u0287\u0265\u01dd \u025fn\u0287n\u0279\u01dd", "Unpublished changes to live content": "\u0244ndnbl\u1d09s\u0265\u01ddd \u0254\u0265\u0250n\u0183\u01dds \u0287\u00f8 l\u1d09\u028c\u01dd \u0254\u00f8n\u0287\u01ddn\u0287", "Unpublished units will not be released": "\u0244ndnbl\u1d09s\u0265\u01ddd nn\u1d09\u0287s \u028d\u1d09ll n\u00f8\u0287 b\u01dd \u0279\u01ddl\u01dd\u0250s\u01ddd", + "Unreport": "\u0244n\u0279\u01ddd\u00f8\u0279\u0287", "Unscheduled": "\u0244ns\u0254\u0265\u01dddnl\u01ddd", "Update": "\u0244dd\u0250\u0287\u01dd", "Update Settings": "\u0244dd\u0250\u0287\u01dd S\u01dd\u0287\u0287\u1d09n\u0183s", + "Update comment": "\u0244dd\u0250\u0287\u01dd \u0254\u00f8\u026f\u026f\u01ddn\u0287", + "Update post": "\u0244dd\u0250\u0287\u01dd d\u00f8s\u0287", + "Update response": "\u0244dd\u0250\u0287\u01dd \u0279\u01ddsd\u00f8ns\u01dd", "Update team.": "\u0244dd\u0250\u0287\u01dd \u0287\u01dd\u0250\u026f.", "Updating Tags": "\u0244dd\u0250\u0287\u1d09n\u0183 \u0166\u0250\u0183s", "Updating with latest library content": "\u0244dd\u0250\u0287\u1d09n\u0183 \u028d\u1d09\u0287\u0265 l\u0250\u0287\u01dds\u0287 l\u1d09b\u0279\u0250\u0279\u028e \u0254\u00f8n\u0287\u01ddn\u0287", @@ -1787,7 +1849,7 @@ "Upload Videos": "\u0244dl\u00f8\u0250d V\u1d09d\u01dd\u00f8s", "Upload a CSV file": "\u0244dl\u00f8\u0250d \u0250 \u023bSV \u025f\u1d09l\u01dd", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u0244dl\u00f8\u0250d \u0250 \u0254\u00f8\u026f\u026f\u0250 s\u01ddd\u0250\u0279\u0250\u0287\u01ddd \u028c\u0250ln\u01dds (.\u0254s\u028c) \u025f\u1d09l\u01dd \u0287\u0265\u0250\u0287 \u0254\u00f8n\u0287\u0250\u1d09ns \u0287\u0265\u01dd ns\u01dd\u0279n\u0250\u026f\u01dds \u00f8\u0279 \u01dd\u026f\u0250\u1d09l \u0250dd\u0279\u01ddss\u01dds \u00f8\u025f l\u01dd\u0250\u0279n\u01dd\u0279s \u028d\u0265\u00f8 \u0265\u0250\u028c\u01dd b\u01dd\u01ddn \u0183\u1d09\u028c\u01ddn \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8ns. \u0197n\u0254lnd\u01dd \u0287\u0265\u01dd ns\u01dd\u0279n\u0250\u026f\u01dd \u00f8\u0279 \u01dd\u026f\u0250\u1d09l \u0250dd\u0279\u01ddss \u1d09n \u0287\u0265\u01dd \u025f\u1d09\u0279s\u0287 \u0254\u00f8\u026f\u026f\u0250 s\u01ddd\u0250\u0279\u0250\u0287\u01ddd \u025f\u1d09\u01ddld. \u024e\u00f8n \u0254\u0250n \u1d09n\u0254lnd\u01dd \u0250n \u00f8d\u0287\u1d09\u00f8n\u0250l n\u00f8\u0287\u01dd d\u01dds\u0254\u0279\u1d09b\u1d09n\u0183 \u0287\u0265\u01dd \u0279\u01dd\u0250s\u00f8n \u025f\u00f8\u0279 \u0287\u0265\u01dd \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8n \u1d09n \u0287\u0265\u01dd s\u01dd\u0254\u00f8nd \u0254\u00f8\u026f\u026f\u0250 s\u01ddd\u0250\u0279\u0250\u0287\u01ddd \u025f\u1d09\u01ddld.", - "Upload a new PDF to \u201c<%= name %>\u201d": "\u0244dl\u00f8\u0250d \u0250 n\u01dd\u028d \u2c63\u0110F \u0287\u00f8 \u201c<%= name %>\u201d", + "Upload a new PDF to \u201c<%- name %>\u201d": "\u0244dl\u00f8\u0250d \u0250 n\u01dd\u028d \u2c63\u0110F \u0287\u00f8 \u201c<%- name %>\u201d", "Upload an image": "\u0244dl\u00f8\u0250d \u0250n \u1d09\u026f\u0250\u0183\u01dd", "Upload an image or capture one with your web or phone camera.": "\u0244dl\u00f8\u0250d \u0250n \u1d09\u026f\u0250\u0183\u01dd \u00f8\u0279 \u0254\u0250d\u0287n\u0279\u01dd \u00f8n\u01dd \u028d\u1d09\u0287\u0265 \u028e\u00f8n\u0279 \u028d\u01ddb \u00f8\u0279 d\u0265\u00f8n\u01dd \u0254\u0250\u026f\u01dd\u0279\u0250.", "Upload completed": "\u0244dl\u00f8\u0250d \u0254\u00f8\u026fdl\u01dd\u0287\u01ddd", @@ -1822,7 +1884,7 @@ "Use my university info": "\u0244s\u01dd \u026f\u028e nn\u1d09\u028c\u01dd\u0279s\u1d09\u0287\u028e \u1d09n\u025f\u00f8", "Use the All Topics menu to find specific topics.": "\u0244s\u01dd \u0287\u0265\u01dd \u023all \u0166\u00f8d\u1d09\u0254s \u026f\u01ddnn \u0287\u00f8 \u025f\u1d09nd sd\u01dd\u0254\u1d09\u025f\u1d09\u0254 \u0287\u00f8d\u1d09\u0254s.", "Use the Retake Photo button if you are not pleased with your photo": "\u0244s\u01dd \u0287\u0265\u01dd \u024c\u01dd\u0287\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8 bn\u0287\u0287\u00f8n \u1d09\u025f \u028e\u00f8n \u0250\u0279\u01dd n\u00f8\u0287 dl\u01dd\u0250s\u01ddd \u028d\u1d09\u0287\u0265 \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u0244s\u01dd \u028e\u00f8n\u0279 \u028d\u01ddb\u0254\u0250\u026f \u0287\u00f8 \u0287\u0250\u029e\u01dd \u0250 d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u0197\u0110. W\u01dd \u028d\u1d09ll \u026f\u0250\u0287\u0254\u0265 \u0287\u0265\u1d09s d\u0265\u00f8\u0287\u00f8 \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd \u0250nd \u0287\u0265\u01dd n\u0250\u026f\u01dd \u00f8n \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287.", + "Use your webcam to take a photo of your ID.": "\u0244s\u01dd \u028e\u00f8n\u0279 \u028d\u01ddb\u0254\u0250\u026f \u0287\u00f8 \u0287\u0250\u029e\u01dd \u0250 d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u0197\u0110.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u0244s\u01dd \u028e\u00f8n\u0279 \u028d\u01ddb\u0254\u0250\u026f \u0287\u00f8 \u0287\u0250\u029e\u01dd \u0250 d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd. W\u01dd \u028d\u1d09ll \u026f\u0250\u0287\u0254\u0265 \u0287\u0265\u1d09s d\u0265\u00f8\u0287\u00f8 \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8n \u028e\u00f8n\u0279 \u0197\u0110.", "Used": "\u0244s\u01ddd", "Used in {count} location": [ @@ -1845,7 +1907,6 @@ "Verified Certificate upgrade": "V\u01dd\u0279\u1d09\u025f\u1d09\u01ddd \u023b\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd nd\u0183\u0279\u0250d\u01dd", "Verified Status": "V\u01dd\u0279\u1d09\u025f\u1d09\u01ddd S\u0287\u0250\u0287ns", "Verified mode price": "V\u01dd\u0279\u1d09\u025f\u1d09\u01ddd \u026f\u00f8d\u01dd d\u0279\u1d09\u0254\u01dd", - "Verify Now": "V\u01dd\u0279\u1d09\u025f\u028e N\u00f8\u028d", "Version": "V\u01dd\u0279s\u1d09\u00f8n", "Vertical space": "V\u01dd\u0279\u0287\u1d09\u0254\u0250l sd\u0250\u0254\u01dd", "Very loud": "V\u01dd\u0279\u028e l\u00f8nd", @@ -1872,16 +1933,19 @@ "View Teams in the {topic_name} Topic": "V\u1d09\u01dd\u028d \u0166\u01dd\u0250\u026fs \u1d09n \u0287\u0265\u01dd {topic_name} \u0166\u00f8d\u1d09\u0254", "View all errors": "V\u1d09\u01dd\u028d \u0250ll \u01dd\u0279\u0279\u00f8\u0279s", "View child items": "V\u1d09\u01dd\u028d \u0254\u0265\u1d09ld \u1d09\u0287\u01dd\u026fs", + "View discussion": "V\u1d09\u01dd\u028d d\u1d09s\u0254nss\u1d09\u00f8n", "View {span_start} {team_name} {span_end}": "V\u1d09\u01dd\u028d {span_start} {team_name} {span_end}", "Viewing %s course": [ "V\u1d09\u01dd\u028d\u1d09n\u0183 %s \u0254\u00f8n\u0279s\u01dd", "V\u1d09\u01dd\u028d\u1d09n\u0183 %s \u0254\u00f8n\u0279s\u01dds" ], "Visibility": "V\u1d09s\u1d09b\u1d09l\u1d09\u0287\u028e", + "Visible to": "V\u1d09s\u1d09bl\u01dd \u0287\u00f8", "Visible to Staff Only": "V\u1d09s\u1d09bl\u01dd \u0287\u00f8 S\u0287\u0250\u025f\u025f \u00d8nl\u028e", "Visual aids": "V\u1d09sn\u0250l \u0250\u1d09ds", "Volume": "V\u00f8ln\u026f\u01dd", "Vote for good posts and responses": "V\u00f8\u0287\u01dd \u025f\u00f8\u0279 \u0183\u00f8\u00f8d d\u00f8s\u0287s \u0250nd \u0279\u01ddsd\u00f8ns\u01dds", + "Vote for this post,": "V\u00f8\u0287\u01dd \u025f\u00f8\u0279 \u0287\u0265\u1d09s d\u00f8s\u0287,", "Want to confirm your identity later?": "W\u0250n\u0287 \u0287\u00f8 \u0254\u00f8n\u025f\u1d09\u0279\u026f \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e l\u0250\u0287\u01dd\u0279?", "Warning": "W\u0250\u0279n\u1d09n\u0183", "Warnings": "W\u0250\u0279n\u1d09n\u0183s", @@ -1890,9 +1954,11 @@ "We couldn't find any results for \"%s\".": "W\u01dd \u0254\u00f8nldn'\u0287 \u025f\u1d09nd \u0250n\u028e \u0279\u01ddsnl\u0287s \u025f\u00f8\u0279 \"%s\".", "We couldn't sign you in.": "W\u01dd \u0254\u00f8nldn'\u0287 s\u1d09\u0183n \u028e\u00f8n \u1d09n.", "We have encountered an error. Refresh your browser and then try again.": "W\u01dd \u0265\u0250\u028c\u01dd \u01ddn\u0254\u00f8nn\u0287\u01dd\u0279\u01ddd \u0250n \u01dd\u0279\u0279\u00f8\u0279. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u028e\u00f8n\u0279 b\u0279\u00f8\u028ds\u01dd\u0279 \u0250nd \u0287\u0265\u01ddn \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "W\u01dd \u0265\u0250\u028c\u01dd \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01ddd \u028e\u00f8n\u0279 \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u0250nd \u0250\u0279\u01dd \u028c\u01dd\u0279\u1d09\u025f\u028e\u1d09n\u0183 \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e. \u024e\u00f8n \u028d\u1d09ll s\u01dd\u01dd \u0250 \u026f\u01ddss\u0250\u0183\u01dd \u00f8n \u028e\u00f8n\u0279 d\u0250s\u0265b\u00f8\u0250\u0279d \u028d\u0265\u01ddn \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss \u1d09s \u0254\u00f8\u026fdl\u01dd\u0287\u01dd (nsn\u0250ll\u028e \u028d\u1d09\u0287\u0265\u1d09n 1-2 d\u0250\u028es). \u0197n \u0287\u0265\u01dd \u026f\u01dd\u0250n\u0287\u1d09\u026f\u01dd, \u028e\u00f8n \u0254\u0250n s\u0287\u1d09ll \u0250\u0254\u0254\u01ddss \u0250ll \u0250\u028c\u0250\u1d09l\u0250bl\u01dd \u0254\u00f8n\u0279s\u01dd \u0254\u00f8n\u0287\u01ddn\u0287.", + "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days). In the meantime, you can still access all available course content.": "W\u01dd \u0265\u0250\u028c\u01dd \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01ddd \u028e\u00f8n\u0279 \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u0250nd \u0250\u0279\u01dd \u028c\u01dd\u0279\u1d09\u025f\u028e\u1d09n\u0183 \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e. \u024e\u00f8n \u028d\u1d09ll s\u01dd\u01dd \u0250 \u026f\u01ddss\u0250\u0183\u01dd \u00f8n \u028e\u00f8n\u0279 d\u0250s\u0265b\u00f8\u0250\u0279d \u028d\u0265\u01ddn \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss \u1d09s \u0254\u00f8\u026fdl\u01dd\u0287\u01dd (nsn\u0250ll\u028e \u028d\u1d09\u0287\u0265\u1d09n 5-7 d\u0250\u028es). \u0197n \u0287\u0265\u01dd \u026f\u01dd\u0250n\u0287\u1d09\u026f\u01dd, \u028e\u00f8n \u0254\u0250n s\u0287\u1d09ll \u0250\u0254\u0254\u01ddss \u0250ll \u0250\u028c\u0250\u1d09l\u0250bl\u01dd \u0254\u00f8n\u0279s\u01dd \u0254\u00f8n\u0287\u01ddn\u0287.", "We just need a little more information before you start learning with %(platformName)s.": "W\u01dd \u027ens\u0287 n\u01dd\u01ddd \u0250 l\u1d09\u0287\u0287l\u01dd \u026f\u00f8\u0279\u01dd \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n b\u01dd\u025f\u00f8\u0279\u01dd \u028e\u00f8n s\u0287\u0250\u0279\u0287 l\u01dd\u0250\u0279n\u1d09n\u0183 \u028d\u1d09\u0287\u0265 %(platformName)s.", + "We securely encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "W\u01dd s\u01dd\u0254n\u0279\u01ddl\u028e \u01ddn\u0254\u0279\u028ed\u0287 \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8 \u0250nd s\u01ddnd \u1d09\u0287 \u0287\u00f8 \u00f8n\u0279 \u0250n\u0287\u0265\u00f8\u0279\u1d09z\u0250\u0287\u1d09\u00f8n s\u01dd\u0279\u028c\u1d09\u0254\u01dd \u025f\u00f8\u0279 \u0279\u01dd\u028c\u1d09\u01dd\u028d. \u024e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8 \u0250nd \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u0250\u0279\u01dd n\u00f8\u0287 s\u0250\u028c\u01ddd \u00f8\u0279 \u028c\u1d09s\u1d09bl\u01dd \u0250n\u028e\u028d\u0265\u01dd\u0279\u01dd \u00f8n %(platformName)s \u0250\u025f\u0287\u01dd\u0279 \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss \u1d09s \u0254\u00f8\u026fdl\u01dd\u0287\u01dd.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "W\u01dd ns\u01dd \u0287\u0265\u01dd \u0265\u1d09\u0183\u0265\u01dds\u0287 l\u01dd\u028c\u01ddls \u00f8\u025f s\u01dd\u0254n\u0279\u1d09\u0287\u028e \u0250\u028c\u0250\u1d09l\u0250bl\u01dd \u0287\u00f8 \u01ddn\u0254\u0279\u028ed\u0287 \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8 \u0250nd s\u01ddnd \u1d09\u0287 \u0287\u00f8 \u00f8n\u0279 \u0250n\u0287\u0265\u00f8\u0279\u1d09z\u0250\u0287\u1d09\u00f8n s\u01dd\u0279\u028c\u1d09\u0254\u01dd \u025f\u00f8\u0279 \u0279\u01dd\u028c\u1d09\u01dd\u028d. \u024e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8 \u0250nd \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u0250\u0279\u01dd n\u00f8\u0287 s\u0250\u028c\u01ddd \u00f8\u0279 \u028c\u1d09s\u1d09bl\u01dd \u0250n\u028e\u028d\u0265\u01dd\u0279\u01dd \u00f8n %(platformName)s \u0250\u025f\u0287\u01dd\u0279 \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss \u1d09s \u0254\u00f8\u026fdl\u01dd\u0287\u01dd.", + "We use your verification photos to confirm your identity and ensure the validity of your certificate.": "W\u01dd ns\u01dd \u028e\u00f8n\u0279 \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0265\u00f8\u0287\u00f8s \u0287\u00f8 \u0254\u00f8n\u025f\u1d09\u0279\u026f \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e \u0250nd \u01ddnsn\u0279\u01dd \u0287\u0265\u01dd \u028c\u0250l\u1d09d\u1d09\u0287\u028e \u00f8\u025f \u028e\u00f8n\u0279 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd.", "We're sorry to see you go! Your account will be deleted shortly.": "W\u01dd'\u0279\u01dd s\u00f8\u0279\u0279\u028e \u0287\u00f8 s\u01dd\u01dd \u028e\u00f8n \u0183\u00f8! \u024e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 \u028d\u1d09ll b\u01dd d\u01ddl\u01dd\u0287\u01ddd s\u0265\u00f8\u0279\u0287l\u028e.", "We're sorry, there was an error": "W\u01dd'\u0279\u01dd s\u00f8\u0279\u0279\u028e, \u0287\u0265\u01dd\u0279\u01dd \u028d\u0250s \u0250n \u01dd\u0279\u0279\u00f8\u0279", "We've encountered an error. Refresh your browser and then try again.": "W\u01dd'\u028c\u01dd \u01ddn\u0254\u00f8nn\u0287\u01dd\u0279\u01ddd \u0250n \u01dd\u0279\u0279\u00f8\u0279. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u028e\u00f8n\u0279 b\u0279\u00f8\u028ds\u01dd\u0279 \u0250nd \u0287\u0265\u01ddn \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", @@ -1915,6 +1981,7 @@ "When learners submit an answer to an assessment, they immediately see whether the answer is correct or incorrect, and the score received.": "W\u0265\u01ddn l\u01dd\u0250\u0279n\u01dd\u0279s snb\u026f\u1d09\u0287 \u0250n \u0250ns\u028d\u01dd\u0279 \u0287\u00f8 \u0250n \u0250ss\u01ddss\u026f\u01ddn\u0287, \u0287\u0265\u01dd\u028e \u1d09\u026f\u026f\u01ddd\u1d09\u0250\u0287\u01ddl\u028e s\u01dd\u01dd \u028d\u0265\u01dd\u0287\u0265\u01dd\u0279 \u0287\u0265\u01dd \u0250ns\u028d\u01dd\u0279 \u1d09s \u0254\u00f8\u0279\u0279\u01dd\u0254\u0287 \u00f8\u0279 \u1d09n\u0254\u00f8\u0279\u0279\u01dd\u0254\u0287, \u0250nd \u0287\u0265\u01dd s\u0254\u00f8\u0279\u01dd \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01ddd.", "When your face is in position, use the Take Photo button {icon} below to take your photo.": "W\u0265\u01ddn \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd \u1d09s \u1d09n d\u00f8s\u1d09\u0287\u1d09\u00f8n, ns\u01dd \u0287\u0265\u01dd \u0166\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8 bn\u0287\u0287\u00f8n {icon} b\u01ddl\u00f8\u028d \u0287\u00f8 \u0287\u0250\u029e\u01dd \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8.", "Which timed transcript would you like to use?": "W\u0265\u1d09\u0254\u0265 \u0287\u1d09\u026f\u01ddd \u0287\u0279\u0250ns\u0254\u0279\u1d09d\u0287 \u028d\u00f8nld \u028e\u00f8n l\u1d09\u029e\u01dd \u0287\u00f8 ns\u01dd?", + "While our support team is happy to assist with the edX platform, the course staff has the expertise for specific assignment questions, grading or the proper procedures in each course. Please post all course related questions within the Discussion Forum where the Course Staff can directly respond.": "W\u0265\u1d09l\u01dd \u00f8n\u0279 sndd\u00f8\u0279\u0287 \u0287\u01dd\u0250\u026f \u1d09s \u0265\u0250dd\u028e \u0287\u00f8 \u0250ss\u1d09s\u0287 \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd \u01dddX dl\u0250\u0287\u025f\u00f8\u0279\u026f, \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd s\u0287\u0250\u025f\u025f \u0265\u0250s \u0287\u0265\u01dd \u01ddxd\u01dd\u0279\u0287\u1d09s\u01dd \u025f\u00f8\u0279 sd\u01dd\u0254\u1d09\u025f\u1d09\u0254 \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287 bn\u01dds\u0287\u1d09\u00f8ns, \u0183\u0279\u0250d\u1d09n\u0183 \u00f8\u0279 \u0287\u0265\u01dd d\u0279\u00f8d\u01dd\u0279 d\u0279\u00f8\u0254\u01dddn\u0279\u01dds \u1d09n \u01dd\u0250\u0254\u0265 \u0254\u00f8n\u0279s\u01dd. \u2c63l\u01dd\u0250s\u01dd d\u00f8s\u0287 \u0250ll \u0254\u00f8n\u0279s\u01dd \u0279\u01ddl\u0250\u0287\u01ddd bn\u01dds\u0287\u1d09\u00f8ns \u028d\u1d09\u0287\u0265\u1d09n \u0287\u0265\u01dd \u0110\u1d09s\u0254nss\u1d09\u00f8n F\u00f8\u0279n\u026f \u028d\u0265\u01dd\u0279\u01dd \u0287\u0265\u01dd \u023b\u00f8n\u0279s\u01dd S\u0287\u0250\u025f\u025f \u0254\u0250n d\u1d09\u0279\u01dd\u0254\u0287l\u028e \u0279\u01ddsd\u00f8nd.", "Whole words": "W\u0265\u00f8l\u01dd \u028d\u00f8\u0279ds", "Why activate?": "W\u0265\u028e \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u01dd?", "Why does %(platformName)s need my photo?": "W\u0265\u028e d\u00f8\u01dds %(platformName)s n\u01dd\u01ddd \u026f\u028e d\u0265\u00f8\u0287\u00f8?", @@ -1987,14 +2054,13 @@ "You must specify a name": "\u024e\u00f8n \u026fns\u0287 sd\u01dd\u0254\u1d09\u025f\u028e \u0250 n\u0250\u026f\u01dd", "You must specify a name for the cohort": "\u024e\u00f8n \u026fns\u0287 sd\u01dd\u0254\u1d09\u025f\u028e \u0250 n\u0250\u026f\u01dd \u025f\u00f8\u0279 \u0287\u0265\u01dd \u0254\u00f8\u0265\u00f8\u0279\u0287", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u024e\u00f8n \u026fns\u0287 sd\u01dd\u0254\u1d09\u025f\u028e \u028e\u00f8n\u0279 b\u1d09\u0279\u0287\u0265 \u028e\u01dd\u0250\u0279 b\u01dd\u025f\u00f8\u0279\u01dd \u028e\u00f8n \u0254\u0250n s\u0265\u0250\u0279\u01dd \u028e\u00f8n\u0279 \u025fnll d\u0279\u00f8\u025f\u1d09l\u01dd. \u0166\u00f8 sd\u01dd\u0254\u1d09\u025f\u028e \u028e\u00f8n\u0279 b\u1d09\u0279\u0287\u0265 \u028e\u01dd\u0250\u0279, \u0183\u00f8 \u0287\u00f8 \u0287\u0265\u01dd {account_settings_page_link}", - "You need a computer or cell phone that has a webcam. When you receive a browser prompt, make sure that you allow access to the camera.": "\u024e\u00f8n n\u01dd\u01ddd \u0250 \u0254\u00f8\u026fdn\u0287\u01dd\u0279 \u00f8\u0279 \u0254\u01ddll d\u0265\u00f8n\u01dd \u0287\u0265\u0250\u0287 \u0265\u0250s \u0250 \u028d\u01ddb\u0254\u0250\u026f. W\u0265\u01ddn \u028e\u00f8n \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd \u0250 b\u0279\u00f8\u028ds\u01dd\u0279 d\u0279\u00f8\u026fd\u0287, \u026f\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u0265\u0250\u0287 \u028e\u00f8n \u0250ll\u00f8\u028d \u0250\u0254\u0254\u01ddss \u0287\u00f8 \u0287\u0265\u01dd \u0254\u0250\u026f\u01dd\u0279\u0250.", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u024e\u00f8n n\u01dd\u01ddd \u0250 d\u0279\u1d09\u028c\u01dd\u0279's l\u1d09\u0254\u01ddns\u01dd, d\u0250ssd\u00f8\u0279\u0287, \u00f8\u0279 \u00f8\u0287\u0265\u01dd\u0279 \u0183\u00f8\u028c\u01dd\u0279n\u026f\u01ddn\u0287-\u1d09ssn\u01ddd \u0197\u0110 \u0287\u0265\u0250\u0287 \u0265\u0250s \u028e\u00f8n\u0279 n\u0250\u026f\u01dd \u0250nd d\u0265\u00f8\u0287\u00f8.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u024e\u00f8n n\u01dd\u01ddd \u0250n \u0197\u0110 \u028d\u1d09\u0287\u0265 \u028e\u00f8n\u0279 n\u0250\u026f\u01dd \u0250nd d\u0265\u00f8\u0287\u00f8. \u023a d\u0279\u1d09\u028c\u01dd\u0279's l\u1d09\u0254\u01ddns\u01dd, d\u0250ssd\u00f8\u0279\u0287, \u00f8\u0279 \u00f8\u0287\u0265\u01dd\u0279 \u0183\u00f8\u028c\u01dd\u0279n\u026f\u01ddn\u0287-\u1d09ssn\u01ddd \u0197\u0110s \u0250\u0279\u01dd \u0250ll \u0250\u0254\u0254\u01ddd\u0287\u0250bl\u01dd.", + "You need a device that has a webcam. If you receive a browser prompt for access to your camera, please make sure to click 'Allow'.": "\u024e\u00f8n n\u01dd\u01ddd \u0250 d\u01dd\u028c\u1d09\u0254\u01dd \u0287\u0265\u0250\u0287 \u0265\u0250s \u0250 \u028d\u01ddb\u0254\u0250\u026f. \u0197\u025f \u028e\u00f8n \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd \u0250 b\u0279\u00f8\u028ds\u01dd\u0279 d\u0279\u00f8\u026fd\u0287 \u025f\u00f8\u0279 \u0250\u0254\u0254\u01ddss \u0287\u00f8 \u028e\u00f8n\u0279 \u0254\u0250\u026f\u01dd\u0279\u0250, dl\u01dd\u0250s\u01dd \u026f\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u00f8 \u0254l\u1d09\u0254\u029e '\u023all\u00f8\u028d'.", + "You need a valid ID that contains your full name and photo.": "\u024e\u00f8n n\u01dd\u01ddd \u0250 \u028c\u0250l\u1d09d \u0197\u0110 \u0287\u0265\u0250\u0287 \u0254\u00f8n\u0287\u0250\u1d09ns \u028e\u00f8n\u0279 \u025fnll n\u0250\u026f\u01dd \u0250nd d\u0265\u00f8\u0287\u00f8.", + "You need an ID with your name and photo. A driver's license, passport, or ID are all acceptable.": "\u024e\u00f8n n\u01dd\u01ddd \u0250n \u0197\u0110 \u028d\u1d09\u0287\u0265 \u028e\u00f8n\u0279 n\u0250\u026f\u01dd \u0250nd d\u0265\u00f8\u0287\u00f8. \u023a d\u0279\u1d09\u028c\u01dd\u0279's l\u1d09\u0254\u01ddns\u01dd, d\u0250ssd\u00f8\u0279\u0287, \u00f8\u0279 \u0197\u0110 \u0250\u0279\u01dd \u0250ll \u0250\u0254\u0254\u01ddd\u0287\u0250bl\u01dd.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u024e\u00f8n n\u01dd\u01ddd \u0287\u00f8 \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u01dd \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 b\u01dd\u025f\u00f8\u0279\u01dd \u028e\u00f8n \u0254\u0250n \u01ddn\u0279\u00f8ll \u1d09n \u0254\u00f8n\u0279s\u01dds. \u023b\u0265\u01dd\u0254\u029e \u028e\u00f8n\u0279 \u1d09nb\u00f8x \u025f\u00f8\u0279 \u0250n \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u1d09\u00f8n \u01dd\u026f\u0250\u1d09l.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u024e\u00f8n n\u01dd\u01ddd \u0287\u00f8 \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u01dd \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 b\u01dd\u025f\u00f8\u0279\u01dd \u028e\u00f8n \u0254\u0250n \u01ddn\u0279\u00f8ll \u1d09n \u0254\u00f8n\u0279s\u01dds. \u023b\u0265\u01dd\u0254\u029e \u028e\u00f8n\u0279 \u1d09nb\u00f8x \u025f\u00f8\u0279 \u0250n \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u1d09\u00f8n \u01dd\u026f\u0250\u1d09l. \u023a\u025f\u0287\u01dd\u0279 \u028e\u00f8n \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u1d09\u00f8n \u028e\u00f8n \u0254\u0250n \u0279\u01dd\u0287n\u0279n \u0250nd \u0279\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u1d09s d\u0250\u0183\u01dd.", "You receive messages from {platform_name} and course teams at this address.": "\u024e\u00f8n \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd \u026f\u01ddss\u0250\u0183\u01dds \u025f\u0279\u00f8\u026f {platform_name} \u0250nd \u0254\u00f8n\u0279s\u01dd \u0287\u01dd\u0250\u026fs \u0250\u0287 \u0287\u0265\u1d09s \u0250dd\u0279\u01ddss.", "You reserve all rights for your work": "\u024e\u00f8n \u0279\u01dds\u01dd\u0279\u028c\u01dd \u0250ll \u0279\u1d09\u0183\u0265\u0287s \u025f\u00f8\u0279 \u028e\u00f8n\u0279 \u028d\u00f8\u0279\u029e", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u024e\u00f8n s\u0287\u1d09ll n\u01dd\u01ddd \u0287\u00f8 \u028c\u1d09s\u1d09\u0287 \u0287\u0265\u01dd %(display_name)s \u028d\u01ddbs\u1d09\u0287\u01dd \u0287\u00f8 \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0287\u0265\u01dd \u0254\u0279\u01ddd\u1d09\u0287 d\u0279\u00f8\u0254\u01ddss.", "You submitted {filename}; only {allowedFiles} are allowed.": "\u024e\u00f8n snb\u026f\u1d09\u0287\u0287\u01ddd {filename}; \u00f8nl\u028e {allowedFiles} \u0250\u0279\u01dd \u0250ll\u00f8\u028d\u01ddd.", "You waive some rights for your work, such that others can use it too": "\u024e\u00f8n \u028d\u0250\u1d09\u028c\u01dd s\u00f8\u026f\u01dd \u0279\u1d09\u0183\u0265\u0287s \u025f\u00f8\u0279 \u028e\u00f8n\u0279 \u028d\u00f8\u0279\u029e, sn\u0254\u0265 \u0287\u0265\u0250\u0287 \u00f8\u0287\u0265\u01dd\u0279s \u0254\u0250n ns\u01dd \u1d09\u0287 \u0287\u00f8\u00f8", "You will be refunded the amount you paid.": "\u024e\u00f8n \u028d\u1d09ll b\u01dd \u0279\u01dd\u025fnnd\u01ddd \u0287\u0265\u01dd \u0250\u026f\u00f8nn\u0287 \u028e\u00f8n d\u0250\u1d09d.", @@ -2061,6 +2127,7 @@ "and others": "\u0250nd \u00f8\u0287\u0265\u01dd\u0279s", "anonymous": "\u0250n\u00f8n\u028e\u026f\u00f8ns", "answer": "\u0250ns\u028d\u01dd\u0279", + "answered question": "\u0250ns\u028d\u01dd\u0279\u01ddd bn\u01dds\u0287\u1d09\u00f8n", "asset_path is required": "\u0250ss\u01dd\u0287_d\u0250\u0287\u0265 \u1d09s \u0279\u01ddbn\u1d09\u0279\u01ddd", "bytes": "b\u028e\u0287\u01dds", "certificate": "\u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd", @@ -2072,6 +2139,8 @@ "delete chapter": "d\u01ddl\u01dd\u0287\u01dd \u0254\u0265\u0250d\u0287\u01dd\u0279", "delete group": "d\u01ddl\u01dd\u0287\u01dd \u0183\u0279\u00f8nd", "details about the failure": "d\u01dd\u0287\u0250\u1d09ls \u0250b\u00f8n\u0287 \u0287\u0265\u01dd \u025f\u0250\u1d09ln\u0279\u01dd", + "discussion": "d\u1d09s\u0254nss\u1d09\u00f8n", + "discussion posted %(time_ago)s by %(author)s": "d\u1d09s\u0254nss\u1d09\u00f8n d\u00f8s\u0287\u01ddd %(time_ago)s b\u028e %(author)s", "dragging": "d\u0279\u0250\u0183\u0183\u1d09n\u0183", "dragging out of slider": "d\u0279\u0250\u0183\u0183\u1d09n\u0183 \u00f8n\u0287 \u00f8\u025f sl\u1d09d\u01dd\u0279", "dropped in slider": "d\u0279\u00f8dd\u01ddd \u1d09n sl\u1d09d\u01dd\u0279", @@ -2081,15 +2150,19 @@ "e.g. 'http://google.com'": "\u01dd.\u0183. '\u0265\u0287\u0287d://\u0183\u00f8\u00f8\u0183l\u01dd.\u0254\u00f8\u026f'", "e.g. johndoe@example.com, JaneDoe, joeydoe@example.com": "\u01dd.\u0183. \u027e\u00f8\u0265nd\u00f8\u01dd@\u01ddx\u0250\u026fdl\u01dd.\u0254\u00f8\u026f, \u0248\u0250n\u01dd\u0110\u00f8\u01dd, \u027e\u00f8\u01dd\u028ed\u00f8\u01dd@\u01ddx\u0250\u026fdl\u01dd.\u0254\u00f8\u026f", "emphasized text": "\u01dd\u026fd\u0265\u0250s\u1d09z\u01ddd \u0287\u01ddx\u0287", + "endorsed %(time_ago)s": "\u01ddnd\u00f8\u0279s\u01ddd %(time_ago)s", + "endorsed %(time_ago)s by %(user)s": "\u01ddnd\u00f8\u0279s\u01ddd %(time_ago)s b\u028e %(user)s", "enter code here": "\u01ddn\u0287\u01dd\u0279 \u0254\u00f8d\u01dd \u0265\u01dd\u0279\u01dd", "enter link description here": "\u01ddn\u0287\u01dd\u0279 l\u1d09n\u029e d\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n \u0265\u01dd\u0279\u01dd", + "follow this post": "\u025f\u00f8ll\u00f8\u028d \u0287\u0265\u1d09s d\u00f8s\u0287", "for": "\u025f\u00f8\u0279", - "for {courseName}": "\u025f\u00f8\u0279 {courseName}", "group configuration": "\u0183\u0279\u00f8nd \u0254\u00f8n\u025f\u1d09\u0183n\u0279\u0250\u0287\u1d09\u00f8n", "image omitted": "\u1d09\u026f\u0250\u0183\u01dd \u00f8\u026f\u1d09\u0287\u0287\u01ddd", "incorrect": "\u1d09n\u0254\u00f8\u0279\u0279\u01dd\u0254\u0287", "last activity": "l\u0250s\u0287 \u0250\u0254\u0287\u1d09\u028c\u1d09\u0287\u028e", "less than a minute": "l\u01ddss \u0287\u0265\u0250n \u0250 \u026f\u1d09nn\u0287\u01dd", + "marked as answer %(time_ago)s": "\u026f\u0250\u0279\u029e\u01ddd \u0250s \u0250ns\u028d\u01dd\u0279 %(time_ago)s", + "marked as answer %(time_ago)s by %(user)s": "\u026f\u0250\u0279\u029e\u01ddd \u0250s \u0250ns\u028d\u01dd\u0279 %(time_ago)s b\u028e %(user)s", "minute": "\u026f\u1d09nn\u0287\u01dd", "minutes": "\u026f\u1d09nn\u0287\u01dds", "name": "n\u0250\u026f\u01dd", @@ -2100,9 +2173,13 @@ "or create a new one here": "\u00f8\u0279 \u0254\u0279\u01dd\u0250\u0287\u01dd \u0250 n\u01dd\u028d \u00f8n\u01dd \u0265\u01dd\u0279\u01dd", "or sign in with": "\u00f8\u0279 s\u1d09\u0183n \u1d09n \u028d\u1d09\u0287\u0265", "path/to/introductionToCookieBaking-CH{order}.pdf": "d\u0250\u0287\u0265/\u0287\u00f8/\u1d09n\u0287\u0279\u00f8dn\u0254\u0287\u1d09\u00f8n\u0166\u00f8\u023b\u00f8\u00f8\u029e\u1d09\u01dd\u0243\u0250\u029e\u1d09n\u0183-\u023b\u0126{order}.dd\u025f", + "post anonymously": "d\u00f8s\u0287 \u0250n\u00f8n\u028e\u026f\u00f8nsl\u028e", + "post anonymously to classmates": "d\u00f8s\u0287 \u0250n\u00f8n\u028e\u026f\u00f8nsl\u028e \u0287\u00f8 \u0254l\u0250ss\u026f\u0250\u0287\u01dds", + "posted %(time_ago)s by %(author)s": "d\u00f8s\u0287\u01ddd %(time_ago)s b\u028e %(author)s", "price": "d\u0279\u1d09\u0254\u01dd", "provide the title/name of the chapter that will be used in navigating": "d\u0279\u00f8\u028c\u1d09d\u01dd \u0287\u0265\u01dd \u0287\u1d09\u0287l\u01dd/n\u0250\u026f\u01dd \u00f8\u025f \u0287\u0265\u01dd \u0254\u0265\u0250d\u0287\u01dd\u0279 \u0287\u0265\u0250\u0287 \u028d\u1d09ll b\u01dd ns\u01ddd \u1d09n n\u0250\u028c\u1d09\u0183\u0250\u0287\u1d09n\u0183", "provide the title/name of the text book as you would like your students to see it": "d\u0279\u00f8\u028c\u1d09d\u01dd \u0287\u0265\u01dd \u0287\u1d09\u0287l\u01dd/n\u0250\u026f\u01dd \u00f8\u025f \u0287\u0265\u01dd \u0287\u01ddx\u0287 b\u00f8\u00f8\u029e \u0250s \u028e\u00f8n \u028d\u00f8nld l\u1d09\u029e\u01dd \u028e\u00f8n\u0279 s\u0287nd\u01ddn\u0287s \u0287\u00f8 s\u01dd\u01dd \u1d09\u0287", + "question posted %(time_ago)s by %(author)s": "bn\u01dds\u0287\u1d09\u00f8n d\u00f8s\u0287\u01ddd %(time_ago)s b\u028e %(author)s", "remove": "\u0279\u01dd\u026f\u00f8\u028c\u01dd", "remove all": "\u0279\u01dd\u026f\u00f8\u028c\u01dd \u0250ll", "second": "s\u01dd\u0254\u00f8nd", @@ -2114,6 +2191,7 @@ "team count": "\u0287\u01dd\u0250\u026f \u0254\u00f8nn\u0287", "text_word_{uniqueId}": "\u0287\u01ddx\u0287_\u028d\u00f8\u0279d_{uniqueId}", "text_word_{uniqueId} title_word_{uniqueId}": "\u0287\u01ddx\u0287_\u028d\u00f8\u0279d_{uniqueId} \u0287\u1d09\u0287l\u01dd_\u028d\u00f8\u0279d_{uniqueId}", + "the more quickly and helpfully we can respond!": "\u0287\u0265\u01dd \u026f\u00f8\u0279\u01dd bn\u1d09\u0254\u029el\u028e \u0250nd \u0265\u01ddld\u025fnll\u028e \u028d\u01dd \u0254\u0250n \u0279\u01ddsd\u00f8nd!", "there is currently {numVotes} vote": [ "\u0287\u0265\u01dd\u0279\u01dd \u1d09s \u0254n\u0279\u0279\u01ddn\u0287l\u028e {numVotes} \u028c\u00f8\u0287\u01dd", "\u0287\u0265\u01dd\u0279\u01dd \u0250\u0279\u01dd \u0254n\u0279\u0279\u01ddn\u0287l\u028e {numVotes} \u028c\u00f8\u0287\u01dds" @@ -2121,6 +2199,7 @@ "title_word_{uniqueId}": "\u0287\u1d09\u0287l\u01dd_\u028d\u00f8\u0279d_{uniqueId}", "toggle chapter %(displayName)s": "\u0287\u00f8\u0183\u0183l\u01dd \u0254\u0265\u0250d\u0287\u01dd\u0279 %(displayName)s", "toggle subsection %(displayName)s": "\u0287\u00f8\u0183\u0183l\u01dd snbs\u01dd\u0254\u0287\u1d09\u00f8n %(displayName)s", + "unanswered question": "nn\u0250ns\u028d\u01dd\u0279\u01ddd bn\u01dds\u0287\u1d09\u00f8n", "unit": "nn\u1d09\u0287", "unsubmitted": "nnsnb\u026f\u1d09\u0287\u0287\u01ddd", "upload a PDF file or provide the path to a Studio asset file": "ndl\u00f8\u0250d \u0250 \u2c63\u0110F \u025f\u1d09l\u01dd \u00f8\u0279 d\u0279\u00f8\u028c\u1d09d\u01dd \u0287\u0265\u01dd d\u0250\u0287\u0265 \u0287\u00f8 \u0250 S\u0287nd\u1d09\u00f8 \u0250ss\u01dd\u0287 \u025f\u1d09l\u01dd", @@ -2217,6 +2296,7 @@ ], "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}": "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}", "{type} Progress": "{type} \u2c63\u0279\u00f8\u0183\u0279\u01ddss", + "{unread_comments_count} new": "{unread_comments_count} n\u01dd\u028d", "\u2026": "\u2026" }; for (var key in newcatalog) { @@ -2239,7 +2319,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2303,9 +2383,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/fi-fi/djangojs.js b/cms/static/js/i18n/fi-fi/djangojs.js index 916c14585ca114ed3cdc42705299b014ed22c5b5..aa650929ca0bb5519e9677bb08ed857bc36e5699 100644 --- a/cms/static/js/i18n/fi-fi/djangojs.js +++ b/cms/static/js/i18n/fi-fi/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -157,9 +157,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j.n.Y G.i", "SHORT_DATE_FORMAT": "j.n.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/fil/djangojs.js b/cms/static/js/i18n/fil/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/cms/static/js/i18n/fil/djangojs.js +++ b/cms/static/js/i18n/fil/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/fr/djangojs.js b/cms/static/js/i18n/fr/djangojs.js index 9eb5f638662f9400a6b60a9db179558c39cbe27a..906bf743c693fcab6afd470c7689cf7ec6e7d0a1 100644 --- a/cms/static/js/i18n/fr/djangojs.js +++ b/cms/static/js/i18n/fr/djangojs.js @@ -505,7 +505,6 @@ "Default (Local Time Zone)": "D\u00e9faut (fuseau horaire local)", "Default Timed Transcript": "Transcription synchronis\u00e9e par d\u00e9faut", "Delete": "Supprimer", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "Supprimer \"<%= signatoryName %>\" de la liste de signataires.", "Delete File Confirmation": "Confirmation de la suppression du fichier", "Delete My Account": "Supprimer mon compte", "Delete Team": "Supprimer l'\u00e9quipe", @@ -544,7 +543,6 @@ "Do you want to upload your file before submitting?": "Charger le fichier avant l'envoi?", "Document properties": "Propri\u00e9t\u00e9s du document", "Does the name on your ID match your account name: %(fullName)s?": "Le nom sur votre ID correspond-il \u00e0 votre nom de compte: %(fullName)s?", - "Does the photo of you match your ID photo?": "Votre photo correspond-elle \u00e0 celle de votre document d'identit\u00e9 ?", "Does the photo of you show your whole face?": "Votre photo montre-t-elle votre visage en entier ?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Vous ne voyez pas votre photo ? Assurez-vous que votre navigateur est autoris\u00e9 \u00e0 utiliser votre webcam quand il le demande.", "Donate": "Faire un don", @@ -720,7 +718,6 @@ "Generate": "G\u00e9n\u00e9r\u00e9", "Generate Exception Certificates": "G\u00e9n\u00e9rer les attestations de d\u00e9rogation", "Generate the user's certificate": "G\u00e9n\u00e9rer le certificat de l'utilisateur", - "Get Credit": "Obtenir un cr\u00e9dit", "Go Back": "Retour", "Go to Dashboard": "Aller au tableau de bord", "Go to your Dashboard": "Aller \u00e0 votre tableau de bord", @@ -1438,7 +1435,6 @@ "Text to display": "Texte \u00e0 afficher", "Textbook Name": "Nom du manuel", "Textbook information": "information sur le manuel", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Merci %(full_name)s! Nous avons re\u00e7u votre paiement pour %(course_name)s.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Merci d'avoir soumis votre demande d'aide financi\u00e8re pour {course_name}! Vous aurez une r\u00e9ponse dans 2-4 jours ouvrables.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Merci d'avoir envoyer vos photos. Nous allons les valider rapidement. Vous pouvez maintenant vous inscrire \u00e0 tous les cours %(platformName)s offrants un certificat v\u00e9rifi\u00e9. La v\u00e9rification est valide un an. Apr\u00e8s un an, vous devrez renvoyer vos photos pour v\u00e9rification.", "Thank you! We have received your payment for {courseName}.": "Merci. Nous avons re\u00e7u votre paiement pour {courseName}.", @@ -1448,8 +1444,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Le certificat de cet apprenant a \u00e9t\u00e9 re-valid\u00e9 et le syst\u00e8me est en train de re-\u00e9valuer les notes de cet apprenant. ", "The cohort cannot be added": "La cohorte ne peut pas \u00eatre ajout\u00e9e", "The cohort cannot be saved": "La cohorte ne peut pas \u00eatre enregistr\u00e9e", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "La longueur totale des champs organisation et codes de biblioth\u00e8que ne doit pas d\u00e9passer <%=limit%> caract\u00e8res.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "La longueur totale des champs organisation, num\u00e9ro du cours et session du cours ne peut d\u00e9passer <%=limit%> caract\u00e8res.", "The country or region where you live.": "Votre pays ou r\u00e9gion de r\u00e9sidence.", "The country that team members primarily identify with.": "Le pays avec lequel les membres de l'\u00e9quipe sont le plus proche.", "The course end date must be later than the course start date.": "La date de fin du cours doit \u00eatre post\u00e9rieure \u00e0 la date de d\u00e9but du cours.", @@ -1464,7 +1458,6 @@ "The following email addresses and/or usernames are invalid:": "Les adresses email et/ou noms d'utilisateurs suivants sont invalides :", "The following errors were generated:": "Les erreurs suivantes ont \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9es:", "The following file types are not allowed: ": "Les types de fichiers suivants ne sont pas support\u00e9s :", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "L'information suivante fait d\u00e9j\u00e0 partie de votre profil {platform}. Nous l\\'avons inclus ici pour votre demander.", "The following message will be displayed at the bottom of the courseware pages within your course:": "Le message suivant sera affich\u00e9 au bas des pages du cours :", "The following options are available for the {license_name} license.": "Les options suivantes sont disponibles pour la licence {license_name}", "The following users are no longer enrolled in the course:": "Les utilisateurs suivants ont \u00e9t\u00e9 d\u00e9sinscrits du cours\u00a0:", @@ -1482,7 +1475,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Le nombre de sous-sections de ce cours qui contiennent des probl\u00e8mes de ce type de devoir.", "The organization that this signatory belongs to, as it should appear on certificates.": "L'organisation \u00e0 laquelle ce signataire appartient, telle qu'elle devrait apparaitre sur les attestations.", "The page \"{route}\" could not be found.": "Page \"{route}\" non trouv\u00e9e.", - "The photo of your face matches the photo on your ID.": "La photo de votre visage concorde avec la photo sur votre pi\u00e8ce d'identit\u00e9.", "The post you selected has been deleted.": "Le message que vous avez s\u00e9lectionn\u00e9 a \u00e9t\u00e9 effac\u00e9.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "La version de la branche publi\u00e9e, {published}, a \u00e9t\u00e9 r\u00e9initialis\u00e9e \u00e0 la branche de la version du brouillon, {draft}.", "The raw error message is:": "Le message d'erreur est:", @@ -1597,7 +1589,6 @@ "Titles more than 100 characters may prevent students from printing their certificate on a single page.": "Les titres de plus de 100 caract\u00e8res peuvent emp\u00eacher les \u00e9tudiants d'imprimer leur certificat sur une seule page.", "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "Afin que tous les \u00e9tudiants puisse acc\u00e9der \u00e0 la vid\u00e9o, nous vous recommandons de fournir une version .mp4 ainsi qu'une version .webm de la vid\u00e9o. Cliquer ci-dessous pour ajouter une URL pour une autre version. Les URLs youtube ne sont pas support\u00e9es. La premi\u00e8re vid\u00e9o de la liste compatible avec l'ordinateur de l'\u00e9tudiant sera vue.", "To complete the program, you must earn a verified certificate for each course.": "Afin de compl\u00e9ter ce programme, vous devez obtenir un certificat v\u00e9rifi\u00e9 pour chacun de ces cours.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "Pour finaliser l'obtention de cr\u00e9dit de cours, %(display_name)s demande aux apprenants de %(platform_name)s de soumettre une demande de cr\u00e9dit.", "To invalidate a certificate for a particular learner, add the username or email address below.": "Pour invalider une attestation pour un apprenant, ajouter le nom d'usager ou l'adresse courriel ci-dessous.", "To pass this exam, you must complete the problems in the time allowed.": "Pour r\u00e9ussir l'examen, vous devez r\u00e9pondre aux questions dans le temps imparti.", "To receive a certificate, you must also verify your identity before {date}.": "Pour recevoir un certificat, vous devez aussi valider votre identit\u00e9 avant le {date}.", @@ -1699,7 +1690,6 @@ "Use as a Prerequisite": "Utilis\u00e9 comme Pr\u00e9-requis", "Use my institution/campus credentials": "Utiliser mes informations institution/campus", "Use the All Topics menu to find specific topics.": "Utilisez le menu 'Tous les sujets' pour trouver un sujet sp\u00e9cific", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Utilisez votre webcam pour prendre une photo de votre pi\u00e8ce d'identit\u00e9. Nous allons v\u00e9rifier sa concordance avec la photo de votre visage et le nom de votre compte.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Utiliser votre webcam pour prendre une photo de votre visage, afin que nous puissions la comparer avec celle de votre pi\u00e8ce d'identit\u00e9.", "Used": "Utilis\u00e9", "Used in {count} location": [ @@ -1723,7 +1713,6 @@ "Verified Certificate upgrade": "Passer \u00e0 un certificat v\u00e9rifi\u00e9", "Verified Status": "Statut v\u00e9rifi\u00e9", "Verified mode price": "Prix du mode v\u00e9rifi\u00e9", - "Verify Now": "V\u00e9rifier Maintenant", "Vertical space": "Espace Vertical", "Very loud": "Tr\u00e8s fort", "Very low": "Tr\u00e8s faible", @@ -1760,7 +1749,6 @@ "We couldn't create your account.": "Nous n'avons pas pu cr\u00e9er votre compte.", "We couldn't find any results for \"%s\".": "Nous ne trouvons pas de r\u00e9sultat pour \"%s\".", "We couldn't sign you in.": "Nous n'avons pas pu vous connecter.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Nous avons re\u00e7us vos informations et nous v\u00e9rifions votre identit\u00e9. Un message sera visible sur votre tableau de bord (1-2 jours de d\u00e9lai). Entre temps, vous avez toujours acc\u00e8s \u00e0 l'ensemble du cours.", "We just need a little more information before you start learning with %(platformName)s.": "Nous avons juste besoin d'un peu plus d'informations avant que vous commenciez votre apprentissage avec %(platformName)s.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Nous utilisons le niveau de s\u00e9curit\u00e9 le plus \u00e9lev\u00e9 pour chiffrer votre photo et l'envoyer \u00e0 notre service d\u2019autorisation afin d'y \u00eatre examin\u00e9e. Votre photo et vos informations ne sont pas enregistr\u00e9es, et ils ne sont pas visible nulle part sur %(platformName)s apr\u00e8s l'accomplissement de processus de v\u00e9rification.", "We've encountered an error. Refresh your browser and then try again.": "Nous avons rencontr\u00e9 une erreur. Rafra\u00eechissez votre navigateur puis r\u00e9essayer.", @@ -1826,7 +1814,7 @@ "You have not created any certificates yet.": "Vous n'avez pas encore cr\u00e9e de certificat.", "You have not created any content groups yet.": "Vous n'avez pas encore cr\u00e9\u00e9 de groupes de contenu.", "You have not created any group configurations yet.": "Vous n'avez pas encore cr\u00e9\u00e9 de configuration des groupes.", - "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "Vous avez s\u00e9lectionn\u00e9 une action, et vous n'avez fait aucune modification sur des champs. Vous cherchez probablement le bouton Envoyer et non le bouton Sauvegarder.", + "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "Vous avez s\u00e9lectionn\u00e9 une action, et vous n'avez fait aucune modification sur des champs. Vous cherchez probablement le bouton Envoyer et non le bouton Enregistrer.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "Vous avez s\u00e9lectionn\u00e9 une action, mais vous n'avez pas encore sauvegard\u00e9 certains champs modifi\u00e9s. Cliquez sur OK pour sauver. Vous devrez r\u00e9appliquer l'action.", "You have successfully signed into %(currentProvider)s, but your %(currentProvider)s account does not have a linked %(platformName)s account. To link your accounts, sign in now using your %(platformName)s password.": "Vous \u00eates connect\u00e9 \u00e0 %(currentProvider)s avec succ\u00e8s,mais votre compte %(currentProvider)s n'est pas reli\u00e9 \u00e0 votre compte %(platformName)s. Pour lier vos comptes, connectez-vous en utilisant votre mot de passe %(platformName)s.", "You have unsaved changes are you sure you want to navigate away?": "Vous avez des modifications non enregistr\u00e9es, \u00eates-vous s\u00fbr de vouloir quitter cette page ?", @@ -1842,12 +1830,9 @@ "You must sign out and sign back in before your language changes take effect.": "Vous devez vous d\u00e9connecter puis vous connecter \u00e0 nouveau afin que les param\u00e8tres de langue prennent effet.", "You must specify a name for the cohort": "Vous devez indiquer un nom pour la cohorte", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "Vous devez renseigner votre ann\u00e9e de naissance avant de pouvoir partager votre profil complet. Pour renseigner votre ann\u00e9e de naissance, allez sur {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Vous avez besoin d'un permis de conduire, d'un passeport ou d'une pi\u00e8ce d'identit\u00e9 avec votre nom et photo.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Vous avez besoin d'un permis de conduire, un passeport ou toute pi\u00e8ce d'identit\u00e9 avec votre nom et photo.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Vous devez activer votre compte avant de vous inscrire \u00e0 des cours. V\u00e9rifier votre bo\u00eete de r\u00e9ception.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Vous devez activer votre compte avant de pouvoir vous inscrire aux cours. V\u00e9rifier votre bo\u00eete de r\u00e9ception pour un email d'activation. Apr\u00e8s l'activation vous pouvez revenir et rafraichir cette page.", "You receive messages from {platform_name} and course teams at this address.": "Les messages que vous recevrez de la part de la plateforme {platform_name} et des \u00e9quipes p\u00e9dagogiques seront envoy\u00e9s \u00e0 cette adresse.", - "You still need to visit the %(display_name)s website to complete the credit process.": "Vous devez encore visiter le site web de %(display_name)s afinn de compl\u00e9ter le processus de cr\u00e9dit.", "You submitted {filename}; only {allowedFiles} are allowed.": "Vous avez envoy\u00e9 {filename}; seul les {allowedFiles} sont autoris\u00e9s.", "You will be refunded the amount you paid.": "Le montant pay\u00e9 vous sera rembours\u00e9.", "You will not be refunded the amount you paid.": "Le montant pay\u00e9 ne vous sera pas rembours\u00e9.", @@ -1932,7 +1917,6 @@ "enter code here": "saisir du code ici", "enter link description here": "saisir une description du lien ici", "for": "pour", - "for {courseName}": "pour {courseName}", "group configuration": "configuration des groupes", "image omitted": "image manquante", "incorrect": "incorrect", @@ -2051,7 +2035,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2109,9 +2093,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j N Y H:i", "SHORT_DATE_FORMAT": "j N Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/gl/djangojs.js b/cms/static/js/i18n/gl/djangojs.js index 4421a34d0a48ee66fb9e16e9e57f966211017ddb..57ea29c47b406403c0a91f9e9aa6f5f88abe442d 100644 --- a/cms/static/js/i18n/gl/djangojs.js +++ b/cms/static/js/i18n/gl/djangojs.js @@ -71,7 +71,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -135,9 +135,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "d-m-Y, H:i", "SHORT_DATE_FORMAT": "d-m-Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/gu/djangojs.js b/cms/static/js/i18n/gu/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/cms/static/js/i18n/gu/djangojs.js +++ b/cms/static/js/i18n/gu/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/he/djangojs.js b/cms/static/js/i18n/he/djangojs.js index d619f772630476b8229f144a8470af682929f53c..1e710d2403eef3bfe5bf20f63cada82bf0bf8e24 100644 --- a/cms/static/js/i18n/he/djangojs.js +++ b/cms/static/js/i18n/he/djangojs.js @@ -146,6 +146,8 @@ ], "%(programName)s Home Page.": "\u05e2\u05de\u05d5\u05d3 \u05d4\u05d1\u05d9\u05ea \u05e9\u05dc %(programName)s", "%(sel)s of %(cnt)s selected": [ + "%(sel)s \u05de %(cnt)s \u05e0\u05d1\u05d7\u05e8\u05d5\u05ea", + "%(sel)s \u05de %(cnt)s \u05e0\u05d1\u05d7\u05e8\u05d5\u05ea", "%(sel)s \u05de %(cnt)s \u05e0\u05d1\u05d7\u05e8\u05d5\u05ea", "%(sel)s \u05de %(cnt)s \u05e0\u05d1\u05d7\u05e8\u05d5\u05ea" ], @@ -840,10 +842,14 @@ "Note: Do not hide graded assignments after they have been released.": "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05dc \u05ea\u05e1\u05ea\u05d9\u05e8 \u05d0\u05ea \u05d4\u05de\u05d8\u05dc\u05d5\u05ea \u05e9\u05e7\u05d9\u05d1\u05dc\u05d5 \u05e6\u05d9\u05d5\u05df \u05dc\u05d0\u05d7\u05e8 \u05d4\u05e4\u05e6\u05ea\u05df.", "Note: You are %s hour ahead of server time.": [ "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d4 \u05dc\u05e4\u05e0\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", + "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05dc\u05e4\u05e0\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", + "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05dc\u05e4\u05e0\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05dc\u05e4\u05e0\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea." ], "Note: You are %s hour behind server time.": [ "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d4 \u05d0\u05d7\u05e8\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", + "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05d0\u05d7\u05e8\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", + "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05d0\u05d7\u05e8\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05d0\u05d7\u05e8\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea." ], "Noted in:": "\u05e6\u05d5\u05d9\u05d9\u05df \u05d1:", @@ -1731,7 +1737,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1795,9 +1801,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j \u05d1F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/hi/djangojs.js b/cms/static/js/i18n/hi/djangojs.js index e12f673e539f6974834027cc771fa0c6bef2190c..8b99dacc4131ede5daea764dfde3900f0ddd0ae9 100644 --- a/cms/static/js/i18n/hi/djangojs.js +++ b/cms/static/js/i18n/hi/djangojs.js @@ -197,7 +197,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -261,9 +261,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "d-m-Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/hr/djangojs.js b/cms/static/js/i18n/hr/djangojs.js index 2d753e19fe9a9fcc4d331111cff9641142ca462c..d749529db5a7a717d8ca915e44ad4e8683992ecb 100644 --- a/cms/static/js/i18n/hr/djangojs.js +++ b/cms/static/js/i18n/hr/djangojs.js @@ -75,7 +75,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -141,9 +141,9 @@ "%d. %m. %y." ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j.m.Y. H:i", "SHORT_DATE_FORMAT": "j.m.Y.", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/hu/djangojs.js b/cms/static/js/i18n/hu/djangojs.js index 0fa2a87315db5be43c08802b6ec87b3be02d0050..ec606e6c8cfd5c8a45d2141ec8069430be39b27f 100644 --- a/cms/static/js/i18n/hu/djangojs.js +++ b/cms/static/js/i18n/hu/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -135,11 +135,11 @@ /* formatting library */ django.formats = { - "DATETIME_FORMAT": "Y. F j. G.i", + "DATETIME_FORMAT": "Y. F j. H:i", "DATETIME_INPUT_FORMATS": [ - "%Y.%m.%d. %H.%M.%S", - "%Y.%m.%d. %H.%M.%S.%f", - "%Y.%m.%d. %H.%M", + "%Y.%m.%d. %H:%M:%S", + "%Y.%m.%d. %H:%M:%S.%f", + "%Y.%m.%d. %H:%M", "%Y.%m.%d.", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", @@ -152,19 +152,17 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "F j.", - "NUMBER_GROUPING": "3", - "SHORT_DATETIME_FORMAT": "Y.m.d. G.i", + "NUMBER_GROUPING": 3, + "SHORT_DATETIME_FORMAT": "Y.m.d. H:i", "SHORT_DATE_FORMAT": "Y.m.d.", "THOUSAND_SEPARATOR": "\u00a0", - "TIME_FORMAT": "G.i", + "TIME_FORMAT": "H:i", "TIME_INPUT_FORMATS": [ - "%H.%M.%S", - "%H.%M", "%H:%M:%S", - "%H:%M:%S.%f", - "%H:%M" + "%H:%M", + "%H:%M:%S.%f" ], "YEAR_MONTH_FORMAT": "Y. F" }; diff --git a/cms/static/js/i18n/hy-am/djangojs.js b/cms/static/js/i18n/hy-am/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..0bf5a1827911bc293256d5bcd7e73fec757e0eb9 100644 --- a/cms/static/js/i18n/hy-am/djangojs.js +++ b/cms/static/js/i18n/hy-am/djangojs.js @@ -5,13 +5,86 @@ var django = globals.django || (globals.django = {}); - django.pluralidx = function(count) { return (count == 1) ? 0 : 1; }; + django.pluralidx = function(n) { + var v=(n != 1); + if (typeof(v) == 'boolean') { + return v ? 1 : 0; + } else { + return v; + } + }; /* gettext library */ django.catalog = django.catalog || {}; + var newcatalog = { + "%(sel)s of %(cnt)s selected": [ + "\u0538\u0576\u057f\u0580\u057e\u0561\u056e \u0567 %(cnt)s-\u056b\u0581 %(sel)s-\u0568", + "\u0538\u0576\u057f\u0580\u057e\u0561\u056e \u0567 %(cnt)s-\u056b\u0581 %(sel)s-\u0568" + ], + "6 a.m.": "6 a.m.", + "6 p.m.": "6 p.m.", + "April": "\u0531\u057a\u0580\u056b\u056c", + "August": "\u0555\u0563\u0578\u057d\u057f\u0578\u057d", + "Available %s": "\u0540\u0561\u057d\u0561\u0576\u0565\u056c\u056b %s", + "Cancel": "\u0549\u0565\u0572\u0561\u0580\u056f\u0565\u056c", + "Choose": "\u0538\u0576\u057f\u0580\u0565\u056c", + "Choose a Date": "\u0538\u0576\u057f\u0580\u0565\u0584 \u0561\u0574\u057d\u0561\u0569\u056b\u057e", + "Choose a Time": "\u0538\u0576\u057f\u0580\u0565\u0584 \u056a\u0561\u0574\u0561\u0576\u0561\u056f", + "Choose a time": "\u0538\u0576\u057f\u0580\u0565\u0584 \u056a\u0561\u0574\u0561\u0576\u0561\u056f", + "Choose all": "\u0538\u0576\u057f\u0580\u0565\u056c \u0562\u0578\u056c\u0578\u0580\u0568", + "Chosen %s": "\u0538\u0576\u057f\u0580\u057e\u0561\u056e %s", + "Click to choose all %s at once.": "\u054d\u0565\u0572\u0574\u0565\u0584 \u0562\u0578\u056c\u0578\u0580 %s\u0568 \u0568\u0576\u057f\u0580\u0565\u056c\u0578\u0582 \u0570\u0561\u0574\u0561\u0580\u0589", + "Click to remove all chosen %s at once.": "\u054d\u0565\u0572\u0574\u0565\u0584 \u0562\u0578\u056c\u0578\u0580 %s\u0568 \u0570\u0565\u057c\u0561\u0581\u0576\u0565\u056c\u0578\u0582 \u0570\u0561\u0574\u0561\u0580\u0589", + "December": "\u0534\u0565\u056f\u057f\u0565\u0574\u0562\u0565\u0580", + "February": "\u0553\u0565\u057f\u0580\u057e\u0561\u0580", + "Filter": "\u0556\u056b\u056c\u057f\u0580\u0565\u056c", + "Hide": "\u0539\u0561\u0584\u0581\u0576\u0565\u056c", + "January": "\u0540\u0578\u0582\u0576\u057e\u0561\u0580", + "July": "\u0540\u0578\u0582\u056c\u056b\u057d", + "June": "\u0540\u0578\u0582\u0576\u056b\u057d", + "March": "\u0544\u0561\u0580\u057f", + "May": "\u0544\u0561\u0575\u056b\u057d", + "Midnight": "\u053f\u0565\u057d\u0563\u056b\u0577\u0565\u0580", + "Noon": "\u053f\u0565\u057d\u0585\u0580", + "Note: You are %s hour ahead of server time.": [ + "\u0541\u0565\u0580 \u056a\u0561\u0574\u0568 \u0561\u057c\u0561\u057b \u0567 \u057d\u0565\u0580\u057e\u0565\u0580\u056b \u056a\u0561\u0574\u0561\u0576\u0561\u056f\u056b\u0581 %s \u056a\u0561\u0574\u0578\u057e", + "\u0541\u0565\u0580 \u056a\u0561\u0574\u0568 \u0561\u057c\u0561\u057b \u0567 \u057d\u0565\u0580\u057e\u0565\u0580\u056b \u056a\u0561\u0574\u0561\u0576\u0561\u056f\u056b\u0581 %s \u056a\u0561\u0574\u0578\u057e" + ], + "Note: You are %s hour behind server time.": [ + "\u0541\u0565\u0580 \u056a\u0561\u0574\u0568 \u0570\u0565\u057f \u0567 \u057d\u0565\u0580\u057e\u0565\u0580\u056b \u056a\u0561\u0574\u0561\u0576\u0561\u056f\u056b\u0581 %s \u056a\u0561\u0574\u0578\u057e", + "\u0541\u0565\u0580 \u056a\u0561\u0574\u0568 \u0570\u0565\u057f \u0567 \u057d\u0565\u0580\u057e\u0565\u0580\u056b \u056a\u0561\u0574\u0561\u0576\u0561\u056f\u056b\u0581 %s \u056a\u0561\u0574\u0578\u057e" + ], + "November": "\u0546\u0578\u0575\u0565\u0574\u0562\u0565\u0580", + "Now": "\u0540\u056b\u0574\u0561", + "October": "\u0540\u0578\u056f\u057f\u0565\u0574\u0562\u0565\u0580", + "Remove": "\u0540\u0565\u057c\u0561\u0581\u0576\u0565\u056c", + "Remove all": "\u0540\u0565\u057c\u0561\u0581\u0576\u0565\u056c \u0562\u0578\u056c\u0578\u0580\u0568", + "September": "\u054d\u0565\u057a\u057f\u0565\u0574\u0562\u0565\u0580", + "Show": "\u0551\u0578\u0582\u0575\u0581 \u057f\u0561\u056c", + "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "\u054d\u0561 \u0570\u0561\u057d\u0561\u0576\u0565\u056c\u056b %s \u0581\u0578\u0582\u0581\u0561\u056f \u0567\u0589 \u0534\u0578\u0582\u0584 \u056f\u0561\u0580\u0578\u0572 \u0565\u0584 \u0568\u0576\u057f\u0580\u0565\u056c \u0576\u0580\u0561\u0576\u0581\u056b\u0581 \u0578\u0580\u0578\u0577\u0576\u0565\u0580\u0568 \u0568\u0576\u057f\u0580\u0565\u056c\u0578\u057e \u0564\u0580\u0561\u0576\u0584 \u057d\u057f\u0578\u0580\u0587 \u0563\u057f\u0576\u057e\u0578\u0572 \u057e\u0561\u0576\u0564\u0561\u056f\u0578\u0582\u0574 \u0587 \u057d\u0565\u0572\u0574\u0565\u056c\u0578\u057e \u0565\u0580\u056f\u0578\u0582 \u057e\u0561\u0576\u0564\u0561\u056f\u0576\u0565\u0580\u056b \u0574\u056b\u057b\u0587 \u0563\u057f\u0576\u057e\u0578\u0572 \"\u0538\u0576\u057f\u0580\u0565\u056c\" \u057d\u056c\u0561\u0584\u0568\u0589", + "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "\u054d\u0561 \u0570\u0561\u057d\u0561\u0576\u0565\u056c\u056b %s\u056b \u0581\u0578\u0582\u0581\u0561\u056f \u0567\u0589 \u0534\u0578\u0582\u0584 \u056f\u0561\u0580\u0578\u0572 \u0565\u0584 \u0570\u0565\u057c\u0561\u0581\u0576\u0565\u056c \u0576\u0580\u0561\u0576\u0581\u056b\u0581 \u0578\u0580\u0578\u0577\u0576\u0565\u0580\u0568 \u0568\u0576\u057f\u0580\u0565\u056c\u0578\u057e \u0564\u0580\u0561\u0576\u0584 \u057d\u057f\u0578\u0580\u0587 \u0563\u057f\u0576\u057e\u0578\u0572 \u057e\u0561\u0576\u0564\u0561\u056f\u0578\u0582\u0574 \u0587 \u057d\u0565\u0572\u0574\u0565\u056c\u0578\u057e \u0565\u0580\u056f\u0578\u0582 \u057e\u0561\u0576\u0564\u0561\u056f\u0576\u0565\u0580\u056b \u0574\u056b\u057b\u0587 \u0563\u057f\u0576\u057e\u0578\u0572 \"\u0540\u0565\u057c\u0561\u0581\u0576\u0565\u056c\" \u057d\u056c\u0561\u0584\u0568\u0589", + "Today": "\u0531\u0575\u057d\u0585\u0580", + "Tomorrow": "\u054e\u0561\u0572\u0568", + "Type into this box to filter down the list of available %s.": "\u0544\u0578\u0582\u057f\u0584\u0561\u0563\u0580\u0565\u0584 \u0561\u0575\u057d \u0564\u0561\u0577\u057f\u0578\u0582\u0574 \u0570\u0561\u057d\u0561\u0576\u0565\u056c\u056b %s \u0581\u0578\u0582\u0581\u0561\u056f\u0568 \u0586\u056b\u056c\u057f\u0580\u0565\u056c\u0578\u0582 \u0570\u0561\u0574\u0561\u0580\u0589", + "Yesterday": "\u0535\u0580\u0565\u056f", + "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "\u0534\u0578\u0582\u0584 \u0568\u0576\u057f\u0580\u0565\u056c \u0565\u0584 \u0563\u0578\u0580\u056e\u0578\u0572\u0578\u0582\u0569\u0575\u0578\u0582\u0576, \u0562\u0561\u0575\u0581 \u0564\u0565\u057c \u0579\u0565\u0584 \u056f\u0561\u057f\u0561\u0580\u0565\u056c \u0578\u0580\u0587\u0567 \u0561\u0576\u0570\u0561\u057f\u0561\u056f\u0561\u0576 \u056d\u0574\u0562\u0561\u0563\u0580\u0565\u056c\u056b \u0564\u0561\u0577\u057f\u0565\u0580\u056b \u0583\u0578\u0583\u0578\u056d\u0578\u0582\u0569\u0575\u0578\u0582\u0576 \u0541\u0565\u0566 \u0570\u0561\u057e\u0561\u0576\u0561\u0562\u0561\u0580 \u057a\u0565\u057f\u0584 \u0567 \u053f\u0561\u057f\u0561\u0580\u0565\u056c \u056f\u0578\u0573\u0561\u056f\u0568, \u054a\u0561\u0570\u057a\u0561\u0576\u0565\u056c \u056f\u0578\u0573\u0561\u056f\u056b \u0583\u0578\u056d\u0561\u0580\u0565\u0576", + "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "\u0534\u0578\u0582\u0584 \u0568\u0576\u057f\u0580\u0565\u056c \u0565\u0584 \u0563\u0578\u0580\u056e\u0578\u0572\u0578\u0582\u0569\u0575\u0578\u0582\u0576, \u0562\u0561\u0575\u0581 \u0564\u0565\u057c \u0579\u0565\u0584 \u057a\u0561\u0570\u057a\u0561\u0576\u0565\u056c \u0561\u0576\u0570\u0561\u057f\u0561\u056f\u0561\u0576 \u056d\u0574\u0562\u0561\u0563\u0580\u0565\u056c\u056b \u0564\u0561\u0577\u057f\u0565\u0580\u056b \u0583\u0578\u0583\u0578\u056d\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0576\u0565\u0580\u0568 \u054d\u0565\u0572\u0574\u0565\u0584 OK \u057a\u0561\u0570\u057a\u0561\u0576\u0565\u056c\u0578\u0582 \u0570\u0561\u0574\u0561\u0580\u0589 \u0531\u0576\u0570\u0580\u0561\u056a\u0565\u0577\u057f \u056f\u056c\u056b\u0576\u056b \u057e\u0565\u0580\u0561\u0563\u0578\u0580\u056e\u0561\u0580\u056f\u0565\u056c \u0563\u0578\u0580\u056e\u0578\u0572\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568", + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "\u0534\u0578\u0582\u0584 \u0578\u0582\u0576\u0565\u0584 \u0579\u057a\u0561\u0570\u057a\u0561\u0576\u057e\u0561\u056e \u0561\u0576\u0570\u0561\u057f\u0561\u056f\u0561\u0576 \u056d\u0574\u0562\u0561\u0563\u0580\u0565\u056c\u056b \u0564\u0561\u0577\u057f\u0565\u0580\u0589 \u0535\u0569\u0565 \u0564\u0578\u0582\u0584 \u056f\u0561\u057f\u0561\u0580\u0565\u0584 \u0563\u0578\u0580\u056e\u0578\u0572\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568, \u0571\u0565\u0580 \u0579\u057a\u0561\u0570\u057a\u0561\u0576\u057e\u0561\u056e \u0583\u0578\u0583\u0578\u056d\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0576\u0565\u0580\u0568 \u056f\u056f\u0578\u0580\u0565\u0576\u0589", + "one letter Friday\u0004F": "\u0548\u0552", + "one letter Monday\u0004M": "\u0535", + "one letter Saturday\u0004S": "\u0547", + "one letter Sunday\u0004S": "\u053f", + "one letter Thursday\u0004T": "\u0540", + "one letter Tuesday\u0004T": "\u0535", + "one letter Wednesday\u0004W": "\u0549" + }; + for (var key in newcatalog) { + django.catalog[key] = newcatalog[key]; + } + if (!django.jsi18n_initialized) { django.gettext = function(msgid) { @@ -28,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +165,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/id/djangojs.js b/cms/static/js/i18n/id/djangojs.js index 41bad306e3e7de0ee35b2a3f206aa543a7f34bad..9dc978e064c5929ec710d0dd2d7c6580f0e98ba9 100644 --- a/cms/static/js/i18n/id/djangojs.js +++ b/cms/static/js/i18n/id/djangojs.js @@ -465,7 +465,6 @@ "Do you want to upload your file before submitting?": "Apakah Anda ingin mengunggah berkas Anda sebelum mengirimkan?", "Document properties": "Properti dokumen", "Does the name on your ID match your account name: %(fullName)s?": "Apakah nama pada ID anda sesuai dengan nama account anda: %(fullName)s?", - "Does the photo of you match your ID photo?": "Apakah photo anda sesuai dengan photo ID?", "Does the photo of you show your whole face?": "Apakah photo anda menunjukkan seluruh wajah?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Tidakmelihat gambar anda? pastikan membolehkan browser anda untuk menggunakan kamera jika dia meminta izin ", "Donate": "Donasi", @@ -607,7 +606,6 @@ "Fill browser": "Peramban penuh", "Filter": "Filter", "Filter and sort topics": "Saring dan urutkan topik", - "Final Grade": "Nilai Akhir", "Final Grade Received": "Nilai Akhir Diterima", "Financial Aid": "Bantuan Finansial", "Financial Assistance": "Bantuan Finansial", @@ -638,7 +636,6 @@ "General": "Umum", "Generate": "Generate", "Generate Exception Certificates": "Buat Sertifikat Pengecualian", - "Get Credit": "Dapatkan kredit", "Go Back": "Kembali", "Go to Dashboard": "Menuju dashboard", "Go to my Dashboard": "Menuju Dashboard", @@ -701,7 +698,6 @@ "Hyperlink (Ctrl+L)": "Hyperlink (Ctrl+L)", "ID": "ID", "ID-Verification is not required for this Professional Education course.": "Verifikasi ID tidak dibutuhkan untuk kursus pendidikan profesional", - "If you are unable to access your account contact us via email using {email}.": "Jika Anda tidak dapat masuk, hubungi kami melalui email ke {email}.", "If you do not yet have an account, use the button below to register.": "Jika Anda belum memiliki akun, gunakan tombol di bawah untuk registrasi.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "Jika Anda tidak memverifikasi identitas Anda sekarang, Anda masih dapat melihat kursus Anda dari dashboard Anda. Anda akan menerima pengingat dari %(platformName)s secara periodik untuk memverifikasi identitas Anda.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "Jika Anda meninggalkan halaman ini tanpa menyimpan atau mengirim tanggapan Anda, Anda akan kehilangan semua pekerjaan yang Anda buat pada tanggapan Anda.", @@ -860,7 +856,6 @@ "Name of the signatory": "Nama Penandatangan", "Name or short description of the configuration": "Nama atau gambaran singkat dari konfigurasi", "Navigate up": "Navigasi naik", - "Need help logging in?": "Butuh bantuan untuk masuk?", "Needs verified certificate ": "Memerlukan sertifikat terverifikasi", "Never published": "Tidak pernah dipublikasikan", "Never show assessment results": "Jangan tampilkan hasil penilaian", @@ -927,7 +922,6 @@ "Ok": "Ok", "Once you complete one of the program requirements you have a program record. This record is marked complete once you meet all program requirements. A program record can be used to continue your learning journey and demonstrate your learning to others.": "Setelah Anda melengkapi salah satu persyaratan program Anda akan memiliki record program. Record ini ditandai lengkap setelah Anda memenuhi semua persyaratan program. Record program dapat digunakan untuk melanjutkan perjalanan pembelajaran Anda dan menunjukkan pembelajaran Anda kepada orang lain.", "One or more rescheduling tasks failed.": "Salah satu tugas penjadwalan telah gagal.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "Hanya berkas <%= fileTypes %> yang dapat diunggah. Harap pilih berkas dengan ekstensi <%= fileExtensions %> untuk diunggah.", "Only properly formatted .csv files will be accepted.": "Hanya berkas-berkas .csv yang diformat dengan tepat dapat diterima.", "Open Calculator": "Buka Kalkulator", "Open language menu": "Buka menu bahasa", @@ -1158,7 +1152,6 @@ "Select a course or select \"Not specific to a course\" for your support request.": "Pilih satu kursus atau pilih \"Tidak spesifik untuk kursus tertentu\" untuk permintaan Anda.", "Select a section or problem": "Pilih bagian atau masalah", "Select a session:": "Pilih sesi:", - "Select a subject for your support request.": "Berikan judul untuk permintaan dukungan Anda.", "Select a time allotment for the exam. If it is over 24 hours, type in the amount of time. You can grant individual learners extra time to complete the exam through the Instructor Dashboard.": "Pilih penjatahan waktu untuk ujian. Jika lebih dari 24 jam, ketik jumlah waktu. Anda dapat memberikan peserta didik waktu tambahan untuk menyelesaikan ujian melalui Dashboard Instruktur.", "Select all": "pilih semua", "Select fidelity": "Pilih fidelity", @@ -1320,7 +1313,6 @@ "Textbook Name": "Nama textbook", "Textbook information": "Informasi textbook", "Thank you for setting your course goal to {goal}!": "Terima kasih sudah membuat {goal} sebagai tujuan kursus Anda!", - "Thank you for submitting a request! We will contact you within 24 hours.": "Terima kasih atas permintaan Anda! Kami akan menghubungi Anda dalam 24 jam.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Terimakasih sudah mengirimkan aplikasi bantuan finansial untuk {course_name}. Anda dapat mengharapkan balasan dalam 2-4 hari kerja.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Terimakasih sudah mengirimkan foto Anda. Kami akan meninjaunya segera. Anda dapat mengikuti kursus %(platformName)s apapun yang menawarkan sertifikat terverifikasi. Verifikasi berlaku selamat satu tahun. Setelah itu, Anda harus mengirimkan foto untuk verifikasi lagi.", "The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "URL anda tampak seperti alamat email. Apakah anda ingin menambahkan prefiks mailto:?", @@ -1340,7 +1332,6 @@ "The following email addresses and/or usernames are invalid:": "Alamat email dan atau nama pengguna berikut tidak valid:", "The following errors were generated:": "Kesalahan berikut terjadi:", "The following file types are not allowed: ": "Jenis berkas berikut tidak diperkenankan:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "Informasi berikut merupakan bagian dari profil {platform}. Kami memasukkannya untuk aplikasi Anda.", "The following message will be displayed at the bottom of the courseware pages within your course:": "Pesan berikut akan ditunjukkan pada bagian bawah dari halaman courseware dengan kursus anda", "The following options are available for the {license_name} license.": "Opsi berikut tersedia untuk {license_name} license.", "The following users are no longer enrolled in the course:": "Pengguna berikut sudah tidak terdaftar pada pembelajaran:", @@ -1350,7 +1341,6 @@ "The language that team members primarily use to communicate with each other.": "Bahasa yang terutama digunakan oleh anggota tim untuk berkomunikasi.", "The language used throughout this site. This site is currently available in a limited number of languages. Changing the value of this field will cause the page to refresh.": "Bahasa yang digunakan di seluruh situs. Situs ini saat ini tersedia dalam sejumlah bahasa. Mengubah nilai isian ini akan merefresh halaman ini.", "The minimum score percentage must be a whole number between 0 and 100.": "Persentase skor minimum mesti angka diantara 0 dan 100.", - "The more you tell us, the more quickly and helpfully we can respond!": "Semakin lengkap informasimu, semakin cepat dan tepat respon kami!", "The name of this signatory as it should appear on certificates.": "Nama penandatangan yang harus tercetak di sertifikat", "The name that identifies you on {platform_name}. You cannot change your username.": "Nama yang digunakan untuk mengenali Anda pada {platform_name}. Anda tidak dapat mengubah nama pengguna Anda.", "The name that is used for ID verification and that appears on your certificates.": "Nama yang digunakan untuk verifikasi ID dan ditampilkan di sertifikat Anda.", @@ -1358,7 +1348,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Jumlah subbagian dalam kursus yang berisi masalah dari jenis tugas ini.", "The organization that this signatory belongs to, as it should appear on certificates.": "Organisasi penandatangan yang harus tercetak di sertifikat", "The page \"{route}\" could not be found.": "Halaman \"{route}\" tidak dapat ditemukan.", - "The photo of your face matches the photo on your ID.": "Photo wajah anda sesuai dengan photo pada ID anda", "The post you selected has been deleted.": "Post yang Anda pilih telah dihapus.", "The refund deadline for this course has passed,so you will not receive a refund.": "Batas waktu refund untuk kursus ini telah berakhir, sehingga Anda tidak dapat menerima refund.", "The selected content group does not exist": "Grup isi yang dipilih tidak ada", @@ -1537,7 +1526,6 @@ "Upload PDF": "Unggah PDF", "Upload Photo": "Unggah Foto", "Upload Signature Image": "Unggah Gambar Tandatangan", - "Upload a new PDF to \u201c<%= name %>\u201d": "Unggah berkas PDF baru ke \u201c<%= name %>\u201d", "Upload an image": "Unggah gambar", "Upload completed": "Unggah selesai", "Upload is in progress. To avoid errors, stay on this page until the process is complete.": "Proses unggah sedang berlangsung. Untuk menghindari kesalahan, tetap berada di halaman ini sampai proses selesai.", @@ -1559,7 +1547,6 @@ "Use my institution/campus credentials": "Gunakan Kredensial Kampus/Institusi", "Use my university info": "Gunakan informasi universitas saya", "Use the All Topics menu to find specific topics.": "Gunakan menu Semua Topik untuk menemukan topik tertentu.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Gunakan webcan untuk mengambil foto ID Anda. Kami akan mencocokkan foto ini dengan foto wajah Anda dan nama di akun Anda.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Gunakan webcan untuk mengambil foto ID Anda. Kami akan mencocokkan foto ini dengan foto wajah di kartu identitas Anda.", "Used": "Terpakai", "Username": "Pengguna", @@ -1576,7 +1563,6 @@ "Verified Certificate for {courseName}": "Sertifikat Terverifikasi untuk {courseName}", "Verified Certificate upgrade": "Tingkatkan Sertifikat Terverifikasi", "Verified Status": "Status terverifikasi", - "Verify Now": "Verifikasi sekarang", "Vertical space": "Ruang vertikal", "Very loud": "Sangat Keras", "Very low": "Sangat rendah", @@ -1696,8 +1682,6 @@ "You must specify a name": "Anda harus berikan nama", "You must specify a name for the cohort": "Anda harus menentukan nama untuk kohort ini", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "Anda harus menentukan tahun lahir sebelum Anda dapat membagikan profil lengkap Anda. Untuk memilih tahun lahir, klik {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Anda memerlukan surat izin mengemudi, paspor, atau kartu identitas lain yang diterbitkan pemerintah yang memiliki nama dan foto Anda.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Anda membutuhkan kartu identitas dengan nama dan foto Anda. Surat izin mengemudi, paspor, atau kartu identitas lain yang diterbitkan oleh pemerintah dapat digunakan.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Anda memerlukan untuk aktifasi account anda sebelum anda dapat mendaftar kursus. Periksa inbok anda pada aktifasi email", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Anda harus mengaktifkan akun sebelum Anda dapat mendaftar kursus. Periksa kotak masuk email Anda untuk email aktivasi. Setelah Anda menyelesaikan aktivasi Anda dapat memuat kembali halaman ini.", "You receive messages from {platform_name} and course teams at this address.": "Anda menerima pesan dari {platform_name} dan tim kursus di alamat ini.", @@ -1778,7 +1762,6 @@ "enter code here": "masukan kode disini", "enter link description here": "masukan keterangan tautan di sini", "for": "untuk", - "for {courseName}": "untuk {courseName}", "image omitted": "gambar dihilangkan", "incorrect": "Salah", "internally reviewed": "Telah diulas secara internal", @@ -1890,7 +1873,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1958,9 +1941,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d-m-Y G.i", "SHORT_DATE_FORMAT": "d-m-Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/it-it/djangojs.js b/cms/static/js/i18n/it-it/djangojs.js index 98e7f832b1ccd2aa9438b91aa786469294477587..e508d178a06a491ba713296c0d8b0ef0a009c42a 100644 --- a/cms/static/js/i18n/it-it/djangojs.js +++ b/cms/static/js/i18n/it-it/djangojs.js @@ -886,7 +886,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -953,9 +953,9 @@ "%d/%m/%y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", - "MONTH_DAY_FORMAT": "j/F", - "NUMBER_GROUPING": "3", + "FIRST_DAY_OF_WEEK": 1, + "MONTH_DAY_FORMAT": "j F", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/ja-jp/djangojs.js b/cms/static/js/i18n/ja-jp/djangojs.js index ca0bf55248e1c345c3179820d6290706d3519470..e96ac07c645716caa20c4f1e5e279da33eb05ea8 100644 --- a/cms/static/js/i18n/ja-jp/djangojs.js +++ b/cms/static/js/i18n/ja-jp/djangojs.js @@ -365,7 +365,6 @@ "Default (Local Time Zone)": "\u65e2\u5b9a\u5024 (\u5730\u57df\u5225\u30bf\u30a4\u30e0\u30be\u30fc\u30f3)", "Default Timed Transcript": "\u65e2\u5b9a\u306e\u6642\u9593\u4ed8\u304d\u306e\u5b57\u5e55", "Delete": "\u524a\u9664", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u7f72\u540d\u4e00\u89a7\u304b\u3089 \"<%= signatoryName %>\" \u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f", "Delete File Confirmation": "\u30d5\u30a1\u30a4\u30eb\u524a\u9664\u78ba\u8a8d", "Delete Team": "\u30c1\u30fc\u30e0\u3092\u524a\u9664", "Delete student '<%- student_id %>'s state on problem '<%- problem_id %>'?": "\u53d7\u8b1b\u8005 '<%- student_id %>' \u306e\u554f\u984c '<%- problem_id %>' \u306e\u56de\u7b54\u3092\u524a\u9664\u3057\u3066\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f", @@ -391,7 +390,6 @@ "Do you want to replace the edX transcript with the YouTube transcript?": "edX\u5b57\u5e55\u3092YouTube\u5b57\u5e55\u3067\u7f6e\u304d\u63db\u3048\u307e\u3059\u304b\uff1f", "Do you want to upload your file before submitting?": "\u63d0\u51fa\u524d\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u307e\u3059\u304b\uff1f", "Does the name on your ID match your account name: %(fullName)s?": "\u8eab\u5206\u8a3c\u660e\u66f8\u4e0a\u306e\u6c0f\u540d\u306f\u3042\u306a\u305f\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u6c0f\u540d\u3068\u4e00\u81f4\u3057\u307e\u3059\u304b\uff1f: %(fullName)s", - "Does the photo of you match your ID photo?": "\u8eab\u5206\u8a3c\u660e\u66f8\u306e\u5199\u771f\u3068\u3042\u306a\u305f\u306e\u5199\u771f\u306f\u4e00\u81f4\u3057\u307e\u3059\u304b\uff1f", "Does the photo of you show your whole face?": "\u5199\u771f\u306b\u3042\u306a\u305f\u306e\u9854\u5168\u4f53\u304c\u5199\u3063\u3066\u3044\u307e\u3059\u304b\uff1f", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u5199\u771f\u304c\u898b\u3048\u306a\u3044\u3067\u3059\u304b\uff1f\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u3001\u30d6\u30e9\u30a6\u30b6\u304c\u30ab\u30e1\u30e9\u3092\u4f7f\u3048\u308b\u72b6\u614b\u304b\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002", "Donate": "\u5bc4\u4ed8", @@ -538,7 +536,6 @@ "Generate": "\u751f\u6210", "Generate Exception Certificates": "\u4f8b\u5916\u4fee\u4e86\u8a3c\u3092\u751f\u6210", "Generate the user's certificate": "\u30e6\u30fc\u30b6\u30fc\u306e\u4fee\u4e86\u8a3c\u3092\u751f\u6210", - "Get Credit": "\u5358\u4f4d\u3092\u7372\u5f97\u3059\u308b", "Go Back": "\u623b\u308b", "Go to Dashboard": "\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u3078\u79fb\u52d5", "Go to your Dashboard": "\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u3078", @@ -583,7 +580,6 @@ "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u30e6\u30cb\u30c3\u30c8\u304c\u4ee5\u524d\u53d7\u8b1b\u8005\u306b\u516c\u958b\u3055\u308c\u3066\u3044\u305f\u5834\u5408\u3001\u975e\u516c\u958b\u4e2d\u306e\u5909\u66f4\u3082\u5f8c\u307b\u3069\u53d7\u8b1b\u8005\u306b\u8868\u793a\u3055\u308c\u307e\u3059\u3002", "If you do not yet have an account, use the button below to register.": "\u307e\u3060\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u767b\u9332\u3057\u3066\u3044\u306a\u3044\u306e\u3067\u3042\u308c\u3070\u3001\u4e0b\u306e\u30dc\u30bf\u30f3\u3092\u4f7f\u3063\u3066\u767b\u9332\u3057\u3066\u304f\u3060\u3055\u3044\u3002", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u3044\u307e\u3059\u3050\u672c\u4eba\u8a8d\u8a3c\u3092\u884c\u308f\u306a\u304f\u3066\u3082\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u3067\u8b1b\u5ea7\u3092\u63a2\u3059\u3053\u3068\u306f\u3067\u304d\u307e\u3059\u3002\u5b9a\u671f\u7684\u306b%(platformName)s\u304b\u3089\u672c\u4eba\u8a8d\u8a3c\u3092\u884c\u3046\u3088\u3046\u306b\u901a\u77e5\u304c\u3042\u308a\u307e\u3059\u3002", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u3059\u3050\u306b\u672c\u4eba\u8a8d\u8a3c\u3092\u884c\u308f\u306a\u3044\u5834\u5408\u3067\u3082\u3001\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u3067\u8b1b\u5ea7\u3092\u63a2\u3059\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u5b9a\u671f\u7684\u306b{platformName}\u304b\u3089\u672c\u4eba\u8a8d\u8a3c\u3092\u884c\u3046\u3088\u3046\u901a\u77e5\u304c\u3042\u308a\u307e\u3059\u3002", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "\u8fd4\u4fe1\u3092\u4fdd\u5b58\u307e\u305f\u306f\u63d0\u51fa\u305b\u305a\u306b\u5225\u306e\u30da\u30fc\u30b8\u3078\u79fb\u52d5\u3059\u308b\u5834\u5408\u3001\u8a18\u8ff0\u3057\u305f\u5185\u5bb9\u304c\u5931\u308f\u308c\u307e\u3059\u3002", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "\u30d4\u30a2\u30fb\u30a2\u30bb\u30b9\u30e1\u30f3\u30c8\u3092\u63d0\u51fa\u305b\u305a\u306b\u5225\u306e\u30da\u30fc\u30b8\u3078\u79fb\u52d5\u3059\u308b\u5834\u5408\u3001\u8a18\u8ff0\u3057\u305f\u5185\u5bb9\u304c\u5931\u308f\u308c\u307e\u3059\u3002", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "\u30bb\u30eb\u30d5\u30fb\u30a2\u30bb\u30b9\u30e1\u30f3\u30c8\u3092\u63d0\u51fa\u305b\u305a\u306b\u5225\u306e\u30da\u30fc\u30b8\u3078\u79fb\u52d5\u3059\u308b\u3068\u3001\u8a18\u8ff0\u3057\u305f\u5185\u5bb9\u304c\u5931\u308f\u308c\u307e\u3059\u3002", @@ -1088,7 +1084,6 @@ "Terms of Service and Honor Code": "\u5229\u7528\u898f\u7d04\u304a\u3088\u3073\u502b\u7406\u898f\u5b9a", "Textbook Name": "\u6559\u79d1\u66f8\u540d", "Textbook information": "\u6559\u79d1\u66f8\u60c5\u5831", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "%(full_name)s\u69d8\u3001\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3059\uff01%(course_name)s\u306b\u95a2\u3059\u308b\u304a\u652f\u6255\u3044\u3092\u53d7\u7406\u3057\u307e\u3057\u305f\u3002", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "{course_name}\u306e\u7d4c\u6e08\u63f4\u52a9\u7533\u8fbc\u66f8\u3092\u3054\u63d0\u51fa\u3044\u305f\u3060\u304d\u3001\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3059\uff012-4\u55b6\u696d\u65e5\u4ee5\u5185\u306b\u8fd4\u4fe1\u304c\u5c4a\u304d\u307e\u3059\u3002", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "\u5199\u771f\u3092\u3054\u63d0\u51fa\u3044\u305f\u3060\u304d\u3001\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3059\u3002\u307e\u3082\u306a\u304f\u78ba\u8a8d\u3044\u305f\u3057\u307e\u3059\u3002%(platformName)s\u306e\u8a8d\u8a3c\u4ed8\u304d\u4fee\u4e86\u8a3c\u3092\u767a\u884c\u3057\u3066\u3044\u308b\u8b1b\u5ea7\u306b\u767b\u9332\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u8a8d\u8a3c\u306f\uff11\u5e74\u9593\u6709\u52b9\u3067\u3059\u3002\uff11\u5e74\u5f8c\u306b\u518d\u3073\u8a8d\u8a3c\u7528\u5199\u771f\u306e\u63d0\u51fa\u304c\u5fc5\u8981\u3068\u306a\u308a\u307e\u3059\u3002", "Thank you! We have received your payment for {courseName}.": "\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3057\u305f\uff01 {courseName}\u8b1b\u5ea7\u306e\u652f\u6255\u3092\u53d7\u9818\u3057\u307e\u3057\u305f\u3002", @@ -1097,8 +1092,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u3053\u306e\u53d7\u8b1b\u8005\u306e\u4fee\u4e86\u8a3c\u306f\u518d\u5ea6\u6709\u52b9\u3068\u306a\u308a\u307e\u3057\u305f\u306e\u3067\u3001\u30b7\u30b9\u30c6\u30e0\u306f\u63a1\u70b9\u3092\u518d\u958b\u3057\u307e\u3059\u3002", "The cohort cannot be added": "\u30b3\u30db\u30fc\u30c8\u304c\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093", "The cohort cannot be saved": "\u30b3\u30db\u30fc\u30c8\u304c\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u7d44\u7e54\u540d\u3001\u30e9\u30a4\u30d6\u30e9\u30ea\u30b3\u30fc\u30c9\u6b04\u306e\u5408\u8a08\u6587\u5b57\u6570\u306f<%=limit%>\u6587\u5b57\u307e\u3067\u3067\u3059\u3002", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u7d44\u7e54\u540d\u3001\u8b1b\u5ea7\u756a\u53f7\u3001course run\u6b04\u306e\u5408\u8a08\u6587\u5b57\u6570\u306f<%=limit%>\u6587\u5b57\u307e\u3067\u3067\u3059\u3002", "The country or region where you live.": "\u304a\u4f4f\u307e\u3044\u306e\u56fd\u30fb\u5730\u57df\u3002", "The country that team members primarily identify with.": "\u30c1\u30fc\u30e0\u306e\u4e3b\u306a\u30e1\u30f3\u30d0\u30fc\u306e\u56fd\u3002", "The course end date must be later than the course start date.": "\u8b1b\u5ea7\u7d42\u4e86\u65e5\u306f\u3001\u8b1b\u5ea7\u958b\u59cb\u65e5\u3088\u308a\u5f8c\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002", @@ -1113,7 +1106,6 @@ "The following email addresses and/or usernames are invalid:": "\u6b21\u306e\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u307e\u305f\u306f\u30e6\u30fc\u30b6\u30fc\u540d\u304c\u7121\u52b9\u3067\u3059: ", "The following errors were generated:": "\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: ", "The following file types are not allowed: ": "\u6b21\u306b\u793a\u3059\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u306f\u4e0d\u6b63\u3067\u3059\uff1a", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "\u4ee5\u4e0b\u306e\u60c5\u5831\u306f\u3059\u3067\u306b\u3042\u306a\u305f\u306e{platform}\u306e\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u306b\u5165\u3063\u3066\u3044\u307e\u3059\u3002\u7533\u8fbc\u66f8\u306b\u4ee5\u4e0b\u306e\u60c5\u5831\u3092\u5165\u308c\u307e\u3057\u305f\u3002", "The following message will be displayed at the bottom of the courseware pages within your course:": "\u6b21\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u306f\u30b3\u30fc\u30b9\u30a6\u30a7\u30a2\u753b\u9762\u306e\u4e0b\u90e8\u306b\u8868\u793a\u3055\u308c\u307e\u3059: ", "The following options are available for the {license_name} license.": " {license_name}\u30e9\u30a4\u30bb\u30f3\u30b9\u3067\u306f\u3001\u4ee5\u4e0b\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u304c\u5229\u7528\u3067\u304d\u307e\u3059\u3002", "The following users are no longer enrolled in the course:": "\u6b21\u306e\u30e6\u30fc\u30b6\u30fc\u306f\u8b1b\u5ea7\u306b\u53d7\u8b1b\u767b\u9332\u3055\u308c\u3066\u3044\u307e\u305b\u3093: ", @@ -1127,7 +1119,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "\u3053\u306e\u8ab2\u984c\u30bf\u30a4\u30d7\u306e\u554f\u984c\u3092\u542b\u3080\u30b5\u30d6\u30bb\u30af\u30b7\u30e7\u30f3\u6570\u3002", "The organization that this signatory belongs to, as it should appear on certificates.": "\u4fee\u4e86\u8a3c\u306b\u8868\u793a\u3055\u308c\u308b\u3053\u306e\u7f72\u540d\u8005\u304c\u6240\u5c5e\u3057\u3066\u3044\u308b\u7d44\u7e54", "The page \"{route}\" could not be found.": "\"{route}\" \u3068\u3044\u3046\u30da\u30fc\u30b8\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002", - "The photo of your face matches the photo on your ID.": "\u9854\u5199\u771f\u3068ID\u306e\u5199\u771f\u304c\u4e00\u81f4\u3057\u3066\u3044\u308b\u3002", "The post you selected has been deleted.": "\u3042\u306a\u305f\u304c\u9078\u629e\u3057\u305f\u6295\u7a3f\u306f\u524a\u9664\u3055\u308c\u3066\u3044\u307e\u3059\u3002", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "\u516c\u958b\u6e08\u307f\u30d6\u30e9\u30f3\u30c1\u306e\u30d0\u30fc\u30b8\u30e7\u30f3{published}\u306f\u30c9\u30e9\u30d5\u30c8\u30d6\u30e9\u30f3\u30c1\u306e\u30d0\u30fc\u30b8\u30e7\u30f3{draft}\u306b\u30ea\u30bb\u30c3\u30c8\u3055\u308c\u307e\u3057\u305f\u3002", "The raw error message is:": "\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u539f\u6587\uff1a", @@ -1238,7 +1229,6 @@ "Titles more than 100 characters may prevent students from printing their certificate on a single page.": "\u5f79\u8077\u304c100\u6587\u5b57\u4ee5\u4e0a\u3060\u3068\u3001\u4fee\u4e86\u8a3c\u30921\u30da\u30fc\u30b8\u306b\u53ce\u3081\u3066\u5370\u5237\u3067\u304d\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002", "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "\u5168\u53d7\u8b1b\u8005\u304c\u52d5\u753b\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u308b\u3088\u3046\u306b\u3001.mp4\u3068.webm\u306e\u4e21\u65b9\u306e\u7a2e\u985e\u306e\u52d5\u753b\u3092\u63d0\u4f9b\u3059\u308b\u3053\u3068\u3092\u304a\u52e7\u3081\u3057\u307e\u3059\u3002\u5225\u306e\u7a2e\u985e\u306eURL\u3092\u8ffd\u52a0\u3059\u308b\u306b\u306f\u4ee5\u4e0b\u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059\u3002\u3053\u308c\u3089\u306eURL\u306fYouTube\u306f\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002\u4e00\u89a7\u306e\u4e2d\u304b\u3089\u53d7\u8b1b\u8005\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u306b\u5bfe\u5fdc\u3059\u308b\uff11\u756a\u76ee\u306e\u52d5\u753b\u304c\u518d\u751f\u3055\u308c\u307e\u3059\u3002", "To complete the program, you must earn a verified certificate for each course.": "\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u4fee\u4e86\u3059\u308b\u306b\u306f\u3001\u5404\u8b1b\u5ea7\u306e\u8a8d\u8a3c\u4ed8\u304d\u4fee\u4e86\u8a3c\u3092\u7372\u5f97\u3057\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "\u5358\u4f4d\u8a8d\u5b9a\u306e\u6700\u7d42\u51e6\u7406\u3092\u3059\u308b\u305f\u3081\u306b\u3001%(display_name)s\u3067\u306f%(platform_name)s\u53d7\u8b1b\u8005\u306b\u5358\u4f4d\u8a8d\u5b9a\u7533\u8acb\u3092\u63d0\u51fa\u3059\u308b\u3088\u3046\u6c42\u3081\u3066\u3044\u307e\u3059\u3002", "To invalidate a certificate for a particular learner, add the username or email address below.": "\u7279\u5b9a\u306e\u53d7\u8b1b\u8005\u306e\u4fee\u4e86\u8a3c\u3092\u7121\u52b9\u306b\u3059\u308b\u306b\u306f\u3001\u30e6\u30fc\u30b6\u30fc\u540d\u307e\u305f\u306f\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3092\u4ee5\u4e0b\u306b\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002", "To receive a certificate, you must also verify your identity before {date}.": "\u4fee\u4e86\u8a3c\u3092\u53d6\u5f97\u3059\u308b\u305f\u3081\u306b\u306f\u3001{date}\u307e\u3067\u306b\u672c\u4eba\u8a8d\u8a3c\u3092\u3057\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002", "To receive a certificate, you must also verify your identity.": "\u4fee\u4e86\u8a3c\u3092\u53d6\u5f97\u3059\u308b\u305f\u3081\u306b\u306f\u3001\u672c\u4eba\u8a8d\u8a3c\u3092\u3057\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002", @@ -1328,7 +1318,6 @@ "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "\u30c7\u30a3\u30b9\u30ab\u30c3\u30b7\u30e7\u30f3\u3092\u5206\u5272\u3059\u308b\u57fa\u6e96\u3068\u3057\u3066\u53d7\u8b1b\u767b\u9332\u30c8\u30e9\u30c3\u30af\u3092\u5229\u7528\u3057\u307e\u3059\u3002\u53d7\u8b1b\u767b\u9332\u30c8\u30e9\u30c3\u30af\u306b\u95a2\u4fc2\u306a\u304f\u3001\u5168\u53d7\u8b1b\u8005\u306b\u540c\u3058\u30c7\u30a3\u30b9\u30ab\u30c3\u30b7\u30e7\u30f3\u30fb\u30c8\u30d4\u30c3\u30af\u304c\u8868\u793a\u3055\u308c\u307e\u3059\u304c\u3001\u5206\u5272\u3055\u308c\u305f\u30c8\u30d4\u30c3\u30af\u5185\u3067\u306f\u540c\u3058\u53d7\u8b1b\u767b\u9332\u30c8\u30e9\u30c3\u30af\u306e\u53d7\u8b1b\u8005\u3060\u3051\u304c\u4e92\u3044\u306e\u6295\u7a3f\u3092\u898b\u305f\u308a\u8fd4\u4fe1\u3057\u305f\u308a\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002", "Use my institution/campus credentials": "\u6a5f\u95a2/\u5b66\u6821\u306e\u8a3c\u660e\u66f8\u3092\u4f7f\u3046", "Use the All Topics menu to find specific topics.": "\u7279\u5b9a\u306e\u30c8\u30d4\u30c3\u30af\u3092\u898b\u3064\u3051\u308b\u306b\u306f'\u5168\u30c8\u30d4\u30c3\u30af'\u30e1\u30cb\u30e5\u30fc\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u30a6\u30a7\u30d6\u30ab\u30e1\u30e9\u3092\u4f7f\u3063\u3066\u3001\u3042\u306a\u305f\u306eID\u306e\u5199\u771f\u3092\u64ae\u5f71\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u305d\u306e\u5199\u771f\u3092\u3042\u306a\u305f\u306e\u9854\u5199\u771f\u304a\u3088\u3073\u30a2\u30ab\u30a6\u30f3\u30c8\u306b\u8a2d\u5b9a\u3055\u308c\u305f\u540d\u524d\u3068\u7167\u5408\u3057\u307e\u3059\u3002", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u30a6\u30a7\u30d6\u30ab\u30e1\u30e9\u3092\u4f7f\u3063\u3066\u3001\u3042\u306a\u305f\u306e\u9854\u5199\u771f\u3092\u64ae\u5f71\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u3053\u306e\u5199\u771f\u3092\u3042\u306a\u305f\u306eID\u306e\u5199\u771f\u3068\u7167\u5408\u3057\u307e\u3059\u3002", "Used": "\u5229\u7528\u6e08", "Used in {count} location": [ @@ -1349,7 +1338,6 @@ "Verified Certificate upgrade": "\u8a8d\u8a3c\u4ed8\u304d\u4fee\u4e86\u8a3c\u306e\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9", "Verified Status": "\u8a8d\u8a3c\u30b9\u30c6\u30fc\u30bf\u30b9", "Verified mode price": "\u8a8d\u8a3c\u30e2\u30fc\u30c9\u4fa1\u683c", - "Verify Now": "\u3044\u307e\u3059\u3050\u8a8d\u8a3c\u3057\u3088\u3046", "Video Capture Error": "\u30d3\u30c7\u30aa\u30ad\u30e3\u30d7\u30c1\u30e3\u30a8\u30e9\u30fc", "Video ID": "\u52d5\u753bID", "Video duration is {humanizeDuration}": "\u52d5\u753b\u306e\u9577\u3055\u306f {humanizeDuration}", @@ -1377,7 +1365,6 @@ "We couldn't find any results for \"%s\".": "\"%s\" \u306e\u691c\u7d22\u7d50\u679c\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002", "We couldn't sign you in.": "\u30b5\u30a4\u30f3\u30a4\u30f3\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002", "We have encountered an error. Refresh your browser and then try again.": "\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u30d6\u30e9\u30a6\u30b6\u3092\u66f4\u65b0\u3057\u3066\u518d\u8a66\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "\u3042\u306a\u305f\u306e\u60c5\u5831\u3092\u53d7\u3051\u53d6\u308a\u3001\u672c\u4eba\u8a8d\u8a3c\u4e2d\u3067\u3059\u3002\u8a8d\u8a3c\u624b\u7d9a\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f\u3089\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u8868\u793a\u3055\u308c\u307e\u3059(\u901a\u5e381\uff5e2\u65e5\u4ee5\u5185)\u3002\u305d\u306e\u9593\u3082\u8b1b\u5ea7\u30b3\u30f3\u30c6\u30f3\u30c4\u306b\u306f\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u3059\u3002", "We just need a little more information before you start learning with %(platformName)s.": "%(platformName)s\u3067\u306e\u5b66\u7fd2\u3092\u59cb\u3081\u308b\u306b\u3042\u305f\u3063\u3066\u3001\u3082\u3046\u5c11\u3057\u60c5\u5831\u304c\u5fc5\u8981\u3067\u3059\u3002", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "\u6700\u9ad8\u30ec\u30d9\u30eb\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u3067\u5199\u771f\u3092\u6697\u53f7\u5316\u3057\u3001\u8a8d\u8a3c\u30b5\u30fc\u30d3\u30b9\u3078\u9001\u308a\u307e\u3059\u3002\u8a8d\u8a3c\u624b\u7d9a\u304c\u5b8c\u4e86\u3057\u305f\u5f8c\u306f\u3001\u5199\u771f\u3084\u60c5\u5831\u3092%(platformName)s\u3067\u4fdd\u5b58\u3057\u305f\u308a\u95b2\u89a7\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002", "We've encountered an error. Refresh your browser and then try again.": "\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u30d6\u30e9\u30a6\u30b6\u3092\u66f4\u65b0\u3057\u3066\u518d\u8a66\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002", @@ -1449,11 +1436,8 @@ "You must sign out and sign back in before your language changes take effect.": "\u8a00\u8a9e\u306e\u5909\u66f4\u3092\u6709\u52b9\u306b\u3059\u308b\u306b\u306f\u3001\u4e00\u65e6\u30b5\u30a4\u30f3\u30a2\u30a6\u30c8\u3057\u3066\u304b\u3089\u518d\u5ea6\u30b5\u30a4\u30f3\u30a4\u30f3\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002", "You must specify a name for the cohort": "\u30b3\u30db\u30fc\u30c8\u306e\u540d\u524d\u3092\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u5168\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u3092\u516c\u958b\u3059\u308b\u305f\u3081\u306b\u306f\u3001\u8a95\u751f\u5e74\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u8a95\u751f\u5e74\u3092\u5165\u529b\u3059\u308b\u306b\u306f {account_settings_page_link}\u3078\u79fb\u52d5\u3057\u307e\u3059\u3002", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u540d\u524d\u3068\u5199\u771f\u304c\u8a18\u8f09\u3055\u308c\u3066\u3044\u308b\u514d\u8a31\u8a3c\u3001\u30d1\u30b9\u30dd\u30fc\u30c8\u307e\u305f\u306f\u653f\u5e9c\u767a\u884c\u306e\u8eab\u5206\u8a3c\u660e\u66f8\u304c\u5fc5\u8981\u3067\u3059\u3002", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u6c0f\u540d\u3068\u5199\u771f\u4ed8\u304d\u306eID\u304c\u5fc5\u8981\u3067\u3059\u3002\u904b\u8ee2\u514d\u8a31\u8a3c\u3001\u30d1\u30b9\u30dd\u30fc\u30c8\u307e\u305f\u306f\u653f\u5e9c\u767a\u884c\u306e\u8eab\u5206\u8a3c\u660e\u66f8\u304c\u6709\u52b9\u3067\u3059\u3002", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u8b1b\u5ea7\u306e\u53d7\u8b1b\u767b\u9332\u3092\u59cb\u3081\u308b\u524d\u306b\u3001\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u6709\u52b9\u5316\u3055\u305b\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u6709\u52b9\u5316\u306b\u95a2\u3059\u308b\u30e1\u30fc\u30eb\u304c\u5c4a\u3044\u3066\u3044\u308b\u304b\u3054\u78ba\u8a8d\u304f\u3060\u3055\u3044\u3002", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u8b1b\u5ea7\u306e\u53d7\u8b1b\u767b\u9332\u3092\u59cb\u3081\u308b\u524d\u306b\u3001\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u6709\u52b9\u5316\u3055\u305b\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u6709\u52b9\u5316\u306b\u95a2\u3059\u308b\u30e1\u30fc\u30eb\u304c\u5c4a\u3044\u3066\u3044\u308b\u304b\u3054\u78ba\u8a8d\u304f\u3060\u3055\u3044\u3002\u6709\u52b9\u5316\u304c\u5b8c\u4e86\u3057\u305f\u3089\u3001\u3053\u306e\u753b\u9762\u306b\u623b\u308a\u518d\u8aad\u8fbc\u3057\u3066\u304f\u3060\u3055\u3044\u3002", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u5358\u4f4d\u8a8d\u5b9a\u51e6\u7406\u3092\u5b8c\u4e86\u3059\u308b\u306b\u306f\u5f15\u304d\u7d9a\u304d%(display_name)s\u3092\u898b\u3066\u304f\u3060\u3055\u3044\u3002", "You will be refunded the amount you paid.": "\u304a\u652f\u6255\u3044\u3044\u305f\u3060\u3044\u305f\u91d1\u984d\u304c\u8fd4\u91d1\u3055\u308c\u307e\u3059\u3002", "You will not be refunded the amount you paid.": "\u304a\u652f\u6255\u3044\u3044\u305f\u3060\u3044\u305f\u91d1\u984d\u306f\u8fd4\u91d1\u3055\u308c\u307e\u305b\u3093\u3002", "You will not receive notification for emails that bounce, so double-check your spelling.": "\u623b\u3063\u3066\u304f\u308b\u30e1\u30fc\u30eb\u306b\u95a2\u3059\u308b\u901a\u77e5\u306f\u5c4a\u304d\u307e\u305b\u3093\u306e\u3067\u3001\u7db4\u308a\u306f\u30c0\u30d6\u30eb\u30c1\u30a7\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002", @@ -1624,7 +1608,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1688,9 +1672,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "n\u6708j\u65e5", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "Y/m/d G:i", "SHORT_DATE_FORMAT": "Y/m/d", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/kk-kz/djangojs.js b/cms/static/js/i18n/kk-kz/djangojs.js index b3d2d3342e61f8aefcc8945792a4835f5328e637..7d5ca2071be4313f12b7b0b10d5b9998ae8e201f 100644 --- a/cms/static/js/i18n/kk-kz/djangojs.js +++ b/cms/static/js/i18n/kk-kz/djangojs.js @@ -6,7 +6,7 @@ django.pluralidx = function(n) { - var v=0; + var v=(n!=1); if (typeof(v) == 'boolean') { return v ? 1 : 0; } else { @@ -21,6 +21,7 @@ var newcatalog = { "%(sel)s of %(cnt)s selected": [ + "%(cnt)s-\u04a3 %(sel)s-\u044b(\u0456) \u0442\u0430\u04a3\u0434\u0430\u043b\u0434\u044b", "%(cnt)s-\u04a3 %(sel)s-\u044b(\u0456) \u0442\u0430\u04a3\u0434\u0430\u043b\u0434\u044b" ], "6 a.m.": "06", @@ -61,7 +62,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -125,9 +126,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/km-kh/djangojs.js b/cms/static/js/i18n/km-kh/djangojs.js index b81c0e23b144d2b3aa608876cd99cea0418643bc..d0454035fb36405954c14ceb8d05a776a6bd4750 100644 --- a/cms/static/js/i18n/km-kh/djangojs.js +++ b/cms/static/js/i18n/km-kh/djangojs.js @@ -55,7 +55,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -119,9 +119,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "j M Y, G:i", "SHORT_DATE_FORMAT": "j M Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/kn/djangojs.js b/cms/static/js/i18n/kn/djangojs.js index d9e92345796feed018057d6118f81cc367c8ecf1..9a3e4908fc5084cc3f03c4feea0bba260a920844 100644 --- a/cms/static/js/i18n/kn/djangojs.js +++ b/cms/static/js/i18n/kn/djangojs.js @@ -59,7 +59,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -123,9 +123,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/ko-kr/djangojs.js b/cms/static/js/i18n/ko-kr/djangojs.js index 9ca94426c37ea76199c183c5e630ba92a929cf83..e6dec1a6a9472833bc67b3be00c6d02fb4df8902 100644 --- a/cms/static/js/i18n/ko-kr/djangojs.js +++ b/cms/static/js/i18n/ko-kr/djangojs.js @@ -398,7 +398,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -457,9 +457,9 @@ "%Y\ub144 %m\uc6d4 %d\uc77c" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "n\uc6d4 j\uc77c", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "Y-n-j H:i", "SHORT_DATE_FORMAT": "Y-n-j.", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/lt-lt/djangojs.js b/cms/static/js/i18n/lt-lt/djangojs.js index afccff2f29f6eadb236db063cb9857c1a7211c59..81595a3f289b18dc254be0e51de6f206403c85e6 100644 --- a/cms/static/js/i18n/lt-lt/djangojs.js +++ b/cms/static/js/i18n/lt-lt/djangojs.js @@ -51,6 +51,7 @@ "%(sel)s of %(cnt)s selected": [ "pasirinktas %(sel)s i\u0161 %(cnt)s", "pasirinkti %(sel)s i\u0161 %(cnt)s", + "pasirinkti %(sel)s i\u0161 %(cnt)s", "pasirinkti %(sel)s i\u0161 %(cnt)s" ], "%(team_count)s Team": [ @@ -382,11 +383,13 @@ "Note: You are %s hour ahead of server time.": [ "Pastaba: J\u016bs\u0173 laikrodis rodo %s valanda daugiau nei serverio laikrodis.", "Pastaba: J\u016bs\u0173 laikrodis rodo %s valandomis daugiau nei serverio laikrodis.", + "Pastaba: J\u016bs\u0173 laikrodis rodo %s valand\u0173 daugiau nei serverio laikrodis.", "Pastaba: J\u016bs\u0173 laikrodis rodo %s valand\u0173 daugiau nei serverio laikrodis." ], "Note: You are %s hour behind server time.": [ "Pastaba: J\u016bs\u0173 laikrodis rodo %s valanda ma\u017eiau nei serverio laikrodis.", "Pastaba: J\u016bs\u0173 laikrodis rodo %s valandomis ma\u017eiau nei serverio laikrodis.", + "Pastaba: J\u016bs\u0173 laikrodis rodo %s valand\u0173 ma\u017eiau nei serverio laikrodis.", "Pastaba: J\u016bs\u0173 laikrodis rodo %s valand\u0173 ma\u017eiau nei serverio laikrodis." ], "Noted in:": "Pa\u017eym\u0117ta:", @@ -783,7 +786,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -842,9 +845,9 @@ "%d.%m.%y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "E j \\d.", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "Y-m-d H:i", "SHORT_DATE_FORMAT": "Y-m-d", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/ml/djangojs.js b/cms/static/js/i18n/ml/djangojs.js index eb8845d2cd02aee5c670d40ce7ad28bdb378fd91..d514e594908e17edce92f8cd989762522999be28 100644 --- a/cms/static/js/i18n/ml/djangojs.js +++ b/cms/static/js/i18n/ml/djangojs.js @@ -25,16 +25,28 @@ "%(cnt)s\u0d32\u0d4d\u200d %(sel)s \u0d0e\u0d23\u0d4d\u0d23\u0d02 \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d24\u0d4d\u0d24\u0d41" ], "6 a.m.": "6 a.m.", + "6 p.m.": "6 p.m", + "April": "\u0d0f\u0d2a\u0d4d\u0d30\u0d3f\u0d7d", + "August": "\u0d06\u0d17\u0d38\u0d4d\u0d31\u0d4d\u0d31\u0d4d", "Available %s": "\u0d32\u0d2d\u0d4d\u0d2f\u0d2e\u0d3e\u0d2f %s", "Cancel": "\u0d31\u0d26\u0d4d\u0d26\u0d3e\u0d15\u0d4d\u0d15\u0d42", "Choose": "\u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d42", + "Choose a Date": "\u0d12\u0d30\u0d41 \u0d24\u0d40\u0d2f\u0d24\u0d3f \u0d24\u0d3f\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d41\u0d15", + "Choose a Time": "\u0d38\u0d2e\u0d2f\u0d02 \u0d24\u0d3f\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d41\u0d15", "Choose a time": "\u0d38\u0d2e\u0d2f\u0d02 \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d42", "Choose all": "\u0d0e\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d41\u0d15", "Chosen %s": "\u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d24\u0d4d\u0d24 %s", "Click to choose all %s at once.": "%s \u0d0e\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d12\u0d28\u0d4d\u0d28\u0d3f\u0d1a\u0d4d\u0d1a\u0d4d \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d3e\u0d28\u0d4d\u200d \u0d15\u0d4d\u0d32\u0d3f\u0d15\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15.", "Click to remove all chosen %s at once.": "\u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d2a\u0d4d\u0d2a\u0d46\u0d1f\u0d4d\u0d1f %s \u0d0e\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d12\u0d30\u0d41\u0d2e\u0d3f\u0d1a\u0d4d\u0d1a\u0d4d \u0d28\u0d40\u0d15\u0d4d\u0d15\u0d02 \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d28\u0d4d\u200d \u0d15\u0d4d\u0d32\u0d3f\u0d15\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15.", + "December": "\u0d21\u0d3f\u0d38\u0d02\u0d2c\u0d30\u0d4d", + "February": "\u0d2b\u0d46\u0d2c\u0d4d\u0d30\u0d41\u0d35\u0d30\u0d3f", "Filter": "Filter", "Hide": "\u0d2e\u0d31\u0d2f\u0d1f\u0d4d\u0d1f\u0d46", + "January": "\u0d1c\u0d28\u0d41\u0d35\u0d30\u0d3f", + "July": "\u0d1c\u0d42\u0d32\u0d48", + "June": "\u0d1c\u0d42\u0d7a", + "March": "\u0d2e\u0d3e\u0d7c\u0d1a\u0d4d\u0d1a\u0d4d", + "May": "\u0d2e\u0d46\u0d2f\u0d4d", "Midnight": "\u0d05\u0d30\u0d4d\u200d\u0d27\u0d30\u0d3e\u0d24\u0d4d\u0d30\u0d3f", "Noon": "\u0d09\u0d1a\u0d4d\u0d1a", "Note: You are %s hour ahead of server time.": [ @@ -45,9 +57,12 @@ "\u0d12\u0d7c\u0d15\u0d4d\u0d15\u0d41\u0d15: \u0d38\u0d46\u0d7c\u0d35\u0d7c \u0d38\u0d2e\u0d2f\u0d24\u0d4d\u0d24\u0d3f\u0d28\u0d46\u0d15\u0d4d\u0d15\u0d3e\u0d33\u0d41\u0d02 \u0d28\u0d3f\u0d19\u0d4d\u0d19\u0d7e %s \u0d38\u0d2e\u0d2f\u0d02 \u0d2a\u0d3f\u0d28\u0d4d\u0d28\u0d3f\u0d32\u0d3e\u0d23\u0d4d.", "\u0d12\u0d7c\u0d15\u0d4d\u0d15\u0d41\u0d15: \u0d38\u0d46\u0d7c\u0d35\u0d7c \u0d38\u0d2e\u0d2f\u0d24\u0d4d\u0d24\u0d3f\u0d28\u0d46\u0d15\u0d4d\u0d15\u0d3e\u0d33\u0d41\u0d02 \u0d28\u0d3f\u0d19\u0d4d\u0d19\u0d7e %s \u0d38\u0d2e\u0d2f\u0d02 \u0d2a\u0d3f\u0d28\u0d4d\u0d28\u0d3f\u0d32\u0d3e\u0d23\u0d4d." ], + "November": "\u0d28\u0d35\u0d02\u0d2c\u0d7c", "Now": "\u0d07\u0d2a\u0d4d\u0d2a\u0d4b\u0d33\u0d4d\u200d", + "October": "\u0d12\u0d15\u0d4d\u0d1f\u0d47\u0d3e\u0d2c\u0d7c", "Remove": "\u0d28\u0d40\u0d15\u0d4d\u0d15\u0d02 \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d42", "Remove all": "\u0d0e\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d28\u0d40\u0d15\u0d4d\u0d15\u0d02 \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15", + "September": "\u0d38\u0d46\u0d2a\u0d4d\u0d31\u0d4d\u0d31\u0d02\u0d2c\u0d7c", "Show": "\u0d15\u0d3e\u0d23\u0d1f\u0d4d\u0d1f\u0d46", "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "\u0d07\u0d24\u0d3e\u0d23\u0d4d \u0d32\u0d2d\u0d4d\u0d2f\u0d2e\u0d3e\u0d2f %s \u0d2a\u0d1f\u0d4d\u0d1f\u0d3f\u0d15. \u0d05\u0d24\u0d3f\u0d32\u0d4d\u200d \u0d1a\u0d3f\u0d32\u0d24\u0d4d \u0d24\u0d3f\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d3e\u0d28\u0d4d\u200d \u0d24\u0d3e\u0d34\u0d46 \u0d15\u0d33\u0d24\u0d4d\u0d24\u0d3f\u0d32\u0d4d\u200d \u0d28\u0d3f\u0d28\u0d4d\u0d28\u0d41\u0d02 \u0d09\u0d1a\u0d3f\u0d24\u0d2e\u0d3e\u0d2f\u0d35 \u0d38\u0d46\u0d32\u0d15\u0d4d\u0d1f\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d24 \u0d36\u0d47\u0d37\u0d02 \u0d30\u0d23\u0d4d\u0d1f\u0d41 \u0d15\u0d33\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d\u0d15\u0d4d\u0d15\u0d41\u0d2e\u0d3f\u0d1f\u0d2f\u0d3f\u0d32\u0d46 \"\u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d42\" \u0d05\u0d1f\u0d2f\u0d3e\u0d33\u0d24\u0d4d\u0d24\u0d3f\u0d32\u0d4d\u200d \u0d15\u0d4d\u0d32\u0d3f\u0d15\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15.", "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "\u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d2a\u0d4d\u0d2a\u0d46\u0d1f\u0d4d\u0d1f %s \u0d2a\u0d1f\u0d4d\u0d1f\u0d3f\u0d15\u0d2f\u0d3e\u0d23\u0d3f\u0d24\u0d4d. \u0d05\u0d35\u0d2f\u0d3f\u0d32\u0d4d\u200d \u0d1a\u0d3f\u0d32\u0d24\u0d4d \u0d12\u0d34\u0d3f\u0d35\u0d3e\u0d15\u0d4d\u0d15\u0d23\u0d2e\u0d46\u0d28\u0d4d\u0d28\u0d41\u0d23\u0d4d\u0d1f\u0d46\u0d19\u0d4d\u0d15\u0d3f\u0d32\u0d4d\u200d \u0d24\u0d3e\u0d34\u0d46 \u0d15\u0d33\u0d24\u0d4d\u0d24\u0d3f\u0d32\u0d4d\u200d \u0d28\u0d3f\u0d28\u0d4d\u0d28\u0d41\u0d02 \u0d05\u0d35 \u0d38\u0d46\u0d32\u0d15\u0d4d\u0d1f\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d24\u0d4d \u0d15\u0d33\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d\u0d15\u0d4d\u0d15\u0d3f\u0d1f\u0d2f\u0d3f\u0d32\u0d41\u0d33\u0d4d\u0d33 \"\u0d28\u0d40\u0d15\u0d4d\u0d15\u0d02 \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d42\" \u0d0e\u0d28\u0d4d\u0d28 \u0d05\u0d1f\u0d2f\u0d3e\u0d33\u0d24\u0d4d\u0d24\u0d3f\u0d32\u0d4d\u200d \u0d15\u0d4d\u0d32\u0d3f\u0d15\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15.", @@ -57,7 +72,14 @@ "Yesterday": "\u0d07\u0d28\u0d4d\u0d28\u0d32\u0d46", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "\u0d28\u0d3f\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d12\u0d30\u0d41 \u0d06\u0d15\u0d4d\u0d37\u0d28\u0d4d\u200d \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d24\u0d4d\u0d24\u0d3f\u0d1f\u0d4d\u0d1f\u0d41\u0d23\u0d4d\u0d1f\u0d4d. \u0d15\u0d33\u0d19\u0d4d\u0d19\u0d33\u0d3f\u0d32\u0d4d\u200d \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d24\u0d4d\u0d24 \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d07\u0d32\u0d4d\u0d32. \u0d28\u0d3f\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d\u0d38\u0d47\u0d35\u0d4d \u0d2c\u0d1f\u0d4d\u0d1f\u0d23\u0d4d\u200d \u0d24\u0d28\u0d4d\u0d28\u0d46\u0d2f\u0d3e\u0d23\u0d4b \u0d05\u0d24\u0d4b \u0d17\u0d4b \u0d2c\u0d1f\u0d4d\u0d1f\u0d23\u0d3e\u0d23\u0d4b \u0d09\u0d26\u0d4d\u0d26\u0d47\u0d36\u0d3f\u0d1a\u0d4d\u0d1a\u0d24\u0d4d.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "\u0d28\u0d3f\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d12\u0d30\u0d41 \u0d06\u0d15\u0d4d\u0d37\u0d28\u0d4d\u200d \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d24\u0d4d\u0d24\u0d3f\u0d1f\u0d4d\u0d1f\u0d41\u0d23\u0d4d\u0d1f\u0d4d. \u0d2a\u0d15\u0d4d\u0d37\u0d47, \u0d15\u0d33\u0d19\u0d4d\u0d19\u0d33\u0d3f\u0d32\u0d46 \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d07\u0d28\u0d3f\u0d2f\u0d41\u0d02 \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d28\u0d41\u0d23\u0d4d\u0d1f\u0d4d. \u0d06\u0d26\u0d4d\u0d2f\u0d02 \u0d38\u0d47\u0d35\u0d4d\u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d28\u0d3e\u0d2f\u0d3f OK \u0d15\u0d4d\u0d32\u0d3f\u0d15\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15. \u0d05\u0d24\u0d3f\u0d28\u0d41 \u0d36\u0d47\u0d37\u0d02 \u0d06\u0d15\u0d4d\u0d37\u0d28\u0d4d\u200d \u0d12\u0d28\u0d4d\u0d28\u0d41 \u0d15\u0d42\u0d1f\u0d3f \u0d2a\u0d4d\u0d30\u0d2f\u0d4b\u0d17\u0d3f\u0d15\u0d4d\u0d15\u0d47\u0d23\u0d4d\u0d1f\u0d3f \u0d35\u0d30\u0d41\u0d02.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "\u0d35\u0d30\u0d41\u0d24\u0d4d\u0d24\u0d3f\u0d2f \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d24\u0d3f\u0d1f\u0d4d\u0d1f\u0d3f\u0d32\u0d4d\u0d32. \u0d12\u0d30\u0d41 \u0d06\u0d15\u0d4d\u0d37\u0d28\u0d4d\u200d \u0d2a\u0d4d\u0d30\u0d2f\u0d4b\u0d17\u0d3f\u0d1a\u0d4d\u0d1a\u0d3e\u0d32\u0d4d\u200d \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d24\u0d4d\u0d24 \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d46\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d28\u0d37\u0d4d\u0d1f\u0d2a\u0d4d\u0d2a\u0d46\u0d1f\u0d41\u0d02." + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "\u0d35\u0d30\u0d41\u0d24\u0d4d\u0d24\u0d3f\u0d2f \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d24\u0d3f\u0d1f\u0d4d\u0d1f\u0d3f\u0d32\u0d4d\u0d32. \u0d12\u0d30\u0d41 \u0d06\u0d15\u0d4d\u0d37\u0d28\u0d4d\u200d \u0d2a\u0d4d\u0d30\u0d2f\u0d4b\u0d17\u0d3f\u0d1a\u0d4d\u0d1a\u0d3e\u0d32\u0d4d\u200d \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d24\u0d4d\u0d24 \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d46\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d28\u0d37\u0d4d\u0d1f\u0d2a\u0d4d\u0d2a\u0d46\u0d1f\u0d41\u0d02.", + "one letter Friday\u0004F": "\u0d35\u0d46", + "one letter Monday\u0004M": "\u0d24\u0d3f", + "one letter Saturday\u0004S": "\u0d36", + "one letter Sunday\u0004S": "\u0d1e\u0d4d\u0d1e\u200d", + "one letter Thursday\u0004T": "\u0d35\u0d4d\u0d2f\u0d3e", + "one letter Tuesday\u0004T": "\u0d1a\u0d4a", + "one letter Wednesday\u0004W": "\u0d2c\u0d41" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -79,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -135,9 +157,9 @@ "%m/%d/%y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/mn/djangojs.js b/cms/static/js/i18n/mn/djangojs.js index 0ec7b611171ace2ce8dc056831a33feb29568809..024b2c328d9ad165b7cebbcabe52758201b56029 100644 --- a/cms/static/js/i18n/mn/djangojs.js +++ b/cms/static/js/i18n/mn/djangojs.js @@ -28,8 +28,8 @@ "%s ago": "%s \u04e9\u043c\u043d\u04e9", "(Optional)": "(\u041d\u044d\u043c\u044d\u043b\u0442)", "(Required Field)": "(\u0417\u0430\u0430\u0432\u0430\u043b \u0431\u04e9\u0433\u043b\u04e9\u0445 \u0442\u0430\u043b\u0431\u0430\u0440)", - "6 a.m.": "6 \u0446\u0430\u0433", - "6 p.m.": "\u041e\u0440\u043e\u0439\u043d 6 \u0446\u0430\u0433", + "6 a.m.": "06 \u0446\u0430\u0433", + "6 p.m.": "18 \u0446\u0430\u0433", "A valid email address is required": "\u0425\u04af\u0447\u0438\u043d\u0442\u044d\u0439 \u0446\u0430\u0445\u0438\u043c \u0445\u0430\u044f\u0433\u0438\u0439\u0433 \u0448\u0430\u0430\u0440\u0434\u0430\u0436 \u0431\u0430\u0439\u043d\u0430.", "ABCDEFGHIJKLMNOPQRSTUVWXYZ": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "About Me": "\u041c\u0438\u043d\u0438\u0439 \u0442\u0443\u0445\u0430\u0439", @@ -52,12 +52,14 @@ "Alternative source": "\u04e8\u04e9\u0440 \u044d\u0445 \u04af\u04af\u0441\u0432\u044d\u0440", "An error has occurred. Please try again.": "\u0410\u043b\u0434\u0430\u0430 \u0433\u0430\u0440\u043b\u0430\u0430. \u0414\u0430\u0445\u0438\u043d \u043e\u0440\u043e\u043b\u0434\u043e\u043d\u043e \u04af\u04af", "An error has occurred. Wait a few minutes, and then try again.": "\u0410\u043b\u0434\u0430\u0430 \u0433\u0430\u0440\u0441\u0430\u043d \u0431\u0430\u0439\u043d\u0430. \u0422\u04af\u0440 \u0445\u04af\u043b\u044d\u044d\u0433\u044d\u044d\u0434 \u0434\u0430\u0445\u0438\u043d \u043e\u0440\u043e\u043b\u0434\u043e\u043d\u043e \u0443\u0443.", + "April": "4-\u0440 \u0441\u0430\u0440", "Are you sure you want to delete this page? This action cannot be undone.": "\u0422\u0430 \u04af\u043d\u044d\u0445\u044d\u044d\u0440 \u044d\u043d\u044d \u0445\u0443\u0443\u0434\u0441\u044b\u0433 \u0443\u0441\u0442\u0433\u0430\u0445\u0434\u0430\u0430 \u0438\u0442\u0433\u044d\u043b\u0442\u044d\u0439 \u0431\u0430\u0439\u043d\u0430 \u0443\u0443? \u042d\u043d\u044d\u0445\u04af\u04af \u04af\u0439\u043b\u0434\u043b\u0438\u0439\u0433 \u0431\u0443\u0446\u0430\u0430\u0445 \u0431\u043e\u043b\u043e\u043c\u0436\u0433\u04af\u0439. ", "Are you sure you want to delete this update?": "\u042d\u043d\u044d \u0448\u0438\u043d\u044d\u0447\u043b\u044d\u043b\u0438\u0439\u0433 \u0443\u0441\u0442\u0433\u0430\u0445 \u0443\u0443?", "Are you sure you want to revert to the last published version of the unit? You cannot undo this action.": "\u042d\u043d\u044d \u043c\u043e\u0434\u0443\u043b\u0438\u0439\u043d \u0445\u044d\u0432\u043b\u044d\u0433\u0434\u0441\u044d\u043d \u0445\u044d\u0441\u0433\u0438\u0439\u0433 \u0441\u044d\u0440\u0433\u044d\u044d\u0445\u0438\u0439\u0433 \u0442\u0430 \u0445\u04af\u0441\u0447 \u0431\u0430\u0439\u043d\u0430? \u042d\u043d\u044d \u04af\u0439\u043b\u0434\u043b\u0438\u0439\u0433 \u0431\u0443\u0446\u0430\u0430\u0445 \u0431\u043e\u043b\u043e\u043c\u0436\u0433\u04af\u0439.", "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "\u042d\u043d\u044d \u0437\u04af\u0439\u043b\u0438\u0439\u0433 \u0443\u0441\u0442\u0433\u0430\u0432\u0430\u043b \u0430\u0445\u0438\u043d \u0441\u044d\u0440\u0433\u044d\u044d\u0445 \u0431\u043e\u043b\u043e\u043c\u0436\u0433\u04af\u0439!\n\n\u042d\u043d\u044d \u0445\u043e\u043b\u0431\u043e\u043e\u0441 \u0448\u0438\u0433 \u0437\u0430\u0440\u0438\u043c \u0430\u0433\u0443\u0443\u043b\u0433\u0443\u0443\u0434 /\u0445\u044d\u0441\u044d\u0433 \u0445\u0443\u0433\u0430\u0446\u0430\u0430\u043d\u0434 \u0430\u0436\u0438\u043b\u043b\u0430\u0445\u0433\u04af\u0439 \u0431\u0430\u0439\u0445 \u0431\u043e\u043b\u043e\u043c\u0436\u0442\u043e\u0439 (\u0430\u0448\u0438\u0433\u043b\u0430\u0433\u0434\u0430\u0445\u0433\u04af\u0439 \u0431\u043e\u043b\u0441\u043e\u043d \u0437\u0443\u0440\u0430\u0433/\u0445\u043e\u043b\u0431\u043e\u043e\u0441)", "Are you sure?": "\u0422\u0430 \u0438\u0442\u0433\u044d\u043b\u0442\u044d\u0439 \u0431\u0430\u0439\u043d\u0430 \u0443\u0443?", "Attribution": "\u0410\u0442\u0442\u0440\u0438\u0431\u0443\u0442", + "August": "8-\u0440 \u0441\u0430\u0440", "Author": "\u0417\u043e\u0445\u0438\u043e\u0433\u0447", "Automatic transcripts are disabled.": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442 \u0445\u0443\u0443\u043b\u0431\u0430\u0440\u044b\u0433 \u0438\u0434\u044d\u0432\u0445\u0433\u04af\u0439 \u0431\u043e\u043b\u0433\u043e\u0441\u043e\u043d \u0431\u0430\u0439\u043d\u0430.", "Available %s": "\u0411\u043e\u043b\u043e\u043c\u0436\u0442\u043e\u0439 %s", @@ -137,6 +139,7 @@ "Cut row": "\u041c\u04e9\u0440\u0438\u0439\u0433 \u0442\u0430\u0439\u0440\u0447 \u0430\u0432\u0430\u0445", "Date": "\u041e\u0433\u043d\u043e\u043e", "Date Added": "\u04e8\u0434\u04e9\u0440 \u0442\u043e\u0432\u043b\u043e\u0433\u0434\u043b\u043e\u043e.", + "December": "12-\u0440 \u0441\u0430\u0440", "Default": "\u04e8\u0433\u04e9\u0433\u0434\u043c\u04e9\u043b", "Delete": "\u0423\u0441\u0442\u0433\u0430\u0445", "Delete File Confirmation": "\u0424\u0430\u0439\u043b\u044b\u043d \u0431\u0430\u0442\u0430\u043b\u0433\u0430\u0430\u0436\u0443\u0443\u043b\u0430\u043b\u0442\u044b\u0433 \u0443\u0441\u0442\u0433\u0430\u0445", @@ -169,6 +172,7 @@ "Error removing user": "\u0425\u044d\u0440\u044d\u0433\u043b\u044d\u0433\u0447\u0438\u0439\u0433 \u0443\u0441\u0442\u0433\u0430\u0445 \u04af\u0435\u0438\u0439\u043d \u0430\u043b\u0434\u0430\u0430", "Expand Instructions": "\u0417\u0430\u0430\u0432\u0440\u0443\u0443\u0434\u044b\u0433 \u0434\u044d\u043b\u0433\u044d\u0445", "Explanation": "\u0422\u0430\u0439\u043b\u0431\u0430\u0440", + "February": "2-\u0440 \u0441\u0430\u0440", "File": "\u0424\u0430\u0439\u043b", "File format not supported. Please upload a file with a {ext} extension.": "\u0444\u0430\u0439\u043b\u044b\u043d \u0442\u04e9\u0440\u04e9\u043b \u0442\u043e\u0445\u0438\u0440\u043e\u0445\u0433\u04af\u0439 \u0431\u0430\u0439\u043d\u0430. {ext} \u04e9\u0440\u0433\u04e9\u0442\u0433\u04e9\u043b\u0442\u044d\u0439 \u0444\u0430\u0439\u043b \u043e\u0440\u0443\u0443\u043b\u043d\u0430 \u0443\u0443", "Files must be in JPEG or PNG format.": "\u0424\u0430\u0439\u043b\u044b\u043d \u0444\u043e\u0440\u043c\u0430\u0442 \u043d\u044c JPEG \u044d\u0441\u0432\u044d\u043b PNG \u0431\u0430\u0439\u043d\u0430.", @@ -218,8 +222,11 @@ "Insert video": "\u0411\u0438\u0447\u043b\u044d\u0433 \u043e\u0440\u0443\u0443\u043b\u0430\u0445", "Insert/edit link": "\u0425\u043e\u043b\u0431\u043e\u043e\u0441 \u043e\u0440\u0443\u0443\u043b\u0430\u0445/\u0437\u0430\u0441\u0430\u0445", "Insert/edit video": "\u0411\u0438\u0447\u043b\u044d\u0433 \u043e\u0440\u0443\u0443\u043b\u0430\u0445/\u0437\u0430\u0441\u0430\u0445", + "January": "1-\u0440 \u0441\u0430\u0440", "Joined": "\u042d\u043b\u0441\u0441\u044d\u043d", "Joined Date": "\u042d\u043b\u0441\u0441\u044d\u043d \u043e\u0433\u043d\u043e\u043e", + "July": "7-\u0440 \u0441\u0430\u0440", + "June": "6-\u0440 \u0441\u0430\u0440", "Justify": "\u041c\u04e9\u0440\u0438\u0439\u0433 \u0442\u044d\u0433\u0448\u043b\u044d\u0445", "KB": "KB", "Key should only contain letters, numbers, _, or -": "\u0422\u04af\u043b\u0445\u04af\u04af\u0440 \u04af\u0433 \u043d\u044c \u0437\u04e9\u0432\u0445\u04e9\u043d \u04af\u0441\u0433\u04af\u04af\u0434, \u0442\u043e\u043e, _ \u044d\u0441\u0432\u044d\u043b - \u0430\u0433\u0443\u0443\u043b\u0441\u0430\u043d \u0431\u0430\u0439\u0445 \u0448\u0430\u0430\u0440\u0434\u043b\u0430\u0433\u0430\u0442\u0430\u0439.", @@ -235,8 +242,10 @@ "Low": "\u0421\u0443\u043b", "MB": "MB", "Make Visible to Students": "\u041e\u044e\u0443\u0442\u043d\u0443\u0443\u0434\u0430\u0434 \u0445\u0430\u0440\u0430\u0433\u0434\u0434\u0430\u0433 \u0431\u043e\u043b\u0433\u043e\u0445", + "March": "3-\u0440 \u0441\u0430\u0440", "Max file size exceeded": "\u0424\u0430\u0439\u043b\u044b\u043d \u0434\u044d\u044d\u0434 \u0445\u044d\u043c\u0436\u044d\u044d \u0445\u044d\u0442\u044d\u0440\u0441\u044d\u043d \u0431\u0430\u0439\u043d\u0430", "Maximum": "\u0425\u0430\u043c\u0433\u0438\u0439\u043d \u0438\u0445", + "May": "5-\u0440 \u0441\u0430\u0440", "Membership": "\u0413\u0438\u0448\u04af\u04af\u043d\u0447\u043b\u044d\u043b", "Merge cells": "\u041d\u04af\u0434\u043d\u04af\u04af\u0434\u0438\u0439\u0433 \u043d\u044d\u0433\u0442\u0433\u044d\u0445", "Message:": "\u0417\u0443\u0440\u0432\u0430\u0441: ", @@ -266,9 +275,11 @@ "\u0422\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0438\u0439\u043d \u0446\u0430\u0433\u0430\u0430\u0441 %s \u0446\u0430\u0433\u0430\u0430\u0440 \u0445\u043e\u0446\u043e\u0440\u0447 \u0431\u0430\u0439\u043d\u0430", "\u0422\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0438\u0439\u043d \u0446\u0430\u0433\u0430\u0430\u0441 %s \u0446\u0430\u0433\u0430\u0430\u0440 \u0445\u043e\u0446\u043e\u0440\u0447 \u0431\u0430\u0439\u043d\u0430" ], + "November": "11-\u0440 \u0441\u0430\u0440", "Now": "\u041e\u0434\u043e\u043e", "Numbered list": "\u0414\u0443\u0433\u0430\u0430\u0440\u043b\u0430\u0441\u0430\u043d \u0436\u0430\u0433\u0441\u0430\u0430\u043b\u0442", "OK": "\u041e\u041a", + "October": "10-\u0440 \u0441\u0430\u0440", "Ok": "\u0422\u0438\u0439\u043c", "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u0417\u04e9\u0432\u0445\u04e9\u043d <%= fileTypes %> \u0444\u0430\u0439\u043b\u0443\u0443\u0434 \u043e\u0440\u0443\u0443\u043b\u0430\u0445 \u0431\u043e\u043b\u043e\u043c\u0436\u0442\u043e\u0439. <%= fileExtensions %> \u04e9\u0440\u0433\u04e9\u043b\u0442\u044d\u0439 \u0444\u0430\u0439\u043b \u043e\u0440\u0443\u0443\u043b\u043d\u0430 \u0443\u0443.", "Open Calculator": "\u0422\u043e\u043e\u043d\u044b \u043c\u0430\u0448\u0438\u043d \u043d\u044d\u044d\u0445 ", @@ -337,6 +348,7 @@ "Select language": "\u0425\u044d\u043b\u0438\u0439\u0433 \u0441\u043e\u043d\u0433\u043e\u0445", "Select turnaround": "\u04e8\u04e9\u0440\u0447\u043b\u04e9\u043b\u0442\u0438\u0439\u0433 \u0441\u043e\u043d\u0433\u043e", "Send to:": "\u0425\u0430\u0430\u0448\u0430\u0430 \u044f\u0432\u0443\u0443\u043b\u0430\u0445: ", + "September": "9-\u0440 \u0441\u0430\u0440", "Set up your certificate": "\u04e8\u04e9\u0440\u0438\u0439\u043d \u0433\u044d\u0440\u0447\u0438\u043b\u0433\u044d\u044d\u043d\u0438\u0439 \u0442\u043e\u0445\u0438\u0440\u0433\u043e\u043e", "Settings": "\u0422\u043e\u0445\u0438\u0440\u0433\u043e\u043e", "Settings updated": "\u0422\u043e\u0445\u0438\u0440\u0443\u0443\u043b\u0433\u0430 \u0448\u0438\u043d\u044d\u0447\u043b\u044d\u0433\u0434\u043b\u044d\u044d", @@ -476,6 +488,13 @@ "enter code here": "\u041a\u043e\u0434\u043e\u043e \u044d\u043d\u0434 \u043e\u0440\u0443\u0443\u043b\u043d\u0430 \u0443\u0443", "incorrect": "\u0411\u0443\u0440\u0443\u0443", "name": "\u041d\u044d\u0440", + "one letter Friday\u0004F": "\u0411\u0430", + "one letter Monday\u0004M": "\u0414", + "one letter Saturday\u0004S": "\u0411\u044f", + "one letter Sunday\u0004S": "\u041d", + "one letter Thursday\u0004T": "\u041f", + "one letter Tuesday\u0004T": "\u041c", + "one letter Wednesday\u0004W": "\u041b", "or": "\u044d\u0441\u0432\u044d\u043b", "section": "\u0445\u044d\u0441\u044d\u0433", "subsection": "\u0434\u044d\u0434 \u0445\u044d\u0441\u044d\u0433", @@ -507,7 +526,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -571,9 +590,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/mr/djangojs.js b/cms/static/js/i18n/mr/djangojs.js index 09ab0ad1017c413c3bafcb7fa641bef68644a979..f099ebfc1d7e1fb0cc02eda8cbc11276c49368c9 100644 --- a/cms/static/js/i18n/mr/djangojs.js +++ b/cms/static/js/i18n/mr/djangojs.js @@ -35,7 +35,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -99,9 +99,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/ms/djangojs.js b/cms/static/js/i18n/ms/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/cms/static/js/i18n/ms/djangojs.js +++ b/cms/static/js/i18n/ms/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/nb/djangojs.js b/cms/static/js/i18n/nb/djangojs.js index 85bcd2bf9bf715004dfa8396d7e18825433ec9e3..0efb343e44d338310e543dbc2304443493155b68 100644 --- a/cms/static/js/i18n/nb/djangojs.js +++ b/cms/static/js/i18n/nb/djangojs.js @@ -229,7 +229,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -285,9 +285,9 @@ "%d.%m.%y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/ne/djangojs.js b/cms/static/js/i18n/ne/djangojs.js index a048ff9f0979cbeed8d2b2ec70e4a81d78cf39f7..ca9b2ddb2a40fd798ac27ecb3ff1ecd3543febb7 100644 --- a/cms/static/js/i18n/ne/djangojs.js +++ b/cms/static/js/i18n/ne/djangojs.js @@ -82,7 +82,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -146,9 +146,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/nl-nl/djangojs.js b/cms/static/js/i18n/nl-nl/djangojs.js index c8a75c6f7ea672a2e2d9ae0a81ae72a6bfb69cca..5cb72ceef2991047703bd28b29cc5ebcce43501e 100644 --- a/cms/static/js/i18n/nl-nl/djangojs.js +++ b/cms/static/js/i18n/nl-nl/djangojs.js @@ -34,7 +34,7 @@ "Choose a Date": "Kies een datum", "Choose a Time": "Kies een tijdstip", "Choose a time": "Kies een tijd", - "Choose all": "Kies alle", + "Choose all": "Alle kiezen", "Chosen %s": "Gekozen %s", "Click to choose all %s at once.": "Klik om alle %s te kiezen.", "Click to remove all chosen %s at once.": "Klik om alle gekozen %s tegelijk te verwijderen.", @@ -50,12 +50,12 @@ "Midnight": "Middernacht", "Noon": "12 uur 's middags", "Note: You are %s hour ahead of server time.": [ - "Let op: U ligt %s uur voor ten opzichte van de server-tijd.", - "Let op: U ligt %s uren voor ten opzichte van de server-tijd." + "Let op: u ligt %s uur voor ten opzichte van de servertijd.", + "Let op: u ligt %s uur voor ten opzichte van de servertijd." ], "Note: You are %s hour behind server time.": [ - "Let op: U ligt %s uur achter ten opzichte van de server-tijd.", - "Let op: U ligt %s uren achter ten opzichte van de server-tijd." + "Let op: u ligt %s uur achter ten opzichte van de servertijd.", + "Let op: u ligt %s uur achter ten opzichte van de servertijd." ], "November": "november", "Now": "Nu", @@ -64,15 +64,15 @@ "Remove all": "Verwijder alles", "September": "september", "Show": "Tonen", - "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "Dit is de lijst met beschikbare %s. U kunt kiezen uit een aantal door ze te selecteren in het vak hieronder en vervolgens op de \"Kiezen\" pijl tussen de twee lijsten te klikken.", - "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "Dit is de lijst van de gekozen %s. Je kunt ze verwijderen door ze te selecteren in het vak hieronder en vervolgens op de \"Verwijderen\" pijl tussen de twee lijsten te klikken.", + "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "Dit is de lijst met beschikbare %s. U kunt er een aantal kiezen door ze in het vak hieronder te selecteren en daarna op de pijl 'Kiezen' tussen de twee vakken te klikken.", + "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "Dit is de lijst met gekozen %s. U kunt er een aantal verwijderen door ze in het vak hieronder te selecteren en daarna op de pijl 'Verwijderen' tussen de twee vakken te klikken.", "Today": "Vandaag", "Tomorrow": "Morgen", - "Type into this box to filter down the list of available %s.": "Type in dit vak om te filteren in de lijst met beschikbare %s.", + "Type into this box to filter down the list of available %s.": "Typ in dit vak om de lijst met beschikbare %s te filteren.", "Yesterday": "Gisteren", - "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "U heeft een actie geselecteerd en heeft geen wijzigingen gemaakt op de individuele velden. U zoekt waarschijnlijk naar de Gaan knop in plaats van de Opslaan knop.", - "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "U heeft een actie geselecteerd, maar heeft de wijzigingen op de individuele velden nog niet opgeslagen. Klik alstublieft op OK om op te slaan. U zult vervolgens de actie opnieuw moeten uitvoeren.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "U heeft niet opgeslagen wijzigingen op enkele indviduele velden. Als u nu een actie uitvoert zullen uw wijzigingen verloren gaan.", + "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "U hebt een actie geselecteerd, en geen wijzigingen in afzonderlijke velden aangebracht. Waarschijnlijk zoekt u de knop Gaan in plaats van de knop Opslaan.", + "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "U hebt een actie geselecteerd, maar uw wijzigingen in afzonderlijke velden nog niet opgeslagen. Klik op OK om op te slaan. U dient de actie opnieuw uit te voeren.", + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "U hebt niet-opgeslagen wijzigingen op afzonderlijke bewerkbare velden. Als u een actie uitvoert, gaan uw wijzigingen verloren.", "one letter Friday\u0004F": "F", "one letter Monday\u0004M": "M", "one letter Saturday\u0004S": "S", @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -183,9 +183,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j-n-Y H:i", "SHORT_DATE_FORMAT": "j-n-Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/or/djangojs.js b/cms/static/js/i18n/or/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/cms/static/js/i18n/or/djangojs.js +++ b/cms/static/js/i18n/or/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/pl/djangojs.js b/cms/static/js/i18n/pl/djangojs.js index 6ad335b42757b3cdfa5c96c16d6e8adfdb2bf361..3589c6a19059c880eb229354b634d67c7419e993 100644 --- a/cms/static/js/i18n/pl/djangojs.js +++ b/cms/static/js/i18n/pl/djangojs.js @@ -46,10 +46,10 @@ "%(new_item_message)s": "%(new_item_message)s", "%(programName)s Home Page.": "Strona g\u0142\u00f3wna programu %(programName)s.", "%(sel)s of %(cnt)s selected": [ - "Zaznaczono %(sel)s z %(cnt)s", - "Zaznaczono %(sel)s z %(cnt)s", - "Zaznaczono %(sel)s z %(cnt)s", - "Zaznaczono %(sel)s z %(cnt)s" + "Wybrano %(sel)s z %(cnt)s", + "Wybrano %(sel)s z %(cnt)s", + "Wybrano %(sel)s z %(cnt)s", + "Wybrano %(sel)s z %(cnt)s" ], "%(type)s Component Template Menu": "%(type)s menu szablon\u00f3w elementu", "(Add signatories for a certificate)": "(Dodaj sygnatariuszy certyfikatu)", @@ -402,7 +402,6 @@ "Default (Local Time Zone)": "Domy\u015blna (lokalna strefa czasowa)", "Default Timed Transcript": "Domy\u015blna transkrypcja", "Delete": "Usu\u0144", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "Usun\u0105\u0107 \"<%= signatoryName %>\" z listy sygnatariuszy?", "Delete File Confirmation": "Potwierdzenie usuni\u0119cia pliku", "Delete Team": "Usu\u0144 zesp\u00f3\u0142", "Delete student '<%- student_id %>'s state on problem '<%- problem_id %>'?": "Czy usun\u0105\u0107 stan studenta '<%- student_id %>' dla \u0107wiczenia '<%- problem_id %>'?", @@ -428,7 +427,6 @@ "Do you want to replace the edX transcript with the YouTube transcript?": "Czy chcesz podmieni\u0107 bie\u017c\u0105c\u0105 transkrypcj\u0119 na nowsz\u0105 transkrypcj\u0119 z YouTube?", "Do you want to upload your file before submitting?": "Czy chcesz wgra\u0107 sw\u00f3j plik przed wys\u0142aniem odpowiedzi?", "Does the name on your ID match your account name: %(fullName)s?": "Czy imi\u0119 i nazwisko na dokumencie zgadzaj\u0105 si\u0119 z danymi konta: %(fullName)s?", - "Does the photo of you match your ID photo?": "Czy zdj\u0119cie twojej twarzy odpowiada temu z dokumentu to\u017csamo\u015bci?", "Does the photo of you show your whole face?": "Czy na zdj\u0119ciu wida\u0107 ca\u0142\u0105 twoj\u0105 twarz?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Nie widzisz swojego zdj\u0119cia? Upewnij si\u0119, \u017ce zezwalasz swojej przegl\u0105darce na u\u017cycie kamerki, gdy pojawia si\u0119 pro\u015bba o zgod\u0119.", "Donate": "Przeka\u017c darowizn\u0119", @@ -564,7 +562,6 @@ "Files must be in JPEG or PNG format.": "Pliki musz\u0105 by\u0107 w formacie JPEG lub PNG.", "Filter": "Filtr", "Filter and sort topics": "Filtruj i sortuj tematy", - "Final Grade": "Ocena ko\u0144cowa", "Final Grade Received": "Uzyskana ocena ko\u0144cowa", "Financial Assistance": "Wsparcie finansowe", "Financial Assistance Application": "Program wsparcia finansowego", @@ -584,7 +581,6 @@ "Generate": "Wygeneruj", "Generate Exception Certificates": "Wygeneruj certyfikaty w wyj\u0105tku", "Generate the user's certificate": "Wygeneruj certyfikat studenta", - "Get Credit": "Odbierz punkty", "Go to Dashboard": "Przejd\u017a do pulpitu", "Go to your Dashboard": "Przejd\u017a do swojego pulpitu", "Going forward, your account information will be updated and maintained by {enterprise_name}.": "Informacje na temat Twojego konta b\u0119d\u0105 aktualizowane i zarz\u0105dzane przez {enterprise_name}.", @@ -633,7 +629,6 @@ "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "Je\u015bli ten ekran zosta\u0142 wcze\u015bniej opublikowany i upubliczniony dla student\u00f3w, wszystkie zmiany, jakich dokona\u0142e\u015b kiedy ekran by\u0142 ukryty, b\u0119d\u0105 teraz widoczne dla student\u00f3w.", "If you do not yet have an account, use the button below to register.": "Je\u015bli nie posiadasz konta, u\u017cyj poni\u017cszego przycisku, aby si\u0119 zarejestrowa\u0107.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "Je\u015bli nie potwierdzisz swojej to\u017csamo\u015bci ju\u017c teraz, wci\u0105\u017c mo\u017cesz uczestniczy\u0107 w kursie z poziomu pulpitu studenta. B\u0119dziesz otrzymywa\u0107 cykliczne powiadomienia od %(platformName)s z pro\u015bb\u0105 o poddanie si\u0119 weryfikacji to\u017csamo\u015bci.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "Je\u015bli nie potwierdzisz swojej to\u017csamo\u015bci ju\u017c teraz, wci\u0105\u017c mo\u017cesz uczestniczy\u0107 w kursie z poziomu pulpitu studenta. B\u0119dziesz otrzymywa\u0107 cykliczne powiadomienia od {platformName} z pro\u015bb\u0105 o poddanie si\u0119 weryfikacji to\u017csamo\u015bci.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "Je\u017celi opu\u015bcisz t\u0119 stron\u0119 bez zapisania lub przes\u0142ania swojej odpowiedzi, stracisz ca\u0142\u0105 swoj\u0105 prac\u0119.", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "Je\u017celi opu\u015bcisz t\u0119 stron\u0119 bez przes\u0142ania zadania do oceny, stracisz ca\u0142\u0105 swoj\u0105 prac\u0119.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "Je\u017celi opu\u015bcisz t\u0119 stron\u0119 bez przes\u0142ania swojego zadania, stracisz ca\u0142\u0105 swoj\u0105 prac\u0119.", @@ -1184,7 +1179,6 @@ "Terms of Service and Honor Code": "Warunki korzystania z Serwisu oraz Kodeks Honorowy", "Textbook Name": "Nazwa podr\u0119cznika", "Textbook information": "Informacje o podr\u0119czniku", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Dzi\u0119kujemy, %(full_name)s! Otrzymali\u015bmy twoj\u0105 op\u0142at\u0119 za %(course_name)s.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Dzi\u0119kujemy za twoje zg\u0142oszenie do wsparcia finansowego dla kursu {course_name}. Mo\u017cesz spodziewa\u0107 si\u0119 odpowiedzi w ci\u0105gu 2-4 dni roboczych.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Dzi\u0119kujemy za przes\u0142anie twoich zdj\u0119\u0107. Wkr\u00f3tce dokonamy ich sprawdzenia. Mo\u017cesz si\u0119 teraz zapisa\u0107 na dowolny kurs w %(platformName)s, kt\u00f3ry oferuje potwierdzone certyfikaty. Weryfikacja to\u017csamo\u015bci jest wa\u017cna przez okres jednego roku. Po tym okresie konieczne b\u0119dzie ponowne przes\u0142anie zdj\u0119\u0107 do cel\u00f3w potwierdzenia to\u017csamo\u015bci.", "Thank you! We have received your payment for {courseName}.": "Dzi\u0119kujemy! Otrzymali\u015bmy twoj\u0105 op\u0142at\u0119 za kurs {courseName}.", @@ -1194,8 +1188,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Certyfikat tego studenta zosta\u0142 ponownie zatwierdzony, a uzyskana ocena przywr\u00f3cona.", "The cohort cannot be added": "Kohorta nie mo\u017ce zosta\u0107 dodana", "The cohort cannot be saved": "Kohorta nie mo\u017ce zosta\u0107 zapisana", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u0141\u0105czna d\u0142ugo\u015b\u0107 p\u00f3l nazwy organizacji i kodu biblioteki nie mo\u017ce przekroczy\u0107 <%=limit%> znak\u00f3w.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u0141\u0105czna d\u0142ugo\u015b\u0107 nazwy organizacji, numeru kursu i edycji kursu nie mo\u017ce przekroczy\u0107 <%=limit%> znak\u00f3w.", "The country or region where you live.": "Kraj lub region w kt\u00f3rym mieszkasz.", "The country that team members primarily identify with.": "G\u0142\u00f3wny region, z kt\u00f3rym identyfikuj\u0105 si\u0119 cz\u0142onkowie zespo\u0142u.", "The course end date must be later than the course start date.": "Data zako\u0144czenia kursu musi by\u0107 p\u00f3\u017aniejsza od daty rozpocz\u0119cia.", @@ -1211,7 +1203,6 @@ "The following email addresses and/or usernames are invalid:": "Nast\u0119puj\u0105ce adresy e-mail i/lub nazwy u\u017cytkownika s\u0105 nieprawid\u0142owe:", "The following errors were generated:": "Wyst\u0105pi\u0142y nast\u0119puj\u0105ce b\u0142\u0119dy:", "The following file types are not allowed: ": "Nast\u0119puj\u0105ce typy plik\u00f3w s\u0105 niedozwolone:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "Poni\u017csze informacje s\u0105 cz\u0119\u015bci\u0105 twojego profilu w {platform}. Za\u0142\u0105czyli\u015bmy je jako element twojego zg\u0142oszenia.", "The following message will be displayed at the bottom of the courseware pages within your course:": "Nast\u0119puj\u0105ca wiadomo\u015b\u0107 b\u0119dzie wy\u015bwietlana w dolnej cz\u0119\u015bci stron twojego kursu:", "The following options are available for the {license_name} license.": "Nast\u0119puj\u0105ce opcje s\u0105 dost\u0119pne dla licencji {license_name}.", "The following users are no longer enrolled in the course:": "Nast\u0119puj\u0105cy u\u017cytkownicy nie s\u0105 ju\u017c zapisani na kurs:", @@ -1228,7 +1219,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Liczba lekcji kursu zawieraj\u0105cych \u0107wiczenia wykorzystuj\u0105ce tego typu zadanie.", "The organization that this signatory belongs to, as it should appear on certificates.": "Organizacja, do kt\u00f3rej nale\u017cy sygnatariusz, zapisana w takiej formie, w jakiem ma si\u0119 znale\u017a\u0107 na certyfikatach.", "The page \"{route}\" could not be found.": "Nie uda\u0142o si\u0119 odnale\u017a\u0107 strony \"{route}\".", - "The photo of your face matches the photo on your ID.": "Zdj\u0119cie twojej twarzy odpowiada temu z dokumentu to\u017csamo\u015bci.", "The post you selected has been deleted.": "Wybrany przez ciebie wpis zosta\u0142 usuni\u0119ty.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "Opublikowana wersja ga\u0142\u0119zi {published} zosta\u0142a zresetowana do wersji roboczej ga\u0142\u0119zi {draft}.", "The raw error message is:": "Surowy komunikat b\u0142\u0119du:", @@ -1350,7 +1340,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "Aby upewni\u0107 si\u0119, \u017ce wszyscy studenci b\u0119d\u0105 mogli odtworzy\u0107 film, zalecamy dostarczenie wersji filmu w formatach .mp4 jak i .webm. Kliknij poni\u017cej, aby doda\u0107 odno\u015bnik do kolejnej wersji. Odno\u015bnik nie mo\u017ce prowadzi\u0107 do Youtube. Studentowi odtworzony zostanie pierwszy film kompatybilny z jego komputerem.", "To complete the program, you must earn a verified certificate for each course.": "Aby uko\u0144czy\u0107 program, musisz uzyska\u0107 potwierdzony certyfikat z ka\u017cdego kursu.", "To continue learning with this account, sign in below.": "Aby kontynuowa\u0107 nauk\u0119 za po\u015brednictwem tego konta, zaloguj si\u0119.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "W celu sfinalizowania procesu przyznawania punkt\u00f3w edukacyjnych, %(display_name)s wymaga od student\u00f3w %(platform_name)s przes\u0142ania zg\u0142oszenia \u017c\u0105dania przyznania punkt\u00f3w.", "To invalidate a certificate for a particular learner, add the username or email address below.": "W celu uniewa\u017cnienia certyfikatu dla okre\u015blonego studenta, wprowad\u017a poni\u017cej jego nazw\u0119 u\u017cytkownika lub adres e-mail.", "To receive a certificate, you must also verify your identity before {date}.": "Aby otrzyma\u0107 certyfikat, musisz r\u00f3wnie\u017c potwierdzi\u0107 swoj\u0105 to\u017csamo\u015b\u0107 przed {date}.", "To receive a certificate, you must also verify your identity.": "Aby otrzyma\u0107 certyfikat, musisz r\u00f3wnie\u017c potwierdzi\u0107 swoj\u0105 to\u017csamo\u015b\u0107.", @@ -1446,7 +1435,6 @@ "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "U\u017cywaj \u015bcie\u017cek kursu jako podstawy do dzielenia dyskusji. Wszyscy studenci, niezale\u017cnie od ich \u015bcie\u017cki, widz\u0105 te same tematy dyskusji, natomiast wpisy wewn\u0105trz podzielonych dyskusji widz\u0105 wy\u0142\u0105cznie studenci b\u0119d\u0105cy na tych samych \u015bcie\u017ckach kursu.", "Use my institution/campus credentials": "U\u017cyj danych do logowania z mojej uczelni", "Use the All Topics menu to find specific topics.": "U\u017cyj menu \"Wszystkie tematy\", aby znale\u017a\u0107 okre\u015blone tematy.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "U\u017cyj kamerki internetowej, aby zrobi\u0107 zdj\u0119cie swojego dokumentu to\u017csamo\u015bci. Por\u00f3wnamy to zdj\u0119cie ze zdj\u0119ciem twojej twarzy oraz zweryfikujemy dane osobowe.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "U\u017cyj kamerki internetowej, aby zrobi\u0107 zdj\u0119cie swojej twarzy. Por\u00f3wnamy to zdj\u0119cie ze zdj\u0119ciem w twoim dokumencie to\u017csamo\u015bci.", "Used": "Wykorzystany", "Used in {count} location": [ @@ -1470,7 +1458,6 @@ "Verified Certificate upgrade": "Zg\u0142oszenie do potwierdzonego certyfikatu", "Verified Status": "Status potwierdzony", "Verified mode price": "Cena trybu potwierdzonego", - "Verify Now": "Potwierd\u017a teraz", "Video Capture Error": "B\u0142\u0105d przechwytywania obrazu wideo", "Video ID": "Identyfikator filmu", "Video Source Language": "Oryginalny j\u0119zyk filmu", @@ -1502,7 +1489,6 @@ "We couldn't find any results for \"%s\".": "Nie uda\u0142o si\u0119 znale\u017a\u0107 \u017cadnych wynik\u00f3w dla \"%s\".", "We couldn't sign you in.": "Logowanie nie powiod\u0142o si\u0119.", "We have encountered an error. Refresh your browser and then try again.": "Napotkali\u015bmy b\u0142\u0105d. Od\u015bwie\u017c przegl\u0105dark\u0119 i spr\u00f3buj jeszcze raz.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Otrzymali\u015bmy twoje dane i sprawdzimy je by potwierdzi\u0107 twoj\u0105 to\u017csamo\u015b\u0107. Na swoim pulpicie studenta znajdziesz wiadomo\u015b\u0107 gdy proces weryfikacyjny zostanie zako\u0144czony (zwykle w ci\u0105gu 1-2 dni). W mi\u0119dzyczasie mo\u017cesz bez przeszk\u00f3d korzysta\u0107 ze wszystkich materia\u0142\u00f3w kursowych.", "We just need a little more information before you start learning with %(platformName)s.": "Potrzebujemy jeszcze nieco informacji zanim b\u0119dziesz m\u00f3g\u0142 rozpocz\u0105\u0107 nauk\u0119 w %(platformName)s.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "U\u017cywamy najwy\u017cszych dost\u0119pnych poziom\u00f3w bezpiecze\u0144stwa w celu szyfrowania zdj\u0119\u0107 i przesy\u0142ania ich do sprawdzenia. Po zako\u0144czeniu czynno\u015bci weryfikacyjnych, twoje zdj\u0119cia i dane z dokumentu nie s\u0105 zapisywane ani widoczne gdziekolwiek na \u0142amach %(platformName)s.", "We've encountered an error. Refresh your browser and then try again.": "Napotkali\u015bmy b\u0142\u0105d. Od\u015bwie\u017c przegl\u0105dark\u0119 i spr\u00f3buj ponownie.", @@ -1582,12 +1568,9 @@ "You must sign out and sign back in before your language changes take effect.": "Musisz si\u0119 wylogowa\u0107 i ponownie zalogowa\u0107, aby zmiany j\u0119zykowe zacz\u0119\u0142y obowi\u0105zywa\u0107.", "You must specify a name for the cohort": "Musisz okre\u015bli\u0107 nazw\u0119 tej kohorty", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "Przed udost\u0119pnieniem swojego pe\u0142nego profilu musisz poda\u0107 rok urodzenia. Aby wskaza\u0107 sw\u00f3j rok urodzenia, odwied\u017a {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Potrzebujesz dowodu osobistego, paszportu lub innego oficjalnego dokumentu to\u017csamo\u015bci ze zdj\u0119ciem i twoim nazwiskiem.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Potrzebujesz dokumentu to\u017csamo\u015bci ze zdj\u0119ciem i danymi osobowymi. Zaakceptujemy dow\u00f3d osobisty, paszport, prawo jazdy lub inny oficjalny dokument.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Aby m\u00f3c zarejestrowa\u0107 si\u0119 na kursy, musisz najpierw aktywowa\u0107 swoje konto. Sprawd\u017a poczt\u0119 i odnajd\u017a e-mail z odno\u015bnikiem aktywacyjnym.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Przed zapisaniem si\u0119 na pierwszy kurs musisz aktywowa\u0107 swoje konto. Sprawd\u017a poczt\u0119 e-mail i znajd\u017a wiadomo\u015b\u0107 z instrukcj\u0105 aktywacji. Po jej dokonaniu wr\u00f3\u0107 i od\u015bwie\u017c t\u0119 stron\u0119.", "You receive messages from {platform_name} and course teams at this address.": "Na ten adres otrzymujesz wiadomo\u015bci z {platform_name} i od prowadz\u0105cych kursy.", - "You still need to visit the %(display_name)s website to complete the credit process.": "Wci\u0105\u017c musisz odwiedzi\u0107 stron\u0119 %(display_name)s w celu dope\u0142nienia formalno\u015bci zwi\u0105zanych z przyznaniem punkt\u00f3w edukacyjnych.", "You will be refunded the amount you paid.": "Zap\u0142acona kwota zostanie zwr\u00f3cona.", "You will not be refunded the amount you paid.": "Zap\u0142acona kwota nie zostanie zwr\u00f3cona.", "You will not receive notification for emails that bounce, so double-check your spelling.": "Nie otrzymasz powiadomie\u0144 na nieprawid\u0142owe adresy e-mail, dlatego raz jeszcze sprawd\u017a poprawno\u015b\u0107.", @@ -1658,7 +1641,6 @@ "enter code here": "Wprowad\u017a kod", "enter link description here": "Wprowad\u017a opis linku", "for": "za", - "for {courseName}": "z kursu {courseName}", "group configuration": "konfiguracja grupy", "image omitted": "pomini\u0119ty obrazek", "last activity": "ostatnia aktywno\u015b\u0107", @@ -1792,7 +1774,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1845,9 +1827,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", - "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "FIRST_DAY_OF_WEEK": 1, + "MONTH_DAY_FORMAT": "j E", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d-m-Y H:i", "SHORT_DATE_FORMAT": "d-m-Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/pt-br/djangojs.js b/cms/static/js/i18n/pt-br/djangojs.js index 22d490dbf52d6b6e47ef7f7c129246968665c98b..9b02020d582e51d0b8664033c1ed6be7ee7f878d 100644 --- a/cms/static/js/i18n/pt-br/djangojs.js +++ b/cms/static/js/i18n/pt-br/djangojs.js @@ -258,7 +258,6 @@ "December": "Dezembro", "Default Timed Transcript": "Transcri\u00e7\u00e3o Sincronizada Padr\u00e3o", "Delete": "Apagar", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "Apagar \"<%= signatoryName %>\" da lista de emissores?", "Delete File Confirmation": "Confirma\u00e7\u00e3o da exclus\u00e3o do arquivo", "Delete Team": "Apagar equipe.", "Delete student '<%- student_id %>'s state on problem '<%- problem_id %>'?": "Excluir status do aluno '<%- student_id %>' para o problema '<%- problem_id %>'?", @@ -277,7 +276,6 @@ "Do you want to replace the edX transcript with the YouTube transcript?": "Voc\u00ea quer substituir a transcri\u00e7\u00e3o do edX pela do YouTube?", "Do you want to upload your file before submitting?": "Voc\u00ea deseja fazer upload de seu arquivo antes de enviar?", "Does the name on your ID match your account name: %(fullName)s?": "O nome de sua identifica\u00e7\u00e3o correspondo ao nome de sua conta: %(fullName)s?", - "Does the photo of you match your ID photo?": "A foto a seguir \u00e9 a mesma foto de sua identidade?", "Does the photo of you show your whole face?": "A sua foto escolhida exibe todo o seu rosto?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "N\u00e3o v\u00ea sua fotografia? Certifique-se de permitir que o seu navegador utilize a c\u00e2mera quando ele pedir permiss\u00e3o.", "Donate": "Doar", @@ -385,7 +383,6 @@ "Generate": "Emitir", "Generate Exception Certificates": "Gerar certificados de exce\u00e7\u00e3o", "Generate the user's certificate": "Emitir certificado do usu\u00e1rio", - "Get Credit": "Obter Cr\u00e9dito", "Go to Dashboard": "Ir para a P\u00e1gina Inicial", "Go to your Dashboard": "Ir para o seu Painel de controle", "Government-Issued Photo ID": "Foto de um documento de identidade oficial", @@ -772,8 +769,6 @@ "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Obrigado por enviar suas fotos. N\u00f3s vamos analis\u00e1-las rapidamente. Voc\u00ea pode inscrever-se para qualquer curso da plataforma %(platformName)s que ofere\u00e7a certificados verificados. A verifica\u00e7\u00e3o \u00e9 v\u00e1lida por um ano. Depois disso, voc\u00ea precisa enviar fotos para verificar novamente.", "The cohort cannot be added": "O grupo n\u00e3o pode ser adicionado", "The cohort cannot be saved": "O grupo n\u00e3o p\u00f4de ser salvo", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "Os campos comprimento combinando da Organiza\u00e7\u00e3o e c\u00f3digo da biblioteca n\u00e3o podem ultrapassar <%=limit%> caracteres. ", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "Os campos comprimento total da Organiza\u00e7\u00e3o, n\u00famero do curso e funcionamento do curso n\u00e3o podem exceder <%=limit%> caracteres. ", "The country that team members primarily identify with.": "O pa\u00eds com o qual os membros da equipe se identificam.", "The course end date must be later than the course start date.": "A data do final do curso deve ser posterior \u00e0 data de in\u00edcio da matr\u00edcula. ", "The course must have an assigned start date.": "O curso deve ter uma data de in\u00edcio designada.", @@ -787,7 +782,6 @@ "The following email addresses and/or usernames are invalid:": "Os seguintes endere\u00e7os de email e/ou nomes de usu\u00e1rio s\u00e3o inv\u00e1lidos:", "The following errors were generated:": "Os seguintes erros foram gerados:", "The following file types are not allowed: ": "Os seguintes tipos de arquivos n\u00e3o s\u00e3o permitidos:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "As informa\u00e7\u00f5es a seguir j\u00e1 fazem parte do seu perfil {platform}. N\u00f3s as inclu\u00edmos aqui para seu pedido.", "The following message will be displayed at the bottom of the courseware pages within your course:": "A mensagem a seguir ser\u00e1 exibida na parte inferior das p\u00e1ginas do seu curso:", "The following options are available for the {license_name} license.": "As seguintes op\u00e7\u00f5es est\u00e3o dispon\u00edveis para a licen\u00e7a {license_name}.", "The following users are no longer enrolled in the course:": "Os seguintes usu\u00e1rios n\u00e3o est\u00e3o mais inscritos no curso:", @@ -796,7 +790,6 @@ "The minimum grade for course credit is not set.": "A nota m\u00ednima para obter cr\u00e9ditos para o curso n\u00e3o est\u00e1 especificada.", "The name of this signatory as it should appear on certificates.": "O nome deste signat\u00e1rio conforme deve aparecer nos certificados.", "The organization that this signatory belongs to, as it should appear on certificates.": "A organiza\u00e7\u00e3o a qual este signat\u00e1rio pertence, conforme deve aparecer nos certificados.", - "The photo of your face matches the photo on your ID.": "A foto do seu rosto corresponde \u00e0 foto no seu documento.", "The raw error message is:": "A mensagem bruta de erro \u00e9:", "The selected content group does not exist": "O grupo de conte\u00fado selecionado n\u00e3o existe", "The server could not be contacted.": "N\u00e3o foi poss\u00edvel contactar o servidor.", @@ -860,7 +853,6 @@ "Title of the signatory": "T\u00edtulo da assinatura", "Titles more than 100 characters may prevent students from printing their certificate on a single page.": "T\u00edtulos com mais de 100 caracteres podem impedir que os estudantes imprimam seu certificado em uma \u00fanica p\u00e1gina.", "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "Para garantir que todos os estudantes poder\u00e3o acessar o video, n\u00f3s recomendamos providenciar vers\u00f5es em .mp4 e .webm do video. Clique abaixo para adicionar um URL para outra vers\u00e3o. Esses URLs n\u00e3o podem ser do YouTube. O primeiro v\u00eddeo que for compat\u00edvel com o computador dos alunos ser\u00e1 exibido.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "Para finalizar os cr\u00e9ditos do curso, %(display_name)s exige que os alunos %(platform_name)s enviem uma solicita\u00e7\u00e3o de cr\u00e9ditos. ", "To invalidate a certificate for a particular learner, add the username or email address below.": "Para invalidar um certificado para um aluno em particular, adicionar o nome do usu\u00e1rio ou endere\u00e7o de e-mail abaixo", "To receive a certificate, you must also verify your identity.": "Para receber um certificado, voc\u00ea tamb\u00e9m deve verificar a sua identidade.", "To take a successful photo, make sure that:": "Para tirar uma foto corretamente, certifique-se que:", @@ -917,7 +909,6 @@ "Use a practice proctored exam to introduce learners to the proctoring tools and processes. Results of a practice exam do not affect a learner's grade.": "Usar uma prova supervisionada pr\u00e1tica para apresentar aos alunos as ferramentas e processos de supervis\u00e3o. Os resultados de prova pr\u00e1tica n\u00e3o afetam a nota dos alunos", "Use a timed exam to limit the time learners can spend on problems in this subsection. Learners must submit answers before the time expires. You can allow additional time for individual learners through the Instructor Dashboard.": "Use uma prova cronometrada para limitar o tempo que os alunos podem gastar nos problemas nesta subse\u00e7\u00e3o. Os alunos devem enviar as respostas antes que o tempo acabe. Voc\u00ea pode permitir um tempo adicional para alunos individuais atrav\u00e9s do Painel do Instrutor.", "Use my institution/campus credentials": "Entrar com credenciais de Institui\u00e7\u00e3o/Campus", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Use a webcam para tirar uma foto do seu documento. N\u00f3s vamos conferir esta foto com a foto do seu rosto e o nome na sua conta.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Use a webcam para tirar uma foto do seu rosto. N\u00f3s vamos conferir essa foto com a do seu documento de identidade.", "Used": "Usado", "User Email": "E-mail do Usu\u00e1rio", @@ -934,7 +925,6 @@ "Verified Certificate upgrade": "Atualiza\u00e7\u00e3o do certificado verificado", "Verified Status": "Status verificado", "Verified mode price": "Pre\u00e7o de modo verificado", - "Verify Now": "Verifique agora", "Video Capture Error": "Falha na captura de v\u00eddeo", "Video ID": "ID do V\u00eddeo", "View": "Visualizar", @@ -950,7 +940,6 @@ "Warning": "Aviso", "Warnings": "Avisos", "We couldn't find any results for \"%s\".": "N\u00e3o foi poss\u00edvel encontrar resultados para \"%s\".", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Recebemos as suas informa\u00e7\u00f5es e estamos verificando a sua identifica\u00e7\u00e3o. Voc\u00ea receber\u00e1 uma mensagem em seu painel de controle quando o processo de verifica\u00e7\u00e3o estiver conclu\u00eddo (normalmente entre 1-2 dias). Enquanto isso, voc\u00ea ainda pode acessar a todo o conte\u00fado do curso.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "N\u00f3s usamos os mais altos n\u00edveis de seguran\u00e7a dispon\u00edveis para encriptar sua foto e envi\u00e1-la para no servi\u00e7o de autoriza\u00e7\u00e3o para an\u00e1lise. Informa\u00e7\u00f5es sobre voc\u00ea e sua foto n\u00e3o s\u00e3o salvas ou vis\u00edveis em qualquer lugar em %(platformName)s depois que o processo de verifica\u00e7\u00e3o \u00e9 completado.", "We've encountered an error. Refresh your browser and then try again.": "Encontramos um erro. Atualize seu navegador e tente novamente.", "Web:": "Web:", @@ -1001,11 +990,8 @@ "You must provide a learner name.": "Voc\u00ea deve fornecer o nome do aluno.", "You must sign out and sign back in before your language changes take effect.": "Voc\u00ea deve sair e entrar antes que as mudan\u00e7as de idioma tenham efeito.", "You must specify a name for the cohort": "Voc\u00ea deve especificar um nome para o grupo", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Voc\u00ea precisa de uma carteira de habilita\u00e7\u00e3o, passaporte ou outra identifica\u00e7\u00e3o emitida pelo governo que possua o seu nome e foto.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Voc\u00ea precisa de um documento com o seu nome e foto. Uma carteira de motorista, passaporte ou outro documento emitido pelo governo s\u00e3o aceit\u00e1veis.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Voc\u00ea precisa ativar a sua conta antes de se matricular nos cursos. Verifique em sua caixa de entrada o e-mail de ativa\u00e7\u00e3o.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Voc\u00ea precisa ativar a sua conta antes de matricular-se nos cursos. Confira se o e-mail de ativa\u00e7\u00e3o est\u00e1 na sua caixa de entrada. Depois de completar a ativa\u00e7\u00e3o, voc\u00ea pode voltar e atualizar esta p\u00e1gina.", - "You still need to visit the %(display_name)s website to complete the credit process.": "Voc\u00ea ainda precisa visitar o site %(display_name)s para completar o processo de cr\u00e9dito.", "You will not receive notification for emails that bounce, so double-check your spelling.": "Voc\u00ea n\u00e3o receber\u00e1 notifica\u00e7\u00f5es de e-mails que n\u00e3o entregues, ent\u00e3o verifique novamente se digitou corretamente.", "You will use your webcam to take a picture of your face and of your government-issued photo ID.": "Voc\u00ea vai usar sua webcam para tirar uma foto do seu rosto e do seu documento com foto emitido pelo governo.", "You!": "Voc\u00ea!", @@ -1102,7 +1088,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1158,9 +1144,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/pt-pt/djangojs.js b/cms/static/js/i18n/pt-pt/djangojs.js index 7053973d23d04878cd2329032dd316dcc0d5cf81..e29688adc7b3484782642ac2d6cd747f0a40f87d 100644 --- a/cms/static/js/i18n/pt-pt/djangojs.js +++ b/cms/static/js/i18n/pt-pt/djangojs.js @@ -27,8 +27,10 @@ "(required):": "(obrigat\u00f3rio):", "6 a.m.": "6 a.m.", "6 p.m.": "6 p.m.", + "April": "Abril", "Assessment": "Avalia\u00e7\u00e3o", "Assessments": "Avalia\u00e7\u00f5es", + "August": "Agosto", "Available %s": "Dispon\u00edvel %s", "Back to Full List": "Voltar \u00e0 lista completa", "Block view is unavailable": "A visualiza\u00e7\u00e3o em grelha n\u00e3o est\u00e1 dispon\u00edvel", @@ -47,10 +49,12 @@ "Couldn't Save This Assignment": "N\u00e3o \u00e9 poss\u00edvel guardar esta tarefa", "Criterion Added": "Crit\u00e9rio Adicionado", "Criterion Deleted": "Crit\u00e9rio eliminado", + "December": "Dezembro", "Describe ": "Descreva", "Do you want to upload your file before submitting?": "Deseja carregar o seu ficheiro antes de submeter?", "Error": "Erro", "Error getting the number of ungraded responses": "Erro ao obter o n\u00famero de respostas sem classifica\u00e7\u00e3o", + "February": "Fevereiro", "Feedback available for selection.": "Coment\u00e1rio dispon\u00edvel para a sele\u00e7\u00e3o.", "File type is not allowed.": "O tipo de ficheiro n\u00e3o \u00e9 permitido.", "File types can not be empty.": "Indique o tipo de ficheiro. ", @@ -65,7 +69,12 @@ "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "Caso saia desta p\u00e1gina sem submeter o seu teste, ir\u00e1 perder todo o trabalho at\u00e9 aqui realizado.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "Caso saia desta p\u00e1gina sem submeter a sua auto-avalia\u00e7\u00e3o, ir\u00e1 perder todo o trabalho at\u00e9 aqui realizado.", "If you leave this page without submitting your staff assessment, you will lose any work you have done.": "Caso saia desta p\u00e1gina sem submeter a sua avalia\u00e7\u00e3o individual, ir\u00e1 perder todo o trabalho at\u00e9 aqui realizado.", + "January": "Janeiro", + "July": "Julho", + "June": "Junho", "List of Open Assessments is unavailable": "Lista de Avalia\u00e7\u00f5es Abertas n\u00e3o est\u00e1 dispon\u00edvel", + "March": "Mar\u00e7o", + "May": "Maio", "Midnight": "Meia-noite", "Noon": "Meio-dia", "Not Selected": "N\u00e3o Selecionado", @@ -77,7 +86,9 @@ "Nota: O use fuso hor\u00e1rio est\u00e1 %s hora atrasado em rela\u00e7\u00e3o ao servidor.", "Nota: O use fuso hor\u00e1rio est\u00e1 %s horas atrasado em rela\u00e7\u00e3o ao servidor." ], + "November": "Novembro", "Now": "Agora", + "October": "Outubro", "One or more rescheduling tasks failed.": "Ocorreu erro no reagendamento de uma ou mais tarefas.", "Option Deleted": "Op\u00e7\u00e3o eliminada", "Paragraph": "Par\u00e1grafo", @@ -89,6 +100,7 @@ "Remove all": "Remover todos", "Saving...": "A guardar...", "Self": "Auto", + "September": "Setembro", "Server error.": "Erro de servidor.", "Show": "Mostrar", "Staff": "Equipa", @@ -133,7 +145,14 @@ "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Tem mudan\u00e7as por guardar nos campos individuais. Se usar uma a\u00e7\u00e3o, as suas mudan\u00e7as por guardar ser\u00e3o perdidas.", "You must provide a learner name.": "Deve indicar o nome de um estudante.", "You're about to submit your response for this assignment. After you submit this response, you can't change it or submit a new response.": "Est\u00e1 prestes a submeter a sua resposta para esta tarefa. Depois de a submeter, n\u00e3o \u00e9 poss\u00edvel alter\u00e1-la ou submeter uma nova resposta.", - "Your file ": "O seu ficheiro " + "Your file ": "O seu ficheiro ", + "one letter Friday\u0004F": "S", + "one letter Monday\u0004M": "S", + "one letter Saturday\u0004S": "S", + "one letter Sunday\u0004S": "D", + "one letter Thursday\u0004T": "Q", + "one letter Tuesday\u0004T": "T", + "one letter Wednesday\u0004W": "Q" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -155,7 +174,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -211,9 +230,9 @@ "%d/%m/%y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/ro/djangojs.js b/cms/static/js/i18n/ro/djangojs.js index 00d4da422f1220007f5244390c0af2b53ff7f483..eefb5186216cb1ce2de6321a52942b5b6b25d287 100644 --- a/cms/static/js/i18n/ro/djangojs.js +++ b/cms/static/js/i18n/ro/djangojs.js @@ -27,6 +27,8 @@ ], "6 a.m.": "6 a.m.", "6 p.m.": "6 p.m.", + "April": "Aprilie", + "August": "August", "Available %s": "%s disponibil", "Cancel": "Anuleaz\u0103", "Choose": "Alege", @@ -39,32 +41,42 @@ "Click to remove all chosen %s at once.": "Click pentru a elimina toate %s alese.", "Could not retrieve download url.": "Nu s-a putut ob\u0163ine linkul de desc\u0103rcare.", "Could not retrieve upload url.": "Nu s-a putut ob\u0163ine linkul de \u00eenc\u0103rcare.", + "December": "Decembrie", "Error": "Eroare", + "February": "Februarie", "Filter": "Filtru", "Heading 3": "Titlu 3", "Heading 4": "Titlu 4", "Heading 5": "Titlu 5", "Heading 6": "Titlu 6", "Hide": "Ascunde", + "January": "Ianuarie", + "July": "Iulie", + "June": "Iunie", + "March": "Martie", + "May": "Mai", "Midnight": "Miezul nop\u021bii", "Noon": "Amiaz\u0103", "Note: You are %s hour ahead of server time.": [ - "Not\u0103: Sunte\u021bi cu %s ora \u00eenaintea orei serverului.", + "Not\u0103: Sunte\u021bi cu %s or\u0103 \u00eenaintea orei serverului.", "Not\u0103: Sunte\u021bi cu %s ore \u00eenaintea orei serverului.", - "Not\u0103: Sunte\u021bi cu %s ore \u00eenaintea orei serverului." + "Not\u0103: Sunte\u021bi cu %s de ore \u00eenaintea orei serverului." ], "Note: You are %s hour behind server time.": [ "Not\u0103: Sunte\u021bi cu %s or\u0103 \u00een urma orei serverului.", "Not\u0103: Sunte\u021bi cu %s ore \u00een urma orei serverului.", - "Not\u0103: Sunte\u021bi cu %s ore \u00een urma orei serverului." + "Not\u0103: Sunte\u021bi cu %s de ore \u00een urma orei serverului." ], + "November": "Noiembrie", "Now": "Acum", + "October": "Octombrie", "One or more rescheduling tasks failed.": "Una sau mai multe reprogram\u0103ri au e\u015fuat.", "Paragraph": "Paragraf", "Preformatted": "Preformatat", "Remove": "Elimin\u0103", "Remove all": "Elimin\u0103 toate", "Saving...": "Se salveaz\u0103...", + "September": "Septembrie", "Server error.": "Eroare de server.", "Show": "Arat\u0103", "Status of Your Response": "Statusul r\u0103spunsului t\u0103u", @@ -86,7 +98,14 @@ "Yesterday": "Ieri", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "A\u021bi selectat o ac\u0163iune \u0219i nu a\u021b\u0163i f\u0103cut modific\u0103ri \u00een c\u00eempuri individuale. Probabil c\u0103uta\u021bi butonul Go, \u00een loc de Salveaz\u0103.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "A\u0163i selectat o ac\u0163iune, dar nu a\u0163i salvat \u00eenc\u0103 modific\u0103rile la c\u00e2mpuri individuale. Face\u0163i clic pe OK pentru a salva. Va trebui s\u0103 executa\u021bi ac\u021biunea din nou.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Ave\u0163i modific\u0103ri nesalvate \u00een c\u00eempuri individuale editabile. Dac\u0103 executa\u0163i o ac\u021biune, modific\u0103rile nesalvate vor fi pierdute." + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Ave\u0163i modific\u0103ri nesalvate \u00een c\u00eempuri individuale editabile. Dac\u0103 executa\u0163i o ac\u021biune, modific\u0103rile nesalvate vor fi pierdute.", + "one letter Friday\u0004F": "V", + "one letter Monday\u0004M": "L", + "one letter Saturday\u0004S": "S", + "one letter Sunday\u0004S": "D", + "one letter Thursday\u0004T": "J", + "one letter Tuesday\u0004T": "M", + "one letter Wednesday\u0004W": "M" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -108,7 +127,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -144,45 +163,35 @@ django.formats = { "DATETIME_FORMAT": "j F Y, H:i", "DATETIME_INPUT_FORMATS": [ + "%d.%m.%Y, %H:%M", + "%d.%m.%Y, %H:%M:%S", + "%d.%B.%Y, %H:%M", + "%d.%B.%Y, %H:%M:%S", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", "%Y-%m-%d %H:%M", - "%Y-%m-%d", - "%m/%d/%Y %H:%M:%S", - "%m/%d/%Y %H:%M:%S.%f", - "%m/%d/%Y %H:%M", - "%m/%d/%Y", - "%m/%d/%y %H:%M:%S", - "%m/%d/%y %H:%M:%S.%f", - "%m/%d/%y %H:%M", - "%m/%d/%y" + "%Y-%m-%d" ], "DATE_FORMAT": "j F Y", "DATE_INPUT_FORMATS": [ - "%Y-%m-%d", - "%m/%d/%Y", - "%m/%d/%y", - "%b %d %Y", - "%b %d, %Y", - "%d %b %Y", - "%d %b, %Y", - "%B %d %Y", - "%B %d, %Y", + "%d.%m.%Y", + "%d.%b.%Y", "%d %B %Y", - "%d %B, %Y" + "%A, %d %B %Y", + "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y, H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": ".", "TIME_FORMAT": "H:i", "TIME_INPUT_FORMATS": [ + "%H:%M", "%H:%M:%S", - "%H:%M:%S.%f", - "%H:%M" + "%H:%M:%S.%f" ], "YEAR_MONTH_FORMAT": "F Y" }; diff --git a/cms/static/js/i18n/rtl/djangojs.js b/cms/static/js/i18n/rtl/djangojs.js index 961551da9b06a3f391453168f81bff9f67105836..a1ef603fdfcb800a0c27b90cd1178b4116f372d9 100644 --- a/cms/static/js/i18n/rtl/djangojs.js +++ b/cms/static/js/i18n/rtl/djangojs.js @@ -27,6 +27,7 @@ " \u0648\u062b\u0648\u0632\u062b\u0642\u0633" ], " and ": " \u0634\u0631\u064a ", + " as many questions may have already been answered.": " \u0634\u0633 \u0648\u0634\u0631\u063a \u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631\u0633 \u0648\u0634\u063a \u0627\u0634\u062f\u062b \u0634\u0645\u0642\u062b\u0634\u064a\u063a \u0632\u062b\u062b\u0631 \u0634\u0631\u0633\u0635\u062b\u0642\u062b\u064a.", " learner does not exist in LMS and not added to the exception list": " \u0645\u062b\u0634\u0642\u0631\u062b\u0642 \u064a\u062e\u062b\u0633 \u0631\u062e\u0641 \u062b\u0637\u0647\u0633\u0641 \u0647\u0631 \u0645\u0648\u0633 \u0634\u0631\u064a \u0631\u062e\u0641 \u0634\u064a\u064a\u062b\u064a \u0641\u062e \u0641\u0627\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0645\u0647\u0633\u0641", " learner is already white listed and not added to the exception list": " \u0645\u062b\u0634\u0642\u0631\u062b\u0642 \u0647\u0633 \u0634\u0645\u0642\u062b\u0634\u064a\u063a \u0635\u0627\u0647\u0641\u062b \u0645\u0647\u0633\u0641\u062b\u064a \u0634\u0631\u064a \u0631\u062e\u0641 \u0634\u064a\u064a\u062b\u064a \u0641\u062e \u0641\u0627\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0645\u0647\u0633\u0641", " learner is not enrolled in course and not added to the exception list": " \u0645\u062b\u0634\u0642\u0631\u062b\u0642 \u0647\u0633 \u0631\u062e\u0641 \u062b\u0631\u0642\u062e\u0645\u0645\u062b\u064a \u0647\u0631 \u0630\u062e\u0639\u0642\u0633\u062b \u0634\u0631\u064a \u0631\u062e\u0641 \u0634\u064a\u064a\u062b\u064a \u0641\u062e \u0641\u0627\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0645\u0647\u0633\u0641", @@ -39,6 +40,8 @@ " records are not in correct format and not added to the exception list": " \u0642\u062b\u0630\u062e\u0642\u064a\u0633 \u0634\u0642\u062b \u0631\u062e\u0641 \u0647\u0631 \u0630\u062e\u0642\u0642\u062b\u0630\u0641 \u0628\u062e\u0642\u0648\u0634\u0641 \u0634\u0631\u064a \u0631\u062e\u0641 \u0634\u064a\u064a\u062b\u064a \u0641\u062e \u0641\u0627\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0645\u0647\u0633\u0641", "${listPrice}": "${listPrice}", "%(cohort_name)s (%(user_count)s)": "%(cohort_name)s (%(user_count)s)", + "%(comments_count)s %(span_sr_open)scomments %(span_close)s": "%(comments_count)s %(span_sr_open)s\u0630\u062e\u0648\u0648\u062b\u0631\u0641\u0633 %(span_close)s", + "%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s unread comments)%(span_close)s": "%(comments_count)s %(span_sr_open)s\u0630\u062e\u0648\u0648\u062b\u0631\u0641\u0633 (%(unread_comments_count)s \u0639\u0631\u0642\u062b\u0634\u064a \u0630\u062e\u0648\u0648\u062b\u0631\u0641\u0633)%(span_close)s", "%(errorCount)s error found in form.": [ "%(errorCount)s \u062b\u0642\u0642\u062e\u0642 \u0628\u062e\u0639\u0631\u064a \u0647\u0631 \u0628\u062e\u0642\u0648.", "%(errorCount)s \u062b\u0642\u0642\u062e\u0642\u0633 \u0628\u062e\u0639\u0631\u064a \u0647\u0631 \u0628\u062e\u0642\u0648." @@ -80,6 +83,7 @@ "%s from now": "%s \u0628\u0642\u062e\u0648 \u0631\u062e\u0635", "(Add signatories for a certificate)": "(\u0634\u064a\u064a \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u0647\u062b\u0633 \u0628\u062e\u0642 \u0634 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b)", "(Caption will be displayed when you start playing the video.)": "(\u0630\u0634\u062d\u0641\u0647\u062e\u0631 \u0635\u0647\u0645\u0645 \u0632\u062b \u064a\u0647\u0633\u062d\u0645\u0634\u063a\u062b\u064a \u0635\u0627\u062b\u0631 \u063a\u062e\u0639 \u0633\u0641\u0634\u0642\u0641 \u062d\u0645\u0634\u063a\u0647\u0631\u0644 \u0641\u0627\u062b \u062f\u0647\u064a\u062b\u062e.)", + "(Community TA)": "(\u0630\u062e\u0648\u0648\u0639\u0631\u0647\u0641\u063a \u0641\u0634)", "(Optional)": "(\u062e\u062d\u0641\u0647\u062e\u0631\u0634\u0645)", "(Read-only)": "(\u0642\u062b\u0634\u064a-\u062e\u0631\u0645\u063a)", "(Required Field)": "(\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a \u0628\u0647\u062b\u0645\u064a)", @@ -87,6 +91,7 @@ "(Self-paced) Ends {end}": "(\u0633\u062b\u0645\u0628-\u062d\u0634\u0630\u062b\u064a) \u062b\u0631\u064a\u0633 {end}", "(Self-paced) Started {start}": "(\u0633\u062b\u0645\u0628-\u062d\u0634\u0630\u062b\u064a) \u0633\u0641\u0634\u0642\u0641\u062b\u064a {start}", "(Self-paced) Starts {start}": "(\u0633\u062b\u0645\u0628-\u062d\u0634\u0630\u062b\u064a) \u0633\u0641\u0634\u0642\u0641\u0633 {start}", + "(Staff)": "(\u0633\u0641\u0634\u0628\u0628)", "(contains %(student_count)s student)": [ "(\u0630\u062e\u0631\u0641\u0634\u0647\u0631\u0633 %(student_count)s \u0633\u0641\u0639\u064a\u062b\u0631\u0641)", "(\u0630\u062e\u0631\u0641\u0634\u0647\u0631\u0633 %(student_count)s \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633)" @@ -145,7 +150,12 @@ "Add URLs for additional versions": "\u0634\u064a\u064a \u0639\u0642\u0645\u0633 \u0628\u062e\u0642 \u0634\u064a\u064a\u0647\u0641\u0647\u062e\u0631\u0634\u0645 \u062f\u062b\u0642\u0633\u0647\u062e\u0631\u0633", "Add a Chapter": "\u0634\u064a\u064a \u0634 \u0630\u0627\u0634\u062d\u0641\u062b\u0642", "Add a New Cohort": "\u0634\u064a\u064a \u0634 \u0631\u062b\u0635 \u0630\u062e\u0627\u062e\u0642\u0641", + "Add a Post": "\u0634\u064a\u064a \u0634 \u062d\u062e\u0633\u0641", + "Add a Response": "\u0634\u064a\u064a \u0634 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b", + "Add a clear and descriptive title to encourage participation. (Required)": "\u0634\u064a\u064a \u0634 \u0630\u0645\u062b\u0634\u0642 \u0634\u0631\u064a \u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062f\u062b \u0641\u0647\u0641\u0645\u062b \u0641\u062e \u062b\u0631\u0630\u062e\u0639\u0642\u0634\u0644\u062b \u062d\u0634\u0642\u0641\u0647\u0630\u0647\u062d\u0634\u0641\u0647\u062e\u0631. (\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a)", + "Add a comment": "\u0634\u064a\u064a \u0634 \u0630\u062e\u0648\u0648\u062b\u0631\u0641", "Add a learning outcome here": "\u0634\u064a\u064a \u0634 \u0645\u062b\u0634\u0642\u0631\u0647\u0631\u0644 \u062e\u0639\u0641\u0630\u062e\u0648\u062b \u0627\u062b\u0642\u062b", + "Add a response:": "\u0634\u064a\u064a \u0634 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b:", "Add another group": "\u0634\u064a\u064a \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u0644\u0642\u062e\u0639\u062d", "Add language": "\u0634\u064a\u064a \u0645\u0634\u0631\u0644\u0639\u0634\u0644\u062b", "Add learners to this cohort": "\u0634\u064a\u064a \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0641\u062e \u0641\u0627\u0647\u0633 \u0630\u062e\u0627\u062e\u0642\u0641", @@ -155,6 +165,7 @@ "Add your first content group": "\u0634\u064a\u064a \u063a\u062e\u0639\u0642 \u0628\u0647\u0642\u0633\u0641 \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0644\u0642\u062e\u0639\u062d", "Add your first group configuration": "\u0634\u064a\u064a \u063a\u062e\u0639\u0642 \u0628\u0647\u0642\u0633\u0641 \u0644\u0642\u062e\u0639\u062d \u0630\u062e\u0631\u0628\u0647\u0644\u0639\u0642\u0634\u0641\u0647\u062e\u0631", "Add your first textbook": "\u0634\u064a\u064a \u063a\u062e\u0639\u0642 \u0628\u0647\u0642\u0633\u0641 \u0641\u062b\u0637\u0641\u0632\u062e\u062e\u0646", + "Add your post to a relevant topic to help others find it. (Required)": "\u0634\u064a\u064a \u063a\u062e\u0639\u0642 \u062d\u062e\u0633\u0641 \u0641\u062e \u0634 \u0642\u062b\u0645\u062b\u062f\u0634\u0631\u0641 \u0641\u062e\u062d\u0647\u0630 \u0641\u062e \u0627\u062b\u0645\u062d \u062e\u0641\u0627\u062b\u0642\u0633 \u0628\u0647\u0631\u064a \u0647\u0641. (\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a)", "Add {role} Access": "\u0634\u064a\u064a {role} \u0634\u0630\u0630\u062b\u0633\u0633", "Adding": "\u0634\u064a\u064a\u0647\u0631\u0644", "Adding the selected course to your cart": "\u0634\u064a\u064a\u0647\u0631\u0644 \u0641\u0627\u062b \u0633\u062b\u0645\u062b\u0630\u0641\u062b\u064a \u0630\u062e\u0639\u0642\u0633\u062b \u0641\u062e \u063a\u062e\u0639\u0642 \u0630\u0634\u0642\u0641", @@ -173,6 +184,7 @@ "Align left": "\u0634\u0645\u0647\u0644\u0631 \u0645\u062b\u0628\u0641", "Align right": "\u0634\u0645\u0647\u0644\u0631 \u0642\u0647\u0644\u0627\u0641", "Alignment": "\u0634\u0645\u0647\u0644\u0631\u0648\u062b\u0631\u0641", + "All Groups": "\u0634\u0645\u0645 \u0644\u0642\u062e\u0639\u062d\u0633", "All Learners and Staff": "\u0634\u0645\u0645 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0634\u0631\u064a \u0633\u0641\u0634\u0628\u0628", "All Posts": "\u0634\u0645\u0645 \u062d\u062e\u0633\u0641\u0633", "All Rights Reserved": "\u0634\u0645\u0645 \u0642\u0647\u0644\u0627\u0641\u0633 \u0642\u062b\u0633\u062b\u0642\u062f\u062b\u064a", @@ -254,6 +266,7 @@ "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "\u0634\u0642\u062b \u063a\u062e\u0639 \u0633\u0639\u0642\u062b \u063a\u062e\u0639 \u0635\u0647\u0633\u0627 \u0641\u062e \u064a\u062b\u0645\u062b\u0641\u062b \u0641\u0627\u0647\u0633 \u0647\u0641\u062b\u0648. \u0647\u0641 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0642\u062b\u062f\u062b\u0642\u0633\u062b\u064a!\n\n\u0634\u0645\u0633\u062e \u0634\u0631\u063a \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0641\u0627\u0634\u0641 \u0645\u0647\u0631\u0646\u0633/\u0642\u062b\u0628\u062b\u0642\u0633 \u0641\u062e \u0641\u0627\u0647\u0633 \u0647\u0641\u062b\u0648 \u0635\u0647\u0645\u0645 \u0631\u062e \u0645\u062e\u0631\u0644\u062b\u0642 \u0635\u062e\u0642\u0646 (\u062b.\u0644. \u0632\u0642\u062e\u0646\u062b\u0631 \u0647\u0648\u0634\u0644\u062b\u0633 \u0634\u0631\u064a/\u062e\u0642 \u0645\u0647\u0631\u0646\u0633)", "Are you sure?": "\u0634\u0642\u062b \u063a\u062e\u0639 \u0633\u0639\u0642\u062b?", "As part of the verification process, you take a photo of both your face and a government-issued photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u0634\u0633 \u062d\u0634\u0642\u0641 \u062e\u0628 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633, \u063a\u062e\u0639 \u0641\u0634\u0646\u062b \u0634 \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u0632\u062e\u0641\u0627 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b \u0634\u0631\u064a \u0634 \u0644\u062e\u062f\u062b\u0642\u0631\u0648\u062b\u0631\u0641-\u0647\u0633\u0633\u0639\u062b\u064a \u062d\u0627\u062e\u0641\u062e \u0647\u064a. \u062e\u0639\u0642 \u0634\u0639\u0641\u0627\u062e\u0642\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0633\u062b\u0642\u062f\u0647\u0630\u062b \u0630\u062e\u0631\u0628\u0647\u0642\u0648\u0633 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0632\u063a \u0630\u062e\u0648\u062d\u0634\u0642\u0647\u0631\u0644 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u063a\u062e\u0639 \u0641\u0634\u0646\u062b \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0631 \u063a\u062e\u0639\u0642 \u0647\u064a.", + "As part of the verification process, you take a photo of both your face and a photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u0634\u0633 \u062d\u0634\u0642\u0641 \u062e\u0628 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633, \u063a\u062e\u0639 \u0641\u0634\u0646\u062b \u0634 \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u0632\u062e\u0641\u0627 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b \u0634\u0631\u064a \u0634 \u062d\u0627\u062e\u0641\u062e \u0647\u064a. \u062e\u0639\u0642 \u0634\u0639\u0641\u0627\u062e\u0642\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0633\u062b\u0642\u062f\u0647\u0630\u062b \u0630\u062e\u0631\u0628\u0647\u0642\u0648\u0633 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0632\u063a \u0630\u062e\u0648\u062d\u0634\u0642\u0647\u0631\u0644 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u063a\u062e\u0639 \u0641\u0634\u0646\u062b \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0631 \u063a\u062e\u0639\u0642 \u0647\u064a.", "As you complete courses, you will see them listed here.": "\u0634\u0633 \u063a\u062e\u0639 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0630\u062e\u0639\u0642\u0633\u062b\u0633, \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0633\u062b\u062b \u0641\u0627\u062b\u0648 \u0645\u0647\u0633\u0641\u062b\u064a \u0627\u062b\u0642\u062b.", "Assessment Results Visibility": "\u0634\u0633\u0633\u062b\u0633\u0633\u0648\u062b\u0631\u0641 \u0642\u062b\u0633\u0639\u0645\u0641\u0633 \u062f\u0647\u0633\u0647\u0632\u0647\u0645\u0647\u0641\u063a", "Assign Team Memberships": "\u0634\u0633\u0633\u0647\u0644\u0631 \u0641\u062b\u0634\u0648 \u0648\u062b\u0648\u0632\u062b\u0642\u0633\u0627\u0647\u062d\u0633", @@ -381,6 +394,7 @@ "Click to edit": "\u0630\u0645\u0647\u0630\u0646 \u0641\u062e \u062b\u064a\u0647\u0641", "Close": "\u0630\u0645\u062e\u0633\u062b", "Close Calculator": "\u0630\u0645\u062e\u0633\u062b \u0630\u0634\u0645\u0630\u0639\u0645\u0634\u0641\u062e\u0642", + "Closed": "\u0630\u0645\u062e\u0633\u062b\u064a", "Code": "\u0630\u062e\u064a\u062b", "Code Sample (Ctrl+K)": "\u0630\u062e\u064a\u062b \u0633\u0634\u0648\u062d\u0645\u062b (\u0630\u0641\u0642\u0645+\u0646)", "Code block": "\u0630\u062e\u064a\u062b \u0632\u0645\u062e\u0630\u0646", @@ -399,6 +413,7 @@ "Coming Soon": "\u0630\u062e\u0648\u0647\u0631\u0644 \u0633\u062e\u062e\u0631", "Commentary": "\u0630\u062e\u0648\u0648\u062b\u0631\u0641\u0634\u0642\u063a", "Common Problem Types": "\u0630\u062e\u0648\u0648\u062e\u0631 \u062d\u0642\u062e\u0632\u0645\u062b\u0648 \u0641\u063a\u062d\u062b\u0633", + "Community TA": "\u0630\u062e\u0648\u0648\u0639\u0631\u0647\u0641\u063a \u0641\u0634", "Complete courses on your schedule to ensure you stand out in your field!": "\u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0630\u062e\u0639\u0642\u0633\u062b\u0633 \u062e\u0631 \u063a\u062e\u0639\u0642 \u0633\u0630\u0627\u062b\u064a\u0639\u0645\u062b \u0641\u062e \u062b\u0631\u0633\u0639\u0642\u062b \u063a\u062e\u0639 \u0633\u0641\u0634\u0631\u064a \u062e\u0639\u0641 \u0647\u0631 \u063a\u062e\u0639\u0642 \u0628\u0647\u062b\u0645\u064a!", "Completed": "\u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b\u064a", "Component": "\u0630\u062e\u0648\u062d\u062e\u0631\u062b\u0631\u0641", @@ -445,6 +460,7 @@ ], "Course Content": "\u0630\u062e\u0639\u0642\u0633\u062b \u0630\u062e\u0631\u0641\u062b\u0631\u0641", "Course Credit Requirements": "\u0630\u062e\u0639\u0642\u0633\u062b \u0630\u0642\u062b\u064a\u0647\u0641 \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0648\u062b\u0631\u0641\u0633", + "Course Discussion Forum": "\u0630\u062e\u0639\u0642\u0633\u062b \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0628\u062e\u0642\u0639\u0648", "Course End": "\u0630\u062e\u0639\u0642\u0633\u062b \u062b\u0631\u064a", "Course Handouts": "\u0630\u062e\u0639\u0642\u0633\u062b \u0627\u0634\u0631\u064a\u062e\u0639\u0641\u0633", "Course ID": "\u0630\u062e\u0639\u0642\u0633\u062b \u0647\u064a", @@ -467,6 +483,7 @@ "Create": "\u0630\u0642\u062b\u0634\u0641\u062b", "Create Account": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Create Re-run": "\u0630\u0642\u062b\u0634\u0641\u062b \u0642\u062b-\u0642\u0639\u0631", + "Create Support Ticket": "\u0630\u0642\u062b\u0634\u0641\u062b \u0633\u0639\u062d\u062d\u062e\u0642\u0641 \u0641\u0647\u0630\u0646\u062b\u0641", "Create a New Team": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634 \u0631\u062b\u0635 \u0641\u062b\u0634\u0648", "Create a content group": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634 \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0644\u0642\u062e\u0639\u062d", "Create a new team if you can't find an existing team to join, or if you would like to learn with friends you know.": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634 \u0631\u062b\u0635 \u0641\u062b\u0634\u0648 \u0647\u0628 \u063a\u062e\u0639 \u0630\u0634\u0631'\u0641 \u0628\u0647\u0631\u064a \u0634\u0631 \u062b\u0637\u0647\u0633\u0641\u0647\u0631\u0644 \u0641\u062b\u0634\u0648 \u0641\u062e \u062a\u062e\u0647\u0631, \u062e\u0642 \u0647\u0628 \u063a\u062e\u0639 \u0635\u062e\u0639\u0645\u064a \u0645\u0647\u0646\u062b \u0641\u062e \u0645\u062b\u0634\u0642\u0631 \u0635\u0647\u0641\u0627 \u0628\u0642\u0647\u062b\u0631\u064a\u0633 \u063a\u062e\u0639 \u0646\u0631\u062e\u0635.", @@ -474,6 +491,7 @@ "Create account using %(providerName)s.": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0639\u0633\u0647\u0631\u0644 %(providerName)s.", "Create an Account": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0631 \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Create an Account.": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0631 \u0634\u0630\u0630\u062e\u0639\u0631\u0641.", + "Create an account": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0631 \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Create an account using": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0631 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0639\u0633\u0647\u0631\u0644", "Create team.": "\u0630\u0642\u062b\u0634\u0641\u062b \u0641\u062b\u0634\u0648.", "Creating missing groups": "\u0630\u0642\u062b\u0634\u0641\u0647\u0631\u0644 \u0648\u0647\u0633\u0633\u0647\u0631\u0644 \u0644\u0642\u062e\u0639\u062d\u0633", @@ -496,13 +514,14 @@ "Date Placed": "\u064a\u0634\u0641\u062b \u062d\u0645\u0634\u0630\u062b\u064a", "Date added": "\u064a\u0634\u0641\u062b \u0634\u064a\u064a\u062b\u064a", "Deactivate": "\u064a\u062b\u0634\u0630\u0641\u0647\u062f\u0634\u0641\u062b", + "Deactivating": "\u064a\u062b\u0634\u0630\u0641\u0647\u062f\u0634\u0641\u0647\u0631\u0644", "Deadlines": "\u064a\u062b\u0634\u064a\u0645\u0647\u0631\u062b\u0633", "Decrease indent": "\u064a\u062b\u0630\u0642\u062b\u0634\u0633\u062b \u0647\u0631\u064a\u062b\u0631\u0641", "Default": "\u064a\u062b\u0628\u0634\u0639\u0645\u0641", "Default (Local Time Zone)": "\u064a\u062b\u0628\u0634\u0639\u0645\u0641 (\u0645\u062e\u0630\u0634\u0645 \u0641\u0647\u0648\u062b \u0638\u062e\u0631\u062b)", "Default Timed Transcript": "\u064a\u062b\u0628\u0634\u0639\u0645\u0641 \u0641\u0647\u0648\u062b\u064a \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641", "Delete": "\u064a\u062b\u0645\u062b\u0641\u062b", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u064a\u062b\u0645\u062b\u0641\u062b \"<%= signatoryName %>\" \u0628\u0642\u062e\u0648 \u0641\u0627\u062b \u0645\u0647\u0633\u0641 \u062e\u0628 \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u0647\u062b\u0633?", + "Delete \"<%- signatoryName %>\" from the list of signatories?": "\u064a\u062b\u0645\u062b\u0641\u062b \"<%- signatoryName %>\" \u0628\u0642\u062e\u0648 \u0641\u0627\u062b \u0645\u0647\u0633\u0641 \u062e\u0628 \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u0647\u062b\u0633?", "Delete File Confirmation": "\u064a\u062b\u0645\u062b\u0641\u062b \u0628\u0647\u0645\u062b \u0630\u062e\u0631\u0628\u0647\u0642\u0648\u0634\u0641\u0647\u062e\u0631", "Delete My Account": "\u064a\u062b\u0645\u062b\u0641\u062b \u0648\u063a \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Delete Page Confirmation": "\u064a\u062b\u0645\u062b\u0641\u062b \u062d\u0634\u0644\u062b \u0630\u062e\u0631\u0628\u0647\u0642\u0648\u0634\u0641\u0647\u062e\u0631", @@ -529,11 +548,14 @@ "Description": "\u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631", "Description of the certificate": "\u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631 \u062e\u0628 \u0641\u0627\u062b \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b", "Details": "\u064a\u062b\u0641\u0634\u0647\u0645\u0633", + "Device with Camera": "\u064a\u062b\u062f\u0647\u0630\u062b \u0635\u0647\u0641\u0627 \u0630\u0634\u0648\u062b\u0642\u0634", "Dimensions": "\u064a\u0647\u0648\u062b\u0631\u0633\u0647\u062e\u0631\u0633", "Disc": "\u064a\u0647\u0633\u0630", "Discard Changes": "\u064a\u0647\u0633\u0630\u0634\u0642\u064a \u0630\u0627\u0634\u0631\u0644\u062b\u0633", "Discarding Changes": "\u064a\u0647\u0633\u0630\u0634\u0642\u064a\u0647\u0631\u0644 \u0630\u0627\u0634\u0631\u0644\u062b\u0633", + "Discussion": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631", "Discussion Home": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0627\u062e\u0648\u062b", + "Discussion admins, moderators, and TAs can make their posts visible to all students or specify a single group.": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0634\u064a\u0648\u0647\u0631\u0633, \u0648\u062e\u064a\u062b\u0642\u0634\u0641\u062e\u0642\u0633, \u0634\u0631\u064a \u0641\u0634\u0633 \u0630\u0634\u0631 \u0648\u0634\u0646\u062b \u0641\u0627\u062b\u0647\u0642 \u062d\u062e\u0633\u0641\u0633 \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u0634\u0645\u0645 \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633 \u062e\u0642 \u0633\u062d\u062b\u0630\u0647\u0628\u063a \u0634 \u0633\u0647\u0631\u0644\u0645\u062b \u0644\u0642\u062e\u0639\u062d.", "Discussion topics in the course are not divided.": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0641\u062e\u062d\u0647\u0630\u0633 \u0647\u0631 \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0634\u0642\u062b \u0631\u062e\u0641 \u064a\u0647\u062f\u0647\u064a\u062b\u064a.", "Discussions are unified; all learners interact with posts from other learners, regardless of the group they are in.": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631\u0633 \u0634\u0642\u062b \u0639\u0631\u0647\u0628\u0647\u062b\u064a; \u0634\u0645\u0645 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0647\u0631\u0641\u062b\u0642\u0634\u0630\u0641 \u0635\u0647\u0641\u0627 \u062d\u062e\u0633\u0641\u0633 \u0628\u0642\u062e\u0648 \u062e\u0641\u0627\u062b\u0642 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633, \u0642\u062b\u0644\u0634\u0642\u064a\u0645\u062b\u0633\u0633 \u062e\u0628 \u0641\u0627\u062b \u0644\u0642\u062e\u0639\u062d \u0641\u0627\u062b\u063a \u0634\u0642\u062b \u0647\u0631.", "Display Name": "\u064a\u0647\u0633\u062d\u0645\u0634\u063a \u0631\u0634\u0648\u062b", @@ -545,7 +567,6 @@ "Do you want to replace the edX transcript with the YouTube transcript?": "\u064a\u062e \u063a\u062e\u0639 \u0635\u0634\u0631\u0641 \u0641\u062e \u0642\u062b\u062d\u0645\u0634\u0630\u062b \u0641\u0627\u062b \u062b\u064a\u0637 \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641 \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u063a\u062e\u0639\u0641\u0639\u0632\u062b \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641?", "Document properties": "\u064a\u062e\u0630\u0639\u0648\u062b\u0631\u0641 \u062d\u0642\u062e\u062d\u062b\u0642\u0641\u0647\u062b\u0633", "Does the name on your ID match your account name: %(fullName)s?": "\u064a\u062e\u062b\u0633 \u0641\u0627\u062b \u0631\u0634\u0648\u062b \u062e\u0631 \u063a\u062e\u0639\u0642 \u0647\u064a \u0648\u0634\u0641\u0630\u0627 \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0631\u0634\u0648\u062b: %(fullName)s?", - "Does the photo of you match your ID photo?": "\u064a\u062e\u062b\u0633 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639 \u0648\u0634\u0641\u0630\u0627 \u063a\u062e\u0639\u0642 \u0647\u064a \u062d\u0627\u062e\u0641\u062e?", "Does the photo of you show your whole face?": "\u064a\u062e\u062b\u0633 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639 \u0633\u0627\u062e\u0635 \u063a\u062e\u0639\u0642 \u0635\u0627\u062e\u0645\u062b \u0628\u0634\u0630\u062b?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u064a\u062e\u0631'\u0641 \u0633\u062b\u062b \u063a\u062e\u0639\u0642 \u062d\u0647\u0630\u0641\u0639\u0642\u062b? \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u062e \u0634\u0645\u0645\u062e\u0635 \u063a\u062e\u0639\u0642 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u0641\u062e \u0639\u0633\u062b \u063a\u062e\u0639\u0642 \u0630\u0634\u0648\u062b\u0642\u0634 \u0635\u0627\u062b\u0631 \u0647\u0641 \u0634\u0633\u0646\u0633 \u0628\u062e\u0642 \u062d\u062b\u0642\u0648\u0647\u0633\u0633\u0647\u062e\u0631.", "Donate": "\u064a\u062e\u0631\u0634\u0641\u062b", @@ -566,6 +587,7 @@ "Due Date:": "\u064a\u0639\u062b \u064a\u0634\u0641\u062b:", "Due Time in UTC:": "\u064a\u0639\u062b \u0641\u0647\u0648\u062b \u0647\u0631 \u0639\u0641\u0630:", "Due date cannot be before start date.": "\u064a\u0639\u062b \u064a\u0634\u0641\u062b \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0632\u062b\u0628\u062e\u0642\u062b \u0633\u0641\u0634\u0642\u0641 \u064a\u0634\u0641\u062b.", + "Due to the recent increase in interest in online education and edX, we are currently experiencing an unusually high volume of support requests. We appreciate your patience as we work to review each request. Please check the ": "\u064a\u0639\u062b \u0641\u062e \u0641\u0627\u062b \u0642\u062b\u0630\u062b\u0631\u0641 \u0647\u0631\u0630\u0642\u062b\u0634\u0633\u062b \u0647\u0631 \u0647\u0631\u0641\u062b\u0642\u062b\u0633\u0641 \u0647\u0631 \u062e\u0631\u0645\u0647\u0631\u062b \u062b\u064a\u0639\u0630\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u062b\u064a\u0637, \u0635\u062b \u0634\u0642\u062b \u0630\u0639\u0642\u0642\u062b\u0631\u0641\u0645\u063a \u062b\u0637\u062d\u062b\u0642\u0647\u062b\u0631\u0630\u0647\u0631\u0644 \u0634\u0631 \u0639\u0631\u0639\u0633\u0639\u0634\u0645\u0645\u063a \u0627\u0647\u0644\u0627 \u062f\u062e\u0645\u0639\u0648\u062b \u062e\u0628 \u0633\u0639\u062d\u062d\u062e\u0642\u0641 \u0642\u062b\u0636\u0639\u062b\u0633\u0641\u0633. \u0635\u062b \u0634\u062d\u062d\u0642\u062b\u0630\u0647\u0634\u0641\u062b \u063a\u062e\u0639\u0642 \u062d\u0634\u0641\u0647\u062b\u0631\u0630\u062b \u0634\u0633 \u0635\u062b \u0635\u062e\u0642\u0646 \u0641\u062e \u0642\u062b\u062f\u0647\u062b\u0635 \u062b\u0634\u0630\u0627 \u0642\u062b\u0636\u0639\u062b\u0633\u0641. \u062d\u0645\u062b\u0634\u0633\u062b \u0630\u0627\u062b\u0630\u0646 \u0641\u0627\u062b ", "Due:": "\u064a\u0639\u062b:", "Duplicate": "\u064a\u0639\u062d\u0645\u0647\u0630\u0634\u0641\u062b", "Duplicating": "\u064a\u0639\u062d\u0645\u0647\u0630\u0634\u0641\u0647\u0631\u0644", @@ -585,8 +607,12 @@ "Edit Title": "\u062b\u064a\u0647\u0641 \u0641\u0647\u0641\u0645\u062b", "Edit Your Name": "\u062b\u064a\u0647\u0641 \u063a\u062e\u0639\u0642 \u0631\u0634\u0648\u062b", "Edit this certificate?": "\u062b\u064a\u0647\u0641 \u0641\u0627\u0647\u0633 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b?", + "Edit your post below.": "\u062b\u064a\u0647\u0641 \u063a\u062e\u0639\u0642 \u062d\u062e\u0633\u0641 \u0632\u062b\u0645\u062e\u0635.", "Editable": "\u062b\u064a\u0647\u0641\u0634\u0632\u0645\u062b", "Editing access for: {title}": "\u062b\u064a\u0647\u0641\u0647\u0631\u0644 \u0634\u0630\u0630\u062b\u0633\u0633 \u0628\u062e\u0642: {title}", + "Editing comment": "\u062b\u064a\u0647\u0641\u0647\u0631\u0644 \u0630\u062e\u0648\u0648\u062b\u0631\u0641", + "Editing post": "\u062b\u064a\u0647\u0641\u0647\u0631\u0644 \u062d\u062e\u0633\u0641", + "Editing response": "\u062b\u064a\u0647\u0641\u0647\u0631\u0644 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b", "Editing: {title}": "\u062b\u064a\u0647\u0641\u0647\u0631\u0644: {title}", "Editor": "\u062b\u064a\u0647\u0641\u062e\u0642", "Education Completed": "\u062b\u064a\u0639\u0630\u0634\u0641\u0647\u062e\u0631 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b\u064a", @@ -604,6 +630,7 @@ "Encoding": "\u062b\u0631\u0630\u062e\u064a\u0647\u0631\u0644", "End My Exam": "\u062b\u0631\u064a \u0648\u063a \u062b\u0637\u0634\u0648", "End of transcript. Skip to the start.": "\u062b\u0631\u064a \u062e\u0628 \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641. \u0633\u0646\u0647\u062d \u0641\u062e \u0641\u0627\u062b \u0633\u0641\u0634\u0642\u0641.", + "Endorse": "\u062b\u0631\u064a\u062e\u0642\u0633\u062b", "Ends {end}": "\u062b\u0631\u064a\u0633 {end}", "Engage with posts": "\u062b\u0631\u0644\u0634\u0644\u062b \u0635\u0647\u0641\u0627 \u062d\u062e\u0633\u0641\u0633", "Enroll Now": "\u062b\u0631\u0642\u062e\u0645\u0645 \u0631\u062e\u0635", @@ -658,6 +685,7 @@ "Error getting task history for problem '<%- problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "\u062b\u0642\u0642\u062e\u0642 \u0644\u062b\u0641\u0641\u0647\u0631\u0644 \u0641\u0634\u0633\u0646 \u0627\u0647\u0633\u0641\u062e\u0642\u063a \u0628\u062e\u0642 \u062d\u0642\u062e\u0632\u0645\u062b\u0648 '<%- problem_id %>' \u0634\u0631\u064a \u0633\u0641\u0639\u064a\u062b\u0631\u0641 '<%- student_id %>'. \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u0627\u0634\u0641 \u0641\u0627\u062b \u062d\u0642\u062e\u0632\u0645\u062b\u0648 \u0634\u0631\u064a \u0633\u0641\u0639\u064a\u062b\u0631\u0641 \u0647\u064a\u062b\u0631\u0641\u0647\u0628\u0647\u062b\u0642\u0633 \u0634\u0642\u062b \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0634\u0631\u064a \u0630\u062e\u0642\u0642\u062b\u0630\u0641.", "Error importing course": "\u062b\u0642\u0642\u062e\u0642 \u0647\u0648\u062d\u062e\u0642\u0641\u0647\u0631\u0644 \u0630\u062e\u0639\u0642\u0633\u062b", "Error listing task history for this student and problem.": "\u062b\u0642\u0642\u062e\u0642 \u0645\u0647\u0633\u0641\u0647\u0631\u0644 \u0641\u0634\u0633\u0646 \u0627\u0647\u0633\u0641\u062e\u0642\u063a \u0628\u062e\u0642 \u0641\u0627\u0647\u0633 \u0633\u0641\u0639\u064a\u062b\u0631\u0641 \u0634\u0631\u064a \u062d\u0642\u062e\u0632\u0645\u062b\u0648.", + "Error posting your message.": "\u062b\u0642\u0642\u062e\u0642 \u062d\u062e\u0633\u0641\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u0648\u062b\u0633\u0633\u0634\u0644\u062b.", "Error removing user": "\u062b\u0642\u0642\u062e\u0642 \u0642\u062b\u0648\u062e\u062f\u0647\u0631\u0644 \u0639\u0633\u062b\u0642", "Error resetting entrance exam attempts for student '{student_id}'. Make sure student identifier is correct.": "\u062b\u0642\u0642\u062e\u0642 \u0642\u062b\u0633\u062b\u0641\u0641\u0647\u0631\u0644 \u062b\u0631\u0641\u0642\u0634\u0631\u0630\u062b \u062b\u0637\u0634\u0648 \u0634\u0641\u0641\u062b\u0648\u062d\u0641\u0633 \u0628\u062e\u0642 \u0633\u0641\u0639\u064a\u062b\u0631\u0641 '{student_id}'. \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0633\u0641\u0639\u064a\u062b\u0631\u0641 \u0647\u064a\u062b\u0631\u0641\u0647\u0628\u0647\u062b\u0642 \u0647\u0633 \u0630\u062e\u0642\u0642\u062b\u0630\u0641.", "Error resetting problem attempts for problem '<%= problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "\u062b\u0642\u0642\u062e\u0642 \u0642\u062b\u0633\u062b\u0641\u0641\u0647\u0631\u0644 \u062d\u0642\u062e\u0632\u0645\u062b\u0648 \u0634\u0641\u0641\u062b\u0648\u062d\u0641\u0633 \u0628\u062e\u0642 \u062d\u0642\u062e\u0632\u0645\u062b\u0648 '<%= problem_id %>' \u0634\u0631\u064a \u0633\u0641\u0639\u064a\u062b\u0631\u0641 '<%- student_id %>'. \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u0627\u0634\u0641 \u0641\u0627\u062b \u062d\u0642\u062e\u0632\u0645\u062b\u0648 \u0634\u0631\u064a \u0633\u0641\u0639\u064a\u062b\u0631\u0641 \u0647\u064a\u062b\u0631\u0641\u0647\u0628\u0647\u062b\u0642\u0633 \u0634\u0642\u062b \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0634\u0631\u064a \u0630\u062e\u0642\u0642\u062b\u0630\u0641.", @@ -709,7 +737,6 @@ "Files that you upload must be smaller than 5MB in size.": "\u0628\u0647\u0645\u062b\u0633 \u0641\u0627\u0634\u0641 \u063a\u062e\u0639 \u0639\u062d\u0645\u062e\u0634\u064a \u0648\u0639\u0633\u0641 \u0632\u062b \u0633\u0648\u0634\u0645\u0645\u062b\u0642 \u0641\u0627\u0634\u0631 5\u0648\u0632 \u0647\u0631 \u0633\u0647\u0638\u062b.", "Fill browser": "\u0628\u0647\u0645\u0645 \u0632\u0642\u062e\u0635\u0633\u062b\u0642", "Filter and sort topics": "\u0628\u0647\u0645\u0641\u062b\u0642 \u0634\u0631\u064a \u0633\u062e\u0642\u0641 \u0641\u062e\u062d\u0647\u0630\u0633", - "Final Grade": "\u0628\u0647\u0631\u0634\u0645 \u0644\u0642\u0634\u064a\u062b", "Financial Aid": "\u0628\u0647\u0631\u0634\u0631\u0630\u0647\u0634\u0645 \u0634\u0647\u064a", "Financial Assistance": "\u0628\u0647\u0631\u0634\u0631\u0630\u0647\u0634\u0645 \u0634\u0633\u0633\u0647\u0633\u0641\u0634\u0631\u0630\u062b", "Financial Assistance Application": "\u0628\u0647\u0631\u0634\u0631\u0630\u0647\u0634\u0645 \u0634\u0633\u0633\u0647\u0633\u0641\u0634\u0631\u0630\u062b \u0634\u062d\u062d\u0645\u0647\u0630\u0634\u0641\u0647\u062e\u0631", @@ -722,12 +749,15 @@ "Find previous": "\u0628\u0647\u0631\u064a \u062d\u0642\u062b\u062f\u0647\u062e\u0639\u0633", "Finish": "\u0628\u0647\u0631\u0647\u0633\u0627", "First time here?": "\u0628\u0647\u0642\u0633\u0641 \u0641\u0647\u0648\u062b \u0627\u062b\u0642\u062b?", + "Follow": "\u0628\u062e\u0645\u0645\u062e\u0635", "Follow or unfollow posts": "\u0628\u062e\u0645\u0645\u062e\u0635 \u062e\u0642 \u0639\u0631\u0628\u062e\u0645\u0645\u062e\u0635 \u062d\u062e\u0633\u0641\u0633", + "Following": "\u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644", "Font Family": "\u0628\u062e\u0631\u0641 \u0628\u0634\u0648\u0647\u0645\u063a", "Font Sizes": "\u0628\u062e\u0631\u0641 \u0633\u0647\u0638\u062b\u0633", "Footer": "\u0628\u062e\u062e\u0641\u062b\u0642", "For grading to work, you must change all {oldName} subsections to {newName}.": "\u0628\u062e\u0642 \u0644\u0642\u0634\u064a\u0647\u0631\u0644 \u0641\u062e \u0635\u062e\u0642\u0646, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0630\u0627\u0634\u0631\u0644\u062b \u0634\u0645\u0645 {oldName} \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631\u0633 \u0641\u062e {newName}.", "For inquiries regarding assignments, grades, or structure of a specific course, please post in the discussion forums for that course directly.": "\u0628\u062e\u0642 \u0647\u0631\u0636\u0639\u0647\u0642\u0647\u062b\u0633 \u0642\u062b\u0644\u0634\u0642\u064a\u0647\u0631\u0644 \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641\u0633, \u0644\u0642\u0634\u064a\u062b\u0633, \u062e\u0642 \u0633\u0641\u0642\u0639\u0630\u0641\u0639\u0642\u062b \u062e\u0628 \u0634 \u0633\u062d\u062b\u0630\u0647\u0628\u0647\u0630 \u0630\u062e\u0639\u0642\u0633\u062b, \u062d\u0645\u062b\u0634\u0633\u062b \u062d\u062e\u0633\u0641 \u0647\u0631 \u0641\u0627\u062b \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0628\u062e\u0642\u0639\u0648\u0633 \u0628\u062e\u0642 \u0641\u0627\u0634\u0641 \u0630\u062e\u0639\u0642\u0633\u062b \u064a\u0647\u0642\u062b\u0630\u0641\u0645\u063a.", + "Forgot my password": "\u0628\u062e\u0642\u0644\u062e\u0641 \u0648\u063a \u062d\u0634\u0633\u0633\u0635\u062e\u0642\u064a", "Format": "\u0628\u062e\u0642\u0648\u0634\u0641", "Formats": "\u0628\u062e\u0642\u0648\u0634\u0641\u0633", "Free text notes": "\u0628\u0642\u062b\u062b \u0641\u062b\u0637\u0641 \u0631\u062e\u0641\u062b\u0633", @@ -742,7 +772,6 @@ "Generate": "\u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b", "Generate Exception Certificates": "\u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b\u0633", "Generate the user's certificate": "\u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b \u0641\u0627\u062b \u0639\u0633\u062b\u0642'\u0633 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b", - "Get Credit": "\u0644\u062b\u0641 \u0630\u0642\u062b\u064a\u0647\u0641", "Go to Dashboard": "\u0644\u062e \u0641\u062e \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a", "Go to my Dashboard": "\u0644\u062e \u0641\u062e \u0648\u063a \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a", "Go to your Dashboard": "\u0644\u062e \u0641\u062e \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a", @@ -823,10 +852,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "\u0647\u0628 \u0641\u0627\u062b \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631 \u064a\u062e\u062b\u0633 \u0631\u062e\u0641 \u0627\u0634\u062f\u062b \u0634 \u064a\u0639\u062b \u064a\u0634\u0641\u062b, \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0634\u0645\u0635\u0634\u063a\u0633 \u0633\u062b\u062b \u0641\u0627\u062b\u0647\u0642 \u0633\u0630\u062e\u0642\u062b\u0633 \u0635\u0627\u062b\u0631 \u0641\u0627\u062b\u063a \u0633\u0639\u0632\u0648\u0647\u0641 \u0634\u0631\u0633\u0635\u062b\u0642\u0633 \u0641\u062e \u0634\u0633\u0633\u062b\u0633\u0633\u0648\u062b\u0631\u0641\u0633.", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u0647\u0628 \u0641\u0627\u062b \u0639\u0631\u0647\u0641 \u0635\u0634\u0633 \u062d\u0642\u062b\u062f\u0647\u062e\u0639\u0633\u0645\u063a \u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0634\u0631\u064a \u0642\u062b\u0645\u062b\u0634\u0633\u062b\u064a \u0641\u062e \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633, \u0634\u0631\u063a \u0630\u0627\u0634\u0631\u0644\u062b\u0633 \u063a\u062e\u0639 \u0648\u0634\u064a\u062b \u0641\u062e \u0641\u0627\u062b \u0639\u0631\u0647\u0641 \u0635\u0627\u062b\u0631 \u0647\u0641 \u0635\u0634\u0633 \u0627\u0647\u064a\u064a\u062b\u0631 \u0635\u0647\u0645\u0645 \u0631\u062e\u0635 \u0632\u062b \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633.", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "\u0647\u0628 \u0641\u0627\u062b \u0639\u0631\u0647\u0641 \u0635\u0634\u0633 \u062d\u0642\u062b\u062f\u0647\u062e\u0639\u0633\u0645\u063a \u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0634\u0631\u064a \u0642\u062b\u0645\u062b\u0634\u0633\u062b\u064a \u0641\u062e \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633, \u0634\u0631\u063a \u0630\u0627\u0634\u0631\u0644\u062b\u0633 \u063a\u062e\u0639 \u0648\u0634\u064a\u062b \u0641\u062e \u0641\u0627\u062b \u0639\u0631\u0647\u0641 \u0635\u0627\u062b\u0631 \u0647\u0641 \u0635\u0634\u0633 \u0627\u0647\u064a\u064a\u062b\u0631 \u0635\u0647\u0645\u0645 \u0631\u062e\u0635 \u0632\u062b \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633. \u064a\u062e \u063a\u062e\u0639 \u0635\u0634\u0631\u0641 \u0641\u062e \u062d\u0642\u062e\u0630\u062b\u062b\u064a?", - "If you are unable to access your account contact us via email using {email}.": "\u0647\u0628 \u063a\u062e\u0639 \u0634\u0642\u062b \u0639\u0631\u0634\u0632\u0645\u062b \u0641\u062e \u0634\u0630\u0630\u062b\u0633\u0633 \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0630\u062e\u0631\u0641\u0634\u0630\u0641 \u0639\u0633 \u062f\u0647\u0634 \u062b\u0648\u0634\u0647\u0645 \u0639\u0633\u0647\u0631\u0644 {email}.", "If you do not yet have an account, use the button below to register.": "\u0647\u0628 \u063a\u062e\u0639 \u064a\u062e \u0631\u062e\u0641 \u063a\u062b\u0641 \u0627\u0634\u062f\u062b \u0634\u0631 \u0634\u0630\u0630\u062e\u0639\u0631\u0641, \u0639\u0633\u062b \u0641\u0627\u062b \u0632\u0639\u0641\u0641\u062e\u0631 \u0632\u062b\u0645\u062e\u0635 \u0641\u062e \u0642\u062b\u0644\u0647\u0633\u0641\u062b\u0642.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u0647\u0628 \u063a\u062e\u0639 \u064a\u062e\u0631'\u0641 \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0631\u062e\u0635, \u063a\u062e\u0639 \u0630\u0634\u0631 \u0633\u0641\u0647\u0645\u0645 \u062b\u0637\u062d\u0645\u062e\u0642\u062b \u063a\u062e\u0639\u0642 \u0630\u062e\u0639\u0642\u0633\u062b \u0628\u0642\u062e\u0648 \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a. \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u062d\u062b\u0642\u0647\u062e\u064a\u0647\u0630 \u0642\u062b\u0648\u0647\u0631\u064a\u062b\u0642\u0633 \u0628\u0642\u062e\u0648 %(platformName)s \u0641\u062e \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u0647\u0628 \u063a\u062e\u0639 \u064a\u062e\u0631'\u0641 \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0631\u062e\u0635, \u063a\u062e\u0639 \u0630\u0634\u0631 \u0633\u0641\u0647\u0645\u0645 \u062b\u0637\u062d\u0645\u062e\u0642\u062b \u063a\u062e\u0639\u0642 \u0630\u062e\u0639\u0642\u0633\u062b \u0628\u0642\u062e\u0648 \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a. \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u062d\u062b\u0642\u0647\u062e\u064a\u0647\u0630 \u0642\u062b\u0648\u0647\u0631\u064a\u062b\u0642\u0633 \u0628\u0642\u062e\u0648 {platformName} \u0641\u062e \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a.", "If you leave, you can no longer post in this team's discussions.Your place will be available to another learner.": "\u0647\u0628 \u063a\u062e\u0639 \u0645\u062b\u0634\u062f\u062b, \u063a\u062e\u0639 \u0630\u0634\u0631 \u0631\u062e \u0645\u062e\u0631\u0644\u062b\u0642 \u062d\u062e\u0633\u0641 \u0647\u0631 \u0641\u0627\u0647\u0633 \u0641\u062b\u0634\u0648'\u0633 \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631\u0633.\u063a\u062e\u0639\u0642 \u062d\u0645\u0634\u0630\u062b \u0635\u0647\u0645\u0645 \u0632\u062b \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b \u0641\u062e \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u0645\u062b\u0634\u0642\u0631\u062b\u0642.", "If you make significant changes, make sure you notify members of the team before making these changes.": "\u0647\u0628 \u063a\u062e\u0639 \u0648\u0634\u0646\u062b \u0633\u0647\u0644\u0631\u0647\u0628\u0647\u0630\u0634\u0631\u0641 \u0630\u0627\u0634\u0631\u0644\u062b\u0633, \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u063a\u062e\u0639 \u0631\u062e\u0641\u0647\u0628\u063a \u0648\u062b\u0648\u0632\u062b\u0642\u0633 \u062e\u0628 \u0641\u0627\u062b \u0641\u062b\u0634\u0648 \u0632\u062b\u0628\u062e\u0642\u062b \u0648\u0634\u0646\u0647\u0631\u0644 \u0641\u0627\u062b\u0633\u062b \u0630\u0627\u0634\u0631\u0644\u062b\u0633.", "If you make this %(xblockType)s visible to learners, learners will be able to see its content after the release date has passed and you have published the unit. Only units that are explicitly hidden from learners will remain hidden after you clear this option for the %(xblockType)s.": "\u0647\u0628 \u063a\u062e\u0639 \u0648\u0634\u0646\u062b \u0641\u0627\u0647\u0633 %(xblockType)s \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633, \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0635\u0647\u0645\u0645 \u0632\u062b \u0634\u0632\u0645\u062b \u0641\u062e \u0633\u062b\u062b \u0647\u0641\u0633 \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0634\u0628\u0641\u062b\u0642 \u0641\u0627\u062b \u0642\u062b\u0645\u062b\u0634\u0633\u062b \u064a\u0634\u0641\u062b \u0627\u0634\u0633 \u062d\u0634\u0633\u0633\u062b\u064a \u0634\u0631\u064a \u063a\u062e\u0639 \u0627\u0634\u062f\u062b \u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0641\u0627\u062b \u0639\u0631\u0647\u0641. \u062e\u0631\u0645\u063a \u0639\u0631\u0647\u0641\u0633 \u0641\u0627\u0634\u0641 \u0634\u0642\u062b \u062b\u0637\u062d\u0645\u0647\u0630\u0647\u0641\u0645\u063a \u0627\u0647\u064a\u064a\u062b\u0631 \u0628\u0642\u062e\u0648 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0635\u0647\u0645\u0645 \u0642\u062b\u0648\u0634\u0647\u0631 \u0627\u0647\u064a\u064a\u062b\u0631 \u0634\u0628\u0641\u062b\u0642 \u063a\u062e\u0639 \u0630\u0645\u062b\u0634\u0642 \u0641\u0627\u0647\u0633 \u062e\u062d\u0641\u0647\u062e\u0631 \u0628\u062e\u0642 \u0641\u0627\u062b %(xblockType)s.", @@ -948,6 +975,7 @@ "Live view of webcam": "\u0645\u0647\u062f\u062b \u062f\u0647\u062b\u0635 \u062e\u0628 \u0635\u062b\u0632\u0630\u0634\u0648", "Load Another File": "\u0645\u062e\u0634\u064a \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u0628\u0647\u0645\u062b", "Load all responses": "\u0645\u062e\u0634\u064a \u0634\u0645\u0645 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b\u0633", + "Load more": "\u0645\u062e\u0634\u064a \u0648\u062e\u0642\u062b", "Load next {numResponses} responses": "\u0645\u062e\u0634\u064a \u0631\u062b\u0637\u0641 {numResponses} \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b\u0633", "Load next {num_items} result": [ "\u0645\u062e\u0634\u064a \u0631\u062b\u0637\u0641 {num_items} \u0642\u062b\u0633\u0639\u0645\u0641", @@ -980,6 +1008,7 @@ "Manage Learners": "\u0648\u0634\u0631\u0634\u0644\u062b \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633", "Manual": "\u0648\u0634\u0631\u0639\u0634\u0645", "Mark Exam As Completed": "\u0648\u0634\u0642\u0646 \u062b\u0637\u0634\u0648 \u0634\u0633 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b\u064a", + "Mark as Answer": "\u0648\u0634\u0642\u0646 \u0634\u0633 \u0634\u0631\u0633\u0635\u062b\u0642", "Mark enrollment code as unused": "\u0648\u0634\u0642\u0646 \u062b\u0631\u0642\u062e\u0645\u0645\u0648\u062b\u0631\u0641 \u0630\u062e\u064a\u062b \u0634\u0633 \u0639\u0631\u0639\u0633\u062b\u064a", "Markdown Editing Help": "\u0648\u0634\u0642\u0646\u064a\u062e\u0635\u0631 \u062b\u064a\u0647\u0641\u0647\u0631\u0644 \u0627\u062b\u0645\u062d", "Masters": "\u0648\u0634\u0633\u0641\u062b\u0642\u0633", @@ -1018,6 +1047,8 @@ "Name or short description of the configuration": "\u0631\u0634\u0648\u062b \u062e\u0642 \u0633\u0627\u062e\u0642\u0641 \u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631 \u062e\u0628 \u0641\u0627\u062b \u0630\u062e\u0631\u0628\u0647\u0644\u0639\u0642\u0634\u0641\u0647\u062e\u0631", "Navigate up": "\u0631\u0634\u062f\u0647\u0644\u0634\u0641\u062b \u0639\u062d", "Need help logging in?": "\u0631\u062b\u062b\u064a \u0627\u062b\u0645\u062d \u0645\u062e\u0644\u0644\u0647\u0631\u0644 \u0647\u0631?", + "Need help signing in?": "\u0631\u062b\u062b\u064a \u0627\u062b\u0645\u062d \u0633\u0647\u0644\u0631\u0647\u0631\u0644 \u0647\u0631?", + "Need other help signing in?": "\u0631\u062b\u062b\u064a \u062e\u0641\u0627\u062b\u0642 \u0627\u062b\u0645\u062d \u0633\u0647\u0644\u0631\u0647\u0631\u0644 \u0647\u0631?", "Needs verified certificate ": "\u0631\u062b\u062b\u064a\u0633 \u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b ", "Never published": "\u0631\u062b\u062f\u062b\u0642 \u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a", "Never show assessment results": "\u0631\u062b\u062f\u062b\u0642 \u0633\u0627\u062e\u0635 \u0634\u0633\u0633\u062b\u0633\u0633\u0648\u062b\u0631\u0641 \u0642\u062b\u0633\u0639\u0645\u0641\u0633", @@ -1037,6 +1068,7 @@ "No Flash Detected": "\u0631\u062e \u0628\u0645\u0634\u0633\u0627 \u064a\u062b\u0641\u062b\u0630\u0641\u062b\u064a", "No Timed Transcript": "\u0631\u062e \u0641\u0647\u0648\u062b\u064a \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641", "No Webcam Detected": "\u0631\u062e \u0635\u062b\u0632\u0630\u0634\u0648 \u064a\u062b\u0641\u062b\u0630\u0641\u062b\u064a", + "No assignments for team": "\u0631\u062e \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641\u0633 \u0628\u062e\u0642 \u0641\u062b\u0634\u0648", "No color": "\u0631\u062e \u0630\u062e\u0645\u062e\u0642", "No content-specific discussion topics exist.": "\u0631\u062e \u0630\u062e\u0631\u0641\u062b\u0631\u0641-\u0633\u062d\u062b\u0630\u0647\u0628\u0647\u0630 \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0641\u062e\u062d\u0647\u0630\u0633 \u062b\u0637\u0647\u0633\u0641.", "No description available": "\u0631\u062e \u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631 \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b", @@ -1085,9 +1117,10 @@ "Once in position, use the Take Photo button {icon} to capture your photo": "\u062e\u0631\u0630\u062b \u0647\u0631 \u062d\u062e\u0633\u0647\u0641\u0647\u062e\u0631, \u0639\u0633\u062b \u0641\u0627\u062b \u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e \u0632\u0639\u0641\u0641\u062e\u0631 {icon} \u0641\u062e \u0630\u0634\u062d\u0641\u0639\u0642\u062b \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e", "Once you complete one of the program requirements you have a program record. This record is marked complete once you meet all program requirements. A program record can be used to continue your learning journey and demonstrate your learning to others.": "\u062e\u0631\u0630\u062b \u063a\u062e\u0639 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u062e\u0631\u062b \u062e\u0628 \u0641\u0627\u062b \u062d\u0642\u062e\u0644\u0642\u0634\u0648 \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0648\u062b\u0631\u0641\u0633 \u063a\u062e\u0639 \u0627\u0634\u062f\u062b \u0634 \u062d\u0642\u062e\u0644\u0642\u0634\u0648 \u0642\u062b\u0630\u062e\u0642\u064a. \u0641\u0627\u0647\u0633 \u0642\u062b\u0630\u062e\u0642\u064a \u0647\u0633 \u0648\u0634\u0642\u0646\u062b\u064a \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u062e\u0631\u0630\u062b \u063a\u062e\u0639 \u0648\u062b\u062b\u0641 \u0634\u0645\u0645 \u062d\u0642\u062e\u0644\u0642\u0634\u0648 \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0648\u062b\u0631\u0641\u0633. \u0634 \u062d\u0642\u062e\u0644\u0642\u0634\u0648 \u0642\u062b\u0630\u062e\u0642\u064a \u0630\u0634\u0631 \u0632\u062b \u0639\u0633\u062b\u064a \u0641\u062e \u0630\u062e\u0631\u0641\u0647\u0631\u0639\u062b \u063a\u062e\u0639\u0642 \u0645\u062b\u0634\u0642\u0631\u0647\u0631\u0644 \u062a\u062e\u0639\u0642\u0631\u062b\u063a \u0634\u0631\u064a \u064a\u062b\u0648\u062e\u0631\u0633\u0641\u0642\u0634\u0641\u062b \u063a\u062e\u0639\u0642 \u0645\u062b\u0634\u0642\u0631\u0647\u0631\u0644 \u0641\u062e \u062e\u0641\u0627\u062b\u0642\u0633.", "Once your account is deleted, you cannot use it to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "\u062e\u0631\u0630\u062b \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0647\u0633 \u064a\u062b\u0645\u062b\u0641\u062b\u064a, \u063a\u062e\u0639 \u0630\u0634\u0631\u0631\u062e\u0641 \u0639\u0633\u062b \u0647\u0641 \u0641\u062e \u0641\u0634\u0646\u062b \u0630\u062e\u0639\u0642\u0633\u062b\u0633 \u062e\u0631 \u0641\u0627\u062b {platformName} \u0634\u062d\u062d, {siteName}, \u062e\u0642 \u0634\u0631\u063a \u062e\u0641\u0627\u062b\u0642 \u0633\u0647\u0641\u062b \u0627\u062e\u0633\u0641\u062b\u064a \u0632\u063a {platformName}.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u062e\u0631\u0645\u063a <%= fileTypes %> \u0628\u0647\u0645\u062b\u0633 \u0630\u0634\u0631 \u0632\u062b \u0639\u062d\u0645\u062e\u0634\u064a\u062b\u064a. \u062d\u0645\u062b\u0634\u0633\u062b \u0633\u062b\u0645\u062b\u0630\u0641 \u0634 \u0628\u0647\u0645\u062b \u062b\u0631\u064a\u0647\u0631\u0644 \u0647\u0631 <%= fileExtensions %> \u0641\u062e \u0639\u062d\u0645\u062e\u0634\u064a.", + "Only <%- fileTypes %> files can be uploaded. Please select a file ending in <%- (fileExtensions) %> to upload.": "\u062e\u0631\u0645\u063a <%- fileTypes %> \u0628\u0647\u0645\u062b\u0633 \u0630\u0634\u0631 \u0632\u062b \u0639\u062d\u0645\u062e\u0634\u064a\u062b\u064a. \u062d\u0645\u062b\u0634\u0633\u062b \u0633\u062b\u0645\u062b\u0630\u0641 \u0634 \u0628\u0647\u0645\u062b \u062b\u0631\u064a\u0647\u0631\u0644 \u0647\u0631 <%- (fileExtensions) %> \u0641\u062e \u0639\u062d\u0645\u062e\u0634\u064a.", "Only properly formatted .csv files will be accepted.": "\u062e\u0631\u0645\u063a \u062d\u0642\u062e\u062d\u062b\u0642\u0645\u063a \u0628\u062e\u0642\u0648\u0634\u0641\u0641\u062b\u064a .\u0630\u0633\u062f \u0628\u0647\u0645\u062b\u0633 \u0635\u0647\u0645\u0645 \u0632\u062b \u0634\u0630\u0630\u062b\u062d\u0641\u062b\u064a.", "Only the parent course staff of a CCX can create content groups.": "\u062e\u0631\u0645\u063a \u0641\u0627\u062b \u062d\u0634\u0642\u062b\u0631\u0641 \u0630\u062e\u0639\u0642\u0633\u062b \u0633\u0641\u0634\u0628\u0628 \u062e\u0628 \u0634 \u0630\u0630\u0637 \u0630\u0634\u0631 \u0630\u0642\u062b\u0634\u0641\u062b \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0644\u0642\u062e\u0639\u062d\u0633.", + "Open": "\u062e\u062d\u062b\u0631", "Open Calculator": "\u062e\u062d\u062b\u0631 \u0630\u0634\u0645\u0630\u0639\u0645\u0634\u0641\u062e\u0642", "Open language menu": "\u062e\u062d\u062b\u0631 \u0645\u0634\u0631\u0644\u0639\u0634\u0644\u062b \u0648\u062b\u0631\u0639", "Open the certificate you earned for the %(title)s program.": "\u062e\u062d\u062b\u0631 \u0641\u0627\u062b \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u063a\u062e\u0639 \u062b\u0634\u0642\u0631\u062b\u064a \u0628\u062e\u0642 \u0641\u0627\u062b %(title)s \u062d\u0642\u062e\u0644\u0642\u0634\u0648.", @@ -1107,6 +1140,7 @@ "Organization of the signatory": "\u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u062e\u0628 \u0641\u0627\u062b \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u063a", "Organization:": "\u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631:", "Other": "\u062e\u0641\u0627\u062b\u0642", + "Other sign-in issues": "\u062e\u0641\u0627\u062b\u0642 \u0633\u0647\u0644\u0631-\u0647\u0631 \u0647\u0633\u0633\u0639\u062b\u0633", "Overall Score": "\u062e\u062f\u062b\u0642\u0634\u0645\u0645 \u0633\u0630\u062e\u0642\u062b", "PDF Chapters": "\u062d\u064a\u0628 \u0630\u0627\u0634\u062d\u0641\u062b\u0642\u0633", "Page break": "\u062d\u0634\u0644\u062b \u0632\u0642\u062b\u0634\u0646", @@ -1135,6 +1169,8 @@ "Photo of %(fullName)s's ID": "\u062d\u0627\u062e\u0641\u062e \u062e\u0628 %(fullName)s'\u0633 \u0647\u064a", "Photo requirements:": "\u062d\u0627\u062e\u0641\u062e \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0648\u062b\u0631\u0641\u0633:", "Photos don't meet the requirements?": "\u062d\u0627\u062e\u0641\u062e\u0633 \u064a\u062e\u0631'\u0641 \u0648\u062b\u062b\u0641 \u0641\u0627\u062b \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0648\u062b\u0631\u0641\u0633?", + "Pin": "\u062d\u0647\u0631", + "Pinned": "\u062d\u0647\u0631\u0631\u062b\u064a", "Placeholder": "\u062d\u0645\u0634\u0630\u062b\u0627\u062e\u0645\u064a\u062b\u0642", "Play": "\u062d\u0645\u0634\u063a", "Play video": "\u062d\u0645\u0634\u063a \u062f\u0647\u064a\u062b\u062e", @@ -1177,6 +1213,7 @@ "Please verify that your webcam is connected and that you have allowed your browser to access it.": "\u062d\u0645\u062b\u0634\u0633\u062b \u062f\u062b\u0642\u0647\u0628\u063a \u0641\u0627\u0634\u0641 \u063a\u062e\u0639\u0642 \u0635\u062b\u0632\u0630\u0634\u0648 \u0647\u0633 \u0630\u062e\u0631\u0631\u062b\u0630\u0641\u062b\u064a \u0634\u0631\u064a \u0641\u0627\u0634\u0641 \u063a\u062e\u0639 \u0627\u0634\u062f\u062b \u0634\u0645\u0645\u062e\u0635\u062b\u064a \u063a\u062e\u0639\u0642 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u0641\u062e \u0634\u0630\u0630\u062b\u0633\u0633 \u0647\u0641.", "Plugins": "\u062d\u0645\u0639\u0644\u0647\u0631\u0633", "Post": "\u062d\u062e\u0633\u0641", + "Post type": "\u062d\u062e\u0633\u0641 \u0641\u063a\u062d\u062b", "Poster": "\u062d\u062e\u0633\u0641\u062b\u0642", "Practice Proctored": "\u062d\u0642\u0634\u0630\u0641\u0647\u0630\u062b \u062d\u0642\u062e\u0630\u0641\u062e\u0642\u062b\u064a", "Practice proctored Exam": "\u062d\u0642\u0634\u0630\u0641\u0647\u0630\u062b \u062d\u0642\u062e\u0630\u0641\u062e\u0642\u062b\u064a \u062b\u0637\u0634\u0648", @@ -1231,6 +1268,8 @@ "Published and Live": "\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0634\u0631\u064a \u0645\u0647\u062f\u062b", "Publishing": "\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u0647\u0631\u0644", "Publishing Status": "\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u0647\u0631\u0644 \u0633\u0641\u0634\u0641\u0639\u0633", + "Question": "\u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631", + "Questions raise issues that need answers. Discussions share ideas and start conversations. (Required)": "\u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631\u0633 \u0642\u0634\u0647\u0633\u062b \u0647\u0633\u0633\u0639\u062b\u0633 \u0641\u0627\u0634\u0641 \u0631\u062b\u062b\u064a \u0634\u0631\u0633\u0635\u062b\u0642\u0633. \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631\u0633 \u0633\u0627\u0634\u0642\u062b \u0647\u064a\u062b\u0634\u0633 \u0634\u0631\u064a \u0633\u0641\u0634\u0642\u0641 \u0630\u062e\u0631\u062f\u062b\u0642\u0633\u0634\u0641\u0647\u062e\u0631\u0633. (\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a)", "Queued": "\u0636\u0639\u062b\u0639\u062b\u064a", "REMAINING COURSES": "\u0642\u062b\u0648\u0634\u0647\u0631\u0647\u0631\u0644 \u0630\u062e\u0639\u0642\u0633\u062b\u0633", "Re-run Course": "\u0642\u062b-\u0642\u0639\u0631 \u0630\u062e\u0639\u0642\u0633\u062b", @@ -1250,6 +1289,7 @@ "Regenerate": "\u0642\u062b\u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b", "Regenerate the user's certificate": "\u0642\u062b\u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b \u0641\u0627\u062b \u0639\u0633\u062b\u0642'\u0633 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b", "Register with Institution/Campus Credentials": "\u0642\u062b\u0644\u0647\u0633\u0641\u062b\u0642 \u0635\u0647\u0641\u0627 \u0647\u0631\u0633\u0641\u0647\u0641\u0639\u0641\u0647\u062e\u0631/\u0630\u0634\u0648\u062d\u0639\u0633 \u0630\u0642\u062b\u064a\u062b\u0631\u0641\u0647\u0634\u0645\u0633", + "Related to: %(courseware_title_linked)s": "\u0642\u062b\u0645\u0634\u0641\u062b\u064a \u0641\u062e: %(courseware_title_linked)s", "Release Date and Time": "\u0642\u062b\u0645\u062b\u0634\u0633\u062b \u064a\u0634\u0641\u062b \u0634\u0631\u064a \u0641\u0647\u0648\u062b", "Release Date:": "\u0642\u062b\u0645\u062b\u0634\u0633\u062b \u064a\u0634\u0641\u062b:", "Release Status:": "\u0642\u062b\u0645\u062b\u0634\u0633\u062b \u0633\u0641\u0634\u0641\u0639\u0633:", @@ -1277,7 +1317,10 @@ "Replace all": "\u0642\u062b\u062d\u0645\u0634\u0630\u062b \u0634\u0645\u0645", "Replace with": "\u0642\u062b\u062d\u0645\u0634\u0630\u062b \u0635\u0647\u0641\u0627", "Reply to Annotation": "\u0642\u062b\u062d\u0645\u063a \u0641\u062e \u0634\u0631\u0631\u062e\u0641\u0634\u0641\u0647\u062e\u0631", + "Report": "\u0642\u062b\u062d\u062e\u0642\u0641", + "Report abuse": "\u0642\u062b\u062d\u062e\u0642\u0641 \u0634\u0632\u0639\u0633\u062b", "Report abuse, topics, and responses": "\u0642\u062b\u062d\u062e\u0642\u0641 \u0634\u0632\u0639\u0633\u062b, \u0641\u062e\u062d\u0647\u0630\u0633, \u0634\u0631\u064a \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b\u0633", + "Reported": "\u0642\u062b\u062d\u062e\u0642\u0641\u062b\u064a", "Requester": "\u0642\u062b\u0636\u0639\u062b\u0633\u0641\u062b\u0642", "Required": "\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a", "Required field.": "\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a \u0628\u0647\u062b\u0645\u064a.", @@ -1296,6 +1339,7 @@ "Return and add email address": "\u0642\u062b\u0641\u0639\u0642\u0631 \u0634\u0631\u064a \u0634\u064a\u064a \u062b\u0648\u0634\u0647\u0645 \u0634\u064a\u064a\u0642\u062b\u0633\u0633", "Return to Export": "\u0642\u062b\u0641\u0639\u0642\u0631 \u0641\u062e \u062b\u0637\u062d\u062e\u0642\u0641", "Return to Your Dashboard": "\u0642\u062b\u0641\u0639\u0642\u0631 \u0641\u062e \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a", + "Return to all posts": "\u0642\u062b\u0641\u0639\u0642\u0631 \u0641\u062e \u0634\u0645\u0645 \u062d\u062e\u0633\u0641\u0633", "Return to team listing": "\u0642\u062b\u0641\u0639\u0642\u0631 \u0641\u062e \u0641\u062b\u0634\u0648 \u0645\u0647\u0633\u0641\u0647\u0631\u0644", "Review Rules": "\u0642\u062b\u062f\u0647\u062b\u0635 \u0642\u0639\u0645\u062b\u0633", "Review Your Photos": "\u0642\u062b\u062f\u0647\u062b\u0635 \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e\u0633", @@ -1373,6 +1417,10 @@ "Short explanation": "\u0633\u0627\u062e\u0642\u0641 \u062b\u0637\u062d\u0645\u0634\u0631\u0634\u0641\u0647\u062e\u0631", "Show All": "\u0633\u0627\u062e\u0635 \u0634\u0645\u0645", "Show Annotations": "\u0633\u0627\u062e\u0635 \u0634\u0631\u0631\u062e\u0641\u0634\u0641\u0647\u062e\u0631\u0633", + "Show Comment (%(num_comments)s)": [ + "\u0633\u0627\u062e\u0635 \u0630\u062e\u0648\u0648\u062b\u0631\u0641 (%(num_comments)s)", + "\u0633\u0627\u062e\u0635 \u0630\u062e\u0648\u0648\u062b\u0631\u0641\u0633 (%(num_comments)s)" + ], "Show Deprecated Settings": "\u0633\u0627\u062e\u0635 \u064a\u062b\u062d\u0642\u062b\u0630\u0634\u0641\u062b\u064a \u0633\u062b\u0641\u0641\u0647\u0631\u0644\u0633", "Show Discussion": "\u0633\u0627\u062e\u0635 \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631", "Show Less": "\u0633\u0627\u062e\u0635 \u0645\u062b\u0633\u0633", @@ -1409,6 +1457,7 @@ "Sign in using %(providerName)s": "\u0633\u0647\u0644\u0631 \u0647\u0631 \u0639\u0633\u0647\u0631\u0644 %(providerName)s", "Sign in with %(providerName)s": "\u0633\u0647\u0644\u0631 \u0647\u0631 \u0635\u0647\u0641\u0627 %(providerName)s", "Sign in with Institution/Campus Credentials": "\u0633\u0647\u0644\u0631 \u0647\u0631 \u0635\u0647\u0641\u0627 \u0647\u0631\u0633\u0641\u0647\u0641\u0639\u0641\u0647\u062e\u0631/\u0630\u0634\u0648\u062d\u0639\u0633 \u0630\u0642\u062b\u064a\u062b\u0631\u0641\u0647\u0634\u0645\u0633", + "Sign in with your company or school": "\u0633\u0647\u0644\u0631 \u0647\u0631 \u0635\u0647\u0641\u0627 \u063a\u062e\u0639\u0642 \u0630\u062e\u0648\u062d\u0634\u0631\u063a \u062e\u0642 \u0633\u0630\u0627\u062e\u062e\u0645", "Sign in.": "\u0633\u0647\u0644\u0631 \u0647\u0631.", "Signatory": "\u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u063a", "Signatory field(s) has invalid data.": "\u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u063a \u0628\u0647\u062b\u0645\u064a(\u0633) \u0627\u0634\u0633 \u0647\u0631\u062f\u0634\u0645\u0647\u064a \u064a\u0634\u0641\u0634.", @@ -1515,6 +1564,7 @@ "Task inputs": "\u0641\u0634\u0633\u0646 \u0647\u0631\u062d\u0639\u0641\u0633", "Teaching Assistant": "\u0641\u062b\u0634\u0630\u0627\u0647\u0631\u0644 \u0634\u0633\u0633\u0647\u0633\u0641\u0634\u0631\u0641", "Team \"{team}\" successfully deleted.": "\u0641\u062b\u0634\u0648 \"{team}\" \u0633\u0639\u0630\u0630\u062b\u0633\u0633\u0628\u0639\u0645\u0645\u063a \u064a\u062b\u0645\u062b\u0641\u062b\u064a.", + "Team Assignments": "\u0641\u062b\u0634\u0648 \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641\u0633", "Team Description (Required) *": "\u0641\u062b\u0634\u0648 \u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631 (\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a) *", "Team Details": "\u0641\u062b\u0634\u0648 \u064a\u062b\u0641\u0634\u0647\u0645\u0633", "Team Name (Required) *": "\u0641\u062b\u0634\u0648 \u0631\u0634\u0648\u062b (\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a) *", @@ -1533,9 +1583,8 @@ "Textbook Name": "\u0641\u062b\u0637\u0641\u0632\u062e\u062e\u0646 \u0631\u0634\u0648\u062b", "Textbook information": "\u0641\u062b\u0637\u0641\u0632\u062e\u062e\u0646 \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631", "Textbook name is required": "\u0641\u062b\u0637\u0641\u0632\u062e\u062e\u0646 \u0631\u0634\u0648\u062b \u0647\u0633 \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 %(full_name)s! \u0635\u062b \u0627\u0634\u062f\u062b \u0642\u062b\u0630\u062b\u0647\u062f\u062b\u064a \u063a\u062e\u0639\u0642 \u062d\u0634\u063a\u0648\u062b\u0631\u0641 \u0628\u062e\u0642 %(course_name)s.", "Thank you for setting your course goal to {goal}!": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 \u0628\u062e\u0642 \u0633\u062b\u0641\u0641\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u0630\u062e\u0639\u0642\u0633\u062b \u0644\u062e\u0634\u0645 \u0641\u062e {goal}!", - "Thank you for submitting a request! We will contact you within 24 hours.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 \u0628\u062e\u0642 \u0633\u0639\u0632\u0648\u0647\u0641\u0641\u0647\u0631\u0644 \u0634 \u0642\u062b\u0636\u0639\u062b\u0633\u0641! \u0635\u062b \u0635\u0647\u0645\u0645 \u0630\u062e\u0631\u0641\u0634\u0630\u0641 \u063a\u062e\u0639 \u0635\u0647\u0641\u0627\u0647\u0631 24 \u0627\u062e\u0639\u0642\u0633.", + "Thank you for submitting a request! We appreciate your patience while we work to review your request.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 \u0628\u062e\u0642 \u0633\u0639\u0632\u0648\u0647\u0641\u0641\u0647\u0631\u0644 \u0634 \u0642\u062b\u0636\u0639\u062b\u0633\u0641! \u0635\u062b \u0634\u062d\u062d\u0642\u062b\u0630\u0647\u0634\u0641\u062b \u063a\u062e\u0639\u0642 \u062d\u0634\u0641\u0647\u062b\u0631\u0630\u062b \u0635\u0627\u0647\u0645\u062b \u0635\u062b \u0635\u062e\u0642\u0646 \u0641\u062e \u0642\u062b\u062f\u0647\u062b\u0635 \u063a\u062e\u0639\u0642 \u0642\u062b\u0636\u0639\u062b\u0633\u0641.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 \u0628\u062e\u0642 \u0633\u0639\u0632\u0648\u0647\u0641\u0641\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u0628\u0647\u0631\u0634\u0631\u0630\u0647\u0634\u0645 \u0634\u0633\u0633\u0647\u0633\u0641\u0634\u0631\u0630\u062b \u0634\u062d\u062d\u0645\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u0628\u062e\u0642 {course_name}! \u063a\u062e\u0639 \u0630\u0634\u0631 \u062b\u0637\u062d\u062b\u0630\u0641 \u0634 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b \u0647\u0631 2-4 \u0632\u0639\u0633\u0647\u0631\u062b\u0633\u0633 \u064a\u0634\u063a\u0633.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 \u0628\u062e\u0642 \u0633\u0639\u0632\u0648\u0647\u0641\u0641\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e\u0633. \u0635\u062b \u0635\u0647\u0645\u0645 \u0642\u062b\u062f\u0647\u062b\u0635 \u0641\u0627\u062b\u0648 \u0633\u0627\u062e\u0642\u0641\u0645\u063a. \u063a\u062e\u0639 \u0630\u0634\u0631 \u0631\u062e\u0635 \u0633\u0647\u0644\u0631 \u0639\u062d \u0628\u062e\u0642 \u0634\u0631\u063a %(platformName)s \u0630\u062e\u0639\u0642\u0633\u062b \u0641\u0627\u0634\u0641 \u062e\u0628\u0628\u062b\u0642\u0633 \u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b\u0633. \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u0647\u0633 \u0644\u062e\u062e\u064a \u0628\u062e\u0642 \u062e\u0631\u062b \u063a\u062b\u0634\u0642. \u0634\u0628\u0641\u062b\u0642 \u062e\u0631\u062b \u063a\u062b\u0634\u0642, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0633\u0639\u0632\u0648\u0647\u0641 \u062d\u0627\u062e\u0641\u062e\u0633 \u0628\u062e\u0642 \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u0634\u0644\u0634\u0647\u0631.", "Thank you! We have received your payment for {courseName}.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639! \u0635\u062b \u0627\u0634\u062f\u062b \u0642\u062b\u0630\u062b\u0647\u062f\u062b\u064a \u063a\u062e\u0639\u0642 \u062d\u0634\u063a\u0648\u062b\u0631\u0641 \u0628\u062e\u0642 {courseName}.", @@ -1547,8 +1596,8 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u0641\u0627\u062b \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u0628\u062e\u0642 \u0641\u0627\u0647\u0633 \u0645\u062b\u0634\u0642\u0631\u062b\u0642 \u0627\u0634\u0633 \u0632\u062b\u062b\u0631 \u0642\u062b-\u062f\u0634\u0645\u0647\u064a\u0634\u0641\u062b\u064a \u0634\u0631\u064a \u0641\u0627\u062b \u0633\u063a\u0633\u0641\u062b\u0648 \u0647\u0633 \u0642\u062b-\u0642\u0639\u0631\u0631\u0647\u0631\u0644 \u0641\u0627\u062b \u0644\u0642\u0634\u064a\u062b \u0628\u062e\u0642 \u0641\u0627\u0647\u0633 \u0645\u062b\u0634\u0642\u0631\u062b\u0642.", "The cohort cannot be added": "\u0641\u0627\u062b \u0630\u062e\u0627\u062e\u0642\u0641 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0634\u064a\u064a\u062b\u064a", "The cohort cannot be saved": "\u0641\u0627\u062b \u0630\u062e\u0627\u062e\u0642\u0641 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0633\u0634\u062f\u062b\u064a", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u0641\u0627\u062b \u0630\u062e\u0648\u0632\u0647\u0631\u062b\u064a \u0645\u062b\u0631\u0644\u0641\u0627 \u062e\u0628 \u0641\u0627\u062b \u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u0645\u0647\u0632\u0642\u0634\u0642\u063a \u0630\u062e\u064a\u062b \u0628\u0647\u062b\u0645\u064a\u0633 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0648\u062e\u0642\u062b \u0641\u0627\u0634\u0631 <%=limit%> \u0630\u0627\u0634\u0642\u0634\u0630\u0641\u062b\u0642\u0633.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u0641\u0627\u062b \u0630\u062e\u0648\u0632\u0647\u0631\u062b\u064a \u0645\u062b\u0631\u0644\u0641\u0627 \u062e\u0628 \u0641\u0627\u062b \u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631, \u0630\u062e\u0639\u0642\u0633\u062b \u0631\u0639\u0648\u0632\u062b\u0642, \u0634\u0631\u064a \u0630\u062e\u0639\u0642\u0633\u062b \u0642\u0639\u0631 \u0628\u0647\u062b\u0645\u064a\u0633 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0648\u062e\u0642\u062b \u0641\u0627\u0634\u0631 <%=limit%> \u0630\u0627\u0634\u0642\u0634\u0630\u0641\u062b\u0642\u0633.", + "The combined length of the organization and library code fields cannot be more than <%- limit %> characters.": "\u0641\u0627\u062b \u0630\u062e\u0648\u0632\u0647\u0631\u062b\u064a \u0645\u062b\u0631\u0644\u0641\u0627 \u062e\u0628 \u0641\u0627\u062b \u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u0645\u0647\u0632\u0642\u0634\u0642\u063a \u0630\u062e\u064a\u062b \u0628\u0647\u062b\u0645\u064a\u0633 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0648\u062e\u0642\u062b \u0641\u0627\u0634\u0631 <%- limit %> \u0630\u0627\u0634\u0642\u0634\u0630\u0641\u062b\u0642\u0633.", + "The combined length of the organization, course number, and course run fields cannot be more than <%- limit %> characters.": "\u0641\u0627\u062b \u0630\u062e\u0648\u0632\u0647\u0631\u062b\u064a \u0645\u062b\u0631\u0644\u0641\u0627 \u062e\u0628 \u0641\u0627\u062b \u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631, \u0630\u062e\u0639\u0642\u0633\u062b \u0631\u0639\u0648\u0632\u062b\u0642, \u0634\u0631\u064a \u0630\u062e\u0639\u0642\u0633\u062b \u0642\u0639\u0631 \u0628\u0647\u062b\u0645\u064a\u0633 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0648\u062e\u0642\u062b \u0641\u0627\u0634\u0631 <%- limit %> \u0630\u0627\u0634\u0642\u0634\u0630\u0641\u062b\u0642\u0633.", "The country or region where you live.": "\u0641\u0627\u062b \u0630\u062e\u0639\u0631\u0641\u0642\u063a \u062e\u0642 \u0642\u062b\u0644\u0647\u062e\u0631 \u0635\u0627\u062b\u0642\u062b \u063a\u062e\u0639 \u0645\u0647\u062f\u062b.", "The country that team members primarily identify with.": "\u0641\u0627\u062b \u0630\u062e\u0639\u0631\u0641\u0642\u063a \u0641\u0627\u0634\u0641 \u0641\u062b\u0634\u0648 \u0648\u062b\u0648\u0632\u062b\u0642\u0633 \u062d\u0642\u0647\u0648\u0634\u0642\u0647\u0645\u063a \u0647\u064a\u062b\u0631\u0641\u0647\u0628\u063a \u0635\u0647\u0641\u0627.", "The course end date must be later than the course start date.": "\u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u062b\u0631\u064a \u064a\u0634\u0641\u062b \u0648\u0639\u0633\u0641 \u0632\u062b \u0645\u0634\u0641\u062b\u0642 \u0641\u0627\u0634\u0631 \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0633\u0641\u0634\u0642\u0641 \u064a\u0634\u0641\u062b.", @@ -1563,7 +1612,7 @@ "The file you are trying to upload is too large.": "\u0641\u0627\u062b \u0628\u0647\u0645\u062b \u063a\u062e\u0639 \u0634\u0642\u062b \u0641\u0642\u063a\u0647\u0631\u0644 \u0641\u062e \u0639\u062d\u0645\u062e\u0634\u064a \u0647\u0633 \u0641\u062e\u062e \u0645\u0634\u0642\u0644\u062b.", "The following email addresses and/or usernames are invalid:": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u062b\u0648\u0634\u0647\u0645 \u0634\u064a\u064a\u0642\u062b\u0633\u0633\u062b\u0633 \u0634\u0631\u064a/\u062e\u0642 \u0639\u0633\u062b\u0642\u0631\u0634\u0648\u062b\u0633 \u0634\u0642\u062b \u0647\u0631\u062f\u0634\u0645\u0647\u064a:", "The following errors were generated:": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u062b\u0642\u0642\u062e\u0642\u0633 \u0635\u062b\u0642\u062b \u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b\u064a:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0647\u0633 \u0634\u0645\u0642\u062b\u0634\u064a\u063a \u0634 \u062d\u0634\u0642\u0641 \u062e\u0628 \u063a\u062e\u0639\u0642 {platform} \u062d\u0642\u062e\u0628\u0647\u0645\u062b. \u0635\u062b\\'\u062f\u062b \u0647\u0631\u0630\u0645\u0639\u064a\u062b\u064a \u0647\u0641 \u0627\u062b\u0642\u062b \u0628\u062e\u0642 \u063a\u062e\u0639\u0642 \u0634\u062d\u062d\u0645\u0647\u0630\u0634\u0641\u0647\u062e\u0631.", + "The following information is already a part of your {platform} profile. We've included it here for your application.": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0647\u0633 \u0634\u0645\u0642\u062b\u0634\u064a\u063a \u0634 \u062d\u0634\u0642\u0641 \u062e\u0628 \u063a\u062e\u0639\u0642 {platform} \u062d\u0642\u062e\u0628\u0647\u0645\u062b. \u0635\u062b'\u062f\u062b \u0647\u0631\u0630\u0645\u0639\u064a\u062b\u064a \u0647\u0641 \u0627\u062b\u0642\u062b \u0628\u062e\u0642 \u063a\u062e\u0639\u0642 \u0634\u062d\u062d\u0645\u0647\u0630\u0634\u0641\u0647\u062e\u0631.", "The following message will be displayed at the bottom of the courseware pages within your course:": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u0648\u062b\u0633\u0633\u0634\u0644\u062b \u0635\u0647\u0645\u0645 \u0632\u062b \u064a\u0647\u0633\u062d\u0645\u0634\u063a\u062b\u064a \u0634\u0641 \u0641\u0627\u062b \u0632\u062e\u0641\u0641\u062e\u0648 \u062e\u0628 \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b\u0635\u0634\u0642\u062b \u062d\u0634\u0644\u062b\u0633 \u0635\u0647\u0641\u0627\u0647\u0631 \u063a\u062e\u0639\u0642 \u0630\u062e\u0639\u0642\u0633\u062b:", "The following options are available for the {license_name} license.": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u062e\u062d\u0641\u0647\u062e\u0631\u0633 \u0634\u0642\u062b \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b \u0628\u062e\u0642 \u0641\u0627\u062b {license_name} \u0645\u0647\u0630\u062b\u0631\u0633\u062b.", "The following users are no longer enrolled in the course:": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u0639\u0633\u062b\u0642\u0633 \u0634\u0642\u062b \u0631\u062e \u0645\u062e\u0631\u0644\u062b\u0642 \u062b\u0631\u0642\u062e\u0645\u0645\u062b\u064a \u0647\u0631 \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b:", @@ -1575,7 +1624,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "\u0641\u0627\u062b \u0648\u0647\u0631\u0647\u0648\u0639\u0648 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u0647\u062e\u0631 \u062d\u062b\u0642\u0630\u062b\u0631\u0641\u0634\u0644\u062b \u0648\u0639\u0633\u0641 \u0632\u062b \u0634 \u0635\u0627\u062e\u0645\u062b \u0631\u0639\u0648\u0632\u062b\u0642 \u0632\u062b\u0641\u0635\u062b\u062b\u0631 0 \u0634\u0631\u064a 100.", "The minimum grade for course credit is not set.": "\u0641\u0627\u062b \u0648\u0647\u0631\u0647\u0648\u0639\u0648 \u0644\u0642\u0634\u064a\u062b \u0628\u062e\u0642 \u0630\u062e\u0639\u0642\u0633\u062b \u0630\u0642\u062b\u064a\u0647\u0641 \u0647\u0633 \u0631\u062e\u0641 \u0633\u062b\u0641.", "The minimum score percentage must be a whole number between 0 and 100.": "\u0641\u0627\u062b \u0648\u0647\u0631\u0647\u0648\u0639\u0648 \u0633\u0630\u062e\u0642\u062b \u062d\u062b\u0642\u0630\u062b\u0631\u0641\u0634\u0644\u062b \u0648\u0639\u0633\u0641 \u0632\u062b \u0634 \u0635\u0627\u062e\u0645\u062b \u0631\u0639\u0648\u0632\u062b\u0642 \u0632\u062b\u0641\u0635\u062b\u062b\u0631 0 \u0634\u0631\u064a 100.", - "The more you tell us, the more quickly and helpfully we can respond!": "\u0641\u0627\u062b \u0648\u062e\u0642\u062b \u063a\u062e\u0639 \u0641\u062b\u0645\u0645 \u0639\u0633, \u0641\u0627\u062b \u0648\u062e\u0642\u062b \u0636\u0639\u0647\u0630\u0646\u0645\u063a \u0634\u0631\u064a \u0627\u062b\u0645\u062d\u0628\u0639\u0645\u0645\u063a \u0635\u062b \u0630\u0634\u0631 \u0642\u062b\u0633\u062d\u062e\u0631\u064a!", "The name of this signatory as it should appear on certificates.": "\u0641\u0627\u062b \u0631\u0634\u0648\u062b \u062e\u0628 \u0641\u0627\u0647\u0633 \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u063a \u0634\u0633 \u0647\u0641 \u0633\u0627\u062e\u0639\u0645\u064a \u0634\u062d\u062d\u062b\u0634\u0642 \u062e\u0631 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b\u0633.", "The name that identifies you on {platform_name}. You cannot change your username.": "\u0641\u0627\u062b \u0631\u0634\u0648\u062b \u0641\u0627\u0634\u0641 \u0647\u064a\u062b\u0631\u0641\u0647\u0628\u0647\u062b\u0633 \u063a\u062e\u0639 \u062e\u0631 {platform_name}. \u063a\u062e\u0639 \u0630\u0634\u0631\u0631\u062e\u0641 \u0630\u0627\u0634\u0631\u0644\u062b \u063a\u062e\u0639\u0642 \u0639\u0633\u062b\u0642\u0631\u0634\u0648\u062b.", "The name that is used for ID verification and that appears on your certificates.": "\u0641\u0627\u062b \u0631\u0634\u0648\u062b \u0641\u0627\u0634\u0641 \u0647\u0633 \u0639\u0633\u062b\u064a \u0628\u062e\u0642 \u0647\u064a \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u0641\u0627\u0634\u0641 \u0634\u062d\u062d\u062b\u0634\u0642\u0633 \u062e\u0631 \u063a\u062e\u0639\u0642 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b\u0633.", @@ -1583,7 +1631,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "\u0641\u0627\u062b \u0631\u0639\u0648\u0632\u062b\u0642 \u062e\u0628 \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631\u0633 \u0647\u0631 \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0641\u0627\u0634\u0641 \u0630\u062e\u0631\u0641\u0634\u0647\u0631 \u062d\u0642\u062e\u0632\u0645\u062b\u0648\u0633 \u062e\u0628 \u0641\u0627\u0647\u0633 \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641 \u0641\u063a\u062d\u062b.", "The organization that this signatory belongs to, as it should appear on certificates.": "\u0641\u0627\u062b \u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0641\u0627\u0634\u0641 \u0641\u0627\u0647\u0633 \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u063a \u0632\u062b\u0645\u062e\u0631\u0644\u0633 \u0641\u062e, \u0634\u0633 \u0647\u0641 \u0633\u0627\u062e\u0639\u0645\u064a \u0634\u062d\u062d\u062b\u0634\u0642 \u062e\u0631 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b\u0633.", "The page \"{route}\" could not be found.": "\u0641\u0627\u062b \u062d\u0634\u0644\u062b \"{route}\" \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0628\u062e\u0639\u0631\u064a.", - "The photo of your face matches the photo on your ID.": "\u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b \u0648\u0634\u0641\u0630\u0627\u062b\u0633 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0631 \u063a\u062e\u0639\u0642 \u0647\u064a.", "The post you selected has been deleted.": "\u0641\u0627\u062b \u062d\u062e\u0633\u0641 \u063a\u062e\u0639 \u0633\u062b\u0645\u062b\u0630\u0641\u062b\u064a \u0627\u0634\u0633 \u0632\u062b\u062b\u0631 \u064a\u062b\u0645\u062b\u0641\u062b\u064a.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "\u0641\u0627\u062b \u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0632\u0642\u0634\u0631\u0630\u0627 \u062f\u062b\u0642\u0633\u0647\u062e\u0631, {published}, \u0635\u0634\u0633 \u0642\u062b\u0633\u062b\u0641 \u0641\u062e \u0641\u0627\u062b \u064a\u0642\u0634\u0628\u0641 \u0632\u0642\u0634\u0631\u0630\u0627 \u062f\u062b\u0642\u0633\u0647\u062e\u0631, {draft}.", "The raw error message is:": "\u0641\u0627\u062b \u0642\u0634\u0635 \u062b\u0642\u0642\u062e\u0642 \u0648\u062b\u0633\u0633\u0634\u0644\u062b \u0647\u0633:", @@ -1675,6 +1722,10 @@ "This post could not be reopened. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0642\u062b\u062e\u062d\u062b\u0631\u062b\u064a. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", "This post could not be unflagged for abuse. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0639\u0631\u0628\u0645\u0634\u0644\u0644\u062b\u064a \u0628\u062e\u0642 \u0634\u0632\u0639\u0633\u062b. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", "This post could not be unpinned. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0639\u0631\u062d\u0647\u0631\u0631\u062b\u064a. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", + "This post is visible only to %(group_name)s.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0647\u0633 \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u062e\u0631\u0645\u063a \u0641\u062e %(group_name)s.", + "This post is visible to everyone.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0647\u0633 \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u062b\u062f\u062b\u0642\u063a\u062e\u0631\u062b.", + "This post will be visible only to %(group_name)s.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0635\u0647\u0645\u0645 \u0632\u062b \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u062e\u0631\u0645\u063a \u0641\u062e %(group_name)s.", + "This post will be visible to everyone.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0635\u0647\u0645\u0645 \u0632\u062b \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u062b\u062f\u062b\u0642\u063a\u062e\u0631\u062b.", "This problem has been reset.": "\u0641\u0627\u0647\u0633 \u062d\u0642\u062e\u0632\u0645\u062b\u0648 \u0627\u0634\u0633 \u0632\u062b\u062b\u0631 \u0642\u062b\u0633\u062b\u0641.", "This response could not be marked as an answer. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0648\u0634\u0642\u0646\u062b\u064a \u0634\u0633 \u0634\u0631 \u0634\u0631\u0633\u0635\u062b\u0642. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", "This response could not be marked as endorsed. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0648\u0634\u0642\u0646\u062b\u064a \u0634\u0633 \u062b\u0631\u064a\u062e\u0642\u0633\u062b\u064a. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", @@ -1682,8 +1733,11 @@ "This response could not be unmarked as an answer. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0639\u0631\u0648\u0634\u0642\u0646\u062b\u064a \u0634\u0633 \u0634\u0631 \u0634\u0631\u0633\u0635\u062b\u0642. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", "This role requires a divided discussions scheme.": "\u0641\u0627\u0647\u0633 \u0642\u062e\u0645\u062b \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0633 \u0634 \u064a\u0647\u062f\u0647\u064a\u062b\u064a \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631\u0633 \u0633\u0630\u0627\u062b\u0648\u062b.", "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.": "\u0641\u0627\u0647\u0633 \u0633\u0627\u062e\u0642\u0641 \u0631\u0634\u0648\u062b \u0628\u062e\u0642 \u0641\u0627\u062b \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641 \u0641\u063a\u062d\u062b (\u0628\u062e\u0642 \u062b\u0637\u0634\u0648\u062d\u0645\u062b, \u0627\u0635 \u062e\u0642 \u0648\u0647\u064a\u0641\u062b\u0642\u0648) \u0634\u062d\u062d\u062b\u0634\u0642\u0633 \u0631\u062b\u0637\u0641 \u0641\u062e \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641\u0633 \u062e\u0631 \u0634 \u0645\u062b\u0634\u0642\u0631\u062b\u0642'\u0633 \u062d\u0642\u062e\u0644\u0642\u062b\u0633\u0633 \u062d\u0634\u0644\u062b.", + "This special exam has been released to learners. You may not convert it to another type of special exam. You may revert this subsection back to being a basic exam by selecting 'None', but you will NOT be able to configure it as a special exam in the future.": "\u0641\u0627\u0647\u0633 \u0633\u062d\u062b\u0630\u0647\u0634\u0645 \u062b\u0637\u0634\u0648 \u0627\u0634\u0633 \u0632\u062b\u062b\u0631 \u0642\u062b\u0645\u062b\u0634\u0633\u062b\u064a \u0641\u062e \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633. \u063a\u062e\u0639 \u0648\u0634\u063a \u0631\u062e\u0641 \u0630\u062e\u0631\u062f\u062b\u0642\u0641 \u0647\u0641 \u0641\u062e \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u0641\u063a\u062d\u062b \u062e\u0628 \u0633\u062d\u062b\u0630\u0647\u0634\u0645 \u062b\u0637\u0634\u0648. \u063a\u062e\u0639 \u0648\u0634\u063a \u0642\u062b\u062f\u062b\u0642\u0641 \u0641\u0627\u0647\u0633 \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631 \u0632\u0634\u0630\u0646 \u0641\u062e \u0632\u062b\u0647\u0631\u0644 \u0634 \u0632\u0634\u0633\u0647\u0630 \u062b\u0637\u0634\u0648 \u0632\u063a \u0633\u062b\u0645\u062b\u0630\u0641\u0647\u0631\u0644 '\u0631\u062e\u0631\u062b', \u0632\u0639\u0641 \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0631\u062e\u0641 \u0632\u062b \u0634\u0632\u0645\u062b \u0641\u062e \u0630\u062e\u0631\u0628\u0647\u0644\u0639\u0642\u062b \u0647\u0641 \u0634\u0633 \u0634 \u0633\u062d\u062b\u0630\u0647\u0634\u0645 \u062b\u0637\u0634\u0648 \u0647\u0631 \u0641\u0627\u062b \u0628\u0639\u0641\u0639\u0642\u062b.", + "This subsection was released to learners as a special exam, but was reverted back to a basic exam. You may not configure it as a special exam now. Contact edX Support for assistance.": "\u0641\u0627\u0647\u0633 \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631 \u0635\u0634\u0633 \u0642\u062b\u0645\u062b\u0634\u0633\u062b\u064a \u0641\u062e \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0634\u0633 \u0634 \u0633\u062d\u062b\u0630\u0647\u0634\u0645 \u062b\u0637\u0634\u0648, \u0632\u0639\u0641 \u0635\u0634\u0633 \u0642\u062b\u062f\u062b\u0642\u0641\u062b\u064a \u0632\u0634\u0630\u0646 \u0641\u062e \u0634 \u0632\u0634\u0633\u0647\u0630 \u062b\u0637\u0634\u0648. \u063a\u062e\u0639 \u0648\u0634\u063a \u0631\u062e\u0641 \u0630\u062e\u0631\u0628\u0647\u0644\u0639\u0642\u062b \u0647\u0641 \u0634\u0633 \u0634 \u0633\u062d\u062b\u0630\u0647\u0634\u0645 \u062b\u0637\u0634\u0648 \u0631\u062e\u0635. \u0630\u062e\u0631\u0641\u0634\u0630\u0641 \u062b\u064a\u0637 \u0633\u0639\u062d\u062d\u062e\u0642\u0641 \u0628\u062e\u0642 \u0634\u0633\u0633\u0647\u0633\u0641\u0634\u0631\u0630\u062b.", "This team does not have any members.": "\u0641\u0627\u0647\u0633 \u0641\u062b\u0634\u0648 \u064a\u062e\u062b\u0633 \u0631\u062e\u0641 \u0627\u0634\u062f\u062b \u0634\u0631\u063a \u0648\u062b\u0648\u0632\u062b\u0642\u0633.", "This team is full.": "\u0641\u0627\u0647\u0633 \u0641\u062b\u0634\u0648 \u0647\u0633 \u0628\u0639\u0645\u0645.", + "This thread is closed.": "\u0641\u0627\u0647\u0633 \u0641\u0627\u0642\u062b\u0634\u064a \u0647\u0633 \u0630\u0645\u062e\u0633\u062b\u064a.", "This unit has validation issues.": "\u0641\u0627\u0647\u0633 \u0639\u0631\u0647\u0641 \u0627\u0634\u0633 \u062f\u0634\u0645\u0647\u064a\u0634\u0641\u0647\u062e\u0631 \u0647\u0633\u0633\u0639\u062b\u0633.", "This vote could not be processed. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u062f\u062e\u0641\u062b \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u062d\u0642\u062e\u0630\u062b\u0633\u0633\u062b\u064a. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", "This {parentCategory} has no {childCategory}": "\u0641\u0627\u0647\u0633 {parentCategory} \u0627\u0634\u0633 \u0631\u062e {childCategory}", @@ -1708,7 +1762,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "\u0641\u062e \u0632\u062b \u0633\u0639\u0642\u062b \u0634\u0645\u0645 \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633 \u0630\u0634\u0631 \u0634\u0630\u0630\u062b\u0633\u0633 \u0641\u0627\u062b \u062f\u0647\u064a\u062b\u062e, \u0635\u062b \u0642\u062b\u0630\u062e\u0648\u0648\u062b\u0631\u064a \u062d\u0642\u062e\u062f\u0647\u064a\u0647\u0631\u0644 \u0632\u062e\u0641\u0627 \u0634\u0631 .\u0648\u062d4 \u0634\u0631\u064a \u0634 .\u0635\u062b\u0632\u0648 \u062f\u062b\u0642\u0633\u0647\u062e\u0631 \u062e\u0628 \u063a\u062e\u0639\u0642 \u062f\u0647\u064a\u062b\u062e. \u0630\u0645\u0647\u0630\u0646 \u0632\u062b\u0645\u062e\u0635 \u0641\u062e \u0634\u064a\u064a \u0634 \u0639\u0642\u0645 \u0628\u062e\u0642 \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u062f\u062b\u0642\u0633\u0647\u062e\u0631. \u0641\u0627\u062b\u0633\u062b \u0639\u0642\u0645\u0633 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u063a\u062e\u0639\u0641\u0639\u0632\u062b \u0639\u0642\u0645\u0633. \u0641\u0627\u062b \u0628\u0647\u0642\u0633\u0641 \u0645\u0647\u0633\u0641\u062b\u064a \u062f\u0647\u064a\u062b\u062e \u0641\u0627\u0634\u0641'\u0633 \u0630\u062e\u0648\u062d\u0634\u0641\u0647\u0632\u0645\u062b \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u0633\u0641\u0639\u064a\u062b\u0631\u0641'\u0633 \u0630\u062e\u0648\u062d\u0639\u0641\u062b\u0642 \u0635\u0647\u0645\u0645 \u062d\u0645\u0634\u063a.", "To complete the program, you must earn a verified certificate for each course.": "\u0641\u062e \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0641\u0627\u062b \u062d\u0642\u062e\u0644\u0642\u0634\u0648, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u062b\u0634\u0642\u0631 \u0634 \u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u0628\u062e\u0642 \u062b\u0634\u0630\u0627 \u0630\u062e\u0639\u0642\u0633\u062b.", "To continue learning with this account, sign in below.": "\u0641\u062e \u0630\u062e\u0631\u0641\u0647\u0631\u0639\u062b \u0645\u062b\u0634\u0642\u0631\u0647\u0631\u0644 \u0635\u0647\u0641\u0627 \u0641\u0627\u0647\u0633 \u0634\u0630\u0630\u062e\u0639\u0631\u0641, \u0633\u0647\u0644\u0631 \u0647\u0631 \u0632\u062b\u0645\u062e\u0635.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "\u0641\u062e \u0628\u0647\u0631\u0634\u0645\u0647\u0638\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0630\u0642\u062b\u064a\u0647\u0641, %(display_name)s \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0633 %(platform_name)s \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0641\u062e \u0633\u0639\u0632\u0648\u0647\u0641 \u0634 \u0630\u0642\u062b\u064a\u0647\u0641 \u0642\u062b\u0636\u0639\u062b\u0633\u0641.", "To invalidate a certificate for a particular learner, add the username or email address below.": "\u0641\u062e \u0647\u0631\u062f\u0634\u0645\u0647\u064a\u0634\u0641\u062b \u0634 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u0628\u062e\u0642 \u0634 \u062d\u0634\u0642\u0641\u0647\u0630\u0639\u0645\u0634\u0642 \u0645\u062b\u0634\u0642\u0631\u062b\u0642, \u0634\u064a\u064a \u0641\u0627\u062b \u0639\u0633\u062b\u0642\u0631\u0634\u0648\u062b \u062e\u0642 \u062b\u0648\u0634\u0647\u0645 \u0634\u064a\u064a\u0642\u062b\u0633\u0633 \u0632\u062b\u0645\u062e\u0635.", "To receive a certificate, you must also verify your identity before {date}.": "\u0641\u062e \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u0634 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0634\u0645\u0633\u062e \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0632\u062b\u0628\u062e\u0642\u062b {date}.", "To receive a certificate, you must also verify your identity.": "\u0641\u062e \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u0634 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0634\u0645\u0633\u062e \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a.", @@ -1716,13 +1769,14 @@ "To review learner cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on the {link_start}Data Download{link_end} page.": "\u0641\u062e \u0642\u062b\u062f\u0647\u062b\u0635 \u0645\u062b\u0634\u0642\u0631\u062b\u0642 \u0630\u062e\u0627\u062e\u0642\u0641 \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641\u0633 \u062e\u0642 \u0633\u062b\u062b \u0641\u0627\u062b \u0642\u062b\u0633\u0639\u0645\u0641\u0633 \u062e\u0628 \u0639\u062d\u0645\u062e\u0634\u064a\u0647\u0631\u0644 \u0634 \u0630\u0633\u062f \u0628\u0647\u0645\u062b, \u064a\u062e\u0635\u0631\u0645\u062e\u0634\u064a \u0630\u062e\u0639\u0642\u0633\u062b \u062d\u0642\u062e\u0628\u0647\u0645\u062b \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u062e\u0642 \u0630\u062e\u0627\u062e\u0642\u0641 \u0642\u062b\u0633\u0639\u0645\u0641\u0633 \u062e\u0631 \u0641\u0627\u062b {link_start}\u064a\u0634\u0641\u0634 \u064a\u062e\u0635\u0631\u0645\u062e\u0634\u064a{link_end} \u062d\u0634\u0644\u062b.", "To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.": "\u0641\u062e \u0633\u0627\u0634\u0642\u062b \u063a\u062e\u0639\u0642 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u062e\u0631 \u0648\u062e\u0638\u0647\u0645\u0645\u0634 \u0632\u0634\u0630\u0646\u062d\u0634\u0630\u0646, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0628\u0647\u0642\u0633\u0641 \u0627\u0634\u062f\u062b \u0634 \u0632\u0634\u0630\u0646\u062d\u0634\u0630\u0646 \u0634\u0630\u0630\u062e\u0639\u0631\u0641. \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u0633\u0641\u062b\u062d\u0633 \u0641\u062e \u0634\u064a\u064a \u063a\u062e\u0639\u0642 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u0641\u062e \u0632\u0634\u0630\u0646\u062d\u0634\u0630\u0646.", "To take a successful photo, make sure that:": "\u0641\u062e \u0641\u0634\u0646\u062b \u0634 \u0633\u0639\u0630\u0630\u062b\u0633\u0633\u0628\u0639\u0645 \u062d\u0627\u062e\u0641\u062e, \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u0627\u0634\u0641:", - "To use the current photo, select the Take Photo button {icon}. To take another photo, select the Retake Photo button {icon}.": "\u0641\u062e \u0639\u0633\u062b \u0641\u0627\u062b \u0630\u0639\u0642\u0642\u062b\u0631\u0641 \u062d\u0627\u062e\u0641\u062e, \u0633\u062b\u0645\u062b\u0630\u0641 \u0641\u0627\u062b \u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e \u0632\u0639\u0641\u0641\u062e\u0631 {icon}. \u0641\u062e \u0641\u0634\u0646\u062b \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u062d\u0627\u062e\u0641\u062e, \u0633\u062b\u0645\u062b\u0630\u0641 \u0641\u0627\u062b \u0642\u062b\u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e \u0632\u0639\u0641\u0641\u062e\u0631 {icon}.", + "To take the photo of your face, click on the camera button {icon}. If you need to try again, click 'Retake Photo'.": "\u0641\u062e \u0641\u0634\u0646\u062b \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b, \u0630\u0645\u0647\u0630\u0646 \u062e\u0631 \u0641\u0627\u062b \u0630\u0634\u0648\u062b\u0642\u0634 \u0632\u0639\u0641\u0641\u062e\u0631 {icon}. \u0647\u0628 \u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0641\u062e \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631, \u0630\u0645\u0647\u0630\u0646 '\u0642\u062b\u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e'.", "To verify your identity, you need a webcam and a government-issued photo ID.": "\u0641\u062e \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a, \u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634 \u0635\u062b\u0632\u0630\u0634\u0648 \u0634\u0631\u064a \u0634 \u0644\u062e\u062f\u062b\u0642\u0631\u0648\u062b\u0631\u0641-\u0647\u0633\u0633\u0639\u062b\u064a \u062d\u0627\u062e\u0641\u062e \u0647\u064a.", "Toggle Account Password (Usable/Unusable)": "\u0641\u062e\u0644\u0644\u0645\u062b \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u062d\u0634\u0633\u0633\u0635\u062e\u0642\u064a (\u0639\u0633\u0634\u0632\u0645\u062b/\u0639\u0631\u0639\u0633\u0634\u0632\u0645\u062b)", "Toggle Notifications Setting": "\u0641\u062e\u0644\u0644\u0645\u062b \u0631\u062e\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631\u0633 \u0633\u062b\u0641\u0641\u0647\u0631\u0644", "Tools": "\u0641\u062e\u062e\u0645\u0633", "Top": "\u0641\u062e\u062d", "Topic": "\u0641\u062e\u062d\u0647\u0630", + "Topic area": "\u0641\u062e\u062d\u0647\u0630 \u0634\u0642\u062b\u0634", "Topics": "\u0641\u062e\u062d\u0647\u0630\u0633", "Total": "\u0641\u062e\u0641\u0634\u0645", "Total Number": "\u0641\u062e\u0641\u0634\u0645 \u0631\u0639\u0648\u0632\u062b\u0642", @@ -1749,6 +1803,8 @@ "Undo Changes": "\u0639\u0631\u064a\u062e \u0630\u0627\u0634\u0631\u0644\u062b\u0633", "Undo move": "\u0639\u0631\u064a\u062e \u0648\u062e\u062f\u062b", "Undo moving": "\u0639\u0631\u064a\u062e \u0648\u062e\u062f\u0647\u0631\u0644", + "Unendorse": "\u0639\u0631\u062b\u0631\u064a\u062e\u0642\u0633\u062b", + "Unfollow": "\u0639\u0631\u0628\u062e\u0645\u0645\u062e\u0635", "Ungraded": "\u0639\u0631\u0644\u0642\u0634\u064a\u062b\u064a", "Unit": "\u0639\u0631\u0647\u0641", "Unit Access": "\u0639\u0631\u0647\u0641 \u0634\u0630\u0630\u062b\u0633\u0633", @@ -1759,13 +1815,19 @@ "Unlink This Account": "\u0639\u0631\u0645\u0647\u0631\u0646 \u0641\u0627\u0647\u0633 \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Unlink your {accountName} account": "\u0639\u0631\u0645\u0647\u0631\u0646 \u063a\u062e\u0639\u0642 {accountName} \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Unlinking": "\u0639\u0631\u0645\u0647\u0631\u0646\u0647\u0631\u0644", + "Unmark as Answer": "\u0639\u0631\u0648\u0634\u0642\u0646 \u0634\u0633 \u0634\u0631\u0633\u0635\u062b\u0642", "Unmute": "\u0639\u0631\u0648\u0639\u0641\u062b", + "Unpin": "\u0639\u0631\u062d\u0647\u0631", "Unpublished changes to content that will release in the future": "\u0639\u0631\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0630\u0627\u0634\u0631\u0644\u062b\u0633 \u0641\u062e \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0641\u0627\u0634\u0641 \u0635\u0647\u0645\u0645 \u0642\u062b\u0645\u062b\u0634\u0633\u062b \u0647\u0631 \u0641\u0627\u062b \u0628\u0639\u0641\u0639\u0642\u062b", "Unpublished changes to live content": "\u0639\u0631\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0630\u0627\u0634\u0631\u0644\u062b\u0633 \u0641\u062e \u0645\u0647\u062f\u062b \u0630\u062e\u0631\u0641\u062b\u0631\u0641", "Unpublished units will not be released": "\u0639\u0631\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0639\u0631\u0647\u0641\u0633 \u0635\u0647\u0645\u0645 \u0631\u062e\u0641 \u0632\u062b \u0642\u062b\u0645\u062b\u0634\u0633\u062b\u064a", + "Unreport": "\u0639\u0631\u0642\u062b\u062d\u062e\u0642\u0641", "Unscheduled": "\u0639\u0631\u0633\u0630\u0627\u062b\u064a\u0639\u0645\u062b\u064a", "Update": "\u0639\u062d\u064a\u0634\u0641\u062b", "Update Settings": "\u0639\u062d\u064a\u0634\u0641\u062b \u0633\u062b\u0641\u0641\u0647\u0631\u0644\u0633", + "Update comment": "\u0639\u062d\u064a\u0634\u0641\u062b \u0630\u062e\u0648\u0648\u062b\u0631\u0641", + "Update post": "\u0639\u062d\u064a\u0634\u0641\u062b \u062d\u062e\u0633\u0641", + "Update response": "\u0639\u062d\u064a\u0634\u0641\u062b \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b", "Update team.": "\u0639\u062d\u064a\u0634\u0641\u062b \u0641\u062b\u0634\u0648.", "Updating Tags": "\u0639\u062d\u064a\u0634\u0641\u0647\u0631\u0644 \u0641\u0634\u0644\u0633", "Updating with latest library content": "\u0639\u062d\u064a\u0634\u0641\u0647\u0631\u0644 \u0635\u0647\u0641\u0627 \u0645\u0634\u0641\u062b\u0633\u0641 \u0645\u0647\u0632\u0642\u0634\u0642\u063a \u0630\u062e\u0631\u0641\u062b\u0631\u0641", @@ -1787,7 +1849,7 @@ "Upload Videos": "\u0639\u062d\u0645\u062e\u0634\u064a \u062f\u0647\u064a\u062b\u062e\u0633", "Upload a CSV file": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634 \u0630\u0633\u062f \u0628\u0647\u0645\u062b", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634 \u0630\u062e\u0648\u0648\u0634 \u0633\u062b\u062d\u0634\u0642\u0634\u0641\u062b\u064a \u062f\u0634\u0645\u0639\u062b\u0633 (.\u0630\u0633\u062f) \u0628\u0647\u0645\u062b \u0641\u0627\u0634\u0641 \u0630\u062e\u0631\u0641\u0634\u0647\u0631\u0633 \u0641\u0627\u062b \u0639\u0633\u062b\u0642\u0631\u0634\u0648\u062b\u0633 \u062e\u0642 \u062b\u0648\u0634\u0647\u0645 \u0634\u064a\u064a\u0642\u062b\u0633\u0633\u062b\u0633 \u062e\u0628 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0635\u0627\u062e \u0627\u0634\u062f\u062b \u0632\u062b\u062b\u0631 \u0644\u0647\u062f\u062b\u0631 \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631\u0633. \u0647\u0631\u0630\u0645\u0639\u064a\u062b \u0641\u0627\u062b \u0639\u0633\u062b\u0642\u0631\u0634\u0648\u062b \u062e\u0642 \u062b\u0648\u0634\u0647\u0645 \u0634\u064a\u064a\u0642\u062b\u0633\u0633 \u0647\u0631 \u0641\u0627\u062b \u0628\u0647\u0642\u0633\u0641 \u0630\u062e\u0648\u0648\u0634 \u0633\u062b\u062d\u0634\u0642\u0634\u0641\u062b\u064a \u0628\u0647\u062b\u0645\u064a. \u063a\u062e\u0639 \u0630\u0634\u0631 \u0647\u0631\u0630\u0645\u0639\u064a\u062b \u0634\u0631 \u062e\u062d\u0641\u0647\u062e\u0631\u0634\u0645 \u0631\u062e\u0641\u062b \u064a\u062b\u0633\u0630\u0642\u0647\u0632\u0647\u0631\u0644 \u0641\u0627\u062b \u0642\u062b\u0634\u0633\u062e\u0631 \u0628\u062e\u0642 \u0641\u0627\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0647\u0631 \u0641\u0627\u062b \u0633\u062b\u0630\u062e\u0631\u064a \u0630\u062e\u0648\u0648\u0634 \u0633\u062b\u062d\u0634\u0642\u0634\u0641\u062b\u064a \u0628\u0647\u062b\u0645\u064a.", - "Upload a new PDF to \u201c<%= name %>\u201d": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634 \u0631\u062b\u0635 \u062d\u064a\u0628 \u0641\u062e \u201c<%= name %>\u201d", + "Upload a new PDF to \u201c<%- name %>\u201d": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634 \u0631\u062b\u0635 \u062d\u064a\u0628 \u0641\u062e \u201c<%- name %>\u201d", "Upload an image": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634\u0631 \u0647\u0648\u0634\u0644\u062b", "Upload an image or capture one with your web or phone camera.": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634\u0631 \u0647\u0648\u0634\u0644\u062b \u062e\u0642 \u0630\u0634\u062d\u0641\u0639\u0642\u062b \u062e\u0631\u062b \u0635\u0647\u0641\u0627 \u063a\u062e\u0639\u0642 \u0635\u062b\u0632 \u062e\u0642 \u062d\u0627\u062e\u0631\u062b \u0630\u0634\u0648\u062b\u0642\u0634.", "Upload completed": "\u0639\u062d\u0645\u062e\u0634\u064a \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b\u064a", @@ -1822,7 +1884,7 @@ "Use my university info": "\u0639\u0633\u062b \u0648\u063a \u0639\u0631\u0647\u062f\u062b\u0642\u0633\u0647\u0641\u063a \u0647\u0631\u0628\u062e", "Use the All Topics menu to find specific topics.": "\u0639\u0633\u062b \u0641\u0627\u062b \u0634\u0645\u0645 \u0641\u062e\u062d\u0647\u0630\u0633 \u0648\u062b\u0631\u0639 \u0641\u062e \u0628\u0647\u0631\u064a \u0633\u062d\u062b\u0630\u0647\u0628\u0647\u0630 \u0641\u062e\u062d\u0647\u0630\u0633.", "Use the Retake Photo button if you are not pleased with your photo": "\u0639\u0633\u062b \u0641\u0627\u062b \u0642\u062b\u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e \u0632\u0639\u0641\u0641\u062e\u0631 \u0647\u0628 \u063a\u062e\u0639 \u0634\u0642\u062b \u0631\u062e\u0641 \u062d\u0645\u062b\u0634\u0633\u062b\u064a \u0635\u0647\u0641\u0627 \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u0639\u0633\u062b \u063a\u062e\u0639\u0642 \u0635\u062b\u0632\u0630\u0634\u0648 \u0641\u062e \u0641\u0634\u0646\u062b \u0634 \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0647\u064a. \u0635\u062b \u0635\u0647\u0645\u0645 \u0648\u0634\u0641\u0630\u0627 \u0641\u0627\u0647\u0633 \u062d\u0627\u062e\u0641\u062e \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b \u0634\u0631\u064a \u0641\u0627\u062b \u0631\u0634\u0648\u062b \u062e\u0631 \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641.", + "Use your webcam to take a photo of your ID.": "\u0639\u0633\u062b \u063a\u062e\u0639\u0642 \u0635\u062b\u0632\u0630\u0634\u0648 \u0641\u062e \u0641\u0634\u0646\u062b \u0634 \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0647\u064a.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u0639\u0633\u062b \u063a\u062e\u0639\u0642 \u0635\u062b\u0632\u0630\u0634\u0648 \u0641\u062e \u0641\u0634\u0646\u062b \u0634 \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b. \u0635\u062b \u0635\u0647\u0645\u0645 \u0648\u0634\u0641\u0630\u0627 \u0641\u0627\u0647\u0633 \u062d\u0627\u062e\u0641\u062e \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0631 \u063a\u062e\u0639\u0642 \u0647\u064a.", "Used": "\u0639\u0633\u062b\u064a", "Used in {count} location": [ @@ -1845,7 +1907,6 @@ "Verified Certificate upgrade": "\u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u0639\u062d\u0644\u0642\u0634\u064a\u062b", "Verified Status": "\u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0633\u0641\u0634\u0641\u0639\u0633", "Verified mode price": "\u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0648\u062e\u064a\u062b \u062d\u0642\u0647\u0630\u062b", - "Verify Now": "\u062f\u062b\u0642\u0647\u0628\u063a \u0631\u062e\u0635", "Version": "\u062f\u062b\u0642\u0633\u0647\u062e\u0631", "Vertical space": "\u062f\u062b\u0642\u0641\u0647\u0630\u0634\u0645 \u0633\u062d\u0634\u0630\u062b", "Very loud": "\u062f\u062b\u0642\u063a \u0645\u062e\u0639\u064a", @@ -1872,16 +1933,19 @@ "View Teams in the {topic_name} Topic": "\u062f\u0647\u062b\u0635 \u0641\u062b\u0634\u0648\u0633 \u0647\u0631 \u0641\u0627\u062b {topic_name} \u0641\u062e\u062d\u0647\u0630", "View all errors": "\u062f\u0647\u062b\u0635 \u0634\u0645\u0645 \u062b\u0642\u0642\u062e\u0642\u0633", "View child items": "\u062f\u0647\u062b\u0635 \u0630\u0627\u0647\u0645\u064a \u0647\u0641\u062b\u0648\u0633", + "View discussion": "\u062f\u0647\u062b\u0635 \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631", "View {span_start} {team_name} {span_end}": "\u062f\u0647\u062b\u0635 {span_start} {team_name} {span_end}", "Viewing %s course": [ "\u062f\u0647\u062b\u0635\u0647\u0631\u0644 %s \u0630\u062e\u0639\u0642\u0633\u062b", "\u062f\u0647\u062b\u0635\u0647\u0631\u0644 %s \u0630\u062e\u0639\u0642\u0633\u062b\u0633" ], "Visibility": "\u062f\u0647\u0633\u0647\u0632\u0647\u0645\u0647\u0641\u063a", + "Visible to": "\u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e", "Visible to Staff Only": "\u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u0633\u0641\u0634\u0628\u0628 \u062e\u0631\u0645\u063a", "Visual aids": "\u062f\u0647\u0633\u0639\u0634\u0645 \u0634\u0647\u064a\u0633", "Volume": "\u062f\u062e\u0645\u0639\u0648\u062b", "Vote for good posts and responses": "\u062f\u062e\u0641\u062b \u0628\u062e\u0642 \u0644\u062e\u062e\u064a \u062d\u062e\u0633\u0641\u0633 \u0634\u0631\u064a \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b\u0633", + "Vote for this post,": "\u062f\u062e\u0641\u062b \u0628\u062e\u0642 \u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641,", "Want to confirm your identity later?": "\u0635\u0634\u0631\u0641 \u0641\u062e \u0630\u062e\u0631\u0628\u0647\u0642\u0648 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0645\u0634\u0641\u062b\u0642?", "Warning": "\u0635\u0634\u0642\u0631\u0647\u0631\u0644", "Warnings": "\u0635\u0634\u0642\u0631\u0647\u0631\u0644\u0633", @@ -1890,9 +1954,11 @@ "We couldn't find any results for \"%s\".": "\u0635\u062b \u0630\u062e\u0639\u0645\u064a\u0631'\u0641 \u0628\u0647\u0631\u064a \u0634\u0631\u063a \u0642\u062b\u0633\u0639\u0645\u0641\u0633 \u0628\u062e\u0642 \"%s\".", "We couldn't sign you in.": "\u0635\u062b \u0630\u062e\u0639\u0645\u064a\u0631'\u0641 \u0633\u0647\u0644\u0631 \u063a\u062e\u0639 \u0647\u0631.", "We have encountered an error. Refresh your browser and then try again.": "\u0635\u062b \u0627\u0634\u062f\u062b \u062b\u0631\u0630\u062e\u0639\u0631\u0641\u062b\u0642\u062b\u064a \u0634\u0631 \u062b\u0642\u0642\u062e\u0642. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u063a\u062e\u0639\u0642 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u0634\u0631\u064a \u0641\u0627\u062b\u0631 \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "\u0635\u062b \u0627\u0634\u062f\u062b \u0642\u062b\u0630\u062b\u0647\u062f\u062b\u064a \u063a\u062e\u0639\u0642 \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u0634\u0642\u062b \u062f\u062b\u0642\u0647\u0628\u063a\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a. \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0633\u062b\u062b \u0634 \u0648\u062b\u0633\u0633\u0634\u0644\u062b \u062e\u0631 \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a \u0635\u0627\u062b\u0631 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633 \u0647\u0633 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b (\u0639\u0633\u0639\u0634\u0645\u0645\u063a \u0635\u0647\u0641\u0627\u0647\u0631 1-2 \u064a\u0634\u063a\u0633). \u0647\u0631 \u0641\u0627\u062b \u0648\u062b\u0634\u0631\u0641\u0647\u0648\u062b, \u063a\u062e\u0639 \u0630\u0634\u0631 \u0633\u0641\u0647\u0645\u0645 \u0634\u0630\u0630\u062b\u0633\u0633 \u0634\u0645\u0645 \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0630\u062e\u0631\u0641\u062b\u0631\u0641.", + "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days). In the meantime, you can still access all available course content.": "\u0635\u062b \u0627\u0634\u062f\u062b \u0642\u062b\u0630\u062b\u0647\u062f\u062b\u064a \u063a\u062e\u0639\u0642 \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u0634\u0642\u062b \u062f\u062b\u0642\u0647\u0628\u063a\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a. \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0633\u062b\u062b \u0634 \u0648\u062b\u0633\u0633\u0634\u0644\u062b \u062e\u0631 \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a \u0635\u0627\u062b\u0631 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633 \u0647\u0633 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b (\u0639\u0633\u0639\u0634\u0645\u0645\u063a \u0635\u0647\u0641\u0627\u0647\u0631 5-7 \u064a\u0634\u063a\u0633). \u0647\u0631 \u0641\u0627\u062b \u0648\u062b\u0634\u0631\u0641\u0647\u0648\u062b, \u063a\u062e\u0639 \u0630\u0634\u0631 \u0633\u0641\u0647\u0645\u0645 \u0634\u0630\u0630\u062b\u0633\u0633 \u0634\u0645\u0645 \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0630\u062e\u0631\u0641\u062b\u0631\u0641.", "We just need a little more information before you start learning with %(platformName)s.": "\u0635\u062b \u062a\u0639\u0633\u0641 \u0631\u062b\u062b\u064a \u0634 \u0645\u0647\u0641\u0641\u0645\u062b \u0648\u062e\u0642\u062b \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0632\u062b\u0628\u062e\u0642\u062b \u063a\u062e\u0639 \u0633\u0641\u0634\u0642\u0641 \u0645\u062b\u0634\u0642\u0631\u0647\u0631\u0644 \u0635\u0647\u0641\u0627 %(platformName)s.", + "We securely encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "\u0635\u062b \u0633\u062b\u0630\u0639\u0642\u062b\u0645\u063a \u062b\u0631\u0630\u0642\u063a\u062d\u0641 \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e \u0634\u0631\u064a \u0633\u062b\u0631\u064a \u0647\u0641 \u0641\u062e \u062e\u0639\u0642 \u0634\u0639\u0641\u0627\u062e\u0642\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0633\u062b\u0642\u062f\u0647\u0630\u062b \u0628\u062e\u0642 \u0642\u062b\u062f\u0647\u062b\u0635. \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e \u0634\u0631\u064a \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0634\u0642\u062b \u0631\u062e\u0641 \u0633\u0634\u062f\u062b\u064a \u062e\u0642 \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0634\u0631\u063a\u0635\u0627\u062b\u0642\u062b \u062e\u0631 %(platformName)s \u0634\u0628\u0641\u062b\u0642 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633 \u0647\u0633 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "\u0635\u062b \u0639\u0633\u062b \u0641\u0627\u062b \u0627\u0647\u0644\u0627\u062b\u0633\u0641 \u0645\u062b\u062f\u062b\u0645\u0633 \u062e\u0628 \u0633\u062b\u0630\u0639\u0642\u0647\u0641\u063a \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b \u0641\u062e \u062b\u0631\u0630\u0642\u063a\u062d\u0641 \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e \u0634\u0631\u064a \u0633\u062b\u0631\u064a \u0647\u0641 \u0641\u062e \u062e\u0639\u0642 \u0634\u0639\u0641\u0627\u062e\u0642\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0633\u062b\u0642\u062f\u0647\u0630\u062b \u0628\u062e\u0642 \u0642\u062b\u062f\u0647\u062b\u0635. \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e \u0634\u0631\u064a \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0634\u0642\u062b \u0631\u062e\u0641 \u0633\u0634\u062f\u062b\u064a \u062e\u0642 \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0634\u0631\u063a\u0635\u0627\u062b\u0642\u062b \u062e\u0631 %(platformName)s \u0634\u0628\u0641\u062b\u0642 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633 \u0647\u0633 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b.", + "We use your verification photos to confirm your identity and ensure the validity of your certificate.": "\u0635\u062b \u0639\u0633\u062b \u063a\u062e\u0639\u0642 \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0627\u062e\u0641\u062e\u0633 \u0641\u062e \u0630\u062e\u0631\u0628\u0647\u0642\u0648 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0634\u0631\u064a \u062b\u0631\u0633\u0639\u0642\u062b \u0641\u0627\u062b \u062f\u0634\u0645\u0647\u064a\u0647\u0641\u063a \u062e\u0628 \u063a\u062e\u0639\u0642 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b.", "We're sorry to see you go! Your account will be deleted shortly.": "\u0635\u062b'\u0642\u062b \u0633\u062e\u0642\u0642\u063a \u0641\u062e \u0633\u062b\u062b \u063a\u062e\u0639 \u0644\u062e! \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0635\u0647\u0645\u0645 \u0632\u062b \u064a\u062b\u0645\u062b\u0641\u062b\u064a \u0633\u0627\u062e\u0642\u0641\u0645\u063a.", "We're sorry, there was an error": "\u0635\u062b'\u0642\u062b \u0633\u062e\u0642\u0642\u063a, \u0641\u0627\u062b\u0642\u062b \u0635\u0634\u0633 \u0634\u0631 \u062b\u0642\u0642\u062e\u0642", "We've encountered an error. Refresh your browser and then try again.": "\u0635\u062b'\u062f\u062b \u062b\u0631\u0630\u062e\u0639\u0631\u0641\u062b\u0642\u062b\u064a \u0634\u0631 \u062b\u0642\u0642\u062e\u0642. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u063a\u062e\u0639\u0642 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u0634\u0631\u064a \u0641\u0627\u062b\u0631 \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", @@ -1915,6 +1981,7 @@ "When learners submit an answer to an assessment, they immediately see whether the answer is correct or incorrect, and the score received.": "\u0635\u0627\u062b\u0631 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0633\u0639\u0632\u0648\u0647\u0641 \u0634\u0631 \u0634\u0631\u0633\u0635\u062b\u0642 \u0641\u062e \u0634\u0631 \u0634\u0633\u0633\u062b\u0633\u0633\u0648\u062b\u0631\u0641, \u0641\u0627\u062b\u063a \u0647\u0648\u0648\u062b\u064a\u0647\u0634\u0641\u062b\u0645\u063a \u0633\u062b\u062b \u0635\u0627\u062b\u0641\u0627\u062b\u0642 \u0641\u0627\u062b \u0634\u0631\u0633\u0635\u062b\u0642 \u0647\u0633 \u0630\u062e\u0642\u0642\u062b\u0630\u0641 \u062e\u0642 \u0647\u0631\u0630\u062e\u0642\u0642\u062b\u0630\u0641, \u0634\u0631\u064a \u0641\u0627\u062b \u0633\u0630\u062e\u0642\u062b \u0642\u062b\u0630\u062b\u0647\u062f\u062b\u064a.", "When your face is in position, use the Take Photo button {icon} below to take your photo.": "\u0635\u0627\u062b\u0631 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b \u0647\u0633 \u0647\u0631 \u062d\u062e\u0633\u0647\u0641\u0647\u062e\u0631, \u0639\u0633\u062b \u0641\u0627\u062b \u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e \u0632\u0639\u0641\u0641\u062e\u0631 {icon} \u0632\u062b\u0645\u062e\u0635 \u0641\u062e \u0641\u0634\u0646\u062b \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e.", "Which timed transcript would you like to use?": "\u0635\u0627\u0647\u0630\u0627 \u0641\u0647\u0648\u062b\u064a \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641 \u0635\u062e\u0639\u0645\u064a \u063a\u062e\u0639 \u0645\u0647\u0646\u062b \u0641\u062e \u0639\u0633\u062b?", + "While our support team is happy to assist with the edX platform, the course staff has the expertise for specific assignment questions, grading or the proper procedures in each course. Please post all course related questions within the Discussion Forum where the Course Staff can directly respond.": "\u0635\u0627\u0647\u0645\u062b \u062e\u0639\u0642 \u0633\u0639\u062d\u062d\u062e\u0642\u0641 \u0641\u062b\u0634\u0648 \u0647\u0633 \u0627\u0634\u062d\u062d\u063a \u0641\u062e \u0634\u0633\u0633\u0647\u0633\u0641 \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u062b\u064a\u0637 \u062d\u0645\u0634\u0641\u0628\u062e\u0642\u0648, \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0633\u0641\u0634\u0628\u0628 \u0627\u0634\u0633 \u0641\u0627\u062b \u062b\u0637\u062d\u062b\u0642\u0641\u0647\u0633\u062b \u0628\u062e\u0642 \u0633\u062d\u062b\u0630\u0647\u0628\u0647\u0630 \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641 \u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631\u0633, \u0644\u0642\u0634\u064a\u0647\u0631\u0644 \u062e\u0642 \u0641\u0627\u062b \u062d\u0642\u062e\u062d\u062b\u0642 \u062d\u0642\u062e\u0630\u062b\u064a\u0639\u0642\u062b\u0633 \u0647\u0631 \u062b\u0634\u0630\u0627 \u0630\u062e\u0639\u0642\u0633\u062b. \u062d\u0645\u062b\u0634\u0633\u062b \u062d\u062e\u0633\u0641 \u0634\u0645\u0645 \u0630\u062e\u0639\u0642\u0633\u062b \u0642\u062b\u0645\u0634\u0641\u062b\u064a \u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631\u0633 \u0635\u0647\u0641\u0627\u0647\u0631 \u0641\u0627\u062b \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0628\u062e\u0642\u0639\u0648 \u0635\u0627\u062b\u0642\u062b \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0633\u0641\u0634\u0628\u0628 \u0630\u0634\u0631 \u064a\u0647\u0642\u062b\u0630\u0641\u0645\u063a \u0642\u062b\u0633\u062d\u062e\u0631\u064a.", "Whole words": "\u0635\u0627\u062e\u0645\u062b \u0635\u062e\u0642\u064a\u0633", "Why activate?": "\u0635\u0627\u063a \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u062b?", "Why does %(platformName)s need my photo?": "\u0635\u0627\u063a \u064a\u062e\u062b\u0633 %(platformName)s \u0631\u062b\u062b\u064a \u0648\u063a \u062d\u0627\u062e\u0641\u062e?", @@ -1987,14 +2054,13 @@ "You must specify a name": "\u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0633\u062d\u062b\u0630\u0647\u0628\u063a \u0634 \u0631\u0634\u0648\u062b", "You must specify a name for the cohort": "\u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0633\u062d\u062b\u0630\u0647\u0628\u063a \u0634 \u0631\u0634\u0648\u062b \u0628\u062e\u0642 \u0641\u0627\u062b \u0630\u062e\u0627\u062e\u0642\u0641", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0633\u062d\u062b\u0630\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0632\u0647\u0642\u0641\u0627 \u063a\u062b\u0634\u0642 \u0632\u062b\u0628\u062e\u0642\u062b \u063a\u062e\u0639 \u0630\u0634\u0631 \u0633\u0627\u0634\u0642\u062b \u063a\u062e\u0639\u0642 \u0628\u0639\u0645\u0645 \u062d\u0642\u062e\u0628\u0647\u0645\u062b. \u0641\u062e \u0633\u062d\u062b\u0630\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0632\u0647\u0642\u0641\u0627 \u063a\u062b\u0634\u0642, \u0644\u062e \u0641\u062e \u0641\u0627\u062b {account_settings_page_link}", - "You need a computer or cell phone that has a webcam. When you receive a browser prompt, make sure that you allow access to the camera.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634 \u0630\u062e\u0648\u062d\u0639\u0641\u062b\u0642 \u062e\u0642 \u0630\u062b\u0645\u0645 \u062d\u0627\u062e\u0631\u062b \u0641\u0627\u0634\u0641 \u0627\u0634\u0633 \u0634 \u0635\u062b\u0632\u0630\u0634\u0648. \u0635\u0627\u062b\u0631 \u063a\u062e\u0639 \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u0634 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u062d\u0642\u062e\u0648\u062d\u0641, \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u0627\u0634\u0641 \u063a\u062e\u0639 \u0634\u0645\u0645\u062e\u0635 \u0634\u0630\u0630\u062b\u0633\u0633 \u0641\u062e \u0641\u0627\u062b \u0630\u0634\u0648\u062b\u0642\u0634.", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634 \u064a\u0642\u0647\u062f\u062b\u0642'\u0633 \u0645\u0647\u0630\u062b\u0631\u0633\u062b, \u062d\u0634\u0633\u0633\u062d\u062e\u0642\u0641, \u062e\u0642 \u062e\u0641\u0627\u062b\u0642 \u0644\u062e\u062f\u062b\u0642\u0631\u0648\u062b\u0631\u0641-\u0647\u0633\u0633\u0639\u062b\u064a \u0647\u064a \u0641\u0627\u0634\u0641 \u0627\u0634\u0633 \u063a\u062e\u0639\u0642 \u0631\u0634\u0648\u062b \u0634\u0631\u064a \u062d\u0627\u062e\u0641\u062e.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634\u0631 \u0647\u064a \u0635\u0647\u0641\u0627 \u063a\u062e\u0639\u0642 \u0631\u0634\u0648\u062b \u0634\u0631\u064a \u062d\u0627\u062e\u0641\u062e. \u0634 \u064a\u0642\u0647\u062f\u062b\u0642'\u0633 \u0645\u0647\u0630\u062b\u0631\u0633\u062b, \u062d\u0634\u0633\u0633\u062d\u062e\u0642\u0641, \u062e\u0642 \u062e\u0641\u0627\u062b\u0642 \u0644\u062e\u062f\u062b\u0642\u0631\u0648\u062b\u0631\u0641-\u0647\u0633\u0633\u0639\u062b\u064a \u0647\u064a\u0633 \u0634\u0642\u062b \u0634\u0645\u0645 \u0634\u0630\u0630\u062b\u062d\u0641\u0634\u0632\u0645\u062b.", + "You need a device that has a webcam. If you receive a browser prompt for access to your camera, please make sure to click 'Allow'.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634 \u064a\u062b\u062f\u0647\u0630\u062b \u0641\u0627\u0634\u0641 \u0627\u0634\u0633 \u0634 \u0635\u062b\u0632\u0630\u0634\u0648. \u0647\u0628 \u063a\u062e\u0639 \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u0634 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u062d\u0642\u062e\u0648\u062d\u0641 \u0628\u062e\u0642 \u0634\u0630\u0630\u062b\u0633\u0633 \u0641\u062e \u063a\u062e\u0639\u0642 \u0630\u0634\u0648\u062b\u0642\u0634, \u062d\u0645\u062b\u0634\u0633\u062b \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u062e \u0630\u0645\u0647\u0630\u0646 '\u0634\u0645\u0645\u062e\u0635'.", + "You need a valid ID that contains your full name and photo.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634 \u062f\u0634\u0645\u0647\u064a \u0647\u064a \u0641\u0627\u0634\u0641 \u0630\u062e\u0631\u0641\u0634\u0647\u0631\u0633 \u063a\u062e\u0639\u0642 \u0628\u0639\u0645\u0645 \u0631\u0634\u0648\u062b \u0634\u0631\u064a \u062d\u0627\u062e\u0641\u062e.", + "You need an ID with your name and photo. A driver's license, passport, or ID are all acceptable.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634\u0631 \u0647\u064a \u0635\u0647\u0641\u0627 \u063a\u062e\u0639\u0642 \u0631\u0634\u0648\u062b \u0634\u0631\u064a \u062d\u0627\u062e\u0641\u062e. \u0634 \u064a\u0642\u0647\u062f\u062b\u0642'\u0633 \u0645\u0647\u0630\u062b\u0631\u0633\u062b, \u062d\u0634\u0633\u0633\u062d\u062e\u0642\u0641, \u062e\u0642 \u0647\u064a \u0634\u0642\u062b \u0634\u0645\u0645 \u0634\u0630\u0630\u062b\u062d\u0641\u0634\u0632\u0645\u062b.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0641\u062e \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u062b \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0632\u062b\u0628\u062e\u0642\u062b \u063a\u062e\u0639 \u0630\u0634\u0631 \u062b\u0631\u0642\u062e\u0645\u0645 \u0647\u0631 \u0630\u062e\u0639\u0642\u0633\u062b\u0633. \u0630\u0627\u062b\u0630\u0646 \u063a\u062e\u0639\u0642 \u0647\u0631\u0632\u062e\u0637 \u0628\u062e\u0642 \u0634\u0631 \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u0647\u062e\u0631 \u062b\u0648\u0634\u0647\u0645.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0641\u062e \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u062b \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0632\u062b\u0628\u062e\u0642\u062b \u063a\u062e\u0639 \u0630\u0634\u0631 \u062b\u0631\u0642\u062e\u0645\u0645 \u0647\u0631 \u0630\u062e\u0639\u0642\u0633\u062b\u0633. \u0630\u0627\u062b\u0630\u0646 \u063a\u062e\u0639\u0642 \u0647\u0631\u0632\u062e\u0637 \u0628\u062e\u0642 \u0634\u0631 \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u0647\u062e\u0631 \u062b\u0648\u0634\u0647\u0645. \u0634\u0628\u0641\u062b\u0642 \u063a\u062e\u0639 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u0647\u062e\u0631 \u063a\u062e\u0639 \u0630\u0634\u0631 \u0642\u062b\u0641\u0639\u0642\u0631 \u0634\u0631\u064a \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u0647\u0633 \u062d\u0634\u0644\u062b.", "You receive messages from {platform_name} and course teams at this address.": "\u063a\u062e\u0639 \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u0648\u062b\u0633\u0633\u0634\u0644\u062b\u0633 \u0628\u0642\u062e\u0648 {platform_name} \u0634\u0631\u064a \u0630\u062e\u0639\u0642\u0633\u062b \u0641\u062b\u0634\u0648\u0633 \u0634\u0641 \u0641\u0627\u0647\u0633 \u0634\u064a\u064a\u0642\u062b\u0633\u0633.", "You reserve all rights for your work": "\u063a\u062e\u0639 \u0642\u062b\u0633\u062b\u0642\u062f\u062b \u0634\u0645\u0645 \u0642\u0647\u0644\u0627\u0641\u0633 \u0628\u062e\u0642 \u063a\u062e\u0639\u0642 \u0635\u062e\u0642\u0646", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u063a\u062e\u0639 \u0633\u0641\u0647\u0645\u0645 \u0631\u062b\u062b\u064a \u0641\u062e \u062f\u0647\u0633\u0647\u0641 \u0641\u0627\u062b %(display_name)s \u0635\u062b\u0632\u0633\u0647\u0641\u062b \u0641\u062e \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0641\u0627\u062b \u0630\u0642\u062b\u064a\u0647\u0641 \u062d\u0642\u062e\u0630\u062b\u0633\u0633.", "You submitted {filename}; only {allowedFiles} are allowed.": "\u063a\u062e\u0639 \u0633\u0639\u0632\u0648\u0647\u0641\u0641\u062b\u064a {filename}; \u062e\u0631\u0645\u063a {allowedFiles} \u0634\u0642\u062b \u0634\u0645\u0645\u062e\u0635\u062b\u064a.", "You waive some rights for your work, such that others can use it too": "\u063a\u062e\u0639 \u0635\u0634\u0647\u062f\u062b \u0633\u062e\u0648\u062b \u0642\u0647\u0644\u0627\u0641\u0633 \u0628\u062e\u0642 \u063a\u062e\u0639\u0642 \u0635\u062e\u0642\u0646, \u0633\u0639\u0630\u0627 \u0641\u0627\u0634\u0641 \u062e\u0641\u0627\u062b\u0642\u0633 \u0630\u0634\u0631 \u0639\u0633\u062b \u0647\u0641 \u0641\u062e\u062e", "You will be refunded the amount you paid.": "\u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0632\u062b \u0642\u062b\u0628\u0639\u0631\u064a\u062b\u064a \u0641\u0627\u062b \u0634\u0648\u062e\u0639\u0631\u0641 \u063a\u062e\u0639 \u062d\u0634\u0647\u064a.", @@ -2061,6 +2127,7 @@ "and others": "\u0634\u0631\u064a \u062e\u0641\u0627\u062b\u0642\u0633", "anonymous": "\u0634\u0631\u062e\u0631\u063a\u0648\u062e\u0639\u0633", "answer": "\u0634\u0631\u0633\u0635\u062b\u0642", + "answered question": "\u0634\u0631\u0633\u0635\u062b\u0642\u062b\u064a \u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631", "asset_path is required": "\u0634\u0633\u0633\u062b\u0641_\u062d\u0634\u0641\u0627 \u0647\u0633 \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a", "bytes": "\u0632\u063a\u0641\u062b\u0633", "certificate": "\u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b", @@ -2072,6 +2139,8 @@ "delete chapter": "\u064a\u062b\u0645\u062b\u0641\u062b \u0630\u0627\u0634\u062d\u0641\u062b\u0642", "delete group": "\u064a\u062b\u0645\u062b\u0641\u062b \u0644\u0642\u062e\u0639\u062d", "details about the failure": "\u064a\u062b\u0641\u0634\u0647\u0645\u0633 \u0634\u0632\u062e\u0639\u0641 \u0641\u0627\u062b \u0628\u0634\u0647\u0645\u0639\u0642\u062b", + "discussion": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631", + "discussion posted %(time_ago)s by %(author)s": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u062d\u062e\u0633\u0641\u062b\u064a %(time_ago)s \u0632\u063a %(author)s", "dragging": "\u064a\u0642\u0634\u0644\u0644\u0647\u0631\u0644", "dragging out of slider": "\u064a\u0642\u0634\u0644\u0644\u0647\u0631\u0644 \u062e\u0639\u0641 \u062e\u0628 \u0633\u0645\u0647\u064a\u062b\u0642", "dropped in slider": "\u064a\u0642\u062e\u062d\u062d\u062b\u064a \u0647\u0631 \u0633\u0645\u0647\u064a\u062b\u0642", @@ -2081,15 +2150,19 @@ "e.g. 'http://google.com'": "\u062b.\u0644. '\u0627\u0641\u0641\u062d://\u0644\u062e\u062e\u0644\u0645\u062b.\u0630\u062e\u0648'", "e.g. johndoe@example.com, JaneDoe, joeydoe@example.com": "\u062b.\u0644. \u062a\u062e\u0627\u0631\u064a\u062e\u062b@\u062b\u0637\u0634\u0648\u062d\u0645\u062b.\u0630\u062e\u0648, \u062a\u0634\u0631\u062b\u064a\u062e\u062b, \u062a\u062e\u062b\u063a\u064a\u062e\u062b@\u062b\u0637\u0634\u0648\u062d\u0645\u062b.\u0630\u062e\u0648", "emphasized text": "\u062b\u0648\u062d\u0627\u0634\u0633\u0647\u0638\u062b\u064a \u0641\u062b\u0637\u0641", + "endorsed %(time_ago)s": "\u062b\u0631\u064a\u062e\u0642\u0633\u062b\u064a %(time_ago)s", + "endorsed %(time_ago)s by %(user)s": "\u062b\u0631\u064a\u062e\u0642\u0633\u062b\u064a %(time_ago)s \u0632\u063a %(user)s", "enter code here": "\u062b\u0631\u0641\u062b\u0642 \u0630\u062e\u064a\u062b \u0627\u062b\u0642\u062b", "enter link description here": "\u062b\u0631\u0641\u062b\u0642 \u0645\u0647\u0631\u0646 \u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631 \u0627\u062b\u0642\u062b", + "follow this post": "\u0628\u062e\u0645\u0645\u062e\u0635 \u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641", "for": "\u0628\u062e\u0642", - "for {courseName}": "\u0628\u062e\u0642 {courseName}", "group configuration": "\u0644\u0642\u062e\u0639\u062d \u0630\u062e\u0631\u0628\u0647\u0644\u0639\u0642\u0634\u0641\u0647\u062e\u0631", "image omitted": "\u0647\u0648\u0634\u0644\u062b \u062e\u0648\u0647\u0641\u0641\u062b\u064a", "incorrect": "\u0647\u0631\u0630\u062e\u0642\u0642\u062b\u0630\u0641", "last activity": "\u0645\u0634\u0633\u0641 \u0634\u0630\u0641\u0647\u062f\u0647\u0641\u063a", "less than a minute": "\u0645\u062b\u0633\u0633 \u0641\u0627\u0634\u0631 \u0634 \u0648\u0647\u0631\u0639\u0641\u062b", + "marked as answer %(time_ago)s": "\u0648\u0634\u0642\u0646\u062b\u064a \u0634\u0633 \u0634\u0631\u0633\u0635\u062b\u0642 %(time_ago)s", + "marked as answer %(time_ago)s by %(user)s": "\u0648\u0634\u0642\u0646\u062b\u064a \u0634\u0633 \u0634\u0631\u0633\u0635\u062b\u0642 %(time_ago)s \u0632\u063a %(user)s", "minute": "\u0648\u0647\u0631\u0639\u0641\u062b", "minutes": "\u0648\u0647\u0631\u0639\u0641\u062b\u0633", "name": "\u0631\u0634\u0648\u062b", @@ -2100,9 +2173,13 @@ "or create a new one here": "\u062e\u0642 \u0630\u0642\u062b\u0634\u0641\u062b \u0634 \u0631\u062b\u0635 \u062e\u0631\u062b \u0627\u062b\u0642\u062b", "or sign in with": "\u062e\u0642 \u0633\u0647\u0644\u0631 \u0647\u0631 \u0635\u0647\u0641\u0627", "path/to/introductionToCookieBaking-CH{order}.pdf": "\u062d\u0634\u0641\u0627/\u0641\u062e/\u0647\u0631\u0641\u0642\u062e\u064a\u0639\u0630\u0641\u0647\u062e\u0631\u0641\u062e\u0630\u062e\u062e\u0646\u0647\u062b\u0632\u0634\u0646\u0647\u0631\u0644-\u0630\u0627{order}.\u062d\u064a\u0628", + "post anonymously": "\u062d\u062e\u0633\u0641 \u0634\u0631\u062e\u0631\u063a\u0648\u062e\u0639\u0633\u0645\u063a", + "post anonymously to classmates": "\u062d\u062e\u0633\u0641 \u0634\u0631\u062e\u0631\u063a\u0648\u062e\u0639\u0633\u0645\u063a \u0641\u062e \u0630\u0645\u0634\u0633\u0633\u0648\u0634\u0641\u062b\u0633", + "posted %(time_ago)s by %(author)s": "\u062d\u062e\u0633\u0641\u062b\u064a %(time_ago)s \u0632\u063a %(author)s", "price": "\u062d\u0642\u0647\u0630\u062b", "provide the title/name of the chapter that will be used in navigating": "\u062d\u0642\u062e\u062f\u0647\u064a\u062b \u0641\u0627\u062b \u0641\u0647\u0641\u0645\u062b/\u0631\u0634\u0648\u062b \u062e\u0628 \u0641\u0627\u062b \u0630\u0627\u0634\u062d\u0641\u062b\u0642 \u0641\u0627\u0634\u0641 \u0635\u0647\u0645\u0645 \u0632\u062b \u0639\u0633\u062b\u064a \u0647\u0631 \u0631\u0634\u062f\u0647\u0644\u0634\u0641\u0647\u0631\u0644", "provide the title/name of the text book as you would like your students to see it": "\u062d\u0642\u062e\u062f\u0647\u064a\u062b \u0641\u0627\u062b \u0641\u0647\u0641\u0645\u062b/\u0631\u0634\u0648\u062b \u062e\u0628 \u0641\u0627\u062b \u0641\u062b\u0637\u0641 \u0632\u062e\u062e\u0646 \u0634\u0633 \u063a\u062e\u0639 \u0635\u062e\u0639\u0645\u064a \u0645\u0647\u0646\u062b \u063a\u062e\u0639\u0642 \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633 \u0641\u062e \u0633\u062b\u062b \u0647\u0641", + "question posted %(time_ago)s by %(author)s": "\u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631 \u062d\u062e\u0633\u0641\u062b\u064a %(time_ago)s \u0632\u063a %(author)s", "remove": "\u0642\u062b\u0648\u062e\u062f\u062b", "remove all": "\u0642\u062b\u0648\u062e\u062f\u062b \u0634\u0645\u0645", "second": "\u0633\u062b\u0630\u062e\u0631\u064a", @@ -2114,6 +2191,7 @@ "team count": "\u0641\u062b\u0634\u0648 \u0630\u062e\u0639\u0631\u0641", "text_word_{uniqueId}": "\u0641\u062b\u0637\u0641_\u0635\u062e\u0642\u064a_{uniqueId}", "text_word_{uniqueId} title_word_{uniqueId}": "\u0641\u062b\u0637\u0641_\u0635\u062e\u0642\u064a_{uniqueId} \u0641\u0647\u0641\u0645\u062b_\u0635\u062e\u0642\u064a_{uniqueId}", + "the more quickly and helpfully we can respond!": "\u0641\u0627\u062b \u0648\u062e\u0642\u062b \u0636\u0639\u0647\u0630\u0646\u0645\u063a \u0634\u0631\u064a \u0627\u062b\u0645\u062d\u0628\u0639\u0645\u0645\u063a \u0635\u062b \u0630\u0634\u0631 \u0642\u062b\u0633\u062d\u062e\u0631\u064a!", "there is currently {numVotes} vote": [ "\u0641\u0627\u062b\u0642\u062b \u0647\u0633 \u0630\u0639\u0642\u0642\u062b\u0631\u0641\u0645\u063a {numVotes} \u062f\u062e\u0641\u062b", "\u0641\u0627\u062b\u0642\u062b \u0634\u0642\u062b \u0630\u0639\u0642\u0642\u062b\u0631\u0641\u0645\u063a {numVotes} \u062f\u062e\u0641\u062b\u0633" @@ -2121,6 +2199,7 @@ "title_word_{uniqueId}": "\u0641\u0647\u0641\u0645\u062b_\u0635\u062e\u0642\u064a_{uniqueId}", "toggle chapter %(displayName)s": "\u0641\u062e\u0644\u0644\u0645\u062b \u0630\u0627\u0634\u062d\u0641\u062b\u0642 %(displayName)s", "toggle subsection %(displayName)s": "\u0641\u062e\u0644\u0644\u0645\u062b \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631 %(displayName)s", + "unanswered question": "\u0639\u0631\u0634\u0631\u0633\u0635\u062b\u0642\u062b\u064a \u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631", "unit": "\u0639\u0631\u0647\u0641", "unsubmitted": "\u0639\u0631\u0633\u0639\u0632\u0648\u0647\u0641\u0641\u062b\u064a", "upload a PDF file or provide the path to a Studio asset file": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634 \u062d\u064a\u0628 \u0628\u0647\u0645\u062b \u062e\u0642 \u062d\u0642\u062e\u062f\u0647\u064a\u062b \u0641\u0627\u062b \u062d\u0634\u0641\u0627 \u0641\u062e \u0634 \u0633\u0641\u0639\u064a\u0647\u062e \u0634\u0633\u0633\u062b\u0641 \u0628\u0647\u0645\u062b", @@ -2217,6 +2296,7 @@ ], "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}": "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}", "{type} Progress": "{type} \u062d\u0642\u062e\u0644\u0642\u062b\u0633\u0633", + "{unread_comments_count} new": "{unread_comments_count} \u0631\u062b\u0635", "\u2026": "\u2026" }; for (var key in newcatalog) { @@ -2239,7 +2319,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2303,9 +2383,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/ru/djangojs.js b/cms/static/js/i18n/ru/djangojs.js index b52cf6d11bacd37aa7b8e4ecfe4ff7c2d6badd8a..885aa1addf59ccddb624fa3e7dd1972ea28e7c82 100644 --- a/cms/static/js/i18n/ru/djangojs.js +++ b/cms/static/js/i18n/ru/djangojs.js @@ -568,7 +568,6 @@ "Default (Local Time Zone)": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e (\u043c\u0435\u0441\u0442\u043d\u044b\u0439 \u0447\u0430\u0441\u043e\u0432\u043e\u0439 \u043f\u043e\u044f\u0441)", "Default Timed Transcript": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e", "Delete": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u00ab<%= signatoryName %>\u00bb \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u0435\u043b\u0435\u0439?", "Delete File Confirmation": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430", "Delete My Account": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043c\u043e\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442", "Delete Team": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443", @@ -604,7 +603,6 @@ "Do you want to upload your file before submitting?": "\u0412\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u0434\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043e\u0442\u0432\u0435\u0442\u0430?", "Document properties": "\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430", "Does the name on your ID match your account name: %(fullName)s?": "\u0421\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043b\u0438 \u0438\u043c\u044f \u0432 \u0432\u0430\u0448\u0435\u043c \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0438 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u0432 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438: %(fullName)s?", - "Does the photo of you match your ID photo?": "\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c\u0430 \u043b\u0438 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f \u0441 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0435\u0439 \u0432 \u0432\u0430\u0448\u0435\u043c \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0438 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438?", "Does the photo of you show your whole face?": "\u0412\u0438\u0434\u043d\u043e \u043b\u0438 \u043d\u0430 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 \u0432\u0430\u0448\u0435 \u043b\u0438\u0446\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c?", "Doing so means that you are no longer eligible for academic credit.": "\u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u0430\u0447\u0451\u0442\u043d\u044b\u0439 \u0431\u0430\u043b\u043b\u044b.", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u041d\u0435 \u0432\u0438\u0434\u0438\u0442\u0435 \u0432\u0430\u0448\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435? \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u044b \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u043b\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0431-\u043a\u0430\u043c\u0435\u0440\u0443, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u043a \u043d\u0435\u0439 \u0434\u043e\u0441\u0442\u0443\u043f.", @@ -777,7 +775,6 @@ "Generate": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c", "Generate Exception Certificates": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b \u0434\u043b\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432", "Generate the user's certificate": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442", - "Get Credit": "\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u0430\u0447\u0451\u0442", "Go Back": "\u0412\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f", "Go to Dashboard": "\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f", "Go to my Dashboard": "\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043c\u043e\u0435\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f", @@ -851,7 +848,6 @@ "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u0415\u0441\u043b\u0438 \u0431\u043b\u043e\u043a \u0431\u044b\u043b \u043f\u0440\u0435\u0436\u0434\u0435 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044f\u043c, \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u0432\u043d\u0435\u0441\u0451\u043d\u043d\u044b\u0435 \u0432 \u043d\u0435\u0433\u043e, \u043f\u043e\u043a\u0430 \u043e\u043d \u0431\u044b\u043b \u0441\u043a\u0440\u044b\u0442, \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0435\u0439.", "If you do not yet have an account, use the button below to register.": "\u0415\u0449\u0451 \u043d\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b? \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u043d\u0438\u0436\u0435.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u0441\u0432\u043e\u0438 \u0434\u0430\u043d\u043d\u044b\u0435, \u0432\u044b \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u0443\u0440\u0441 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u043d\u0435\u043b\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0412\u044b \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0443\u0434\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u00ab%(platformName)s\u00bb.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u0441\u0432\u043e\u044e \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441, \u0432\u044b \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u0443\u0440\u0441\u0443 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u043d\u0435\u043b\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0412\u044b \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0443\u0434\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u00ab{platformName}\u00bb.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043a\u0438\u043d\u0435\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0432 \u0438\u043b\u0438 \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0432 \u0441\u0432\u043e\u0439 \u043e\u0442\u0432\u0435\u0442, \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0439 \u0432\u0430\u043c\u0438 \u043e\u0442\u0432\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0442\u0435\u0440\u044f\u043d.", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043a\u0438\u043d\u0435\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0432 \u0432\u0430\u0448\u0443 \u043e\u0446\u0435\u043d\u043a\u0443, \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u0432\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u044b.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043a\u0438\u043d\u0435\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0432 \u0438\u043b\u0438 \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0432 \u0441\u0432\u043e\u0439 \u043e\u0442\u0432\u0435\u0442, \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u0432\u0430\u043c\u0438 \u043e\u0442\u0432\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0442\u0435\u0440\u044f\u043d.", @@ -1495,7 +1491,6 @@ "Text to display": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442", "Textbook Name": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0443\u0447\u0435\u0431\u043d\u0438\u043a\u0430", "Textbook information": "\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u0443\u0447\u0435\u0431\u043d\u0438\u043a\u0435", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "\u0421\u043f\u0430\u0441\u0438\u0431\u043e, %(full_name)s! \u0412\u0430\u0448 \u043f\u043b\u0430\u0442\u0451\u0436 \u0437\u0430 \u043a\u0443\u0440\u0441 %(course_name)s \u043f\u0440\u0438\u043d\u044f\u0442.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u043c \u0432\u0430\u0441 \u0437\u0430 \u043f\u043e\u0434\u0430\u0447\u0443 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0433\u0440\u0430\u043d\u0442 \u043f\u043e \u043a\u0443\u0440\u0441\u0443 {course_name}! \u0412\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0442\u0432\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 2-4 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0434\u043d\u044f.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "\u0421\u043f\u0430\u0441\u0438\u0431\u043e, \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0444\u043e\u0442\u043e! \u041c\u044b \u0441\u043a\u043e\u0440\u043e \u0438\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c. \u0421\u0435\u0439\u0447\u0430\u0441 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u0438\u0437 \u043a\u0443\u0440\u0441\u043e\u0432 %(platformName)s, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0449\u0438\u0445 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b. \u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0434\u0438\u043d \u0433\u043e\u0434. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0444\u043e\u0442\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e.", "Thank you! We have received your payment for {courseName}.": "\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u043c \u0412\u0430\u0441! \u0412\u0430\u0448 \u043f\u043b\u0430\u0442\u0451\u0436 \u0437\u0430 \u043a\u0443\u0440\u0441 {courseName} \u043f\u0440\u0438\u043d\u044f\u0442.", @@ -1507,8 +1502,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0430\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043f\u0435\u0440\u0435\u0441\u0447\u0451\u0442 \u043e\u0446\u0435\u043d\u043a\u0438.", "The cohort cannot be added": "\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443", "The cohort cannot be saved": "\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u0421\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u0430\u044f \u0434\u043b\u0438\u043d\u0430 \u043a\u043e\u0434\u0430 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c <%=limit%> \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u0421\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u0430\u044f \u0434\u043b\u0438\u043d\u0430 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u043d\u043e\u043c\u0435\u0440\u0430 \u0438 \u043f\u0435\u0440\u0438\u043e\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u0430 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c <%=limit%> \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432.", "The country or region where you live.": "\u0421\u0442\u0440\u0430\u043d\u0430 \u0438\u043b\u0438 \u0440\u0435\u0433\u0438\u043e\u043d, \u0433\u0434\u0435 \u0432\u044b \u0436\u0438\u0432\u0451\u0442\u0435.", "The country that team members primarily identify with.": "\u0421\u0442\u0440\u0430\u043d\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043e\u0442\u043e\u0436\u0434\u0435\u0441\u0442\u0432\u043b\u044f\u044e\u0442 \u0441\u0435\u0431\u044f.", "The course end date must be later than the course start date.": "\u0414\u0430\u0442\u0430 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u0434\u0430\u0442\u044b \u043d\u0430\u0447\u0430\u043b\u0430 \u043a\u0443\u0440\u0441\u0430.", @@ -1523,7 +1516,6 @@ "The following email addresses and/or usernames are invalid:": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0430\u0434\u0440\u0435\u0441\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u0438/\u0438\u043b\u0438 \u0438\u043c\u0435\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b:", "The following errors were generated:": "\u0431\u044b\u043b\u0438 \u0434\u043e\u043f\u0443\u0449\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 ", "The following file types are not allowed: ": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0442\u0438\u043f\u044b \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0443\u0436\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043d\u0430 {platform}.", "The following message will be displayed at the bottom of the courseware pages within your course:": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043e \u0432\u043d\u0438\u0437\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u043a\u0443\u0440\u0441\u0430:", "The following options are available for the {license_name} license.": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u043f\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438 {license_name}", "The following users are no longer enrolled in the course:": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043e\u0442\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u0441 \u043a\u0443\u0440\u0441\u0430:", @@ -1538,7 +1530,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432 \u043a\u0443\u0440\u0441\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430.", "The organization that this signatory belongs to, as it should appear on certificates.": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043b\u0438\u0446\u043e, \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0432\u0448\u0435\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442.", "The page \"{route}\" could not be found.": "\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u00ab{route}\u00bb \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430.", - "The photo of your face matches the photo on your ID.": "\u0424\u043e\u0442\u043e \u0432\u0430\u0448\u0435\u0433\u043e \u043b\u0438\u0446\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0444\u043e\u0442\u043e \u0432 \u0432\u0430\u0448\u0435\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435.", "The post you selected has been deleted.": "\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u0430\u044f \u0432\u0430\u043c\u0438 \u0442\u0435\u043c\u0430 \u0431\u044b\u043b\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0430.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f, {published}, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0430 \u043d\u0430 \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e, {draft}.", "The raw error message is:": "\u041f\u043e\u043b\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435:", @@ -1645,7 +1636,6 @@ "Titles more than 100 characters may prevent students from printing their certificate on a single page.": "\u0415\u0441\u043b\u0438 \u0434\u043b\u0438\u043d\u0430 \u0437\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u0442 100 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u043f\u0435\u0447\u0430\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0439\u0442\u0438 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.", "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "\u0427\u0442\u043e\u0431\u044b \u0431\u044b\u0442\u044c \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u043c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0438\u0434\u0435\u043e, \u043c\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445 .mp4 \u0438 .webm. \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u043d\u0438\u0436\u0435, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0444\u0430\u0439\u043b \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 YouTube \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f. \u041d\u0430 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044f \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e \u043f\u0435\u0440\u0432\u043e\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0435 \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u0435\u043e \u0438\u0437 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430.", "To complete the program, you must earn a verified certificate for each course.": "\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0440\u043e\u0439\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043a\u0443\u0440\u0441\u0443.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u0430\u0447\u0451\u0442\u043d\u044b\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u044b, %(display_name)s \u043e\u0442 %(platform_name)s \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u0434\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441.", "To invalidate a certificate for a particular learner, add the username or email address below.": "\u0414\u043b\u044f \u0430\u043d\u043d\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0441\u044e\u0434\u0430 \u0435\u0433\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441.", "To pass this exam, you must complete the problems in the time allowed.": "\u0412\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0432\u0441\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.", "To receive a certificate, you must also verify your identity before {date}.": "\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u044c \u0434\u043e {date}.", @@ -1751,7 +1741,6 @@ "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0436\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0439. \u0412\u0441\u0435 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0440\u0435\u0436\u0438\u043c\u0430 \u0437\u0430\u043f\u0438\u0441\u0438, \u0432\u0438\u0434\u044f\u0442 \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0442\u0435\u043c\u044b \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0439, \u043d\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438 \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c \u0440\u0435\u0436\u0438\u043c\u043e\u043c \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043d\u0430 \u0447\u0443\u0436\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f.", "Use my institution/campus credentials": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0439 \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c", "Use the All Topics menu to find specific topics.": "\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0439\u0442\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u0442\u0435\u043c\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043c\u0435\u043d\u044e \u00ab\u0412\u0441\u0435 \u0442\u0435\u043c\u044b\u00bb.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u041f\u043e\u043b\u044c\u0437\u0443\u044f\u0441\u044c \u0432\u0435\u0431-\u043a\u0430\u043c\u0435\u0440\u043e\u0439, \u0441\u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0441\u043d\u0438\u043c\u043e\u043a \u0441\u0432\u043e\u0435\u0433\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u044f \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438. \u041c\u044b \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u044d\u0442\u043e\u0442 \u0441\u043d\u0438\u043c\u043e\u043a \u0441\u043e \u0441\u043d\u0438\u043c\u043a\u043e\u043c \u0432\u0430\u0448\u0435\u0433\u043e \u043b\u0438\u0446\u0430 \u0438 \u0438\u043c\u0435\u043d\u0435\u043c \u0432 \u0432\u0430\u0448\u0435\u0439 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u041f\u043e\u043b\u044c\u0437\u0443\u044f\u0441\u044c \u0432\u0435\u0431-\u043a\u0430\u043c\u0435\u0440\u043e\u0439, \u0441\u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0441\u043d\u0438\u043c\u043e\u043a \u0441\u0432\u043e\u0435\u0433\u043e \u043b\u0438\u0446\u0430. \u041c\u044b \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u044d\u0442\u043e\u0442 \u0441\u043d\u0438\u043c\u043e\u043a \u0441 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0435\u0439 \u0432 \u0432\u0430\u0448\u0435\u043c \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0438 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438.", "Used": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043e", "User Email": "\u0410\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", @@ -1771,7 +1760,6 @@ "Verified Certificate upgrade": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430", "Verified Status": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u044b\u0439 \u0441\u0442\u0430\u0442\u0443\u0441", "Verified mode price": "\u0421\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430", - "Verify Now": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c", "Vertical space": "\u041e\u0442\u0441\u0442\u0443\u043f \u043f\u043e \u0432\u044b\u0441\u043e\u0442\u0435", "Very loud": "\u041e\u0447\u0435\u043d\u044c \u0433\u0440\u043e\u043c\u043a\u043e", "Very low": "\u041e\u0447\u0435\u043d\u044c \u0442\u0438\u0445\u043e", @@ -1810,7 +1798,6 @@ "We couldn't find any results for \"%s\".": "\u041d\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0434\u043b\u044f \u00ab%s\u00bb.", "We couldn't sign you in.": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u043e\u0439\u0442\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.", "We have encountered an error. Refresh your browser and then try again.": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430. \u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "\u041c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0432\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0438\u0445 \u0432 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f (1-2 \u0434\u043d\u044f). \u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u044b, \u043d\u0430 \u0432\u0430\u0448\u0435\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0435. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0432\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u0441\u0435 \u0443\u0447\u0435\u0431\u043d\u044b\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b.", "We just need a little more information before you start learning with %(platformName)s.": "\u041f\u0435\u0440\u0435\u0434 \u043d\u0430\u0447\u0430\u043b\u043e\u043c \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 \u00ab%(platformName)s\u00bb \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0430\u043c\u044b\u0439 \u0432\u044b\u0441\u043e\u043a\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0437\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u0444\u043e\u0442\u043e \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0435\u0433\u043e \u043d\u0430 \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u0412\u0430\u0448\u0430 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u0438\u0433\u0434\u0435 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 \u00ab%(platformName)s\u00bb \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d.", "We've encountered an error. Refresh your browser and then try again.": "\u0412\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430. \u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437.", @@ -1891,11 +1878,8 @@ "You must sign out and sign back in before your language changes take effect.": "\u0427\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u044f\u0437\u044b\u043a\u0430 \u0432\u0441\u0442\u0443\u043f\u0438\u043b\u043e \u0432 \u0441\u0438\u043b\u0443, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u0439\u0442\u0438 \u0438 \u0441\u043d\u043e\u0432\u0430 \u0432\u043e\u0439\u0442\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.", "You must specify a name for the cohort": "\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u0414\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0433\u043e\u0434 \u0432\u0430\u0448\u0435\u0433\u043e \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0432 {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u0412\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u0430, \u043f\u0430\u0441\u043f\u043e\u0440\u0442 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u0433\u043e\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0435\u0441\u0442\u044c \u0432\u0430\u0448\u0435 \u0438\u043c\u044f \u0438 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u0412\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0435 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u0441 \u0432\u0430\u0448\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c \u0438 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0435\u0439. \u041f\u043e\u0434\u043e\u0439\u0434\u0451\u0442 \u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0435, \u043f\u0430\u0441\u043f\u043e\u0440\u0442 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u0433\u043e\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0437\u0446\u0430.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043a\u0443\u0440\u0441\u044b, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0443\u0447\u0451\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c. \u041f\u0438\u0441\u044c\u043c\u043e \u0434\u043b\u044f \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u0438 \u0432\u044b\u0441\u043b\u0430\u043d\u043e \u0432\u0430\u043c \u043d\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0443\u044e \u043f\u043e\u0447\u0442\u0443.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043a\u0443\u0440\u0441\u044b, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0443\u0447\u0451\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c. \u041f\u0438\u0441\u044c\u043c\u043e \u0434\u043b\u044f \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u0438 \u0432\u044b\u0441\u043b\u0430\u043d\u043e \u0432\u0430\u043c \u043d\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0443\u044e \u043f\u043e\u0447\u0442\u0443. \u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044e, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u0442\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0435\u0451.", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u0412\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u044c %(display_name)s \u0432\u0435\u0431-\u0441\u0430\u0439\u0442 \u0434\u043b\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u043a\u0443\u043f\u043a\u0438.", "You submitted {filename}; only {allowedFiles} are allowed.": "\u0412\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b\u0438 \u0444\u0430\u0439\u043b {filename}; \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u044b {allowedFiles}.", "You will be refunded the amount you paid.": "\u0412\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u0430 \u0441\u0443\u043c\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u044b \u0437\u0430\u043f\u043b\u0430\u0442\u0438\u043b\u0438.", "You will not be refunded the amount you paid.": "\u0412\u0430\u043c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u0430 \u0441\u0443\u043c\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u044b \u0437\u0430\u043f\u043b\u0430\u0442\u0438\u043b\u0438.", @@ -2098,7 +2082,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2154,9 +2138,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/si/djangojs.js b/cms/static/js/i18n/si/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/cms/static/js/i18n/si/djangojs.js +++ b/cms/static/js/i18n/si/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/sk/djangojs.js b/cms/static/js/i18n/sk/djangojs.js index 8a6b91d45074213dd2e5e1ab46dc8c8f0546d81a..ee1356ee745f156be44e68ec2e568ac79be9cf1d 100644 --- a/cms/static/js/i18n/sk/djangojs.js +++ b/cms/static/js/i18n/sk/djangojs.js @@ -23,9 +23,11 @@ "%(sel)s of %(cnt)s selected": [ "%(sel)s z %(cnt)s vybran\u00e9", "%(sel)s z %(cnt)s vybran\u00e9", + "%(sel)s z %(cnt)s vybran\u00fdch", "%(sel)s z %(cnt)s vybran\u00fdch" ], "6 a.m.": "6:00", + "6 p.m.": "18:00", "A valid email address is required": "Vy\u017eaduje sa platn\u00e1 e-mailov\u00e1 adresa", "ABCDEFGHIJKLMNOPQRSTUVWXYZ": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "Account": "\u00da\u010det", @@ -52,12 +54,14 @@ "Amount": "\u010ciastka", "Anchor": "Ukotvi\u0165", "Anchors": "Ukotvenia", + "April": "apr\u00edl", "Are you sure you want to delete this update?": "Skuto\u010dne chcete odstr\u00e1ni\u0165 t\u00fato aktualiz\u00e1ciu?", "Are you sure you want to delete {email} from the course team for \u201c{container}\u201d?": "Skuto\u010dne chcete vymaza\u0165 {email} z t\u00edmu spravuj\u00faceho kurz pre \u201c{container}\u201d?", "Are you sure you want to delete {email} from the library \u201c{container}\u201d?": "Skuto\u010dne chcete odstr\u00e1ni\u0165 {email} z kni\u017enice \u201c{container}\u201d?", "Are you sure you want to restrict {email} access to \u201c{container}\u201d?": "Naozaj chcete obmedzi\u0165 {email} pr\u00edstup ku \u201c{container}\u201d?", "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "Skuto\u010dne si prajete odstr\u00e1ni\u0165 t\u00fato polo\u017eku? Tento stav nie je mo\u017en\u00e9 zvr\u00e1ti\u0165!\n\nTaktie\u017e ak\u00fdko\u013evek obsah, ktor\u00fd odkazuje na t\u00fato polo\u017eku, nebude viac funk\u010dn\u00fd (t.j. nena\u010d\u00edtan\u00e9 obr\u00e1zky a/alebo nefunk\u010dn\u00e9 odkazy)", "Are you sure?": "Ste si ist\u00ed?", + "August": "august", "Author": "Autor", "Available %s": "Dostupn\u00e9 %s", "Average": "Priemern\u00fd", @@ -87,6 +91,8 @@ "Changes to steps that are not selected as part of the assignment will not be saved.": "Zmeny pre kroky, ktor\u00e9 nie s\u00fa zvolen\u00e9 ako s\u00fa\u010das\u0165 tohto zadania, nebud\u00fa ulo\u017een\u00e9.", "Choose": "Vybra\u0165", "Choose File": "Vybra\u0165 s\u00fabor", + "Choose a Date": "Vybra\u0165 D\u00e1tum", + "Choose a Time": "Vybra\u0165 \u010cas", "Choose a time": "Vybra\u0165 \u010das", "Choose all": "Vybra\u0165 v\u0161etko", "Chosen %s": "Vybran\u00e9 %s", @@ -138,6 +144,7 @@ "Cut row": "Vystrihn\u00fa\u0165 riadok", "Date": "D\u00e1tum", "Date Added": "Doplnen\u00fd d\u00e1tum", + "December": "december", "Decrease indent": "Zmen\u0161i\u0165 odsadenie", "Default": "Predvolen\u00e9", "Delete": "Odstr\u00e1ni\u0165", @@ -179,6 +186,7 @@ "Errors": "Chyby", "Exit full browser": "Ukon\u010di\u0165 re\u017eim celej obrazovky", "Expand Instructions": "Roz\u0161\u00edri\u0165 in\u0161trukcie", + "February": "febru\u00e1r", "File": "S\u00fabor", "File type is not allowed.": "Typ s\u00faboru nie je povolen\u00fd.", "File types can not be empty.": "Typy s\u00faborov nem\u00f4\u017eu by\u0165 pr\u00e1zdne.", @@ -258,6 +266,9 @@ "Insert/edit video": "Vlo\u017ei\u0165/editova\u0165 video", "Italic": "Kurz\u00edva", "Italic (Ctrl+I)": "Kurz\u00edva (Ctrl+I)", + "January": "janu\u00e1r", + "July": "j\u00fal", + "June": "j\u00fan", "Justify": "Zarovna\u0165", "Key should only contain letters, numbers, _, or -": "K\u013e\u00fa\u010d by mal obsahova\u0165 iba p\u00edsmen\u00e1, \u010d\u00edsla, _, alebo -", "Keywords": "K\u013e\u00fa\u010dov\u00e9 slov\u00e1", @@ -276,8 +287,10 @@ "Loading more threads": "Na\u010d\u00edta\u0165 viac vl\u00e1kien", "Loud": "Hlasn\u00fd", "Low": "N\u00edzko", + "March": "marec", "Max file size exceeded": "Prekro\u010den\u00e1 maxim\u00e1lna ve\u013ekos\u0165", "Maximum": "Maximum", + "May": "m\u00e1j", "Membership": "\u010clenstvo", "Merge cells": "Zl\u00fa\u010di\u0165 bunky", "Middle": "Stredn\u00e9", @@ -303,19 +316,23 @@ "Note: You are %s hour ahead of server time.": [ "Pozn\u00e1mka: Ste %s hodinu pred \u010dasom servera.", "Pozn\u00e1mka: Ste %s hodiny pred \u010dasom servera.", + "Pozn\u00e1mka: Ste %s hod\u00edn pred \u010dasom servera.", "Pozn\u00e1mka: Ste %s hod\u00edn pred \u010dasom servera." ], "Note: You are %s hour behind server time.": [ "Pozn\u00e1mka: Ste %s hodinu za \u010dasom servera.", "Pozn\u00e1mka: Ste %s hodiny za \u010dasom servera.", + "Pozn\u00e1mka: Ste %s hod\u00edn za \u010dasom servera.", "Pozn\u00e1mka: Ste %s hod\u00edn za \u010dasom servera." ], "Noted in:": "Pridan\u00e1 pozn\u00e1mka v:", + "November": "november", "Now": "Teraz", "Number of Students": "Po\u010det \u0161tudentov", "Numbered List (Ctrl+O)": "\u010c\u00edslovan\u00fd zoznam (Ctrl+O)", "Numbered list": "\u010c\u00edslovan\u00fd zoznam", "OK": "OK", + "October": "okt\u00f3ber", "Ok": "Ok", "One or more rescheduling tasks failed.": "Jedna alebo viac \u00faloh pre zmenu term\u00ednu zlyhala.", "Open Calculator": "Otvori\u0165 kalkula\u010dku", @@ -394,6 +411,7 @@ "Search teams": "H\u013eadanie t\u00edmov", "Select all": "Vybra\u0165 v\u0161etko", "Sent By": "Odoslan\u00e9", + "September": "september", "Set up your certificate": "Nastavenie v\u00e1\u0161ho certifik\u00e1tu", "Settings": "Nastavenia", "Short explanation": "kr\u00e1tke vysvetlenie", @@ -575,6 +593,13 @@ "last activity": "posledn\u00e1 aktivita", "less than a minute": "menej ako min\u00fatu", "name": "n\u00e1zov", + "one letter Friday\u0004F": "P", + "one letter Monday\u0004M": "P", + "one letter Saturday\u0004S": "S", + "one letter Sunday\u0004S": "N", + "one letter Thursday\u0004T": "\u0160", + "one letter Tuesday\u0004T": "U", + "one letter Wednesday\u0004W": "S", "open slots": "vo\u013en\u00e9 sloty", "remove": "vymaza\u0165", "remove all": "vymaza\u0165 v\u0161etko", @@ -602,7 +627,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -655,9 +680,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y G:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/sl/djangojs.js b/cms/static/js/i18n/sl/djangojs.js index 5cefeba49fa1aef57e22446ef893c0d2e17fe49e..740ec8172b47929278f200dad4228273ba6c0422 100644 --- a/cms/static/js/i18n/sl/djangojs.js +++ b/cms/static/js/i18n/sl/djangojs.js @@ -107,7 +107,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -178,9 +178,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j.n.Y. H:i", "SHORT_DATE_FORMAT": "j. M. Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/sq/djangojs.js b/cms/static/js/i18n/sq/djangojs.js index 514c688171b9ba8a0b190b9e5e5c8820284b3540..bddad372e1fbda85d54699ba35b43dc4b4d03f84 100644 --- a/cms/static/js/i18n/sq/djangojs.js +++ b/cms/static/js/i18n/sq/djangojs.js @@ -26,6 +26,8 @@ ], "6 a.m.": "6 a.m.", "6 p.m.": "6 p.m.", + "April": "Prill", + "August": "Gusht", "Available %s": "%s i gatsh\u00ebm", "Cancel": "Anuloje", "Choose": "Zgjidhni", @@ -36,9 +38,16 @@ "Chosen %s": "U zgjodh %s", "Click to choose all %s at once.": "Klikoni q\u00eb t\u00eb zgjidhen krejt %s nj\u00ebher\u00ebsh.", "Click to remove all chosen %s at once.": "Klikoni q\u00eb t\u00eb hiqen krejt %s e zgjedhura nj\u00ebher\u00ebsh.", + "December": "Dhjetor", "Error": "Problem", + "February": "Shkurt", "Filter": "Filtro", "Hide": "Fshihe", + "January": "Janar", + "July": "Korrik", + "June": "Qershor", + "March": "Mars", + "May": "Maj", "Midnight": "Mesnat\u00eb", "Noon": "Mesdit\u00eb", "Not Selected": "E pa selektuar", @@ -50,11 +59,14 @@ "Sh\u00ebnim: Jeni %s or\u00eb pas koh\u00ebs s\u00eb sh\u00ebrbyesit.", "Sh\u00ebnim: Jeni %s or\u00eb pas koh\u00ebs s\u00eb sh\u00ebrbyesit." ], + "November": "N\u00ebntor", "Now": "Tani", + "October": "Tetor", "Option Deleted": "Opsioni u fshia", "Remove": "Hiqe", "Remove all": "Hiqi krejt", "Saving...": "Ruaj...", + "September": "Shtator", "Show": "Shfaqe", "Status of Your Response": "Statusi i p\u00ebrgjigjjes suaj", "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "Kjo \u00ebsht\u00eb lista e %s t\u00eb gatsh\u00ebm. Mund t\u00eb zgjidhni disa duke i p\u00ebrzgjedhur te kutiza m\u00eb posht\u00eb dhe mandej duke klikuar mbi shigjet\u00ebn \"Zgjidhe\" mes dy kutizave.", @@ -70,7 +82,14 @@ "Yesterday": "Dje", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "Keni p\u00ebrzgjedhur nj\u00eb veprim, dhe nuk keni b\u00ebr\u00eb ndonj\u00eb ndryshim te fusha individuale. Ndoshta po k\u00ebrkonit p\u00ebr butonin Shko, n\u00eb vend se p\u00ebr butonin Ruaje.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "Keni p\u00ebrzgjedhur nj\u00eb veprim, por nuk keni ruajtur ende ndryshimet q\u00eb b\u00ebt\u00eb te fusha individuale. Ju lutemi, klikoni OK q\u00eb t\u00eb b\u00ebhet ruajtja. Do t\u2019ju duhet ta rib\u00ebni veprimin.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Keni ndryshime t\u00eb paruajtura te fusha individuale t\u00eb ndryshueshme. N\u00ebse kryeni nj\u00eb veprim, ndryshimet e paruajtura do t\u00eb humbin." + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Keni ndryshime t\u00eb paruajtura te fusha individuale t\u00eb ndryshueshme. N\u00ebse kryeni nj\u00eb veprim, ndryshimet e paruajtura do t\u00eb humbin.", + "one letter Friday\u0004F": "P", + "one letter Monday\u0004M": "H", + "one letter Saturday\u0004S": "S", + "one letter Sunday\u0004S": "D", + "one letter Thursday\u0004T": "E", + "one letter Tuesday\u0004T": "M", + "one letter Wednesday\u0004W": "M" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -92,7 +111,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -156,9 +175,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "Y-m-d", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/sr/djangojs.js b/cms/static/js/i18n/sr/djangojs.js index 58f1e74e22b6ccee660b211da7682260814acaf4..5a4be1d7f3e34c2a379793cf948c0837732ea11c 100644 --- a/cms/static/js/i18n/sr/djangojs.js +++ b/cms/static/js/i18n/sr/djangojs.js @@ -26,21 +26,46 @@ "%(sel)s \u043e\u0434 %(cnt)s \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0438\u0445" ], "6 a.m.": "18\u0447", + "6 p.m.": "18\u0447", + "April": "\u0410\u043f\u0440\u0438\u043b", + "August": "\u0410\u0432\u0433\u0443\u0441\u0442", "Available %s": "\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438 %s", "Cancel": "\u041f\u043e\u043d\u0438\u0448\u0442\u0438", "Choose": "\u0418\u0437\u0430\u0431\u0435\u0440\u0438", + "Choose a Date": "\u041e\u0434\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0430\u0442\u0443\u043c", + "Choose a Time": "\u041e\u0434\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0440\u0435\u043c\u0435", "Choose a time": "\u041e\u0434\u0430\u0431\u0438\u0440 \u0432\u0440\u0435\u043c\u0435\u043d\u0430", "Choose all": "\u0418\u0437\u0430\u0431\u0435\u0440\u0438 \u0441\u0432\u0435", "Chosen %s": "\u0418\u0437\u0430\u0431\u0440\u0430\u043d\u043e \u201e%s\u201c", "Click to choose all %s at once.": "\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0432\u0435 \u201e%s\u201c \u043e\u0434\u0458\u0435\u0434\u043d\u043e\u043c.", "Click to remove all chosen %s at once.": "\u0423\u043a\u043b\u043e\u043d\u0438\u0442\u0435 \u0441\u0432\u0435 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 \u201e%s\u201c \u043e\u0434\u0458\u0435\u0434\u043d\u043e\u043c.", + "December": "\u0414\u0435\u0446\u0435\u043c\u0431\u0430\u0440", + "February": "\u0424\u0435\u0431\u0440\u0443\u0430\u0440", "Filter": "\u0424\u0438\u043b\u0442\u0435\u0440", "Hide": "\u0421\u0430\u043a\u0440\u0438\u0458", + "January": "\u0408\u0430\u043d\u0443\u0430\u0440", + "July": "\u0408\u0443\u043b", + "June": "\u0408\u0443\u043d", + "March": "\u041c\u0430\u0440\u0442", + "May": "\u041c\u0430\u0458", "Midnight": "\u041f\u043e\u043d\u043e\u045b", "Noon": "\u041f\u043e\u0434\u043d\u0435", + "Note: You are %s hour ahead of server time.": [ + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442 \u0441\u0442\u0435 \u0438\u0441\u043f\u0440\u0435\u0434 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430.", + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442\u0430 \u0441\u0442\u0435 \u0438\u0441\u043f\u0440\u0435\u0434 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430.", + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442\u0438 \u0441\u0442\u0435 \u0438\u0441\u043f\u0440\u0435\u0434 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430." + ], + "Note: You are %s hour behind server time.": [ + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442 \u0441\u0442\u0435 \u0438\u0437\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430.", + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442\u0430 \u0441\u0442\u0435 \u0438\u0437\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430.", + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442\u0438 \u0441\u0442\u0435 \u0438\u0437\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430." + ], + "November": "\u041d\u043e\u0432\u0435\u043c\u0431\u0430\u0440", "Now": "\u0422\u0440\u0435\u043d\u0443\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", + "October": "\u041e\u043a\u0442\u043e\u0431\u0430\u0440", "Remove": "\u0423\u043a\u043b\u043e\u043d\u0438", "Remove all": "\u0423\u043a\u043b\u043e\u043d\u0438 \u0441\u0432\u0435", + "September": "\u0421\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440", "Show": "\u041f\u043e\u043a\u0430\u0436\u0438", "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "\u041e\u0432\u043e \u0458\u0435 \u043b\u0438\u0441\u0442\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u201e%s\u201c. \u041c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u0430\u0431\u0440\u0430\u0442\u0438 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0435 \u0442\u0430\u043a\u043e \u0448\u0442\u043e \u045b\u0435\u0442\u0435 \u0438\u0445 \u0438\u0437\u0430\u0431\u0440\u0430\u0442\u0438 \u0443 \u043b\u0438\u0441\u0442\u0438 \u0438 \u043a\u043b\u0438\u043a\u043d\u0443\u0442\u0438 \u043d\u0430 \u201e\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u201c.", "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "\u041e\u0432\u043e \u0458\u0435 \u043b\u0438\u0441\u0442\u0430 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0438\u0445 \u201e%s\u201c. \u041c\u043e\u0436\u0435\u0442\u0435 \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0438 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0435 \u0442\u0430\u043a\u043e \u0448\u0442\u043e \u045b\u0435\u0442\u0435 \u0438\u0445 \u0438\u0437\u0430\u0431\u0440\u0430\u0442\u0438 \u0443 \u043b\u0438\u0441\u0442\u0438 \u0438 \u043a\u043b\u0438\u043a\u043d\u0443\u0442\u0438 \u043d\u0430 \u201e\u0423\u043a\u043b\u043e\u043d\u0438\u201c.", @@ -50,7 +75,14 @@ "Yesterday": "\u0408\u0443\u0447\u0435", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "\u0418\u0437\u0430\u0431\u0440\u0430\u043b\u0438 \u0441\u0442\u0435 \u0430\u043a\u0446\u0438\u0458\u0443 \u0430\u043b\u0438 \u043d\u0438\u0441\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438 \u043d\u0438 \u0458\u0435\u0434\u043d\u043e \u043f\u043e\u0459\u0435.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "\u0418\u0437\u0430\u0431\u0440\u0430\u043b\u0438 \u0441\u0442\u0435 \u0430\u043a\u0446\u0438\u0458\u0443 \u0430\u043b\u0438 \u043d\u0438\u0441\u0442\u0435 \u0441\u0430\u0447\u0443\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u043c\u0435\u043d\u0435 \u043f\u043e\u0459\u0430.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "\u0418\u043c\u0430\u0442\u0435 \u043d\u0435\u0441\u0430\u0447\u0438\u0432\u0430\u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0435. \u0410\u043a\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0435\u0442\u0435 \u0430\u043a\u0446\u0438\u0458\u0443, \u0438\u0437\u043c\u0435\u043d\u0435 \u045b\u0435 \u0431\u0438\u0442\u0438 \u0438\u0437\u0433\u0443\u0431\u0459\u0435\u043d\u0435." + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "\u0418\u043c\u0430\u0442\u0435 \u043d\u0435\u0441\u0430\u0447\u0438\u0432\u0430\u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0435. \u0410\u043a\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0435\u0442\u0435 \u0430\u043a\u0446\u0438\u0458\u0443, \u0438\u0437\u043c\u0435\u043d\u0435 \u045b\u0435 \u0431\u0438\u0442\u0438 \u0438\u0437\u0433\u0443\u0431\u0459\u0435\u043d\u0435.", + "one letter Friday\u0004F": "\u041f", + "one letter Monday\u0004M": "\u041f", + "one letter Saturday\u0004S": "\u0421", + "one letter Sunday\u0004S": "\u041d", + "one letter Thursday\u0004T": "\u0427", + "one letter Tuesday\u0004T": "\u0423", + "one letter Wednesday\u0004W": "\u0421" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -72,7 +104,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -138,9 +170,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j.m.Y. H:i", "SHORT_DATE_FORMAT": "j.m.Y.", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/sv/djangojs.js b/cms/static/js/i18n/sv/djangojs.js index 8351228d59e7681cee06c137475b91a348534b8e..410215dbe73b9d039c48b4991f4dfea4c780b9e5 100644 --- a/cms/static/js/i18n/sv/djangojs.js +++ b/cms/static/js/i18n/sv/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -157,9 +157,9 @@ "%m/%d/%y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "Y-m-d H:i", "SHORT_DATE_FORMAT": "Y-m-d", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/sw/djangojs.js b/cms/static/js/i18n/sw/djangojs.js index 1b7f576bb5c53b938b58aec1dc858c538964e0c0..59dd4b1b4eab7231b9cac29ea1802e9663c5ee69 100644 --- a/cms/static/js/i18n/sw/djangojs.js +++ b/cms/static/js/i18n/sw/djangojs.js @@ -79,7 +79,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -143,9 +143,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/ta/djangojs.js b/cms/static/js/i18n/ta/djangojs.js index f0a891c0f2be4be6976395c24c63e7ebf693b3b4..f15ff7285b4d4c5df6e66bc93d95621af6a96afa 100644 --- a/cms/static/js/i18n/ta/djangojs.js +++ b/cms/static/js/i18n/ta/djangojs.js @@ -55,7 +55,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -119,9 +119,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M, Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/te/djangojs.js b/cms/static/js/i18n/te/djangojs.js index b4eb9bf12cec3ccba357564c42e518e36bab448e..1a65f9c18512f9875e0f8766f73592da64b4b223 100644 --- a/cms/static/js/i18n/te/djangojs.js +++ b/cms/static/js/i18n/te/djangojs.js @@ -57,7 +57,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -121,9 +121,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/th/djangojs.js b/cms/static/js/i18n/th/djangojs.js index 2077af1c299308641013f2318a4337e472d88c4d..1748ce550a96cc4022d49a9f2b7f26c975791280 100644 --- a/cms/static/js/i18n/th/djangojs.js +++ b/cms/static/js/i18n/th/djangojs.js @@ -46,6 +46,7 @@ "(contains %(student_count)s students)" ], "6 a.m.": "\u0e2b\u0e01\u0e42\u0e21\u0e07\u0e40\u0e0a\u0e49\u0e32", + "6 p.m.": "\u0e2b\u0e01\u0e42\u0e21\u0e07\u0e40\u0e22\u0e47\u0e19", "A driver's license, passport, or government-issued ID with your name and photo.": "\u0e43\u0e1a\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e02\u0e31\u0e1a\u0e02\u0e35\u0e48 \u0e2b\u0e19\u0e31\u0e07\u0e2a\u0e37\u0e2d\u0e40\u0e14\u0e34\u0e19\u0e17\u0e32\u0e07\u0e2b\u0e23\u0e37\u0e2d\u0e40\u0e2d\u0e01\u0e2a\u0e32\u0e23\u0e17\u0e35\u0e48\u0e2d\u0e2d\u0e01\u0e42\u0e14\u0e22\u0e20\u0e32\u0e04\u0e23\u0e31\u0e10\u0e2d\u0e37\u0e48\u0e19\u0e46 \u0e17\u0e35\u0e48\u0e21\u0e35\u0e0a\u0e37\u0e48\u0e2d\u0e41\u0e25\u0e30\u0e23\u0e39\u0e1b\u0e20\u0e32\u0e1e\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13", "A driver's license, passport, or other government-issued ID with your name and photo": "\u0e04\u0e38\u0e13\u0e15\u0e49\u0e2d\u0e07\u0e21\u0e35\u0e43\u0e1a\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e02\u0e31\u0e1a\u0e02\u0e35\u0e48 \u0e2b\u0e19\u0e31\u0e07\u0e2a\u0e37\u0e2d\u0e40\u0e14\u0e34\u0e19\u0e17\u0e32\u0e07\u0e2b\u0e23\u0e37\u0e2d\u0e40\u0e2d\u0e01\u0e2a\u0e32\u0e23\u0e17\u0e35\u0e48\u0e2d\u0e2d\u0e01\u0e42\u0e14\u0e22\u0e20\u0e32\u0e04\u0e23\u0e31\u0e10\u0e2d\u0e37\u0e48\u0e19\u0e46 \u0e17\u0e35\u0e48\u0e21\u0e35\u0e0a\u0e37\u0e48\u0e2d\u0e41\u0e25\u0e30\u0e23\u0e39\u0e1b\u0e20\u0e32\u0e1e\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13", "A list of courses you have just enrolled in as a verified student": "\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e2b\u0e25\u0e31\u0e01\u0e2a\u0e39\u0e15\u0e23\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e44\u0e14\u0e49\u0e17\u0e33\u0e01\u0e32\u0e23\u0e25\u0e07\u0e17\u0e30\u0e40\u0e1a\u0e35\u0e22\u0e19\u0e40\u0e1b\u0e47\u0e19\u0e19\u0e31\u0e01\u0e40\u0e23\u0e35\u0e22\u0e19\u0e17\u0e35\u0e48\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19", @@ -90,6 +91,7 @@ "An error occurred. Please try again.": "\u0e40\u0e01\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 \u0e01\u0e23\u0e38\u0e13\u0e32\u0e25\u0e2d\u0e07\u0e43\u0e2b\u0e21\u0e48\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07", "An error occurred. Try again.": "\u0e40\u0e01\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 \u0e01\u0e23\u0e38\u0e13\u0e32\u0e25\u0e2d\u0e07\u0e43\u0e2b\u0e21\u0e48\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07", "An unexpected error occurred. Please try again.": "\u0e40\u0e01\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e04\u0e32\u0e14\u0e04\u0e34\u0e14 \u0e01\u0e23\u0e38\u0e13\u0e32\u0e25\u0e2d\u0e07\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07", + "April": "\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19", "Are you having trouble finding a team to join?": "\u0e04\u0e38\u0e13\u0e01\u0e33\u0e25\u0e31\u0e07\u0e21\u0e35\u0e1b\u0e31\u0e0d\u0e2b\u0e32\u0e43\u0e19\u0e01\u0e32\u0e23\u0e2b\u0e32\u0e17\u0e35\u0e21?", "Are you sure you want to delete this comment?": "\u0e04\u0e38\u0e13\u0e41\u0e19\u0e48\u0e43\u0e08\u0e2b\u0e23\u0e37\u0e2d\u0e27\u0e48\u0e32\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e17\u0e35\u0e48\u0e08\u0e30\u0e25\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e04\u0e34\u0e14\u0e40\u0e2b\u0e47\u0e19\u0e19\u0e35\u0e49", "Are you sure you want to delete this post?": "\u0e04\u0e38\u0e13\u0e41\u0e19\u0e48\u0e43\u0e08\u0e2b\u0e23\u0e37\u0e2d\u0e27\u0e48\u0e32\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e17\u0e35\u0e48\u0e08\u0e30\u0e25\u0e1a\u0e42\u0e1e\u0e2a\u0e15\u0e4c\u0e19\u0e35\u0e49", @@ -102,6 +104,7 @@ "As part of the verification process, you take a photo of both your face and a government-issued photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u0e43\u0e19\u0e2a\u0e48\u0e27\u0e19\u0e02\u0e2d\u0e07\u0e01\u0e23\u0e30\u0e1a\u0e27\u0e19\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19 \u0e04\u0e38\u0e13\u0e16\u0e48\u0e32\u0e22\u0e23\u0e39\u0e1b\u0e08\u0e32\u0e01\u0e43\u0e1a\u0e2b\u0e19\u0e49\u0e32\u0e41\u0e25\u0e30\u0e23\u0e39\u0e1b\u0e1b\u0e23\u0e30\u0e08\u0e33\u0e15\u0e31\u0e27\u0e17\u0e35\u0e48\u0e23\u0e31\u0e10\u0e2d\u0e2d\u0e01\u0e43\u0e2b\u0e49 \u0e01\u0e32\u0e23\u0e43\u0e2b\u0e49\u0e1a\u0e23\u0e34\u0e01\u0e32\u0e23\u0e02\u0e2d\u0e07\u0e40\u0e23\u0e32\u0e15\u0e49\u0e2d\u0e07\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e2d\u0e31\u0e15\u0e25\u0e31\u0e01\u0e29\u0e13\u0e4c\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e42\u0e14\u0e22\u0e01\u0e32\u0e23\u0e40\u0e1b\u0e23\u0e35\u0e22\u0e1a\u0e40\u0e17\u0e35\u0e22\u0e1a\u0e23\u0e39\u0e1b\u0e17\u0e35\u0e48\u0e16\u0e48\u0e32\u0e22\u0e01\u0e31\u0e1a\u0e23\u0e39\u0e1b\u0e1a\u0e31\u0e15\u0e23\u0e1b\u0e23\u0e30\u0e0a\u0e32\u0e0a\u0e19", "Assign students to cohorts by uploading a CSV file.": "\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e19\u0e31\u0e01\u0e40\u0e23\u0e35\u0e22\u0e19\u0e25\u0e07\u0e01\u0e25\u0e38\u0e48\u0e21\u0e42\u0e14\u0e22\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e44\u0e1f\u0e25\u0e4c CSV", "Associated Content Group": "\u0e01\u0e25\u0e38\u0e48\u0e21\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32\u0e17\u0e35\u0e48\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e02\u0e49\u0e2d\u0e07", + "August": "\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21", "Automatic": "\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34", "Available %s": "%s\u0e17\u0e35\u0e48\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48", "Back to sign in": "\u0e01\u0e25\u0e31\u0e1a\u0e44\u0e1b\u0e17\u0e35\u0e48\u0e40\u0e02\u0e49\u0e32\u0e2a\u0e39\u0e48\u0e23\u0e30\u0e1a\u0e1a", @@ -131,6 +134,8 @@ "Checkout with {processor}": "\u0e0a\u0e33\u0e23\u0e30\u0e40\u0e07\u0e34\u0e19\u0e14\u0e49\u0e27\u0e22 {processor}", "Choose": "\u0e40\u0e25\u0e37\u0e2d\u0e01", "Choose a .csv file": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e44\u0e1f\u0e25\u0e4c .csv", + "Choose a Date": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e27\u0e31\u0e19", + "Choose a Time": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e40\u0e27\u0e25\u0e32", "Choose a content group to associate": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e01\u0e25\u0e38\u0e48\u0e21\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32\u0e17\u0e35\u0e48\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e42\u0e22\u0e07\u0e01\u0e31\u0e19", "Choose a time": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e40\u0e27\u0e25\u0e32", "Choose all": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14", @@ -187,6 +192,7 @@ "Current tab": "\u0e41\u0e17\u0e47\u0e1a\u0e1b\u0e31\u0e08\u0e08\u0e38\u0e1a\u0e31\u0e19", "Date": "\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48", "Date Added": "\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\u0e40\u0e1e\u0e34\u0e48\u0e21", + "December": "\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21", "Delete": "\u0e25\u0e1a", "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u0e25\u0e1a \"<%= signatoryName %>\" \u0e08\u0e32\u0e01\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e01\u0e32\u0e23\u0e25\u0e07\u0e19\u0e32\u0e21?", "Delete File Confirmation": "\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e01\u0e32\u0e23\u0e25\u0e1a\u0e44\u0e1f\u0e25\u0e4c", @@ -261,6 +267,7 @@ "Errors": "\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14", "Expand All": "\u0e41\u0e2a\u0e14\u0e07\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14", "Explore your course!": "\u0e2a\u0e33\u0e23\u0e27\u0e08\u0e2b\u0e25\u0e31\u0e01\u0e2a\u0e39\u0e15\u0e23\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13", + "February": "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c", "File Name": "\u0e0a\u0e37\u0e48\u0e2d\u0e44\u0e1f\u0e25\u0e4c", "File {filename} exceeds maximum size of {maxFileSizeInMBs} MB": "\u0e44\u0e1f\u0e25\u0e4c {filename} \u0e40\u0e01\u0e34\u0e19\u0e02\u0e19\u0e32\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 {maxFileSizeInMBs} MB", "Files must be in JPEG or PNG format.": "\u0e44\u0e1f\u0e25\u0e4c\u0e08\u0e30\u0e15\u0e49\u0e2d\u0e07\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a JPEG \u0e2b\u0e23\u0e37\u0e2d PNG", @@ -308,8 +315,11 @@ "Instructor tools": "\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e21\u0e37\u0e2d\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e1c\u0e39\u0e49\u0e2a\u0e2d\u0e19", "Is your name on your ID readable?": "\u0e0a\u0e37\u0e48\u0e2d\u0e43\u0e19\u0e1a\u0e31\u0e15\u0e23\u0e1b\u0e23\u0e30\u0e0a\u0e32\u0e0a\u0e19\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e2d\u0e48\u0e32\u0e19\u0e44\u0e14\u0e49\u0e2b\u0e23\u0e37\u0e2d\u0e44\u0e21\u0e48?", "Italic (Ctrl+I)": "\u0e15\u0e31\u0e27\u0e40\u0e2d\u0e35\u0e22\u0e07 (Ctrl+I)", + "January": "\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21", "Join Team": "\u0e40\u0e02\u0e49\u0e32\u0e23\u0e48\u0e27\u0e21\u0e17\u0e35\u0e21", "Joined %(date)s": "\u0e40\u0e02\u0e49\u0e32\u0e23\u0e48\u0e27\u0e21\u0e40\u0e21\u0e37\u0e48\u0e2d %(date)s", + "July": "\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21", + "June": "\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19", "KB": "\u0e01\u0e34\u0e42\u0e25\u0e44\u0e1a\u0e15\u0e4c", "Key should only contain letters, numbers, _, or -": "\u0e04\u0e35\u0e22\u0e4c\u0e04\u0e27\u0e23\u0e1b\u0e23\u0e30\u0e01\u0e2d\u0e1a\u0e14\u0e49\u0e27\u0e22\u0e15\u0e31\u0e27\u0e2d\u0e31\u0e01\u0e29\u0e23 \u0e15\u0e31\u0e27\u0e40\u0e25\u0e02, _,\u0e2b\u0e23\u0e37\u0e2d - \u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19", "LEARN MORE": "\u0e40\u0e23\u0e35\u0e22\u0e19\u0e23\u0e39\u0e49\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e40\u0e15\u0e34\u0e21", @@ -342,10 +352,12 @@ "Make sure your ID is well-lit": "\u0e41\u0e19\u0e48\u0e43\u0e08\u0e27\u0e48\u0e32ID\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07", "Make sure your face is well-lit": "\u0e41\u0e19\u0e48\u0e43\u0e08\u0e27\u0e48\u0e32\u0e23\u0e39\u0e1b\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07", "Manual": "\u0e14\u0e49\u0e27\u0e22\u0e15\u0e19\u0e40\u0e2d\u0e07", + "March": "\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21", "Mark Exam As Completed": "\u0e17\u0e33\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e27\u0e48\u0e32\u0e01\u0e32\u0e23\u0e2a\u0e2d\u0e1a\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e41\u0e25\u0e49\u0e27", "Mark enrollment code as unused": "\u0e17\u0e33\u0e2a\u0e31\u0e0d\u0e25\u0e31\u0e01\u0e29\u0e13\u0e4c\u0e27\u0e48\u0e32\u0e40\u0e1b\u0e47\u0e19\u0e23\u0e2b\u0e31\u0e2a\u0e25\u0e07\u0e17\u0e30\u0e40\u0e1a\u0e35\u0e22\u0e19\u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e43\u0e0a\u0e49", "Markdown Editing Help": "\u0e25\u0e14\u0e04\u0e27\u0e32\u0e21\u0e0a\u0e48\u0e27\u0e22\u0e40\u0e2b\u0e25\u0e37\u0e2d\u0e43\u0e19\u0e01\u0e32\u0e23\u0e41\u0e01\u0e49\u0e44\u0e02", "Max file size exceeded": "\u0e40\u0e01\u0e34\u0e19\u0e01\u0e27\u0e48\u0e32\u0e02\u0e19\u0e32\u0e14\u0e44\u0e1f\u0e25\u0e4c\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14", + "May": "\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21", "Membership": "\u0e2a\u0e21\u0e32\u0e0a\u0e34\u0e01", "Message:": "\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21:", "Midnight": "\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07\u0e04\u0e37\u0e19", @@ -372,14 +384,22 @@ "Not in Use": "\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19", "Not selected": "\u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e40\u0e25\u0e37\u0e2d\u0e01", "Note": "\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e2b\u0e15\u0e38", + "Note: You are %s hour ahead of server time.": [ + "\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e2b\u0e15\u0e38: \u0e40\u0e27\u0e25\u0e32\u0e04\u0e38\u0e13\u0e40\u0e23\u0e47\u0e27\u0e01\u0e27\u0e48\u0e32\u0e40\u0e27\u0e25\u0e32\u0e1a\u0e19\u0e40\u0e0b\u0e34\u0e23\u0e4c\u0e1f\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e2d\u0e22\u0e39\u0e48 %s \u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07." + ], + "Note: You are %s hour behind server time.": [ + "\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e2b\u0e15\u0e38: \u0e40\u0e27\u0e25\u0e32\u0e04\u0e38\u0e13\u0e0a\u0e49\u0e32\u0e01\u0e27\u0e48\u0e32\u0e40\u0e27\u0e25\u0e32\u0e1a\u0e19\u0e40\u0e0b\u0e34\u0e23\u0e4c\u0e1f\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e2d\u0e22\u0e39\u0e48 %s \u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07." + ], "Noted in:": "\u0e41\u0e08\u0e49\u0e07\u0e43\u0e19:", "Notes hidden": "\u0e0b\u0e48\u0e2d\u0e19\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01", "Notes visible": "\u0e21\u0e2d\u0e07\u0e40\u0e2b\u0e47\u0e19\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e44\u0e14\u0e49", + "November": "\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19", "Now": "\u0e02\u0e13\u0e30\u0e19\u0e35\u0e49", "Number Sent": "\u0e08\u0e33\u0e19\u0e27\u0e19\u0e17\u0e35\u0e48\u0e2a\u0e48\u0e07\u0e41\u0e25\u0e49\u0e27", "Number of Students": "\u0e08\u0e33\u0e19\u0e27\u0e19\u0e02\u0e2d\u0e07\u0e1c\u0e39\u0e49\u0e40\u0e23\u0e35\u0e22\u0e19", "Numbered List (Ctrl+O)": "\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e15\u0e31\u0e27\u0e40\u0e25\u0e02 (Ctrl + O)", "OK": "\u0e15\u0e01\u0e25\u0e07", + "October": "\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21", "One or more rescheduling tasks failed.": "\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e2b\u0e23\u0e37\u0e2d\u0e21\u0e32\u0e01\u0e01\u0e27\u0e48\u0e32\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e07\u0e32\u0e19\u0e17\u0e35\u0e48\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27\u0e43\u0e19\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e15\u0e32\u0e23\u0e32\u0e07", "Only properly formatted .csv files will be accepted.": "\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a\u0e17\u0e35\u0e48\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 .csv \u0e16\u0e36\u0e07\u0e08\u0e30\u0e22\u0e2d\u0e21\u0e23\u0e31\u0e1a", "Option Deleted": "\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e16\u0e39\u0e01\u0e25\u0e1a", @@ -469,6 +489,7 @@ "Sent By": "\u0e2a\u0e48\u0e07\u0e42\u0e14\u0e22:", "Sent By:": "\u0e2a\u0e48\u0e07\u0e42\u0e14\u0e22:", "Sent To:": "\u0e2a\u0e48\u0e07\u0e44\u0e1b:", + "September": "\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19", "Set up your certificate": "\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e43\u0e1a\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13", "Settings": "\u0e01\u0e32\u0e23\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e15\u0e48\u0e32\u0e07\u0e46 ", "Show": "\u0e41\u0e2a\u0e14\u0e07", @@ -739,6 +760,13 @@ "group configuration": "\u0e01\u0e32\u0e23\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e04\u0e48\u0e32\u0e01\u0e25\u0e38\u0e48\u0e21", "last activity": "\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e38\u0e14\u0e17\u0e49\u0e32\u0e22", "name": "\u0e0a\u0e37\u0e48\u0e2d", + "one letter Friday\u0004F": "\u0e28.", + "one letter Monday\u0004M": "\u0e08.", + "one letter Saturday\u0004S": "\u0e2a.", + "one letter Sunday\u0004S": "\u0e2d\u0e32.", + "one letter Thursday\u0004T": "\u0e1e\u0e24.", + "one letter Tuesday\u0004T": "\u0e2d.", + "one letter Wednesday\u0004W": "\u0e1e.", "open slots": "\u0e40\u0e1b\u0e34\u0e14\u0e0a\u0e48\u0e2d\u0e07\u0e43\u0e2a\u0e48", "or": "\u0e2b\u0e23\u0e37\u0e2d", "or create a new one here": "\u0e2b\u0e23\u0e37\u0e2d\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e1a\u0e31\u0e0d\u0e0a\u0e35\u0e43\u0e2b\u0e21\u0e48\u0e17\u0e35\u0e48\u0e19\u0e35\u0e48", @@ -773,7 +801,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -809,8 +837,8 @@ django.formats = { "DATETIME_FORMAT": "j F Y, G:i", "DATETIME_INPUT_FORMATS": [ - "%d/%m/%Y %H:%M:%S.%f", "%d/%m/%Y %H:%M:%S", + "%d/%m/%Y %H:%M:%S.%f", "%d/%m/%Y %H:%M", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", @@ -825,16 +853,16 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j M Y, G:i", "SHORT_DATE_FORMAT": "j M Y", "THOUSAND_SEPARATOR": ",", "TIME_FORMAT": "G:i", "TIME_INPUT_FORMATS": [ - "%H:%M:%S.%f", "%H:%M:%S", + "%H:%M:%S.%f", "%H:%M" ], "YEAR_MONTH_FORMAT": "F Y" diff --git a/cms/static/js/i18n/tr-tr/djangojs.js b/cms/static/js/i18n/tr-tr/djangojs.js index 3c665246851ab269c35075167db24e29ffe3d6b3..326ba3d22d3c73d535ced523b944c0efb9633985 100644 --- a/cms/static/js/i18n/tr-tr/djangojs.js +++ b/cms/static/js/i18n/tr-tr/djangojs.js @@ -139,6 +139,7 @@ "%s from now": "\u015eimdiden itibaren %s", "(Add signatories for a certificate)": "(Sertifika i\u00e7in imza sahibi ekle)", "(Caption will be displayed when you start playing the video.)": "(Altyaz\u0131 videoyu oynatmaya ba\u015flad\u0131\u011f\u0131n\u0131zda g\u00f6sterilecek.)", + "(Community TA)": "(Topluluk \u00d6\u011fretim Eleman\u0131)", "(Optional)": "(\u0130ste\u011fe Ba\u011fl\u0131)", "(Read-only)": "(Salt-okunur)", "(Required Field)": "(Gerekli Alan)", @@ -146,6 +147,7 @@ "(Self-paced) Ends {end}": "(Kendi kendine) Biti\u015f {end}", "(Self-paced) Started {start}": "(Kendi kendine) Ba\u015flad\u0131 {start}", "(Self-paced) Starts {start}": "(Kendi kendine) Ba\u015flang\u0131\u00e7 {start}", + "(Staff)": "(Personel)", "(optional)": "(iste\u011fe ba\u011fl\u0131)", "(required)": "(gerekli)", "(required):": "(gerekli):", @@ -203,7 +205,12 @@ "Add URLs for additional versions": "Ek s\u00fcr\u00fcmler i\u00e7in URL'leri ekle", "Add a Chapter": "Bir b\u00f6l\u00fcm ekle", "Add a New Cohort": "Yeni Topluluk Ekle", + "Add a Post": "\u0130leti Ekle", + "Add a Response": "Bir Cevap Ekle", + "Add a clear and descriptive title to encourage participation. (Required)": "Kat\u0131l\u0131ma te\u015fvik etmek i\u00e7in a\u00e7\u0131k ve tan\u0131t\u0131c\u0131 bir ba\u015fl\u0131k ekle. (Gerekli)", + "Add a comment": "Bir yorum ekleyin", "Add a learning outcome here": "\u00d6\u011frenme \u00e7\u0131kt\u0131s\u0131n\u0131 buraya ekleyin", + "Add a response:": "Bir cevap ekle:", "Add another group": "Ba\u015fka grup ekle", "Add language": "Dil ekle", "Add learners to this cohort": "Bu toplulu\u011fa \u00f6\u011frenci ekle", @@ -233,6 +240,7 @@ "Align left": "Sola yasla", "Align right": "Sa\u011fa yasla", "Alignment": "Hizalama", + "All Groups": "B\u00fct\u00fcn Gruplar", "All Learners and Staff": "T\u00fcm \u00d6\u011frenciler ve Personeller", "All Posts": "T\u00fcm G\u00f6nderiler", "All Rights Reserved": "T\u00fcm Haklar\u0131 Sakl\u0131d\u0131r", @@ -318,6 +326,7 @@ "Assessment": "De\u011ferlendirme", "Assessment Results Visibility": "De\u011ferlendirme Sonu\u00e7lar\u0131 G\u00f6r\u00fcn\u00fcrl\u00fc\u011f\u00fc", "Assessments": "De\u011ferlendirmeler", + "Assign Team Memberships": "Tak\u0131m \u00dcyeliklerini Belirle", "Assign learners to cohorts by uploading a CSV file": "CSV dosyas\u0131 y\u00fckleyerek \u00f6\u011frencileri topluluklara atay\u0131n", "Assign students to cohorts by uploading a CSV file.": "CSV dosyas\u0131n\u0131 y\u00fckleyerek toplulu\u011fa \u00f6\u011frencileri ata.", "Assignment Type Name": "G\u00f6rev T\u00fcr\u00fc \u0130smi", @@ -454,6 +463,7 @@ "Click to remove all chosen %s at once.": "Bir kerede t\u00fcm se\u00e7ilen %s kald\u0131r\u0131lmas\u0131 i\u00e7in t\u0131klay\u0131n.", "Close": "Kapat", "Close Calculator": "Hesap Makinesini Kapat", + "Closed": "Kapat\u0131ld\u0131", "Code": "Kod", "Code Sample (Ctrl+K)": "Kod \u00d6rne\u011fi (Ctrl+K)", "Code block": "Kod blo\u011fu", @@ -472,6 +482,8 @@ "Coming Soon": "Yak\u0131nda", "Commentary": "Yorum", "Common Problem Types": "S\u0131k Kar\u015f\u0131la\u015f\u0131lan Problem T\u00fcrleri", + "Community TA": "Topluluk \u00d6\u011fretim Eleman\u0131", + "Complete courses on your schedule to ensure you stand out in your field!": "Alan\u0131n\u0131zda \u00f6ne \u00e7\u0131kman\u0131z\u0131 sa\u011flamak i\u00e7in derslerinizi tamamlay\u0131n!", "Completed": "Tamamland\u0131", "Component": "Bile\u015fen", "Components": "Bile\u015fenler", @@ -514,8 +526,13 @@ "Country": "\u00dclke", "Country of residence": "\u0130kamet edilen \u00fclke", "Country or Region of Residence": "\u0130kamet Edilen \u00dclke ya da B\u00f6lge", + "Course": [ + "Ders", + "Dersler" + ], "Course Content": "Ders \u0130\u00e7eri\u011fi", "Course Credit Requirements": "Ders Kredisi Gereklilikleri", + "Course Discussion Forum": "Ders Tart\u0131\u015fma Forumu", "Course End": "Ders Biti\u015fi", "Course Handouts": "Ders Notlar\u0131", "Course ID": "Ders No", @@ -578,7 +595,6 @@ "Default (Local Time Zone)": "Varsay\u0131lan (Yerel Zaman Dilimi)", "Default Timed Transcript": "Varsay\u0131lan Zamanlar\u0131 \u0130\u015faretlenmi\u015f Altyaz\u0131", "Delete": "Sil", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u0130mza sahipleri listesinden \"<%= signatoryName %>\" sil?", "Delete File Confirmation": "Dosya Onay\u0131n\u0131 Kald\u0131r", "Delete My Account": "Hesab\u0131m\u0131 Sil", "Delete Page Confirmation": "Sayfa Onay\u0131n\u0131 Kald\u0131r", @@ -609,6 +625,7 @@ "Disc": "Disk", "Discard Changes": "De\u011fi\u015fiklikleri \u00c7\u0131kart", "Discarding Changes": "\u00c7\u0131kar\u0131lan De\u011fi\u015fiklikler", + "Discussion": "Forum", "Discussion Home": "Tart\u0131\u015fma Anasayfas\u0131", "Discussion topics in the course are not divided.": "Dersteki tart\u0131\u015fma ba\u015fl\u0131klar\u0131 b\u00f6l\u00fcnmemi\u015f.", "Discussions are unified; all learners interact with posts from other learners, regardless of the group they are in.": "Tart\u0131\u015fmalar birle\u015ftirilmi\u015f durumda; t\u00fcm \u00f6\u011frenciler i\u00e7inde olduklar\u0131 gruplardan ba\u011f\u0131ms\u0131z olarak, di\u011fer \u00f6\u011frencilerin g\u00f6nderileriyle etkile\u015fime girebilir.", @@ -622,7 +639,6 @@ "Do you want to upload your file before submitting?": " G\u00f6ndermeden \u00f6nce dosyan\u0131z\u0131 y\u00fcklemek istiyor musunuz?", "Document properties": "Belge \u00f6zellikleri", "Does the name on your ID match your account name: %(fullName)s?": "ID niz \u00fczerindeki isim hesab\u0131n\u0131zdaki isimle e\u015fle\u015fiyor mu: %(fullName)s?", - "Does the photo of you match your ID photo?": "Foto\u011fraf kimlik foto\u011fraf\u0131na uyuyor mu?", "Does the photo of you show your whole face?": "Foto\u011fraf y\u00fcz\u00fcn\u00fcz\u00fcn tamam\u0131n\u0131 g\u00f6steriyor mu?", "Doing so means that you are no longer eligible for academic credit.": "Bu \u015fekilde yapmak, akademik kredinizi dolduramayaca\u011f\u0131n\u0131z anlam\u0131na gelir.", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Resminizi g\u00f6rm\u00fcyor musunuz? Web izleyiciniz izin istedi\u011finde kameran\u0131z\u0131 kullanabilmesi i\u00e7in izin veriniz.", @@ -636,6 +652,7 @@ "Download the user's certificate": "Kullan\u0131c\u0131n\u0131n sertifikas\u0131n\u0131 indir", "Draft (Never published)": "Taslak (Hi\u00e7 yay\u0131nlanmad\u0131)", "Draft (Unpublished changes)": "Taslak (Yay\u0131mlanmayan de\u011fi\u015fiklikler)", + "Draft saved on {lastSavedStart}{editedOn}{lastSavedEnd} by {editedByStart}{editedBy}{editedByEnd}": "Taslak {lastSavedStart}{editedOn}{lastSavedEnd} tarihinde {editedByStart}{editedBy}{editedByEnd} taraf\u0131ndan kaydedildi", "Drag and drop or {spanStart}browse your computer{spanEnd}.": "S\u00fcr\u00fckle b\u0131rak veya {spanStart}bilgisayar\u0131n\u0131z\u0131n dizinlerini taray\u0131n{spanEnd}.", "Drag to reorder": "Tekrar d\u00fczenlemek i\u00e7in s\u00fcr\u00fckle", "Drop target image": "Hedef g\u00f6rseli b\u0131rak\u0131n", @@ -662,8 +679,12 @@ "Edit Title": "Ba\u015fl\u0131\u011f\u0131 D\u00fczenle", "Edit Your Name": "\u0130sminizi D\u00fczeltiniz", "Edit this certificate?": "Bu sertifikay\u0131 d\u00fczenle?", + "Edit your post below.": "\u0130letinizi a\u015fa\u011f\u0131da d\u00fczenleyin.", "Editable": "D\u00fczenlenebilir", "Editing access for: {title}": "{title} i\u00e7in eri\u015fim d\u00fczenleniyor", + "Editing comment": "Yorum de\u011fi\u015ftiriliyor", + "Editing post": "\u0130leti d\u00fczenleniyor", + "Editing response": "Cevap d\u00fczenleniyor", "Editing: {title}": "D\u00fczenleme: {title}", "Editor": "Edit\u00f6r", "Education Completed": "Tamamlanan E\u011fitim", @@ -681,6 +702,7 @@ "Encoding": "Kodlama", "End My Exam": "S\u0131nav\u0131m\u0131 Bitir", "End of transcript. Skip to the start.": "Altyaz\u0131n\u0131n sonu. Ba\u015flang\u0131ca atla.", + "Endorse": "Destekle", "Ends {end}": "Bitti {end}", "Engage with posts": "G\u00f6nderilerle etkile\u015fimde bulunun", "Enroll Now": "Hemen Kaydol", @@ -785,7 +807,6 @@ "Fill browser": "Taray\u0131c\u0131y\u0131 doldurun", "Filter": "S\u00fczge\u00e7", "Filter and sort topics": "Konular\u0131 filtrele ve s\u0131rala", - "Final Grade": "Final Notu", "Final Grade Received": "Final Notu Al\u0131nd\u0131", "Financial Aid": "M\u00e2li Yard\u0131m", "Financial Assistance": "M\u00e2li Yard\u0131m", @@ -799,7 +820,9 @@ "Find previous": "\u00d6ncekini bul", "Finish": "Bitir", "First time here?": "\u0130lk kez mi buradas\u0131n\u0131z?", + "Follow": "Takip et", "Follow or unfollow posts": "G\u00f6nderileri takip et veya takipten \u00e7\u0131k", + "Following": "Takip ediliyor", "Font Family": "Yaz\u0131tipi Ailesi", "Font Sizes": "Yaz\u0131 Boyutlar\u0131", "Footer": "Alt bilgi", @@ -818,7 +841,6 @@ "Generate": "Olu\u015ftur", "Generate Exception Certificates": "\u0130stisna Sertifikalar\u0131 Olu\u015ftur", "Generate the user's certificate": "Kullan\u0131c\u0131n\u0131n sertifikas\u0131n\u0131 olu\u015ftur", - "Get Credit": "Kredi Al", "Go Back": "Geri D\u00f6n", "Go to Dashboard": "Ana Panele Git", "Go to my Dashboard": "Panelime Git", @@ -897,10 +919,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "Bir alt b\u00f6l\u00fcm\u00fcn son tarihi yoksa, \u00f6\u011frenciler cevaplar\u0131n\u0131 de\u011ferlendirmeye g\u00f6nderdi\u011finde notlar\u0131n\u0131 g\u00f6r\u00fcrler.", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "E\u011fer \u00fcnite \u00f6\u011frencilere daha \u00f6nce a\u00e7\u0131ld\u0131 ve yay\u0131nland\u0131ysa, gizliyken \u00fcnitede yapt\u0131\u011f\u0131n\u0131z t\u00fcm de\u011fi\u015fiklikler \u015fimdi \u00f6\u011frencilere g\u00f6r\u00fcn\u00fcr olacak.", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "E\u011fer \u00fcnite \u00f6nceden yay\u0131nlanm\u0131\u015f ve \u00f6\u011frencilere a\u00e7\u0131lm\u0131\u015fsa, \u00fcnite gizliyken yapt\u0131\u011f\u0131n\u0131z de\u011fi\u015fiklikler \u00f6\u011frencilere art\u0131k g\u00f6r\u00fcn\u00fcr olacak. Devam etmek istiyor musunuz?", - "If you are unable to access your account contact us via email using {email}.": "Hesab\u0131n\u0131za ula\u015fam\u0131yorsan\u0131z bizimle {email} e-posta adresi \u00fczerinden ileti\u015fime ge\u00e7ebilirsiniz.", "If you do not yet have an account, use the button below to register.": "Hen\u00fcz bir hesab\u0131n\u0131z yoksa, kay\u0131t i\u00e7in a\u015fa\u011f\u0131daki d\u00fc\u011fmeyi kullan\u0131n.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "E\u011fer kimli\u011finizi \u015fimdi do\u011frulamazsan\u0131z, hala daha ana panelinizden dersinizi ke\u015ffedebilirsiniz. Kimli\u011finizi do\u011frulamak i\u00e7in %(platformName)s \u00fczerinden periyodik hat\u0131rlatma alacaks\u0131n\u0131z.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u015eu an kimli\u011finizi onaylamasan\u0131z da, dersinize h\u00e2l\u00e2 panelinizden ula\u015fabilirsiniz. Kimli\u011finizi onaylaman\u0131z i\u00e7in, {platformName} size d\u00fczenli bildirimler g\u00f6nderecek.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "E\u011fer sayfadan cevab\u0131n\u0131z\u0131 kaydetmeden ya da g\u00f6ndermeden ayr\u0131l\u0131rsan\u0131z, cevap i\u00e7in yapt\u0131\u011f\u0131n\u0131z i\u015flemleri kaybedeceksiniz.", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "Bu sayfay\u0131 \u00f6zde\u011ferlendirmenizi yazmadan terk etmeniz durumunda, yapt\u0131\u011f\u0131n\u0131z t\u00fcm i\u015fleri kaybedeceksiniz.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "Bu sayfay\u0131 de\u011ferlendirmenizi yazmadan terk etmeniz durumunda, yapt\u0131\u011f\u0131n\u0131z t\u00fcm i\u015fleri kaybedeceksiniz.", @@ -985,6 +1005,7 @@ "Last activity {date}": "Son faaliyet {date}", "Last modified by": "Son g\u00fcncelleyen ", "Last published %(last_published_date)s by %(publish_username)s": "%(publish_username)s taraf\u0131ndan son yay\u0131nlanan %(last_published_date)s", + "Last published {lastPublishedStart}{publishedOn}{lastPublishedEnd} by {publishedByStart}{publishedBy}{publishedByEnd}": "En son {lastPublishedStart}{publishedOn}{lastPublishedEnd} tarihinde {publishedByStart}{publishedBy}{publishedByEnd} taraf\u0131ndan yay\u0131na al\u0131nd\u0131", "Last updated": "Son g\u00fcncelleme", "Learn More": "Daha Fazlas\u0131n\u0131 \u00d6\u011fren", "Learn more about {license_name}": "{license_name} hakk\u0131nda daha fazla \u00f6\u011fren", @@ -1025,6 +1046,7 @@ "Live view of webcam": "Web kameran\u0131z\u0131n canl\u0131 g\u00f6r\u00fcnt\u00fcs\u00fc", "Load Another File": "Ba\u015fka Bir Dosya Y\u00fckle", "Load all responses": "B\u00fct\u00fcn cevaplar\u0131 y\u00fckle", + "Load more": "Daha fazla y\u00fckle", "Load next {numResponses} responses": "Sonraki {numResponses} cevap y\u00fckleniyor", "Loading": "Y\u00fckl\u00fcyor...", "Loading content": "\u0130\u00e7erik y\u00fckleniyor", @@ -1054,6 +1076,7 @@ "Manual": "El ile", "March": "Mart", "Mark Exam As Completed": "S\u0131nav\u0131 Tamamland\u0131 Olarak \u0130\u015faretle", + "Mark as Answer": "Cevap olarak \u0130\u015faretle", "Mark enrollment code as unused": "Kay\u0131tlanma kodunu kullan\u0131lmayan olarak i\u015faretle", "Markdown Editing Help": "Markdown \u0130\u015faretleme Dili Yard\u0131m\u0131", "Masters": "Y\u00fcksek Lisanslar", @@ -1167,8 +1190,8 @@ "Ok": "Tamam", "One or more rescheduling tasks failed.": "Bir veya daha fazla yeniden zamanlama g\u00f6revi ba\u015far\u0131s\u0131z oldu.", "Only ": "Sadece", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "Sadece <%= fileTypes %> dosya uzant\u0131lar\u0131n\u0131 y\u00fckleyebilirsiniz. L\u00fctfen sonunda <%= fileExtensions %> uzant\u0131s\u0131 olan bir dosya y\u00fckleyin.", "Only properly formatted .csv files will be accepted.": "Sadece d\u00fczg\u00fcn formatlanm\u0131\u015f .csv dosyalar\u0131 kabul edilecek.", + "Open": "A\u00e7", "Open Calculator": "Hesap Makinesini A\u00e7", "Open language menu": "Dil men\u00fcs\u00fcn\u00fc a\u00e7\u0131n", "Open the certificate you earned for the %(title)s program.": "%(title)s program\u0131nda hak kazand\u0131\u011f\u0131n\u0131z sertifikay\u0131 a\u00e7\u0131n.", @@ -1220,6 +1243,8 @@ "Photo of %(fullName)s's ID": "%(fullName)s'in Foto\u011frafl\u0131 Kimli\u011fi ", "Photo requirements:": "Foto\u011fraf gereklilikleri:", "Photos don't meet the requirements?": "Foto\u011fraflar gereksinimleri kar\u015f\u0131l\u0131yor mu?", + "Pin": "\u0130\u015faretle", + "Pinned": "\u0130\u015faretli", "Placeholder": "Yer tutucu", "Play": "Oynat", "Play video": "Videoyu oynat", @@ -1263,6 +1288,7 @@ "Please wait": "L\u00fctfen bekleyin", "Plugins": "Eklentiler", "Post": "G\u00f6nderi", + "Post type": "G\u00f6nderi t\u00fcr\u00fc", "Poster": "Poster", "Practice Exam Completed": "Al\u0131\u015ft\u0131rma S\u0131nav\u0131 Tamamland\u0131", "Practice Exam Failed": "Al\u0131\u015ft\u0131rma S\u0131nav\u0131 Ba\u015far\u0131s\u0131z", @@ -1322,6 +1348,7 @@ "Published and Live": "Yay\u0131nland\u0131 ve Canl\u0131", "Publishing": "Yay\u0131nlama", "Publishing Status": "Yay\u0131nlanma Durumu", + "Question": "Soru", "Queued": "Kuyru\u011fa Al\u0131nd\u0131", "REMAINING COURSES": "KALAN DERSLER", "Re-run Course": "Dersi Yeniden \u00c7al\u0131\u015ft\u0131r", @@ -1344,6 +1371,7 @@ "Regenerate the user's certificate": "Kullan\u0131c\u0131n\u0131n sertifikas\u0131n\u0131 yeniden olu\u015ftur", "Register with Institution/Campus Credentials": "Kurum / Kamp\u00fcs Kimlik Bilgileri ile Kay\u0131t", "Rejected": "Reddedildi", + "Related to: %(courseware_title_linked)s": "\u0130lgili: %(courseware_title_linked)s", "Release Date and Time": "Yay\u0131m Tarih ve Zaman\u0131", "Release Date:": "Yay\u0131m Tarihi:", "Release Status:": "Yay\u0131n Durumu:", @@ -1372,7 +1400,10 @@ "Replace all": "T\u00fcm\u00fcn\u00fc de\u011fi\u015ftir", "Replace with": "De\u011fi\u015ftir", "Reply to Annotation": "\u0130pu\u00e7lar\u0131na Yan\u0131t Ver", + "Report": "Raporla", + "Report abuse": "K\u00f6t\u00fc kullan\u0131m\u0131 bildir", "Report abuse, topics, and responses": "\u0130hlalleri, konular\u0131 ve yan\u0131tlar\u0131 bildir", + "Reported": "Rapor edildi", "Requester": "\u0130steyen", "Required": "Gerekli", "Required field.": "Gerekli alan.", @@ -1625,9 +1656,7 @@ "Textbook Name": "Ders Kitab\u0131 Ad\u0131", "Textbook information": "Ders Kitab\u0131 bilgisi", "Textbook name is required": "Ders kitab\u0131 ad\u0131 gerekli", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "%(course_name)s dersi i\u00e7in \u00f6demenizi ald\u0131k. Te\u015fekk\u00fcrler %(full_name)s!", "Thank you for setting your course goal to {goal}!": "Ders hedefinizi {goal} olarak belirledi\u011finiz i\u00e7in te\u015fekk\u00fcr ederiz!", - "Thank you for submitting a request! We will contact you within 24 hours.": "Bize talebinizi iletti\u011finiz i\u00e7in te\u015fekk\u00fcr ederiz! Size 24 saat i\u00e7inde geri d\u00f6nece\u011fiz.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "{course_name} i\u00e7in mali yard\u0131m ba\u015fvurunuzu g\u00f6nderdi\u011finiz i\u00e7in te\u015fekk\u00fcrler ! 2-4 i\u015f g\u00fcn\u00fc i\u00e7erisinde size geri d\u00f6nece\u011fiz. ", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Foto\u011fraflar\u0131n\u0131z\u0131 g\u00f6nderdi\u011finiz i\u00e7in te\u015fekk\u00fcr ederiz. K\u0131sa s\u00fcre i\u00e7inde de\u011ferlendirece\u011fiz. \u015eimdi onayl\u0131 sertifika sunan herhangi bir %(platformName)s derse kay\u0131t olabilirsiniz. Do\u011frulama bir y\u0131l i\u00e7indir. Bir y\u0131ldan sonra yeniden do\u011frulama i\u00e7in foto\u011fraflar\u0131n\u0131z\u0131 tekrar g\u00f6ndermelisiniz.", "Thank you! We have received your payment for {courseName}.": "Te\u015fekk\u00fcrler! {courseName} i\u00e7in olan \u00f6demenizi ald\u0131k.", @@ -1639,8 +1668,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Bu \u00f6\u011frenci i\u00e7in sertifika yeniden de\u011ferlendiriliyor ve sistem bu \u00f6\u011frencinin notlar\u0131n\u0131 yeniden hesapl\u0131yor.", "The cohort cannot be added": "Topluluk eklenemedi", "The cohort cannot be saved": "Tapluluk kaydedilemedi", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "Organizasyonun birle\u015fik boyutu ve k\u00fct\u00fcphane kodu alanlar\u0131 <%=limit%> karakterden fazla olamaz.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "Organizasyonun birle\u015fik boyutu, ders say\u0131s\u0131, ve ders alanlar\u0131 <%=limit%> karakterden fazla olamaz.", "The country or region where you live.": "\u0130kamet etti\u011finiz \u00fclke veya b\u00f6lge.", "The country that team members primarily identify with.": "Tak\u0131m \u00fcyelerinin \u00f6ncelikli olarak \u00f6zde\u015fle\u015ftirildi\u011fi \u00fclke.", "The course end date must be later than the course start date.": "Dersin biti\u015f tarihi, ba\u015flang\u0131\u00e7 tarihinden sonra olmal\u0131d\u0131r.", @@ -1656,7 +1683,6 @@ "The following email addresses and/or usernames are invalid:": "A\u015fa\u011f\u0131daki e-posta adresleri veya kullan\u0131c\u0131 adlar\u0131 ge\u00e7ersizdir.", "The following errors were generated:": "A\u015fa\u011f\u0131daki hatalar olu\u015ftu:", "The following file types are not allowed: ": "A\u015fa\u011f\u0131daki dosya t\u00fcr\u00fcne izin verilmiyor:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "A\u015fa\u011f\u0131daki bilgiler profilinizde mevcut {platform} bulunuyor. Ba\u015fvurunuz i\u00e7in buraya ekledik.", "The following message will be displayed at the bottom of the courseware pages within your course:": "A\u015fa\u011f\u0131daki ileti e\u011fitiminizdeki ders yaz\u0131l\u0131m sayfas\u0131n\u0131n alt\u0131nda g\u00f6r\u00fcnt\u00fclenecektir.", "The following options are available for the {license_name} license.": "A\u015fa\u011f\u0131daki se\u00e7enekler {license_name} lisans\u0131 i\u00e7in ge\u00e7erlidir. ", "The following users are no longer enrolled in the course:": "A\u015fa\u011f\u0131daki kullan\u0131c\u0131lar art\u0131k bu derse kay\u0131tl\u0131 de\u011filler:", @@ -1668,7 +1694,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "Minimum tamamlama y\u00fczdesi 0 ile 100 aras\u0131nda bir tamsay\u0131 olmal\u0131.", "The minimum grade for course credit is not set.": "Ders kredisi i\u00e7in minimum not ayarlanmad\u0131.", "The minimum score percentage must be a whole number between 0 and 100.": "Minimum not y\u00fczdesi 0 ile 100 aras\u0131nda bir tamsay\u0131 olmal\u0131.", - "The more you tell us, the more quickly and helpfully we can respond!": "Bize ne kadar \u00e7ok ayr\u0131nt\u0131 verirseniz, size o kadar h\u0131zl\u0131 ve faydal\u0131 bir \u015fekilde cevap verebiliriz!", "The name of this signatory as it should appear on certificates.": "Bu imza sahibinin ad\u0131 sertifikada g\u00f6r\u00fcnd\u00fc\u011f\u00fc gibidir.", "The name that identifies you on {platform_name}. You cannot change your username.": "Sizi {platform_name} platformunda tan\u0131mlayan kullan\u0131c\u0131 ad\u0131n\u0131z. Kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 de\u011fi\u015ftiremezsiniz. ", "The name that is used for ID verification and that appears on your certificates.": "Kimlik do\u011frulamas\u0131nda ve sertifikalar\u0131n\u0131z\u0131n \u00fczerinde kullan\u0131lacak isim.", @@ -1676,7 +1701,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Bu g\u00f6rev t\u00fcr\u00fc problemlerini i\u00e7eren ders altb\u00f6l\u00fcmlerinin say\u0131s\u0131.", "The organization that this signatory belongs to, as it should appear on certificates.": "Bu imza sahibine ait olan organizasyon, sertifikalarda g\u00f6r\u00fcnmeli.", "The page \"{route}\" could not be found.": "\"{route}\" sayfas\u0131 bulunamad\u0131.", - "The photo of your face matches the photo on your ID.": "Foto\u011fraf\u0131n\u0131z, kimlik kart\u0131n\u0131zdaki ile uygun olmal\u0131.", "The post you selected has been deleted.": "Se\u00e7ti\u011finiz ileti silindi.", "The raw error message is:": "\u0130\u015flenmemi\u015f hata mesaj\u0131:", "The refund deadline for this course has passed,so you will not receive a refund.": "Bu ders i\u00e7in iadenin son g\u00fcn\u00fc ge\u00e7ti, bu y\u00fczden iade alamayacaks\u0131n\u0131z.", @@ -1768,6 +1792,8 @@ "This post could not be reopened. Refresh the page and try again.": "Bu g\u00f6nderi yeniden a\u00e7\u0131lamaz. Sayfay\u0131 yenileyin ve tekrar deneyin.", "This post could not be unflagged for abuse. Refresh the page and try again.": "Bu g\u00f6nderinin taciz i\u015faretlemesi kald\u0131r\u0131lamaz. Sayfay\u0131 yenileyin ve tekrar deneyin.", "This post could not be unpinned. Refresh the page and try again.": "Bu g\u00f6nderi sabitlenmesi kald\u0131r\u0131lamad\u0131. Sayfay\u0131 yeniden y\u00fckleyin ve tekrar deneyin.", + "This post is visible to everyone.": "Bu g\u00f6nderi herkese a\u00e7\u0131kt\u0131r", + "This post will be visible to everyone.": "Bu ileti herkese g\u00f6r\u00fcn\u00fcr olacak.", "This problem could not be saved.": "Bu problem kaydedilemedi.", "This problem has already been released. Any changes will apply only to future assessments.": "Bu problem \u015fu anda yay\u0131mlanm\u0131\u015f bulunuyor. Bu durumda herhangi bir de\u011fi\u015fiklik sadece ileriki de\u011ferlendirmelerde uygulanacakt\u0131r.", "This problem has been reset.": "Bu problem s\u0131f\u0131rland\u0131.", @@ -1784,6 +1810,7 @@ "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.": "Bu g\u00f6rev t\u00fcr\u00fc i\u00e7in belirlenen k\u0131saisim (\u00f6rne\u011fin, \u00d6dev veya ARSNV gibi) \u00f6\u011frencinin \u0130lerleme sayfas\u0131nda, g\u00f6revin hemen yan\u0131nda g\u00f6z\u00fck\u00fcr.", "This team does not have any members.": "Bu tak\u0131mda hi\u00e7 \u00fcye yok.", "This team is full.": "Bu tak\u0131m dolu.", + "This thread is closed.": "Bu ileti dizisi kapand\u0131.", "This unit has validation issues.": "Bu \u00fcnitenin do\u011frulama sorunu var.", "This vote could not be processed. Refresh the page and try again.": "Bu oy i\u015flenemedi. Sayfay\u0131 yeniden y\u00fckleyin ve tekrar deneyin.", "Thumbnail": "K\u00fc\u00e7\u00fck resim", @@ -1809,7 +1836,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "T\u00fcm \u00f6\u011frencilerin videoya eri\u015febildi\u011finden emin olmak i\u00e7in, videonuzun .mp4 ve .webm s\u00fcr\u00fcmlerini sa\u011flaman\u0131z\u0131 \u00f6neririz. Ba\u015fka bir s\u00fcr\u00fcm i\u00e7in URL eklemek \u00fczere a\u015fa\u011f\u0131ya t\u0131klay\u0131n. Bu URL'ler YouTube URL'si olamaz. \u00d6\u011frencilerin bilgisayarlar\u0131yla uyumlu olan ilk listelenen video oynayacakt\u0131r.", "To complete the program, you must earn a verified certificate for each course.": "Program\u0131 tamamlamak i\u00e7in, t\u00fcm derslerde onayl\u0131 sertifikaya hak kazanmal\u0131s\u0131n\u0131z.", "To continue learning with this account, sign in below.": "Bu hesap ile \u00f6\u011frenmeye devam etmek i\u00e7in, a\u015fa\u011f\u0131dan giri\u015f yap.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "Ders kredisini sonland\u0131rmak i\u00e7in, %(display_name)s, kredi talebini y\u00fcklemek i\u00e7in %(platform_name)s \u00f6\u011frencilerini gerektirir.", "To invalidate a certificate for a particular learner, add the username or email address below.": "Belli bir \u00f6\u011frencinin sertifikas\u0131n\u0131 ge\u00e7ersizle\u015ftirmek i\u00e7in, kullan\u0131c\u0131 ad\u0131 veya e-posta adresini a\u015fa\u011f\u0131ya girin.", "To pass this exam, you must complete the problems in the time allowed.": "Bu s\u0131navdan ge\u00e7mek i\u00e7in, problemleri size tan\u0131nan s\u00fcrede \u00e7\u00f6zmelisiniz.", "To receive a certificate, you must also verify your identity before {date}.": "Sertifika almak i\u00e7in {date} tarihinden \u00f6nce kimli\u011finizi do\u011frulamal\u0131s\u0131n\u0131z.", @@ -1824,6 +1850,7 @@ "Tools": "Ara\u00e7lar", "Top": "\u00dcst", "Topic": "Konu", + "Topic area": "Ba\u015fl\u0131k alan\u0131", "Topics": "Konular", "Total": "Toplam", "Total Number": "Toplam Say\u0131", @@ -1845,6 +1872,7 @@ "Type into this box to filter down the list of available %s.": "Mevcut %s listesini s\u00fczmek i\u00e7in bu kutu i\u00e7ine yaz\u0131n.", "URL": "URL", "Unable to delete account": "Hesap silinemedi", + "Unable to determine whether we should give you a refund because of System Error. Please try again later.": "\u015eu anda Sistem Hatas\u0131ndan dolay\u0131 geri \u00f6deme verip veremeyece\u011fimizi saptayam\u0131yoruz. L\u00fctfen daha sonra tekrar deneyiniz.", "Unable to load": "Y\u00fcklenemedi", "Unable to submit application": "Ba\u015fvuru g\u00f6nderilemedi", "Underline": "Alt \u00e7izgi", @@ -1853,7 +1881,9 @@ "Undo Changes": "De\u011fi\u015fiklikleri Geri Al", "Undo move": "Ta\u015f\u0131may\u0131 geri al", "Undo moving": "Ta\u015f\u0131may\u0131 geri al", + "Unendorse": "Destekleme", "Unexpected server error.": "Beklenmeyen sunucu hatas\u0131.", + "Unfollow": "Takibi b\u0131rak", "Ungraded": "Puanlanmam\u0131\u015f", "Ungraded Practice Exam": "Puanlanmam\u0131\u015f Al\u0131\u015ft\u0131rma S\u0131nav\u0131", "Unit": "\u00dcnite", @@ -1866,14 +1896,20 @@ "Unlink This Account": "Hesab\u0131n Ba\u011flant\u0131s\u0131n\u0131 Kald\u0131r", "Unlink your {accountName} account": "{accountName} hesab\u0131n\u0131z\u0131n ba\u011flant\u0131s\u0131n\u0131 kald\u0131r\u0131n", "Unlinking": "Ba\u011flant\u0131 kald\u0131rma", + "Unmark as Answer": "Cevap i\u015faretini Kald\u0131r", "Unmute": "Ses", "Unnamed Option": "Adland\u0131r\u0131lmam\u0131\u015f Se\u00e7enek", + "Unpin": "\u0130\u015fareti kald\u0131r", "Unpublished changes to content that will release in the future": "\u0130\u00e7eri\u011fin yay\u0131mlanmam\u0131\u015f de\u011fi\u015fiklikleri ilerde yay\u0131nlanacakt\u0131r.", "Unpublished changes to live content": "Canl\u0131 yay\u0131n i\u00e7eri\u011findeki yay\u0131mlanmam\u0131\u015f de\u011fi\u015fiklikler", "Unpublished units will not be released": "Yay\u0131mlanmam\u0131\u015f birimler yay\u0131nlanmayacakt\u0131r", + "Unreport": "Bildirme", "Unscheduled": "Planlanmam\u0131\u015f", "Update": "G\u00fcncelle", "Update Settings": "Ayarlar\u0131 G\u00fcncelle", + "Update comment": "Yorumu g\u00fcncelle", + "Update post": "\u0130leti g\u00fcncelle", + "Update response": "Cevab\u0131 g\u00fcncelle", "Update team.": "Tak\u0131m\u0131 g\u00fcncelle.", "Updating Tags": "Etiketler G\u00fcncelleniyor", "Updating with latest library content": "Son k\u00fct\u00fcphane i\u00e7eri\u011fiyle g\u00fcncelleniyor", @@ -1893,7 +1929,6 @@ "Upload Videos": "Videolar\u0131 Y\u00fckle", "Upload a CSV file": "CSV dosyas\u0131 y\u00fckle", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u0130stisna hakk\u0131 verilen \u00f6\u011frencilerin kullan\u0131c\u0131 adlar\u0131n\u0131 ve e-posta adreslerini i\u00e7eren ve virg\u00fclle ayr\u0131lan de\u011ferler (.csv) dosyas\u0131n\u0131 y\u00fckleyin. Virg\u00fclle ayr\u0131lm\u0131\u015f ilk alana kullan\u0131c\u0131 ad\u0131 ya da e-posta adreslerini ekleyin. \u0130kinci virg\u00fclle ayr\u0131lm\u0131\u015f alana istisna tan\u0131ma nedenini belirten, iste\u011fe ba\u011fl\u0131 bir not ekleyebilirsiniz.", - "Upload a new PDF to \u201c<%= name %>\u201d": " \u015eu konuma \u201c<%= name %>\u201d yeni bir PDF dosyas\u0131 y\u00fckle", "Upload an image": "G\u00f6rsel y\u00fckle", "Upload an image or capture one with your web or phone camera.": "Resim y\u00fckle veya Web kameran\u0131z veya telefonunuzun kameras\u0131yla \u00e7ekiniz.", "Upload completed": "Y\u00fckleme tamamland\u0131", @@ -1923,7 +1958,6 @@ "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "Tart\u0131\u015fmalar\u0131 b\u00f6lmek i\u00e7in kay\u0131tlanma yollar\u0131n\u0131 kullan. Kay\u0131tlanma yollar\u0131na ba\u011fl\u0131 olmaks\u0131z\u0131n t\u00fcm \u00f6\u011frenciler ayn\u0131 tart\u0131\u015fma ba\u015fl\u0131klar\u0131n\u0131 g\u00f6r\u00fcr; b\u00f6l\u00fcnm\u00fc\u015f ba\u015fl\u0131klarda ise sadece ayn\u0131 ayn\u0131 kay\u0131tlanma yolundaki \u00f6\u011frenciler birbirini g\u00f6r\u00fcp, bir di\u011ferine cevap verebilir.", "Use my institution/campus credentials": "Benim kurum / kamp\u00fcs kimlik bilgilerimi kullan\u0131n", "Use the All Topics menu to find specific topics.": "\u00d6zel konular\u0131 bulmak i\u00e7in T\u00fcm Konular men\u00fcs\u00fcn\u00fc kullan", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Kimli\u011finizin foto\u011fraf\u0131n\u0131 \u00e7ekmek i\u00e7in web kameran\u0131z\u0131 kullan\u0131n. Biz bu foto\u011fraf\u0131n\u0131z\u0131 kimli\u011finiz \u00fczerindeki foto\u011fraf ile e\u015fle\u015ftirece\u011fiz.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Y\u00fcz\u00fcn\u00fcz\u00fcn foto\u011fraf\u0131n\u0131 \u00e7ekmek i\u00e7in web kameran\u0131z\u0131 kullan\u0131n. Biz bu foto\u011fraf\u0131n\u0131z\u0131 kimli\u011finiz \u00fczerindeki foto\u011fraf ile e\u015fle\u015ftirece\u011fiz.", "Used": "Kullan\u0131ld\u0131", "User Email": "Kullan\u0131c\u0131 E-posta", @@ -1943,7 +1977,6 @@ "Verified Certificate upgrade": "Onayl\u0131 Sertifikay\u0131 G\u00fcncelle", "Verified Status": "Onaylanm\u0131\u015f Durum", "Verified mode price": "Onaylanm\u0131\u015f \u00fccret", - "Verify Now": "\u015eimdi Do\u011frula", "Version": "S\u00fcr\u00fcm", "Vertical space": "Dikey a\u00e7\u0131kl\u0131k", "Very loud": "\u00c7ok y\u00fcksek sesli", @@ -1968,12 +2001,15 @@ "View Program Record": "Program Kayd\u0131n\u0131 G\u00f6ster", "View Teams in the {topic_name} Topic": "{topic_name} Ba\u015fl\u0131\u011f\u0131 Alt\u0131ndaki Tak\u0131mlar\u0131 G\u00f6r\u00fcnt\u00fcle ", "View all errors": "T\u00fcm hatalar\u0131 g\u00f6r", + "View discussion": "Tart\u0131\u015fmay\u0131 g\u00f6r\u00fcnt\u00fcle", "View my exam": "S\u0131nav\u0131m\u0131 g\u00f6r\u00fcnt\u00fcle", "Visibility": "G\u00f6r\u00fcn\u00fcrl\u00fck", + "Visible to": "G\u00f6r\u00fcnecek ki\u015filer", "Visible to Staff Only": "Sadece Personele G\u00f6r\u00fcn\u00fcr", "Visual aids": "G\u00f6rsel yard\u0131mlar", "Volume": "Ses \u015eiddeti", "Vote for good posts and responses": "\u0130yi g\u00f6nderi ve yan\u0131tlar\u0131 oyla", + "Vote for this post,": "Bu ileti i\u00e7in oyla,", "Waiting": "Bekleniyor", "Want to confirm your identity later?": "Kimli\u011finizi daha sonra m\u0131 do\u011frulamak istersiniz?", "Warning": "Uyar\u0131", @@ -1983,7 +2019,6 @@ "We couldn't find any results for \"%s\".": "\"%s\" i\u00e7in hi\u00e7bir sonu\u00e7 bulunamad\u0131.", "We couldn't sign you in.": "Oturumunuzu a\u00e7amad\u0131k.", "We have encountered an error. Refresh your browser and then try again.": "Bir hatayla kar\u015f\u0131la\u015ft\u0131k. Taray\u0131c\u0131n\u0131z\u0131 yenileyin ve sonra tekrar deneyin.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Bilgilerinizi ald\u0131k ve kimli\u011finizi do\u011fruluyoruz. Do\u011frulama s\u00fcreci tamaland\u0131\u011f\u0131nda (genelde 1-2 g\u00fcn i\u00e7erisinde tamamlan\u0131r) ana panelinize mesaj gelecektir. Bu s\u00fcre i\u00e7inde mevcut olan ders i\u00e7eriklerine ula\u015fabilirsiniz.", "We just need a little more information before you start learning with %(platformName)s.": "%(platformName)s ile \u00f6\u011frenmeye ba\u015flamadan \u00f6nce biraz daha bilgiye ihtiyac\u0131m\u0131z var.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Foto\u011fraf\u0131n\u0131z\u0131 \u015fifrelemek ve inceleme i\u00e7in yetkilendirme hizmetimize g\u00f6ndermek i\u00e7in uygun olan en y\u00fcksek seviyede g\u00fcvenli\u011fi kullan\u0131yoruz. Foto\u011fraf\u0131n\u0131z ve bilgileriniz kaydedilmez ve do\u011frulama s\u00fcreci tamamland\u0131ktan sonra %(platformName)s \u00fczerinde hi\u00e7bir yerde g\u00f6r\u00fclmez.", "We're sorry to see you go! Your account will be deleted shortly.": "Gitti\u011finizi g\u00f6rmek bizi \u00fcz\u00fcyor! Hesab\u0131n\u0131z yak\u0131nda silinecek.", @@ -2080,13 +2115,10 @@ "You must specify a name": "\u0130sim belirtmelisiniz", "You must specify a name for the cohort": "Topluluk i\u00e7in bir isim belirtmelisiniz", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "T\u00fcm profilinizi payla\u015fmadan \u00f6nce do\u011fum y\u0131l\u0131n\u0131z\u0131 belirlemek zorundas\u0131n\u0131z. Do\u011fum y\u0131l\u0131n\u0131z\u0131 belirlemek i\u00e7in, {account_settings_page_link} gidin", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Ad\u0131n\u0131z\u0131 ve foto\u011fraf\u0131n\u0131z\u0131 i\u00e7eren bir ehliyet, pasaport veya di\u011fer devlet taraf\u0131ndan verilen kimli\u011fe ihtiyac\u0131n\u0131z var.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Ad\u0131n\u0131z\u0131 ve foto\u011fraf\u0131n\u0131z\u0131 i\u00e7eren bir kimli\u011fe ihtiyac\u0131n\u0131z vard\u0131r. Bir ehliyet, pasaport veya di\u011fer h\u00fck\u00fcmet taraf\u0131ndan verilen kimlikler t\u00fcm kabul edilebilir.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Derse kay\u0131t olmadan \u00f6nce hesab\u0131n\u0131z\u0131 aktive edin. Etkinle\u015ftirme e-posta i\u00e7in gelen kutunuzu kontrol edin.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Derse kay\u0131t olmadan \u00f6nce hesab\u0131n\u0131z\u0131 aktive edin. Etkinle\u015ftirme e-posta i\u00e7in gelen kutunuzu kontrol edin. Etkinle\u015ftirmeyi tamamlad\u0131ktan sonra bu sayfaya d\u00f6nebilir ve yenileyebilirsiniz.", "You receive messages from {platform_name} and course teams at this address.": "{platform_name} platformundan ve ders tak\u0131mlar\u0131ndan iletileri bu adrese alacaks\u0131n\u0131z.", "You reserve all rights for your work": "Eserinizin t\u00fcm haklar\u0131 sizde sakl\u0131d\u0131r", - "You still need to visit the %(display_name)s website to complete the credit process.": "Sizin hala daha kredi i\u015flemini tamamlamak i\u00e7in %(display_name)s websitesine ziyaret etmeniz gerekmektedir.", "You submitted {filename}; only {allowedFiles} are allowed.": "{filename} dosyas\u0131n\u0131 g\u00f6nderdiniz; sadece {allowedFiles} dosyalar\u0131na izin veriliyor.", "You waive some rights for your work, such that others can use it too": "Eserinizdeki baz\u0131 haklar\u0131n\u0131zdan feragat edebilirsiniz, b\u00f6ylece ba\u015fkalar\u0131 da onu kolayca kullanabilir", "You will be refunded the amount you paid.": "\u00d6dedi\u011finiz tutar size iade edilecektir.", @@ -2156,6 +2188,7 @@ "and others": "ve di\u011ferleri", "anonymous": "anonim", "answer": "cevap", + "answered question": "soru cevapland\u0131", "asset_path is required": "asset_path gerekli", "bytes": "byte", "certificate": "sertifika", @@ -2169,6 +2202,7 @@ "delete chapter": "b\u00f6l\u00fcm sil", "delete group": "grubu sil", "details about the failure": "ba\u015far\u0131s\u0131zl\u0131\u011fa dair ayr\u0131nt\u0131lar", + "discussion": "tart\u0131\u015fma", "dragging": "s\u00fcr\u00fckleme", "dragging out of slider": "Kayd\u0131r\u0131c\u0131n\u0131n d\u0131\u015f\u0131na s\u00fcr\u00fckleme", "dropped in slider": "kayd\u0131r\u0131c\u0131ya b\u0131rak\u0131ld\u0131", @@ -2180,8 +2214,8 @@ "emphasized text": "vurgulu metin", "enter code here": "kodu buraya girin", "enter link description here": "ba\u011flant\u0131 tan\u0131m\u0131n\u0131 buraya girin", + "follow this post": "bu iletiyi takip et", "for": "i\u00e7in", - "for {courseName}": "{courseName} i\u00e7in", "group configuration": "grup ayar\u0131", "image omitted": "g\u00f6rsel atland\u0131", "incorrect": "yanl\u0131\u015f", @@ -2205,6 +2239,8 @@ "or create a new one here": "ya da burada yeni bir tane olu\u015fturunuz", "or sign in with": "veya oturum a\u00e7\u0131n", "pending": "beklemede", + "post anonymously": "isimsiz olarak ileti yolla", + "posted %(time_ago)s by %(author)s": "%(author)s taraf\u0131ndan %(time_ago)s \u00f6nce g\u00f6nderildi", "practice": "al\u0131\u015ft\u0131rma", "price": "\u00fccret", "proctored": "g\u00f6zetmenli", @@ -2221,6 +2257,7 @@ "subsection": "altb\u00f6l\u00fcm", "team count": "tak\u0131m say\u0131s\u0131", "timed": "zamanlanm\u0131\u015f", + "unanswered question": "cevaplanmayan soru", "unit": "\u00fcnite", "unsatisfactory": "yetersiz", "unsubmitted": "g\u00f6nderilmedi", @@ -2303,6 +2340,7 @@ "{totalItems} total": "toplam {totalItems}", "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}": "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}", "{type} Progress": "{type} \u0130lerleme", + "{unread_comments_count} new": "{unread_comments_count} yeni", "\u2026": "..." }; for (var key in newcatalog) { @@ -2325,7 +2363,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2378,9 +2416,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "d F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d M Y H:i", "SHORT_DATE_FORMAT": "d M Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/uk/djangojs.js b/cms/static/js/i18n/uk/djangojs.js index 592be1dc0d1a4d63f55f878a034aab81cd97931a..6c37475b2786402f8c4701cf9d84b8d3774c4b65 100644 --- a/cms/static/js/i18n/uk/djangojs.js +++ b/cms/static/js/i18n/uk/djangojs.js @@ -42,6 +42,7 @@ "%(field)s must have at least %(count)d characters.": "%(field)s \u043f\u043e\u0432\u0438\u043d\u043d\u043e \u0431\u0443\u0442\u0438 \u043d\u0435 \u043c\u0435\u043d\u0448\u0435 %(count)d \u0441\u0438\u043c\u0432\u043e\u043b\u0456\u0432.", "%(programName)s Home Page.": "%(programName)s \u0414\u043e\u043c\u0430\u0448\u043d\u044f \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0430 ", "%(sel)s of %(cnt)s selected": [ + "\u041e\u0431\u0440\u0430\u043d\u043e %(sel)s \u0437 %(cnt)s", "\u041e\u0431\u0440\u0430\u043d\u043e %(sel)s \u0437 %(cnt)s", "\u041e\u0431\u0440\u0430\u043d\u043e %(sel)s \u0437 %(cnt)s", "\u041e\u0431\u0440\u0430\u043d\u043e %(sel)s \u0437 %(cnt)s" @@ -388,7 +389,6 @@ "Default": "\u041e\u0441\u043d\u043e\u0432\u043d\u0438\u0439", "Default (Local Time Zone)": "\u0417\u0430 \u0437\u0430\u043c\u043e\u0432\u0447\u0430\u043d\u043d\u044f\u043c (\u043c\u0456\u0441\u0446\u0435\u0432\u0438\u0439 \u0447\u0430\u0441\u043e\u0432\u0438\u0439 \u043f\u043e\u044f\u0441)", "Delete": "\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \"<%= signatoryName %>\" \u0437\u0456 \u0441\u043f\u0438\u0441\u043a\u0443 \u043f\u043e\u043b\u0456\u0432?", "Delete File Confirmation": "\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u0432\u0438\u0434\u0430\u043b\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443. ", "Delete My Account": "\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u043c\u0456\u0439 \u043e\u0431\u043b\u0456\u043a\u043e\u0432\u0438\u0439 \u0437\u0430\u043f\u0438\u0441", "Delete Page Confirmation": "\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u0432\u0438\u0434\u0430\u043b\u0435\u043d\u043d\u044f \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438", @@ -778,11 +778,13 @@ "Note: You are %s hour ahead of server time.": [ "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d\u0443 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d\u0438 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", + "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443." ], "Note: You are %s hour behind server time.": [ "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d\u0443 \u043f\u043e\u0437\u0430\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d\u0438 \u043f\u043e\u0437\u0430\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", + "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d \u043f\u043e\u0437\u0430\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d \u043f\u043e\u0437\u0430\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443." ], "Notes hidden": "\u041d\u043e\u0442\u0430\u0442\u043a\u0438 \u043f\u0440\u0438\u0445\u043e\u0432\u0430\u043d\u0456", @@ -800,7 +802,6 @@ "October": "\u0436\u043e\u0432\u0442\u043d\u044f", "Ok": "\u0414\u043e\u0431\u0440\u0435", "One or more rescheduling tasks failed.": "\u041e\u0434\u043d\u0430 \u0430\u0431\u043e \u043a\u0456\u043b\u044c\u043a\u0430 \u0437\u0430\u0434\u0430\u0447 \u043f\u0435\u0440\u0435\u043f\u043b\u0430\u043d\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u043b\u0430\u0441\u044f.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u041b\u0438\u0448\u0435 \u0444\u0430\u0439\u043b\u0438 \u0442\u0438\u043f\u0456\u0432 <%= fileTypes %> \u043c\u043e\u0436\u0443\u0442\u044c \u0431\u0443\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456. \u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043e\u0431\u0435\u0440\u0456\u0442\u044c \u0434\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b \u0437 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u044f\u043c <%= fileExtensions %>.", "Only properly formatted .csv files will be accepted.": "\u0414\u043e\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c\u0441\u044f \u0442\u0456\u043b\u044c\u043a\u0438 .csv \u0444\u0430\u0439\u043b\u0438 \u0437 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u0438\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c.", "Open Calculator": "\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440", "Open language menu": "\u0412\u0438\u0431\u0456\u0440 \u043c\u043e\u0432\u0438", @@ -1103,8 +1104,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u0421\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 \u0434\u043b\u044f \u0434\u0430\u043d\u043e\u0433\u043e \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u0430 \u0432\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439, \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e \u043f\u0435\u0440\u0435\u0440\u0430\u0445\u0443\u043d\u043e\u043a \u043e\u0446\u0456\u043d\u043a\u0438.", "The cohort cannot be added": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0434\u043e\u0434\u0430\u0442\u0438 \u043a\u043e\u0433\u043e\u0440\u0442\u0443", "The cohort cannot be saved": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0437\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u043a\u043e\u0433\u043e\u0440\u0442\u0443", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u0421\u0443\u043a\u0443\u043f\u043d\u0430 \u0434\u043e\u0432\u0436\u0438\u043d\u0430 \u043d\u0430\u0437\u0432\u0438 \u043e\u0440\u0433\u0430\u043d\u0456\u0437\u0430\u0446\u0456\u0457 \u0442\u0430 \u043a\u043e\u0434\u0443 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435 \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0443\u0432\u0430\u0442\u0438 <%=limit%> \u0441\u0438\u043c\u0432\u043e\u043b\u0456\u0432.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u0421\u0443\u043a\u0443\u043f\u043d\u0430 \u0434\u043e\u0432\u0436\u0438\u043d\u0430 \u043d\u0430\u0437\u0432\u0438 \u043e\u0440\u0433\u0430\u043d\u0456\u0437\u0430\u0446\u0456\u0457, \u043d\u043e\u043c\u0435\u0440\u0430 \u043a\u0443\u0440\u0441\u0443 \u0442\u0430 \u043d\u0430\u0432\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u043e\u043a\u0443 \u043d\u0435 \u043c\u043e\u0436\u0435 \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0443\u0432\u0430\u0442\u0438 <%=limit%> \u0441\u0438\u043c\u0432\u043e\u043b\u0456\u0432.", "The country or region where you live.": "\u041a\u0440\u0430\u0457\u043d\u0430 \u0430\u0431\u043e \u0440\u0435\u0433\u0456\u043e\u043d, \u0434\u0435 \u0412\u0438 \u043f\u0440\u043e\u0436\u0438\u0432\u0430\u0454\u0442\u0435.", "The country that team members primarily identify with.": "\u041a\u0440\u0430\u0457\u043d\u0430, \u0434\u043e \u044f\u043a\u043e\u0457 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432\u0456\u0434\u043d\u043e\u0441\u0438\u0442\u044c \u0441\u0435\u0431\u0435.", "The display of ungraded and checked out responses could not be loaded.": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0435\u043a\u0440\u0430\u043d \u043d\u0435\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0438\u0445 \u0442\u0430 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0438\u0445 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0435\u0439.", @@ -1285,7 +1284,6 @@ "Upload Videos": "\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0412\u0456\u0434\u0435\u043e", "Upload a CSV file": "\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 CSV \u0444\u0430\u0439\u043b", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0442\u0435 \u0444\u0430\u0439\u043b \u0437\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u043c\u0438, \u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0438\u043c\u0438 \u043a\u043e\u043c\u0430\u043c\u0438 (.csv), \u044f\u043a\u0438\u0439 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0456\u043c\u0435\u043d\u0430 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 \u0430\u0431\u043e \u0430\u0434\u0440\u0435\u0441\u0438 \u0435\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0457 \u043f\u043e\u0448\u0442\u0438 \u0442\u0438\u0445 \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u0456\u0432, \u044f\u043a\u0438\u043c \u043d\u0430\u0434\u0430\u043d\u043e \u0432\u0438\u043d\u044f\u0442\u043e\u043a. \u041f\u0435\u0440\u0448\u0438\u043c \u0432\u0432\u0435\u0434\u0456\u0442\u044c \u0456\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0430\u0431\u043e \u0430\u0434\u0440\u0435\u0441\u0443 \u0435\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0457 \u043f\u043e\u0448\u0442\u0438 \u0442\u0430 \u0432\u0456\u0434\u043e\u043a\u0440\u0435\u043c\u0442\u0435 \u043a\u043e\u043c\u043e\u044e. \u0417\u0430 \u0431\u0430\u0436\u0430\u043d\u043d\u044f\u043c \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u0438 \u043f\u0440\u0438\u043c\u0456\u0442\u043a\u0443, \u044f\u043a\u0430 \u0431 \u043e\u043f\u0438\u0441\u0443\u0432\u0430\u043b\u0430 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u0432\u0438\u043d\u044f\u0442\u043a\u0443. \u0412\u043e\u043d\u0430 \u0431\u0443\u0434\u0435 \u0432\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u0438\u0441\u044f \u0443 \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u043f\u043e\u043b\u0456.", - "Upload a new PDF to \u201c<%= name %>\u201d": "\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u043d\u043e\u0432\u0438\u0439 PDF \u0432 \u201c<%= name %>\u201d", "Upload an image": "\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f", "Upload completed": "\u0412\u0438\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e", "Upload completed for video {fileName}": "\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0456\u0434\u0435\u043e {fileName}", @@ -1616,7 +1614,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1672,9 +1670,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "d F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/cms/static/js/i18n/ur/djangojs.js b/cms/static/js/i18n/ur/djangojs.js index af088af299a6dfec3655ea926e048d4a8e0a37c7..63d4b562ff70ad4ff54810fa71a1e6bc640473eb 100644 --- a/cms/static/js/i18n/ur/djangojs.js +++ b/cms/static/js/i18n/ur/djangojs.js @@ -64,7 +64,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -128,9 +128,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/uz/djangojs.js b/cms/static/js/i18n/uz/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/cms/static/js/i18n/uz/djangojs.js +++ b/cms/static/js/i18n/uz/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/vi/djangojs.js b/cms/static/js/i18n/vi/djangojs.js index 46ea6adac3ceef46f780460186e244b6ade7b7d4..b307df4fab4b253039cbaa3c00cd236ea22f318e 100644 --- a/cms/static/js/i18n/vi/djangojs.js +++ b/cms/static/js/i18n/vi/djangojs.js @@ -419,7 +419,6 @@ "Default (Local Time Zone)": "M\u1eb7c \u0111\u1ecbnh (M\u00fai gi\u1edd \u0111\u1ecba ph\u01b0\u01a1ng)", "Default Timed Transcript": "M\u1eb7c \u0111\u1ecbnh Timed Transcript", "Delete": "X\u00f3a", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "Xo\u00e1 \"<%= signatoryName %>\" t\u1eeb danh s\u00e1ch k\u00fd t\u00ean?", "Delete File Confirmation": "X\u00e1c Nh\u1eadn X\u00f3a File", "Delete My Account": "X\u00f3a t\u00e0i kho\u1ea3n", "Delete Page Confirmation": "X\u00e1c Nh\u1eadn X\u00f3a Trang", @@ -456,7 +455,6 @@ "Do you want to allow this student ('{student_id}') to skip the entrance exam?": "B\u1ea1n c\u00f3 mu\u1ed1n cho ph\u00e9p sinh vi\u00ean n\u00e0y ('{student_id}') \u0111\u01b0\u1ee3c ph\u00e9p b\u1ecf qua b\u00e0i ki\u1ec3m tra \u0111\u1ea7u v\u00e0o?", "Do you want to replace the edX transcript with the YouTube transcript?": "B\u1ea1n c\u00f3 mu\u1ed1n thay th\u1ebf b\u1ea3n d\u1ecbch edX b\u1eb1ng b\u1ea3n d\u1ecbch c\u1ee7a YouTube kh\u00f4ng?", "Document properties": "\u0110\u1eb7c t\u00ednh t\u00e0i li\u1ec7u", - "Does the photo of you match your ID photo?": "H\u00ecnh c\u1ee7a b\u1ea1n c\u00f3 gi\u1ed1ng v\u1edbi h\u00ecnh tr\u00ean ch\u1ee9ng minh nh\u00e2n d\u00e2n kh\u00f4ng?", "Does the photo of you show your whole face?": "H\u00ecnh c\u1ee7a b\u1ea1n c\u00f3 hi\u1ec3n th\u1ecb to\u00e0n b\u1ed9 khu\u00f4n m\u1eb7t kh\u00f4ng?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Kh\u00f4ng nh\u00ecn th\u1ea5y h\u00ecnh \u1ea3nh c\u1ee7a b\u1ea1n? H\u00e3y ch\u1eafc ch\u1eafn \u0111\u1ec3 cho ph\u00e9p tr\u00ecnh duy\u1ec7t c\u1ee7a b\u1ea1n \u0111\u1ec3 s\u1eed d\u1ee5ng m\u00e1y \u1ea3nh c\u1ee7a b\u1ea1n khi n\u00f3 y\u00eau c\u1ea7u s\u1ef1 cho ph\u00e9p.", "Donate": "Quy\u00ean g\u00f3p", @@ -612,7 +610,6 @@ "Gender": "Gi\u1edbi t\u00ednh", "General": "Chung", "General Proctored Exam Rules": "Quy t\u1eafc Chung v\u1ec1 Thi C\u00f3 gi\u00e1m s\u00e1t", - "Get Credit": "L\u1ea5y t\u00edn ch\u1ec9", "Go to Dashboard": "\u0110i \u0111\u1ebfn b\u1ea3ng \u0111i\u1ec1u khi\u1ec3n", "Go to my Dashboard": "Chuy\u1ec3n \u0111\u1ebfn b\u1ea3ng th\u00f4ng tin c\u1ee7a t\u00f4i", "Go to {platform} Home": "Chuy\u1ec3n \u0111\u1ebfn Trang ch\u1ee7 {platform}", @@ -904,7 +901,6 @@ "ORDER PLACED": "\u0110\u00c3 \u0110\u1eb6T H\u00c0NG", "Ok": "Ok", "One or more rescheduling tasks failed.": "M\u1ed9t ho\u1eb7c nhi\u1ec1u t\u00e1c v\u1ee5 \u0111i\u1ec1u ch\u1ec9nh l\u1ecbch h\u1ecdc \u0111\u00e3 th\u1ea5t b\u1ea1i.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "Ch\u1ec9 t\u1eadp tin d\u1ea1ng <%= fileTypes %> c\u00f3 th\u1ec3 \u0111\u01b0\u1ee3c t\u1ea3i l\u00ean. Xin vui l\u00f2ng ch\u1ecdn m\u1ed9t t\u1eadp tin k\u1ebft th\u00fac b\u1eb1ng <%= fileExtensions %> \u0111\u1ec3 t\u1ea3i l\u00ean.", "Only properly formatted .csv files will be accepted.": "Ch\u1ec9 nh\u1eefng t\u1ec7p tin theo \u0111\u1ecbnh d\u1ea1ng .csv chu\u1ea9n \u0111\u01b0\u1ee3c ch\u1ea5p nh\u1eadn.", "Open Calculator": "M\u1edf m\u00e1y t\u00ednh ", "Open language menu": "M\u1edf menu ng\u00f4n ng\u1eef", @@ -1215,7 +1211,7 @@ "Subject": "Ch\u1ee7 \u0111\u1ec1", "Subject:": "Ch\u1ee7 \u0111\u1ec1:", "Submission aborted! Sorry, your browser does not support file uploads. If you can, please use Chrome or Safari which have been verified to support file uploads.": "G\u1eedi b\u1ecb h\u1ee7y b\u1ecf! Xin l\u1ed7i, tr\u00ecnh duy\u1ec7t c\u1ee7a b\u1ea1n kh\u00f4ng h\u1ed7 tr\u1ee3 t\u1ea3i l\u00ean t\u1ec7p. N\u1ebfu c\u00f3 th\u1ec3, vui l\u00f2ng s\u1eed d\u1ee5ng Chrome ho\u1eb7c Safari \u0111\u00e3 \u0111\u01b0\u1ee3c x\u00e1c nh\u1eadn h\u1ed7 tr\u1ee3 t\u1ea3i l\u00ean t\u1ec7p tin.", - "Submit": "G\u1eedi", + "Submit": "N\u1ed9p", "Submitted": "\u0110\u00e3 g\u1eedi", "Subscript": "Subscript", "Subsection": "Ti\u1ec3u m\u1ee5c", @@ -1288,8 +1284,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Gi\u1ea5y ch\u1ee9ng nh\u1eadn cho h\u1ecdc vi\u00ean n\u00e0y \u0111\u00e3 \u0111\u01b0\u1ee3c x\u00e1c nh\u1eadn l\u1ea1i v\u00e0 h\u1ec7 th\u1ed1ng \u0111ang x\u1eed l\u00fd c\u1ea5p ph\u00e1t l\u1ea1i cho h\u1ecdc vi\u00ean n\u00e0y n\u00e0y.", "The cohort cannot be added": "Kh\u00f4ng th\u00eam \u0111\u01b0\u1ee3c nh\u00f3m h\u1ecdc vi\u00ean n\u00e0y", "The cohort cannot be saved": "Kh\u00f4ng l\u01b0u \u0111\u01b0\u1ee3c nh\u00f3m h\u1ecdc vi\u00ean n\u00e0y", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "Chi\u1ec1u d\u00e0i k\u1ebft h\u1ee3p c\u1ee7a tr\u01b0\u1eddng t\u1ed5 ch\u1ee9c v\u00e0 m\u00e3 m\u00e3 th\u01b0 vi\u1ec7n kh\u00f4ng \u0111\u01b0\u1ee3c nhi\u1ec1u h\u01a1n <%=limit%> k\u00fd t\u1ef1.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "Chi\u1ec1u d\u00e0i k\u1ebft h\u1ee3p c\u1ee7a c\u00e1c tr\u01b0\u1eddng t\u1ed5 ch\u1ee9c, s\u1ed1 hi\u1ec7u kho\u00e1 h\u1ecdc, h\u1ecdc k\u1ef3 kh\u00f4ng \u0111\u01b0\u1ee3c nhi\u1ec1u h\u01a1n <%=limit%> k\u00fd t\u1ef1.", "The country or region where you live.": "Qu\u1ed1c gia ho\u1eb7c n\u01a1i b\u1ea1n sinh s\u1ed1ng.", "The country that team members primarily identify with.": "Qu\u1ed1c gia ch\u00ednh c\u1ee7a c\u00e1c th\u00e0nh vi\u00ean nh\u00f3m.", "The course end date must be later than the course start date.": "Ng\u00e0y k\u1ebft th\u00fac c\u1ee7a kh\u00f3a h\u1ecdc ph\u1ea3i sau ng\u00e0y b\u1eaft \u0111\u1ea7u c\u1ee7a kh\u00f3a h\u1ecdc.", @@ -1319,7 +1313,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "S\u1ed1 ph\u1ea7n con trong kh\u00f3a h\u1ecdc ch\u1ee9a c\u00e1c c\u00e2u h\u1ecfi c\u1ee7a lo\u1ea1i b\u00e0i t\u1eadp n\u00e0y.", "The organization that this signatory belongs to, as it should appear on certificates.": "T\u1ed5 ch\u1ee9c m\u00e0 ng\u01b0\u1eddi k\u00fd t\u00ean n\u00e0y thu\u1ed9c v\u1ec1, nh\u01b0 n\u00f3 s\u1ebd xu\u1ea5t hi\u1ec7n tr\u00ean gi\u1ea5y ch\u1ee9ng nh\u1eadn.", "The page \"{route}\" could not be found.": "Kh\u00f4ng th\u1ea5y trang \"{route}\".", - "The photo of your face matches the photo on your ID.": "Nh\u1eefng h\u00ecnh \u1ea3nh c\u1ee7a khu\u00f4n m\u1eb7t c\u1ee7a b\u1ea1n ph\u00f9 h\u1ee3p v\u1edbi h\u00ecnh \u1ea3nh tr\u00ean ID c\u1ee7a b\u1ea1n.", "The post you selected has been deleted.": "B\u00e0i b\u1ea1n ch\u1ecdn \u0111\u00e3 b\u1ecb x\u00f3a.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "Phi\u00ean b\u1ea3n nh\u00e1nh \u0111\u00e3 xu\u1ea5t b\u1ea3n, {published}, \u0111\u00e3 \u0111\u01b0\u1ee3c \u0111\u1eb7t l\u1ea1i th\u00e0nh phi\u00ean b\u1ea3n nh\u00e1nh d\u1ef1 th\u1ea3o, {draft}.", "The raw error message is:": "Th\u00f4ng b\u00e1o l\u1ed7i ban \u0111\u1ea7u l\u00e0:", @@ -1507,7 +1500,6 @@ "Upload Photo": "T\u1ea3i \u1ea2nh l\u00ean", "Upload Signature Image": "T\u1ea3i l\u00ean H\u00ecnh \u1ea3nh Ch\u1eef k\u00fd", "Upload Videos": "T\u1ea3i l\u00ean Video", - "Upload a new PDF to \u201c<%= name %>\u201d": "T\u1ea3i l\u00ean m\u1ed9t file PDF m\u1edbi l\u00ean \u201c<%= name %>\u201d", "Upload an image": "T\u1ea3i l\u00ean h\u00ecnh \u1ea3nh", "Upload an image or capture one with your web or phone camera.": "T\u1ea3i l\u00ean m\u1ed9t h\u00ecnh \u1ea3nh ho\u1eb7c ch\u1ee5p m\u1ed9t v\u1edbi web c\u1ee7a b\u1ea1n ho\u1eb7c camera \u0111i\u1ec7n tho\u1ea1i.", "Upload completed": "T\u1ea3i l\u00ean ho\u00e0n t\u1ea5t", @@ -1534,7 +1526,6 @@ "Use as a Prerequisite": "S\u1eed d\u1ee5ng nh\u01b0 y\u00eau c\u1ea7u b\u0103t bu\u1ed9c", "Use cohorts as the basis for dividing discussions. All learners, regardless of cohort, see the same discussion topics, but within divided topics, only members of the same cohort see and respond to each others\u2019 posts. ": "S\u1eed d\u1ee5ng c\u00e1c nh\u00f3m l\u00e0m c\u01a1 s\u1edf \u0111\u1ec3 chia s\u1ebb c\u00e1c cu\u1ed9c th\u1ea3o lu\u1eadn. T\u1ea5t c\u1ea3 ng\u01b0\u1eddi h\u1ecdc, kh\u00f4ng ph\u00e2n bi\u1ec7t nh\u00f3m, xem c\u00e1c ch\u1ee7 \u0111\u1ec1 th\u1ea3o lu\u1eadn gi\u1ed1ng nhau, nh\u01b0ng trong c\u00e1c ch\u1ee7 \u0111\u1ec1 chia s\u1ebb, ch\u1ec9 nh\u1eefng th\u00e0nh vi\u00ean c\u1ee7a c\u00f9ng m\u1ed9t nh\u00f3m m\u1edbi th\u1ea5y v\u00e0 tr\u1ea3 l\u1eddi c\u00e1c b\u00e0i \u0111\u0103ng c\u1ee7a nhau.", "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "S\u1eed d\u1ee5ng c\u00e1c ki\u1ec3u \u0111\u0103ng k\u00fd l\u00e0m c\u01a1 s\u1edf \u0111\u1ec3 ph\u00e2n chia c\u00e1c cu\u1ed9c th\u1ea3o lu\u1eadn. T\u1ea5t c\u1ea3 h\u1ecdc vi\u00ean, b\u1ea5t k\u1ec3 ki\u1ec3u \u0111\u0103ng k\u00fd c\u1ee7a h\u1ecd, xem c\u00e1c ch\u1ee7 \u0111\u1ec1 th\u1ea3o lu\u1eadn gi\u1ed1ng nhau, nh\u01b0ng trong c\u00e1c ch\u1ee7 \u0111\u1ec1 \u0111\u00e3 ph\u00e2n chia, ch\u1ec9 nh\u1eefng h\u1ecdc vi\u00ean trong c\u00f9ng m\u1ed9t ki\u1ec3u \u0111\u0103ng k\u00fd m\u1edbi nh\u00ecn th\u1ea5y v\u00e0 tr\u1ea3 l\u1eddi c\u00e1c b\u00e0i vi\u1ebft c\u1ee7a nhau.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "S\u1eed d\u1ee5ng webcam c\u1ee7a b\u1ea1n \u0111\u1ec3 c\u00f3 m\u1ed9t b\u1ee9c \u1ea3nh c\u1ee7a ID c\u1ee7a b\u1ea1n. Ch\u00fang t\u00f4i s\u1ebd \u0111\u1ed1i b\u1ee9c \u1ea3nh n\u00e0y v\u1edbi h\u00ecnh \u1ea3nh c\u1ee7a khu\u00f4n m\u1eb7t c\u1ee7a b\u1ea1n v\u00e0 t\u00ean t\u00e0i kho\u1ea3n c\u1ee7a b\u1ea1n.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "S\u1eed d\u1ee5ng webcam c\u1ee7a b\u1ea1n \u0111\u1ec3 c\u00f3 m\u1ed9t h\u00ecnh \u1ea3nh c\u1ee7a khu\u00f4n m\u1eb7t c\u1ee7a b\u1ea1n \u0111\u1ec3 ch\u00fang t\u00f4i c\u00f3 th\u1ec3 k\u1ebft h\u1ee3p n\u00f3 v\u1edbi h\u00ecnh \u1ea3nh tr\u00ean ID c\u1ee7a b\u1ea1n.", "Used": "\u0110\u01b0\u1ee3c s\u1eed d\u1ee5ng", "Used in {count} location": [ @@ -1550,7 +1541,6 @@ "Verification checkpoint to be completed": "Ki\u1ec3m tra \u0111\u1ec3 ho\u00e0n th\u00e0nh x\u00e1c minh", "Verified Certificate": "Ch\u1ee9ng ch\u1ec9 c\u00f3 x\u00e1c nh\u1eadn", "Verified Certificate upgrade": "N\u00e2ng c\u1ea5p l\u00ean ch\u1ee9ng ch\u1ec9 c\u00f3 x\u00e1c nh\u1eadn", - "Verify Now": "X\u00e1c nh\u1eadn ngay b\u00e2y gi\u1edd", "Version": "Phi\u00ean b\u1ea3n", "Vertical space": "Vertical space", "Very loud": "R\u1ea5t to", @@ -1585,7 +1575,6 @@ "We couldn't find any results for \"%s\".": "Kh\u00f4ng th\u1ec3 t\u00ecm th\u1ea5y k\u1ebft qu\u1ea3 cho \"%s\".", "We couldn't sign you in.": "Ch\u00fang t\u00f4i kh\u00f4ng th\u1ec3 \u0111\u0103ng nh\u1eadp cho b\u1ea1n.", "We have encountered an error. Refresh your browser and then try again.": "\u0110\u00e3 ph\u00e1t hi\u1ec7n l\u1ed7i. L\u00e0m m\u1edbi l\u1ea1i tr\u00ecnh duy\u1ec7t c\u1ee7a b\u1ea1n r\u1ed3i th\u1eed l\u1ea1i.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Ch\u00fang t\u00f4i \u0111\u00e3 nh\u1eadn \u0111\u01b0\u1ee3c th\u00f4ng tin c\u1ee7a b\u1ea1n v\u00e0 \u0111ang ti\u1ebfn x\u00e1c nh\u1eadn danh t\u00ednh c\u1ee7a b\u1ea1n. B\u1ea1n s\u1ebd th\u1ea5y m\u1ed9t tin nh\u1eafn tr\u00ean b\u1ea3ng \u0111i\u1ec1u khi\u1ec3n khi qu\u00e1 tr\u00ecnh x\u00e1c nh\u1eadn ho\u00e0n t\u1ea5t (th\u00f4ng th\u01b0\u1eddng trong v\u00f2ng 1-2 ng\u00e0y). Trong th\u1eddi gian ch\u1edd \u0111\u1ee3i, b\u1ea1n v\u00e3n c\u00f3 th\u1ec3 truy c\u1eadp n\u1ed9i dung c\u00e1c kho\u00e1 h\u1ecdc c\u00f3 s\u1eb5n.", "We just need a little more information before you start learning with %(platformName)s.": "Ch\u00fang t\u00f4i ch\u1ec9 c\u1ea7n th\u00eam m\u1ed9t ch\u00fat th\u00f4ng tin tr\u01b0\u1edbc khi b\u1ea1n b\u1eaft \u0111\u1ea7u h\u1ecdc v\u1edbi %(platformName)s.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Ch\u00fang t\u00f4i s\u1eed d\u1ee5ng c\u00e1c m\u1ee9c b\u1ea3o m\u1eadt cao nh\u1ea5t c\u00f3 s\u1eb5n \u0111\u1ec3 m\u00e3 h\u00f3a h\u00ecnh \u1ea3nh c\u1ee7a b\u1ea1n v\u00e0 g\u1eedi n\u00f3 \u0111\u1ebfn d\u1ecbch v\u1ee5 \u1ee7y quy\u1ec1n c\u1ee7a ch\u00fang t\u00f4i \u0111\u1ec3 xem x\u00e9t. \u1ea2nh v\u00e0 th\u00f4ng tin c\u1ee7a b\u1ea1n s\u1ebd kh\u00f4ng \u0111\u01b0\u1ee3c l\u01b0u hay b\u1ea5t c\u1ee9 n\u01a1i n\u00e0o c\u00f3 th\u1ec3 nh\u00ecn th\u1ea5y tr\u00ean %(platformName)s sau khi qu\u00e1 tr\u00ecnh x\u00e1c minh ho\u00e0n t\u1ea5t.", "We're sorry to see you go! Your account will be deleted shortly.": "Ch\u00fang t\u00f4i r\u1ea5t ti\u1ebfc khi th\u1ea5y b\u1ea1n ra \u0111i! T\u00e0i kho\u1ea3n c\u1ee7a b\u1ea1n s\u1ebd \u0111\u01b0\u1ee3c x\u00f3a ngay.", @@ -1659,12 +1648,9 @@ "You must specify a name": "B\u1ea1n ph\u1ea3i x\u00e1c \u0111\u1ecbnh m\u1ed9t t\u00ean", "You must specify a name for the cohort": "B\u1ea1n ph\u1ea3i \u0111\u1eb7t t\u00ean cho nh\u00f3m.", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "B\u1ea1n ph\u1ea3i nh\u1eadp v\u00e0o n\u0103m sinh tr\u01b0\u1edbc khi b\u1ea1n c\u00f3 th\u1ec3 chia s\u1ebb to\u00e0n b\u1ed9 h\u1ed3 s\u01a1 c\u1ee7a b\u1ea1n. \u0110\u1ec3 nh\u1eadp v\u00e0o n\u0103m sinh, nh\u1ea5p v\u00e0o {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "B\u1ea1n c\u1ea7n c\u00f3 b\u1eb1ng l\u00e1i xe, h\u1ed9 chi\u1ebfu, ho\u1eb7c ID ch\u00ednh ph\u1ee7 ph\u00e1t h\u00e0nh c\u00f3 t\u00ean v\u00e0 \u1ea3nh c\u1ee7a b\u1ea1n.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "B\u1ea1n c\u1ea7n m\u1ed9t ID c\u00f3 t\u00ean v\u00e0 \u1ea3nh c\u1ee7a b\u1ea1n. Gi\u1ea5y ph\u00e9p, h\u1ed9 chi\u1ebfu, ho\u1eb7c ID ch\u00ednh ph\u1ee7 ph\u00e1t h\u00e0nh c\u1ee7a m\u1ed9t tr\u00ecnh \u0111i\u1ec1u khi\u1ec3n \u0111\u01b0\u1ee3c t\u1ea5t c\u1ea3 ch\u1ea5p nh\u1eadn \u0111\u01b0\u1ee3c.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "B\u1ea1n c\u1ea7n k\u00edch ho\u1ea1t t\u00e0i kho\u1ea3n tr\u01b0\u1edbc khi ghi danh v\u00e0o kho\u00e1 h\u1ecdc. Ki\u1ec3m tra h\u1ed9p th\u01b0 \u0111\u1ebfn cho email c\u1ea7n k\u00edch ho\u1ea1t.", "You receive messages from {platform_name} and course teams at this address.": "B\u1ea1n nh\u1eadn \u0111\u01b0\u1ee3c tin nh\u1eafn t\u1eeb {platform_name} t\u1ea1i \u0111\u1ecba ch\u1ec9 n\u00e0y.", "You reserve all rights for your work": "B\u1ea1n d\u00e0nh t\u1ea5t c\u1ea3 c\u00e1c quy\u1ec1n cho t\u00e1c ph\u1ea9m c\u1ee7a b\u1ea1n", - "You still need to visit the %(display_name)s website to complete the credit process.": "B\u1ea1n v\u1eabn c\u1ea7n ph\u1ea3i truy c\u1eadp v\u00e0o c\u00e1c trang web %(display_name)s \u0111\u1ec3 ho\u00e0n t\u1ea5t qu\u00e1 tr\u00ecnh t\u00edn ch\u1ec9.", "You submitted {filename}; only {allowedFiles} are allowed.": "B\u1ea1n \u0111\u00e3 g\u1eedi {filename}; ch\u1ec9 cho ph\u00e9p {allowedFiles}.", "You waive some rights for your work, such that others can use it too": "B\u1ea1n t\u1eeb b\u1ecf m\u1ed9t s\u1ed1 quy\u1ec1n \u0111\u1ed1i v\u1edbi t\u00e1c ph\u1ea9m c\u1ee7a b\u1ea1n, nh\u01b0 v\u1eady nh\u1eefng ng\u01b0\u1eddi kh\u00e1c c\u00f3 th\u1ec3 s\u1eed d\u1ee5ng l\u1ea1i", "You will be refunded the amount you paid.": "B\u1ea1n s\u1ebd \u0111\u01b0\u1ee3c ho\u00e0n tr\u1ea3 s\u1ed1 ti\u1ec1n \u0111\u00e3 thanh to\u00e1n.", @@ -1846,7 +1832,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1910,9 +1896,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "H:i d-m-Y", "SHORT_DATE_FORMAT": "d-m-Y", "THOUSAND_SEPARATOR": ".", diff --git a/cms/static/js/i18n/zh-cn/djangojs.js b/cms/static/js/i18n/zh-cn/djangojs.js index f2382776846935e785d953bc48fc6ec9804f6cb3..c252c047cf253a12d545755f636fe4ee1820729e 100644 --- a/cms/static/js/i18n/zh-cn/djangojs.js +++ b/cms/static/js/i18n/zh-cn/djangojs.js @@ -580,7 +580,6 @@ "Default (Local Time Zone)": "\u9ed8\u8ba4 (\u672c\u5730\u65f6\u533a)", "Default Timed Transcript": "\u9ed8\u8ba4\u5b57\u5e55", "Delete": "\u5220\u9664", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u786e\u5b9a\u8981\u4ece\u7b7e\u7f72\u8005\u5217\u8868\u4e2d\u5220\u9664 \"<%= signatoryName %>\" \u5417\uff1f", "Delete File Confirmation": "\u5220\u9664\u6587\u4ef6\u786e\u8ba4", "Delete My Account": "\u5220\u9664\u6211\u7684\u8d26\u53f7", "Delete Page Confirmation": "\u786e\u8ba4\u5220\u9664\u9875\u9762", @@ -623,7 +622,6 @@ "Do you want to upload your file before submitting?": "\u60a8\u786e\u5b9a\u5728\u63d0\u4ea4\u4e4b\u524d\u4e0a\u4f20\u60a8\u7684\u6587\u4ef6\u5417\uff1f", "Document properties": "\u6587\u6863\u5c5e\u6027", "Does the name on your ID match your account name: %(fullName)s?": "\u60a8\u8eab\u4efd\u8bc1\u4ef6\u4e0a\u7684\u59d3\u540d\u548c\u60a8\u5728\u8d26\u53f7\u4e2d\u586b\u5199\u7684\u59d3\u540d\u201c%(fullName)s\u201d\u76f8\u7b26\u5417\uff1f", - "Does the photo of you match your ID photo?": "\u8fd9\u5f20\u7167\u7247\u548c\u60a8\u8eab\u4efd\u8bc1\u4ef6\u4e0a\u7684\u7167\u7247\u76f8\u5339\u914d\u5417\uff1f", "Does the photo of you show your whole face?": "\u8fd9\u5f20\u7167\u7247\u4e2d\u6709\u60a8\u7684\u6574\u5f20\u8138\u5417\uff1f", "Doing so means that you are no longer eligible for academic credit.": "\u5173\u95ed\u76d1\u8003\u529f\u80fd\u610f\u5473\u7740\u60a8\u5c06\u5931\u53bb\u5b66\u5206\u8d44\u683c\u3002", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u6ca1\u6709\u770b\u5230\u60a8\u81ea\u5df1\uff1f\u8bf7\u786e\u8ba4\u5f53\u6d4f\u89c8\u5668\u8bf7\u6c42\u4f7f\u7528\u6444\u50cf\u5934\u6743\u9650\u7684\u65f6\u5019\u60a8\u9009\u62e9\u4e86\u5141\u8bb8\u3002", @@ -789,7 +787,6 @@ "Files that you upload must be smaller than 5MB in size.": "\u4e0a\u4f20\u7684\u6587\u4ef6\u4e0d\u5f97\u8d85\u8fc75MB\u3002", "Fill browser": "\u5168\u5c4f", "Filter and sort topics": "\u8fc7\u6ee4\u548c\u6574\u7406\u8bdd\u9898", - "Final Grade": "\u6700\u7ec8\u6210\u7ee9", "Final Grade Received": "\u6700\u7ec8\u6536\u83b7\u5f97\u5206", "Financial Assistance": "\u7ecf\u6d4e\u8865\u52a9", "Financial Assistance Application": "\u7ecf\u6d4e\u63f4\u52a9\u7533\u8bf7", @@ -821,7 +818,6 @@ "Generate": "\u751f\u6210", "Generate Exception Certificates": "\u751f\u6210\u7279\u4f8b\u8bc1\u4e66", "Generate the user's certificate": "\u751f\u6210\u7528\u6237\u8bc1\u4e66", - "Get Credit": "\u83b7\u5f97\u5b66\u5206", "Go Back": "\u8fd4\u56de", "Go to Dashboard": "\u524d\u5f80\u8bfe\u7a0b\u9762\u677f", "Go to my Dashboard": "\u524d\u5f80\u6211\u7684\u8bfe\u7a0b\u9762\u677f", @@ -900,10 +896,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "\u5982\u679c\u8282\u4e0d\u8bbe\u6709\u622a\u6b62\u65e5\u671f\uff0c\u90a3\u4e48\u53ea\u8981\u5b66\u5458\u63d0\u4ea4\u7b54\u6848\u81f3\u8bc4\u5206\uff0c\u5c31\u53ef\u4ee5\u67e5\u770b\u81ea\u5df1\u7684\u5f97\u5206\u3002", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u5982\u679c\u6b64\u5355\u5143\u5148\u524d\u5df2\u88ab\u53d1\u5e03\u4e14\u5411\u5b66\u751f\u516c\u5f00\uff0c\u4efb\u4f55\u5728\u8be5\u5355\u5143\u5904\u4e8e\u9690\u85cf\u65f6\u7684\u6539\u52a8\u90fd\u5c06\u5bf9\u5b66\u751f\u53ef\u89c1\u3002", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "\u82e5\u6b64\u5355\u5143\u5148\u524d\u5df2\u53d1\u8868\u4e14\u5411\u5b66\u751f\u516c\u5f00\uff0c\u4efb\u4f55\u5728\u8be5\u5355\u5143\u5904\u4e8e\u9690\u85cf\u72b6\u6001\u65f6\u6240\u4f5c\u51fa\u7684\u6539\u52a8\u90fd\u5c06\u5bf9\u5b66\u751f\u53ef\u89c1\u3002\u662f\u5426\u7ee7\u7eed\uff1f", - "If you are unable to access your account contact us via email using {email}.": "\u5982\u679c\u60a8\u65e0\u6cd5\u8bbf\u95ee\u8d26\u53f7\uff0c\u8bf7\u901a\u8fc7\u7535\u5b50\u90ae\u4ef6\u8054\u7cfb\u6211\u4eec{email}\u3002", "If you do not yet have an account, use the button below to register.": "\u5982\u679c\u60a8\u5c1a\u65e0\u8d26\u53f7\uff0c\u8bf7\u4f7f\u7528\u4ee5\u4e0b\u6309\u94ae\u8fdb\u884c\u6ce8\u518c\u3002", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u5982\u679c\u60a8\u73b0\u5728\u4e0d\u9a8c\u8bc1\u60a8\u7684\u8eab\u4efd\uff0c\u60a8\u4ecd\u53ef\u4ee5\u901a\u8fc7\u63a7\u5236\u9762\u677f\u6d4f\u89c8\u8bfe\u7a0b\u3002\u4f46\u60a8\u4f1a\u5b9a\u671f\u4ece%(platformName)s\u6536\u5230\u8eab\u4efd\u9a8c\u8bc1\u63d0\u9192\u3002", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u5982\u679c\u60a8\u73b0\u5728\u4e0d\u9a8c\u8bc1\u8eab\u4efd\uff0c\u60a8\u4ecd\u53ef\u4ee5\u901a\u8fc7\u8bfe\u7a0b\u9762\u677f\u6d4f\u89c8\u8bfe\u7a0b\u3002\u4f46\u60a8\u4f1a\u5b9a\u671f\u4ece {platformName} \u6536\u5230\u8eab\u4efd\u9a8c\u8bc1\u63d0\u9192\u3002", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "\u5982\u679c\u60a8\u4e0d\u4fdd\u5b58\u6216\u8005\u63d0\u4ea4\u7b54\u6848\u5c31\u79bb\u5f00\uff0c\u60a8\u53ef\u80fd\u4f1a\u4e22\u5931\u6389\u5199\u5b8c\u7684\u4e00\u5207\u3002", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "\u5982\u679c\u60a8\u79bb\u5f00\u672c\u9875\u65f6\u6ca1\u6709\u63d0\u4ea4\u60a8\u7684\u540c\u5b66\u4e92\u8bc4\uff0c\u60a8\u5c06\u4e22\u5931\u60a8\u6240\u505a\u7684\u4e00\u5207\u3002", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "\u5982\u679c\u60a8\u672a\u63d0\u4ea4\u60a8\u7684\u81ea\u6211\u8bc4\u4f30\u5c31\u79bb\u5f00\u6b64\u9875\u9762\uff0c\u60a8\u5c06\u4e22\u5931\u6240\u505a\u7684\u4e00\u5207\u3002", @@ -1090,7 +1084,6 @@ "Name of the signatory": "\u7b7e\u53d1\u8005\u59d3\u540d", "Name or short description of the configuration": "\u8be5\u914d\u7f6e\u7684\u540d\u79f0\u6216\u7b80\u77ed\u63cf\u8ff0", "Navigate up": "\u5411\u4e0a\u5bfc\u822a", - "Need help logging in?": "\u767b\u5f55\u65f6\u9700\u8981\u5e2e\u52a9\uff1f", "Needs verified certificate ": "\u9700\u8981\u5df2\u8ba4\u8bc1\u8bc1\u4e66", "Never published": "\u4ece\u672a\u53d1\u5e03\u8fc7", "Never show assessment results": "\u4e00\u76f4\u9690\u85cf\u8bc4\u5206\u7ed3\u679c", @@ -1156,7 +1149,6 @@ "Onboarding Exam": "\u5165\u804c\u8003\u8bd5", "Once you complete one of the program requirements you have a program record. This record is marked complete once you meet all program requirements. A program record can be used to continue your learning journey and demonstrate your learning to others.": "\u5b8c\u6210\u5176\u4e2d\u4e00\u4e2a\u8bfe\u7a0b\u8981\u6c42\u540e\uff0c\u60a8\u5c06\u62e5\u6709\u4e00\u4e2a\u8bfe\u7a0b\u8bb0\u5f55\u3002\u4e00\u65e6\u6ee1\u8db3\u6240\u6709\u8bfe\u7a0b\u8981\u6c42\uff0c\u6b64\u8bb0\u5f55\u5c31\u4f1a\u6807\u8bb0\u4e3a\u5df2\u5b8c\u6210\u3002\u8bfe\u7a0b\u8bb0\u5f55\u53ef\u7528\u4e8e\u7ee7\u7eed\u60a8\u7684\u5b66\u4e60\u4e4b\u65c5\uff0c\u5e76\u5411\u5176\u4ed6\u4eba\u5c55\u793a\u60a8\u7684\u5b66\u4e60\u7ecf\u5386\u3002", "One or more rescheduling tasks failed.": "\u4e00\u9879\u6216\u51e0\u9879\u6539\u671f\u4efb\u52a1\u5931\u8d25\u4e86\u3002", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u53ea\u6709 <%= fileTypes %> \u683c\u5f0f\u7684\u6587\u4ef6\u53ef\u4ee5\u4e0a\u4f20\u3002\u8bf7\u9009\u62e9\u6269\u5c55\u540d\u4e3a <%= fileExtensions %> \u7684\u6587\u4ef6\u4e0a\u4f20\u3002", "Only properly formatted .csv files will be accepted.": "\u53ea\u6709\u6807\u51c6\u7684CSV\u683c\u5f0f\u6587\u4ef6\u4f1a\u88ab\u63a5\u53d7\u3002", "Only the parent course staff of a CCX can create content groups.": "\u53ea\u6709CCX\u8bfe\u7a0b\u7684\u4e3b\u6559\u5458\u624d\u53ef\u521b\u5efa\u5185\u5bb9\u7ec4\u3002", "Open Calculator": "\u5f00\u542f\u8ba1\u7b97\u5668", @@ -1623,9 +1615,7 @@ "Textbook Name": "\u8bfe\u672c\u540d\u79f0", "Textbook information": "\u8bfe\u672c\u4fe1\u606f", "Textbook name is required": "\u6559\u6750\u540d\u79f0\u5fc5\u586b", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "\u8c22\u8c22\u60a8\uff0c%(full_name)s\uff01\u6211\u4eec\u5df2\u7ecf\u6536\u5230\u4e86\u60a8\u4e3a%(course_name)s\u7684\u4ed8\u6b3e\u3002", "Thank you for setting your course goal to {goal}!": "\u611f\u8c22\u60a8\u5c06\u8bfe\u7a0b\u76ee\u6807\u5b9a\u4e3a{goal}\uff01", - "Thank you for submitting a request! We will contact you within 24 hours.": "\u611f\u8c22\u60a8\u63d0\u4ea4\u7684\u7533\u8bf7\uff01\u6211\u4eec\u4f1a\u572824\u5c0f\u65f6\u5185\u8054\u7cfb\u60a8\u3002", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "\u611f\u8c22\u60a8\u63d0\u4ea4 {course_name} \u7684\u7ecf\u6d4e\u63f4\u52a9\u7533\u8bf7\uff01\u60a8\u5c06\u5728 2 \u81f3 4 \u4e2a\u5de5\u4f5c\u65e5\u5185\u5f97\u5230\u56de\u590d\u3002", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "\u611f\u8c22\u63d0\u4ea4\u60a8\u7684\u7167\u7247\uff0c\u6211\u4eec\u7a0d\u540e\u5c06\u8fdb\u884c\u5ba1\u6838\u3002\u60a8\u73b0\u5728\u5c31\u53ef\u4ee5\u53bb\u52a0\u5165%(platformName)s\u4e0a\u4efb\u4f55\u63d0\u4f9b\u8ba4\u8bc1\u8bc1\u4e66\u7684\u8bfe\u7a0b\u3002\u8ba4\u8bc1\u6709\u6548\u671f\u4e3a\u4e00\u5e74\u3002\u4e00\u5e74\u540e\uff0c\u60a8\u9700\u8981\u91cd\u65b0\u63d0\u4ea4\u7167\u7247\u8fdb\u884c\u8ba4\u8bc1\u3002", "Thank you! We have received your payment for {courseName}.": "\u8c22\u8c22\uff01\u6211\u4eec\u5df2\u7ecf\u6536\u5230\u60a8\u7684 {courseName} \u4ed8\u6b3e\u3002", @@ -1637,8 +1627,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u8fd9\u540d\u5b66\u751f\u7684\u8bc1\u4e66\u5df2\u7ecf\u91cd\u65b0\u9a8c\u8bc1\u53ca\u7cfb\u7edf\u91cd\u65b0\u8ba1\u7b97\u8be5\u540d\u5b66\u751f\u7684\u6210\u7ee9\u3002", "The cohort cannot be added": "\u8be5\u7fa4\u7ec4\u4e0d\u80fd\u6dfb\u52a0", "The cohort cannot be saved": "\u8be5\u7fa4\u7ec4\u4e0d\u80fd\u4fdd\u5b58", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u673a\u6784\u548c\u77e5\u8bc6\u5e93\u7f16\u53f7\u5b57\u6bb5\u5408\u5728\u4e00\u8d77\u4e0d\u80fd\u8d85\u8fc7 <%=limit%> \u4e2a\u5b57\u7b26", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u673a\u6784\u3001\u8bfe\u7a0b\u7f16\u53f7\u548c\u5f00\u8bfe\u65f6\u95f4\u5b57\u6bb5\u5408\u5728\u4e00\u8d77\u4e0d\u80fd\u8d85\u8fc7 <%=limit%> \u4e2a\u5b57\u7b26\u3002", "The country or region where you live.": "\u60a8\u6240\u5c45\u4f4f\u7684\u56fd\u5bb6\u6216\u5730\u533a\u3002", "The country that team members primarily identify with.": "\u591a\u6570\u56e2\u961f\u6210\u5458\u6765\u81ea\u7684\u56fd\u5bb6", "The course end date must be later than the course start date.": "\u8bfe\u7a0b\u7ed3\u675f\u65e5\u671f\u5fc5\u987b\u665a\u4e8e\u8bfe\u7a0b\u5f00\u59cb\u65e5\u671f\u3002", @@ -1654,7 +1642,6 @@ "The following email addresses and/or usernames are invalid:": "\u4ee5\u4e0b\u90ae\u7bb1/\u7528\u6237\u540d\u65e0\u6548\uff1a", "The following errors were generated:": "\u51fa\u73b0\u4ee5\u4e0b\u9519\u8bef\uff1a", "The following file types are not allowed: ": "\u4e0b\u5217\u6587\u4ef6\u7c7b\u578b\u4e0d\u53ef\u7528\uff1a", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "\u4ee5\u4e0b\u4fe1\u606f\u5df2\u7ecf\u662f\u60a8\u7684 {platform} \u7b80\u8ff0\u7684\u4e00\u90e8\u5206\u3002\u6211\u4eec\u5df2\u5c06\u5176\u5217\u5165\u60a8\u7684\u7533\u8bf7\u4e2d\u3002", "The following message will be displayed at the bottom of the courseware pages within your course:": "\u4ee5\u4e0b\u4fe1\u606f\u5c06\u4f1a\u5728\u60a8\u8bfe\u7a0b\u7684\u8bfe\u4ef6\u9875\u9762\u5e95\u90e8\u663e\u793a\uff1a", "The following options are available for the {license_name} license.": "\u4ee5\u4e0b\u4e3a {license_name}\u8bb8\u53ef\u7684\u53ef\u7528\u9009\u9879", "The following users are no longer enrolled in the course:": "\u4ee5\u4e0b\u7528\u6237\u5df2\u4e0d\u518d\u9009\u4fee\u672c\u8bfe\u7a0b\uff1a", @@ -1666,7 +1653,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "\u6700\u4f4e\u5b8c\u6210\u7387\u5fc5\u987b\u4e3a0-100\u7684\u6574\u6570\u3002", "The minimum grade for course credit is not set.": "\u5c1a\u672a\u8bbe\u7f6e\u80fd\u83b7\u53d6\u8bfe\u7a0b\u5b66\u5206\u7684\u6700\u4f4e\u5206\u503c\u3002", "The minimum score percentage must be a whole number between 0 and 100.": "\u5206\u6570\u767e\u5206\u6bd4\u7684\u6700\u5c0f\u503c\u5fc5\u987b\u662f\u57280\u5230100\u4e4b\u95f4\u7684\u6574\u6570\u3002", - "The more you tell us, the more quickly and helpfully we can respond!": "\u60a8\u63d0\u4f9b\u7684\u4fe1\u606f\u8d8a\u8be6\u7ec6\uff0c\u6211\u4eec\u8d8a\u80fd\u5feb\u901f\u5e76\u6709\u6548\u5730\u5e2e\u52a9\u5230\u60a8\uff01", "The name of this signatory as it should appear on certificates.": "\u7b7e\u53d1\u8005\u5728\u8bc1\u4e66\u4e0a\u663e\u793a\u7684\u540d\u5b57", "The name that identifies you on {platform_name}. You cannot change your username.": "\u60a8\u5728{platform_name}\u4e0a\u7684\u540d\u5b57\uff0c\u7528\u6237\u540d\u65e0\u6cd5\u66f4\u6539\u3002", "The name that is used for ID verification and that appears on your certificates.": "\u7528\u4e8e\u8eab\u4efd\u8ba4\u8bc1\u548c\u663e\u793a\u5728\u8bc1\u4e66\u4e0a\u7684\u59d3\u540d\u3002", @@ -1674,7 +1660,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "\u8bfe\u7a0b\u4e2d\u6240\u6709\u5305\u542b\u6b64\u4efb\u52a1\u7c7b\u578b\u7684\u8282\u6570\u3002", "The organization that this signatory belongs to, as it should appear on certificates.": "\u6b64\u7b7e\u7f72\u4eba\u6240\u5c5e\u7684\u7ec4\u7ec7\uff0c\u5e94\u663e\u793a\u5728\u8bc1\u4e66\u4e0a\u3002", "The page \"{route}\" could not be found.": "\u65e0\u6cd5\u627e\u5230\"{route}\"\u9875\u9762\u3002", - "The photo of your face matches the photo on your ID.": "\u60a8\u7684\u9762\u90e8\u7167\u7247\u4e0e\u60a8\u8eab\u4efd\u8bc1\u4ef6\u4e0a\u7684\u7167\u7247\u76f8\u7b26\u3002", "The post you selected has been deleted.": "\u60a8\u6240\u9009\u62e9\u7684\u5e16\u5b50\u5df2\u88ab\u5220\u9664\u3002", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "\u5df2\u53d1\u5e03\u5206\u652f\u7248\u672c{published}\u88ab\u91cd\u7f6e\u4e3a\u521d\u7a3f\u5206\u652f\u7248\u672c{draft}\u3002", "The raw error message is:": "\u539f\u59cb\u7684\u9519\u8bef\u4fe1\u606f\u662f\uff1a", @@ -1810,7 +1795,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "\u8981\u786e\u4fdd\u6240\u6709\u5b66\u751f\u90fd\u80fd\u770b\u5230\u89c6\u9891\uff0c\u6211\u4eec\u5efa\u8bae\u60a8\u540c\u65f6\u63d0\u4f9b.mp4\u7248\u672c\u548c.webm\u7248\u672c\u7684\u89c6\u9891\u3002\u70b9\u51fb\u4e0b\u65b9\u6309\u94ae\u6dfb\u52a0\u53e6\u4e00\u4e2a\u7248\u672c\u7684URL\uff08\u8bf7\u52ff\u4f7f\u7528YouTube\u7684URL\uff09\uff0c\u5b66\u751f\u5c06\u4f1a\u770b\u5230\u5217\u8868\u4e2d\u7b2c\u4e00\u4e2a\u4e0e\u5176\u8ba1\u7b97\u673a\u517c\u5bb9\u7684\u89c6\u9891\u3002", "To complete the program, you must earn a verified certificate for each course.": "\u60a8\u5fc5\u987b\u6bcf\u95e8\u8bfe\u7a0b\u90fd\u83b7\u5f97\u8bc1\u4e66\uff0c\u624d\u53ef\u4ee5\u5b8c\u6210\u6b64\u8bfe\u7a0b\u65b9\u6848\u3002", "To continue learning with this account, sign in below.": "\u5982\u9700\u7ee7\u7eed\u4f7f\u7528\u6b64\u8d26\u53f7\u5b66\u4e60\uff0c\u8bf7\u70b9\u51fb\u4ee5\u4e0b\u6309\u94ae\u767b\u5f55\u3002", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "\u8981\u5b8c\u6210\u8bfe\u7a0b\u5b66\u5206\uff0c%(display_name)s \u8981\u6c42 %(platform_name)s \u5b66\u5458\u63d0\u4ea4\u4e00\u4efd\u5b66\u5206\u7533\u8bf7\u3002", "To invalidate a certificate for a particular learner, add the username or email address below.": "\u8981\u8bbe\u5b9a\u67d0\u4e2a\u7279\u5b9a\u5b66\u5458\u7684\u8bc1\u4e66\u65e0\u6548\uff0c\u8bf7\u5728\u4e0b\u9762\u6dfb\u52a0\u76f8\u5e94\u7684\u7528\u6237\u540d\u6216\u90ae\u7bb1\u3002", "To pass this exam, you must complete the problems in the time allowed.": "\u60a8\u5fc5\u987b\u5728\u65f6\u9650\u5185\u5b8c\u6210\u9898\u76ee\u624d\u53ef\u4ee5\u901a\u8fc7\u8003\u8bd5\u3002", "To receive a certificate, you must also verify your identity before {date}.": "\u8981\u83b7\u5f97\u8bc1\u4e66\uff0c\u60a8\u5fc5\u987b\u5728 {date} \u4e4b\u524d\u9a8c\u8bc1\u60a8\u7684\u8eab\u4efd\u3002", @@ -1895,7 +1879,6 @@ "Upload Videos": "\u4e0a\u4f20\u89c6\u9891", "Upload a CSV file": "\u4e0a\u4f20 CSV \u6587\u4ef6", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u4e0a\u4f20\u4e00\u4e2a\u7528\u9017\u53f7\u9694\u5f00\u7684\u503c (.csv) \u6587\u4ef6\uff0c\u6587\u4ef6\u8981\u5305\u542b\u83b7\u5f97\u7279\u4f8b\u7684\u5b66\u5458\u7684\u7528\u6237\u540d\u6216\u90ae\u7bb1\u3002\u5c06\u7528\u6237\u540d\u6216\u90ae\u7bb1\u5217\u5165\u7b2c\u4e00\u4e2a\u9017\u53f7\u9694\u5f00\u7684\u5b57\u6bb5\u4e2d\u3002\u60a8\u53ef\u4ee5\u5728\u7b2c\u4e8c\u4e2a\u7528\u9017\u53f7\u9694\u5f00\u7684\u5b57\u6bb5\u4e2d\u8f93\u5165\u7279\u6b8a\u5904\u7406\u7684\u539f\u56e0\u63cf\u8ff0\u3002", - "Upload a new PDF to \u201c<%= name %>\u201d": "\u4e0a\u4f20\u65b0\u7684PDF\u6587\u4ef6\u81f3\u201c<%= name %>\u201d", "Upload an image": "\u4e0a\u4f20\u56fe\u7247", "Upload an image or capture one with your web or phone camera.": "\u4e0a\u4f20\u7167\u7247\u6216\u901a\u8fc7\u4f7f\u7528\u60a8\u7684\u7f51\u7edc\uff0f\u624b\u673a\u6444\u50cf\u5934\u62cd\u7167\u4e0a\u4f20\u3002", "Upload completed": "\u4e0a\u4f20\u5b8c\u6210", @@ -1926,7 +1909,6 @@ "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "\u5c06\u9009\u8bfe\u901a\u9053\u4f5c\u4e3a\u5212\u5206\u8ba8\u8bba\u7ec4\u7684\u57fa\u7840\u3002\u6240\u6709\u7684\u5b66\u5458\uff0c\u4e0d\u7ba1\u4ed6\u4eec\u7684\u9009\u8bfe\u901a\u9053\u662f\u4ec0\u4e48\uff0c\u90fd\u53ef\u4ee5\u770b\u5230\u76f8\u540c\u7684\u8ba8\u8bba\u4e3b\u9898\uff0c\u4f46\u662f\u5728\u4e0d\u540c\u7684\u4e3b\u9898\u4e2d\uff0c\u53ea\u6709\u5728\u540c\u4e00\u9009\u8bfe\u901a\u9053\u4e0a\u7684\u5b66\u5458\u624d\u80fd\u770b\u5230\u548c\u56de\u590d\u5f7c\u6b64\u7684\u5e16\u5b50\u3002", "Use my institution/campus credentials": "\u4f7f\u7528\u6211\u7684\u673a\u6784/\u6821\u56ed\u8d26\u53f7", "Use the All Topics menu to find specific topics.": "\u4f7f\u7528\u201c\u6240\u6709\u4e3b\u9898\u201d\u83dc\u5355\u627e\u5230\u7279\u5b9a\u8bdd\u9898", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u8bf7\u7528\u6444\u50cf\u5934\u62cd\u6444\u4e00\u5f20\u60a8\u8eab\u4efd\u8bc1\u4ef6\u7684\u7167\u7247\uff0c\u6211\u4eec\u5c06\u67e5\u770b\u8be5\u7167\u7247\u662f\u5426\u4e0e\u60a8\u7684\u9762\u90e8\u7167\u7247\u53ca\u60a8\u5728\u8d26\u53f7\u4e2d\u586b\u5199\u7684\u59d3\u540d\u5339\u914d\u3002", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u8bf7\u7528\u6444\u50cf\u5934\u62cd\u6444\u4e00\u5f20\u60a8\u7684\u9762\u90e8\u7167\u7247\uff0c\u6211\u4eec\u5c06\u5bf9\u6bd4\u8be5\u7167\u7247\u4e0e\u60a8\u8eab\u4efd\u8bc1\u4ef6\u4e0a\u7684\u7167\u7247\u3002", "Used": "\u5df2\u4f7f\u7528", "Used in {count} location": [ @@ -1949,7 +1931,6 @@ "Verified Certificate upgrade": "\u8ba4\u8bc1\u8bc1\u4e66\u5347\u7ea7", "Verified Status": "\u9a8c\u8bc1\u72b6\u6001", "Verified mode price": "\u901a\u8fc7\u9a8c\u8bc1\u7684\u6a21\u5f0f\u4ef7\u683c", - "Verify Now": "\u73b0\u5728\u8ba4\u8bc1", "Version": "\u7248\u672c", "Vertical space": "\u5782\u76f4\u95f4\u8ddd", "Very loud": "\u97f3\u91cf\u6700\u5927", @@ -1992,7 +1973,6 @@ "We couldn't find any results for \"%s\".": "\u6211\u4eec\u627e\u4e0d\u5230\u6709\u5173\u201c%s\u201d\u7684\u4efb\u4f55\u7ed3\u679c\u3002", "We couldn't sign you in.": "\u767b\u5f55\u5931\u8d25\u3002", "We have encountered an error. Refresh your browser and then try again.": "\u53d1\u751f\u9519\u8bef\uff0c\u8bf7\u5237\u65b0\u60a8\u7684\u6d4f\u89c8\u5668\u5e76\u91cd\u8bd5\u3002", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "\u6211\u4eec\u5df2\u7ecf\u6536\u5230\u60a8\u7684\u4fe1\u606f\u5e76\u6b63\u5728\u9a8c\u8bc1\u60a8\u7684\u8eab\u4efd\u3002\u9a8c\u8bc1\u6d41\u7a0b\u7ed3\u675f\u540e(\u4e00\u822c\u5728 1-2 \u5929\u5185)\uff0c\u60a8\u5c06\u5728\u60a8\u7684\u63a7\u5236\u9762\u677f\u4e0a\u6536\u5230\u4e00\u6761\u6d88\u606f\u3002\u4e0e\u6b64\u540c\u65f6\uff0c\u60a8\u4ecd\u7136\u53ef\u4ee5\u8bbf\u95ee\u6240\u6709\u7684\u8bfe\u7a0b\u5185\u5bb9\u3002", "We just need a little more information before you start learning with %(platformName)s.": "\u60a8\u53ea\u9700\u518d\u591a\u63d0\u4f9b\u4e00\u70b9\u4fe1\u606f\u5c31\u53ef\u4ee5\u5f00\u59cb\u5728%(platformName)s\u5b66\u4e60\u4e86\u3002", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "\u6211\u4eec\u4f1a\u91c7\u7528\u6700\u9ad8\u7ea7\u522b\u7684\u5b89\u5168\u6280\u672f\u6765\u52a0\u5bc6\u60a8\u7684\u7167\u7247\u5e76\u53d1\u9001\u5230\u6211\u4eec\u7684\u6388\u6743\u670d\u52a1\u7528\u4e8e\u5ba1\u6838\u76ee\u7684\uff1b\u4e00\u65e6\u5b8c\u6210\u4e86\u8ba4\u8bc1\u8fc7\u7a0b\uff0c%(platformName)s\u4e0d\u4f1a\u7ee7\u7eed\u4fdd\u5b58\u8fd9\u4e9b\u7167\u7247\u548c\u4fe1\u606f\u3002", "We're sorry to see you go! Your account will be deleted shortly.": "\u5f88\u9057\u61be\u60a8\u8981\u79bb\u5f00\uff01\u60a8\u7684\u8d26\u53f7\u5c06\u5f88\u5feb\u88ab\u5220\u9664\u3002", @@ -2087,13 +2067,10 @@ "You must specify a name": "\u60a8\u5fc5\u987b\u6307\u5b9a\u4e00\u4e2a\u540d\u79f0", "You must specify a name for the cohort": "\u60a8\u5fc5\u987b\u4e3a\u8be5\u7fa4\u7ec4\u547d\u540d\u3002", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u60a8\u5fc5\u987b\u586b\u5199\u51fa\u751f\u5e74\u4efd\u624d\u80fd\u5206\u4eab\u5b8c\u6574\u8d44\u6599\u3002\u70b9\u51fb {account_settings_page_link} \u586b\u5199", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u60a8\u9700\u8981\u9a7e\u7167\u3001\u62a4\u7167\u6216\u8005\u5176\u4ed6\u7531\u653f\u5e9c\u7b7e\u53d1\u7684\u5e26\u6709\u60a8\u59d3\u540d\u548c\u7167\u7247\u7684\u8eab\u4efd\u8bc1\u4ef6\u3002", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u60a8\u9700\u8981\u4e00\u4efd\u5e26\u6709\u60a8\u59d3\u540d\u548c\u7167\u7247\u7684\u8eab\u4efd\u8bc1\u4ef6\uff0c\u6211\u4eec\u53ef\u4ee5\u63a5\u53d7\u9a7e\u7167\u3001\u62a4\u7167\u4ee5\u53ca\u5176\u4ed6\u7531\u653f\u5e9c\u7b7e\u53d1\u7684\u8eab\u4efd\u8bc1\u4ef6\u3002", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u5728\u9009\u8bfe\u4e4b\u524d\u60a8\u9700\u8981\u5148\u6fc0\u6d3b\u60a8\u7684\u8d26\u53f7\uff0c\u8bf7\u68c0\u67e5\u6536\u4ef6\u7bb1\u4e2d\u7684\u6fc0\u6d3b\u90ae\u4ef6\u3002", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u5728\u9009\u8bfe\u4e4b\u524d\u60a8\u9700\u8981\u5148\u6fc0\u6d3b\u60a8\u7684\u8d26\u53f7\uff0c\u8bf7\u68c0\u67e5\u6536\u4ef6\u7bb1\u4e2d\u7684\u6fc0\u6d3b\u90ae\u4ef6\u3002\u5f53\u60a8\u5b8c\u6210\u6fc0\u6d3b\u540e\uff0c\u60a8\u53ef\u4ee5\u8fd4\u56de\u5e76\u5237\u65b0\u672c\u9875\u9762\u3002", "You receive messages from {platform_name} and course teams at this address.": "\u6b64\u90ae\u7bb1\u7528\u4e8e\u63a5\u6536\u6765\u81ea{platform_name}\u548c\u8bfe\u7a0b\u56e2\u961f\u7684\u4fe1\u606f\u3002", "You reserve all rights for your work": "\u60a8\u5bf9\u60a8\u6240\u4f5c\u51fa\u7684\u8d21\u732e\u4fdd\u7559\u6240\u6709\u6743\u5229", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u60a8\u4ecd\u7136\u9700\u8981\u8bbf\u95ee %(display_name)s \u7f51\u7ad9\u5b8c\u6210\u5b66\u5206\u9886\u53d6\u6d41\u7a0b\u3002", "You submitted {filename}; only {allowedFiles} are allowed.": "\u60a8\u63d0\u4ea4\u4e86 {filename}\uff1b\u4ec5\u652f\u6301\u63d0\u4ea4 {allowedFiles} \u683c\u5f0f\u7684\u6587\u4ef6\u3002", "You waive some rights for your work, such that others can use it too": "\u60a8\u9700\u8981\u5bf9\u60a8\u6240\u505a\u7684\u8d21\u732e\u653e\u5f03\u90e8\u5206\u6743\u5229\uff0c\u4f8b\u5982\u4ed6\u4eba\u4e5f\u53ef\u4ee5\u4f7f\u7528\u60a8\u7684\u6210\u679c", "You will be refunded the amount you paid.": "\u60a8\u5c06\u4f1a\u6536\u5230\u5168\u989d\u9000\u6b3e\u3002", @@ -2187,7 +2164,6 @@ "enter code here": "\u6b64\u5904\u8f93\u5165\u4ee3\u7801", "enter link description here": "\u6b64\u5904\u8f93\u5165\u94fe\u63a5\u7684\u63cf\u8ff0", "for": "\u7684", - "for {courseName}": "\u4e3a{courseName}\u8bfe\u7a0b", "group configuration": "\u7ec4\u914d\u7f6e", "image omitted": "\u7701\u7565\u7684\u56fe\u7247", "incorrect": "\u4e0d\u6b63\u786e", @@ -2316,7 +2292,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2380,9 +2356,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/zh-hk/djangojs.js b/cms/static/js/i18n/zh-hk/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/cms/static/js/i18n/zh-hk/djangojs.js +++ b/cms/static/js/i18n/zh-hk/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/i18n/zh-tw/djangojs.js b/cms/static/js/i18n/zh-tw/djangojs.js index adff90275f2768d736bbe8d219a4fe93d49f3e1d..ddccbb9507950767a4d6b9d779ec3a4d162a344f 100644 --- a/cms/static/js/i18n/zh-tw/djangojs.js +++ b/cms/static/js/i18n/zh-tw/djangojs.js @@ -969,7 +969,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1033,9 +1033,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/cms/static/js/index.js b/cms/static/js/index.js index 70def59cadfd97bdc80158ce7b93a649f769f1ff..58f230e6f210f30cae4296fbccec3bf962b6912b 100644 --- a/cms/static/js/index.js +++ b/cms/static/js/index.js @@ -61,8 +61,9 @@ define(['domReady', 'jquery', 'underscore', 'js/utils/cancel_on_escape', 'js/vie analytics.track('Created a Course', course_info); CreateCourseUtils.create(course_info, function(errorMessage) { + var msg = edx.HtmlUtils.joinHtml(edx.HtmlUtils.HTML('<p>'), errorMessage, edx.HtmlUtils.HTML('</p>')); $('.create-course .wrap-error').addClass('is-shown'); - $('#course_creation_error').html('<p>' + errorMessage + '</p>'); + edx.HtmlUtils.setHtml($('#course_creation_error'), msg); $('.new-course-save').addClass('is-disabled').attr('aria-disabled', true); }); }; @@ -136,8 +137,9 @@ define(['domReady', 'jquery', 'underscore', 'js/utils/cancel_on_escape', 'js/vie analytics.track('Created a Library', lib_info); CreateLibraryUtils.create(lib_info, function(errorMessage) { + var msg = edx.HtmlUtils.joinHtml(edx.HtmlUtils.HTML('<p>'), errorMessage, edx.HtmlUtils.HTML('</p>')); $('.create-library .wrap-error').addClass('is-shown'); - $('#library_creation_error').html('<p>' + errorMessage + '</p>'); + edx.HtmlUtils.setHtml($('#library_creation_error'), msg); $('.new-library-save').addClass('is-disabled').attr('aria-disabled', true); }); }; diff --git a/cms/static/js/maintenance/force_publish_course.js b/cms/static/js/maintenance/force_publish_course.js index 65e93ff725ff41d7ba3568d23ec5637eb506e6a1..e7eed221d6779e7796096ca8aab6d8a27d6d225e 100644 --- a/cms/static/js/maintenance/force_publish_course.js +++ b/cms/static/js/maintenance/force_publish_course.js @@ -22,7 +22,11 @@ function($, _, gettext, ViewUtils, StringUtils, HtmlUtils) { showError = function(containerElSelector, error) { var errorWrapperElSelector, errorHtml; errorWrapperElSelector = containerElSelector + ' .wrapper-error'; - errorHtml = '<div class="error" aria-live="polite" id="course-id-error">' + error + '</div>'; + errorHtml = HtmlUtils.joinHtml( + HtmlUtils.HTML('<div class="error" aria-live="polite" id="course-id-error">'), + error, + HtmlUtils.HTML('</div>') + ); HtmlUtils.setHtml($(errorWrapperElSelector), HtmlUtils.HTML(errorHtml)); $(errorWrapperElSelector).css('display', 'inline-block'); $(errorWrapperElSelector).fadeOut(5000); diff --git a/cms/static/js/models/settings/course_details.js b/cms/static/js/models/settings/course_details.js index 394883d48096bf22975f57c00410b08e50a9ed84..c0d8c506f4ffb2ff466c69ecad6cd664abc65915 100644 --- a/cms/static/js/models/settings/course_details.js +++ b/cms/static/js/models/settings/course_details.js @@ -1,5 +1,8 @@ -define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js/utils/date_utils'], - function(Backbone, _, gettext, ValidationHelpers, DateUtils) { +define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js/utils/date_utils', + 'edx-ui-toolkit/js/utils/string-utils' +], + function(Backbone, _, gettext, ValidationHelpers, DateUtils, StringUtils) { + 'use strict'; var CourseDetails = Backbone.Model.extend({ defaults: { org: '', @@ -51,11 +54,17 @@ define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js if (newattrs.start_date && newattrs.end_date && newattrs.start_date >= newattrs.end_date) { errors.end_date = gettext('The course end date must be later than the course start date.'); } - if (newattrs.start_date && newattrs.enrollment_start && newattrs.start_date < newattrs.enrollment_start) { - errors.enrollment_start = gettext('The course start date must be later than the enrollment start date.'); + if (newattrs.start_date && newattrs.enrollment_start && + newattrs.start_date < newattrs.enrollment_start) { + errors.enrollment_start = gettext( + 'The course start date must be later than the enrollment start date.' + ); } - if (newattrs.enrollment_start && newattrs.enrollment_end && newattrs.enrollment_start >= newattrs.enrollment_end) { - errors.enrollment_end = gettext('The enrollment start date cannot be after the enrollment end date.'); + if (newattrs.enrollment_start && newattrs.enrollment_end && + newattrs.enrollment_start >= newattrs.enrollment_end) { + errors.enrollment_end = gettext( + 'The enrollment start date cannot be after the enrollment end date.' + ); } if (newattrs.end_date && newattrs.enrollment_end && newattrs.end_date < newattrs.enrollment_end) { errors.enrollment_end = gettext('The enrollment end date cannot be after the course end date.'); @@ -78,7 +87,9 @@ define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js max: 100 }; if (!ValidationHelpers.validateIntegerRange(newattrs.entrance_exam_minimum_score_pct, range)) { - errors.entrance_exam_minimum_score_pct = interpolate(gettext('Please enter an integer between %(min)s and %(max)s.'), range, true); + errors.entrance_exam_minimum_score_pct = StringUtils.interpolate(gettext( + 'Please enter an integer between %(min)s and %(max)s.' + ), range, true); } } if (!_.isEmpty(errors)) return errors; @@ -90,7 +101,8 @@ define(['backbone', 'underscore', 'gettext', 'js/models/validation_helpers', 'js set_videosource: function(newsource) { // newsource either is <video youtube="speed:key, *"/> or just the "speed:key, *" string // returns the videosource for the preview which iss the key whose speed is closest to 1 - if (_.isEmpty(newsource) && !_.isEmpty(this.get('intro_video'))) this.set({intro_video: null}, {validate: true}); + if (_.isEmpty(newsource) && + !_.isEmpty(this.get('intro_video'))) this.set({intro_video: null}, {validate: true}); // TODO remove all whitespace w/in string else { if (this.get('intro_video') !== newsource) this.set('intro_video', newsource, {validate: true}); diff --git a/cms/static/js/models/settings/course_grading_policy.js b/cms/static/js/models/settings/course_grading_policy.js index 5b2e7003d8930cdc1cac7002fd6153bc5cab6506..f954e5bf03811ccf3079f541259d376dd22152a4 100644 --- a/cms/static/js/models/settings/course_grading_policy.js +++ b/cms/static/js/models/settings/course_grading_policy.js @@ -1,6 +1,7 @@ /* globals _ */ -define(['backbone', 'js/models/location', 'js/collections/course_grader'], - function(Backbone, Location, CourseGraderCollection) { +define(['backbone', 'js/models/location', 'js/collections/course_grader', 'edx-ui-toolkit/js/utils/string-utils'], + function(Backbone, Location, CourseGraderCollection, StringUtils) { + 'use strict'; var CourseGradingPolicy = Backbone.Model.extend({ defaults: { graders: null, // CourseGraderCollection @@ -37,9 +38,15 @@ define(['backbone', 'js/models/location', 'js/collections/course_grader'], }, gracePeriodToDate: function() { var newDate = new Date(); - if (this.has('grace_period') && this.get('grace_period').hours) { newDate.setHours(this.get('grace_period').hours); } else newDate.setHours(0); - if (this.has('grace_period') && this.get('grace_period').minutes) { newDate.setMinutes(this.get('grace_period').minutes); } else newDate.setMinutes(0); - if (this.has('grace_period') && this.get('grace_period').seconds) { newDate.setSeconds(this.get('grace_period').seconds); } else newDate.setSeconds(0); + if (this.has('grace_period') && this.get('grace_period').hours) { + newDate.setHours(this.get('grace_period').hours); + } else newDate.setHours(0); + if (this.has('grace_period') && this.get('grace_period').minutes) { + newDate.setMinutes(this.get('grace_period').minutes); + } else newDate.setMinutes(0); + if (this.has('grace_period') && this.get('grace_period').seconds) { + newDate.setSeconds(this.get('grace_period').seconds); + } else newDate.setSeconds(0); return newDate; }, @@ -62,6 +69,7 @@ define(['backbone', 'js/models/location', 'js/collections/course_grader'], return parseInt(minimum_grade_credit); }, validate: function(attrs) { + var minimumGradeCutoff; if (_.has(attrs, 'grace_period')) { if (attrs.grace_period === null) { return { @@ -71,12 +79,13 @@ define(['backbone', 'js/models/location', 'js/collections/course_grader'], } if (this.get('is_credit_course') && _.has(attrs, 'minimum_grade_credit')) { // Getting minimum grade cutoff value - var minimum_grade_cutoff = _.min(_.values(attrs.grade_cutoffs)); - if (isNaN(attrs.minimum_grade_credit) || attrs.minimum_grade_credit === null || attrs.minimum_grade_credit < minimum_grade_cutoff) { + minimumGradeCutoff = _.min(_.values(attrs.grade_cutoffs)); + if (isNaN(attrs.minimum_grade_credit) || attrs.minimum_grade_credit === null || + attrs.minimum_grade_credit < minimumGradeCutoff) { return { - minimum_grade_credit: interpolate( + minimum_grade_credit: StringUtils.interpolate( gettext('Not able to set passing grade to less than %(minimum_grade_cutoff)s%.'), - {minimum_grade_cutoff: minimum_grade_cutoff * 100}, + {minimum_grade_cutoff: minimumGradeCutoff * 100}, true ) }; diff --git a/cms/static/js/models/uploads.js b/cms/static/js/models/uploads.js index be12dbfb1ab6f810fb1575110622ce84b6a93baa..8db4129d9e689b3497f1286f40f1d480d8561bc9 100644 --- a/cms/static/js/models/uploads.js +++ b/cms/static/js/models/uploads.js @@ -14,7 +14,7 @@ define(['backbone', 'underscore', 'gettext'], function(Backbone, _, gettext) { validate: function(attrs, options) { if (attrs.selectedFile && !this.checkTypeValidity(attrs.selectedFile)) { return { - message: _.template(gettext('Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.'))( // eslint-disable-line max-len + message: _.template(gettext('Only <%- fileTypes %> files can be uploaded. Please select a file ending in <%- (fileExtensions) %> to upload.'))( // eslint-disable-line max-len this.formatValidTypes() ), attributes: {selectedFile: true} @@ -62,7 +62,7 @@ define(['backbone', 'underscore', 'gettext'], function(Backbone, _, gettext) { } var or = gettext('or'); var formatTypes = function(types) { - return _.template('<%= initial %> <%= or %> <%= last %>')({ + return _.template('<%- initial %> <%- or %> <%- last %>')({ initial: _.initial(types).join(', '), or: or, last: _.last(types) diff --git a/cms/static/js/spec/views/previous_video_upload_spec.js b/cms/static/js/spec/views/previous_video_upload_spec.js index f565b5237291dbcab0bc193da244451ee70f4217..a9584f0211f36dc23ebc45c76e1c2a958410b689 100644 --- a/cms/static/js/spec/views/previous_video_upload_spec.js +++ b/cms/static/js/spec/views/previous_video_upload_spec.js @@ -58,7 +58,7 @@ define( it('should render status correctly', function() { var testStatus = 'Test Status'; var $el = render({status: testStatus}); - expect($el.find('.status-col').text()).toEqual(testStatus); + expect($el.find('.video-status').text()).toEqual(testStatus); }); it('should render remove button correctly', function() { diff --git a/cms/static/js/views/abstract_editor.js b/cms/static/js/views/abstract_editor.js index 81ff65a5e1cd86cdc3d6f3ca663f9c3ab435fcd9..c67fc164ad240b83e9f41c6d3a0ac88949e768ce 100644 --- a/cms/static/js/views/abstract_editor.js +++ b/cms/static/js/views/abstract_editor.js @@ -9,6 +9,7 @@ define(['js/views/baseview', 'underscore'], function(BaseView, _) { // Backbone model cid is only unique within the collection. this.uniqueId = _.uniqueId(templateName + '_'); this.template = this.loadTemplate(templateName); + // xss-lint: disable=javascript-jquery-html this.$el.html(this.template({model: this.model, uniqueId: this.uniqueId})); this.listenTo(this.model, 'change', this.render); this.render(); diff --git a/cms/static/js/views/asset.js b/cms/static/js/views/asset.js index 541ffe780c55612c3a7233a545f17fa11d5a890e..ee5721343cc69376e2d405b45d020d91af5f6b24 100644 --- a/cms/static/js/views/asset.js +++ b/cms/static/js/views/asset.js @@ -1,6 +1,7 @@ define(['js/views/baseview', 'underscore', 'gettext', 'common/js/components/views/feedback_prompt', - 'common/js/components/views/feedback_notification'], - function(BaseView, _, gettext, PromptView, NotificationView) { + 'common/js/components/views/feedback_notification', 'edx-ui-toolkit/js/utils/html-utils'], + function(BaseView, _, gettext, PromptView, NotificationView, HtmlUtils) { + 'use strict'; var AssetView = BaseView.extend({ initialize: function() { this.template = this.loadTemplate('asset'); @@ -14,7 +15,7 @@ define(['js/views/baseview', 'underscore', 'gettext', 'common/js/components/view render: function() { var uniqueId = _.uniqueId('lock_asset_'); - this.$el.html(this.template({ + var attributes = { display_name: this.model.get('display_name'), thumbnail: this.model.get('thumbnail'), date_added: this.model.get('date_added'), @@ -23,32 +24,32 @@ define(['js/views/baseview', 'underscore', 'gettext', 'common/js/components/view portable_url: this.model.get('portable_url'), asset_type: this.model.get_extension(), uniqueId: uniqueId - })); + }; + this.$el.html(HtmlUtils.HTML(this.template(attributes)).toString()); this.updateLockState(); return this; }, updateLockState: function() { - var locked_class = 'is-locked'; + var lockedClass = 'is-locked'; // Add a class of "locked" to the tr element if appropriate, // and toggle locked state of hidden checkbox. if (this.model.get('locked')) { - this.$el.addClass(locked_class); + this.$el.addClass(lockedClass); this.$el.find('.lock-checkbox').attr('checked', 'checked'); } else { - this.$el.removeClass(locked_class); + this.$el.removeClass(lockedClass); this.$el.find('.lock-checkbox').removeAttr('checked'); } }, confirmDelete: function(e) { + var asset = this.model; if (e && e.preventDefault) { e.preventDefault(); } - var asset = this.model, - collection = this.model.collection; new PromptView.Warning({ title: gettext('Delete File Confirmation'), - message: gettext('Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)'), + message: gettext('Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)'), // eslint-disable-line max-len actions: { primary: { text: gettext('Delete'), @@ -76,7 +77,7 @@ define(['js/views/baseview', 'underscore', 'gettext', 'common/js/components/view }).show(); }, - lockAsset: function(e) { + lockAsset: function() { var asset = this.model; var saving = new NotificationView.Mini({ title: gettext('Saving') diff --git a/cms/static/js/views/course_info_handout.js b/cms/static/js/views/course_info_handout.js index f2fcc8723fd7c39eaa23c143d9aaa07f661caae4..621f644b2cf97d59e06ece9315ad4e683292c595 100644 --- a/cms/static/js/views/course_info_handout.js +++ b/cms/static/js/views/course_info_handout.js @@ -1,102 +1,105 @@ -define(['js/views/baseview', 'codemirror', 'common/js/components/views/feedback_notification', 'js/views/course_info_helper', 'js/utils/modal'], - function(BaseView, CodeMirror, NotificationView, CourseInfoHelper, ModalUtils) { +define([ + 'js/views/baseview', + 'codemirror', + 'common/js/components/views/feedback_notification', + 'js/views/course_info_helper', + 'js/utils/modal', + 'edx-ui-toolkit/js/utils/html-utils' +], +function(BaseView, CodeMirror, NotificationView, CourseInfoHelper, ModalUtils, HtmlUtils) { + 'use strict'; // the handouts view is dumb right now; it needs tied to a model and all that jazz - var CourseInfoHandoutsView = BaseView.extend({ - // collection is CourseUpdateCollection - events: { - 'click .save-button': 'onSave', - 'click .cancel-button': 'onCancel', - 'click .edit-button': 'onEdit' - }, + var CourseInfoHandoutsView = BaseView.extend({ + // collection is CourseUpdateCollection + events: { + 'click .save-button': 'onSave', + 'click .cancel-button': 'onCancel', + 'click .edit-button': 'onEdit' + }, - initialize: function() { - this.template = this.loadTemplate('course_info_handouts'); - var self = this; - this.model.fetch({ - complete: function() { - self.render(); - }, - reset: true - }); - }, - - render: function() { - CourseInfoHelper.changeContentToPreview( - this.model, 'data', this.options.base_asset_url); - - this.$el.html( - $(this.template({ - model: this.model - })) - ); - $('.handouts-content').html(this.model.get('data')); - this.$preview = this.$el.find('.handouts-content'); - this.$form = this.$el.find('.edit-handouts-form'); - this.$editor = this.$form.find('.handouts-content-editor'); - this.$form.hide(); + initialize: function() { + var self = this; + this.template = this.loadTemplate('course_info_handouts'); + this.model.fetch({ + complete: function() { + self.render(); + }, + reset: true + }); + }, - return this; - }, + render: function() { + CourseInfoHelper.changeContentToPreview( + this.model, 'data', this.options.base_asset_url); + this.$el.html(HtmlUtils.HTML($(this.template({model: this.model}))).toString()); + HtmlUtils.setHtml($('.handouts-content'), HtmlUtils.HTML(this.model.get('data'))); + this.$preview = this.$el.find('.handouts-content'); + this.$form = this.$el.find('.edit-handouts-form'); + this.$editor = this.$form.find('.handouts-content-editor'); + this.$form.hide(); - onEdit: function(event) { - var self = this; - this.$editor.val(this.$preview.html()); - this.$form.show(); + return this; + }, - this.$codeMirror = CourseInfoHelper.editWithCodeMirror( - self.model, 'data', self.options.base_asset_url, this.$editor.get(0)); + onEdit: function() { + var self = this; + this.$editor.val(this.$preview.html()); + this.$form.show(); - ModalUtils.showModalCover(false, function() { self.closeEditor(); }); - }, + this.$codeMirror = CourseInfoHelper.editWithCodeMirror( + self.model, 'data', self.options.base_asset_url, this.$editor.get(0)); - onSave: function(event) { - var handoutsContent = this.$codeMirror.getValue(); - $('#handout_error').removeClass('is-shown'); - $('.save-button').removeClass('is-disabled').attr('aria-disabled', false); - if ($('.CodeMirror-lines').find('.cm-error').length == 0) { - if (handoutsContent === '') { - handoutsContent = '<ol></ol>'; - } - this.model.set('data', handoutsContent); - var saving = new NotificationView.Mini({ - title: gettext('Saving') - }); - saving.show(); - this.model.save({}, { - success: function() { - saving.hide(); - } - }); - this.render(); - this.$form.hide(); - this.closeEditor(); + ModalUtils.showModalCover(false, function() { self.closeEditor(); }); + }, - analytics.track('Saved Course Handouts', { - course: course_location_analytics - }); - } else { - $('#handout_error').addClass('is-shown'); - $('.save-button').addClass('is-disabled').attr('aria-disabled', true); - event.preventDefault(); + onSave: function(event) { + var saving = new NotificationView.Mini({ + title: gettext('Saving') + }); + var handoutsContent = this.$codeMirror.getValue(); + $('#handout_error').removeClass('is-shown'); + $('.save-button').removeClass('is-disabled').attr('aria-disabled', false); + if ($('.CodeMirror-lines').find('.cm-error').length === 0) { + if (handoutsContent === '') { + handoutsContent = '<ol></ol>'; } - }, - - onCancel: function(event) { - $('#handout_error').removeClass('is-shown'); - $('.save-button').removeClass('is-disabled').attr('aria-disabled', false); + this.model.set('data', handoutsContent); + saving.show(); + this.model.save({}, { + success: function() { + saving.hide(); + } + }); + this.render(); this.$form.hide(); this.closeEditor(); - }, - closeEditor: function() { - $('#handout_error').removeClass('is-shown'); - $('.save-button').removeClass('is-disabled').attr('aria-disabled', false); - this.$form.hide(); - ModalUtils.hideModalCover(); - this.$form.find('.CodeMirror').remove(); - this.$codeMirror = null; + analytics.track('Saved Course Handouts', { // eslint-disable-line no-undef + course: course_location_analytics // eslint-disable-line no-undef + }); + } else { + $('#handout_error').addClass('is-shown'); + $('.save-button').addClass('is-disabled').attr('aria-disabled', true); + event.preventDefault(); } - }); + }, + + onCancel: function() { + $('#handout_error').removeClass('is-shown'); + $('.save-button').removeClass('is-disabled').attr('aria-disabled', false); + this.$form.hide(); + this.closeEditor(); + }, + + closeEditor: function() { + $('#handout_error').removeClass('is-shown'); + $('.save-button').removeClass('is-disabled').attr('aria-disabled', false); + this.$form.hide(); + ModalUtils.hideModalCover(); + this.$form.find('.CodeMirror').remove(); + this.$codeMirror = null; + } + }); - return CourseInfoHandoutsView; - }); // end define() + return CourseInfoHandoutsView; +}); // end define() diff --git a/cms/static/js/views/edit_chapter.js b/cms/static/js/views/edit_chapter.js index 3845b5857a7bbb5b18fe760262a7e40bc3a3a369..59ab0d1d28dc8fd13753de967624a41ed9cfbde4 100644 --- a/cms/static/js/views/edit_chapter.js +++ b/cms/static/js/views/edit_chapter.js @@ -59,8 +59,8 @@ define(['underscore', 'jquery', 'gettext', 'edx-ui-toolkit/js/utils/html-utils', asset_path: this.$('input.chapter-asset-path').val() }); var msg = new FileUploadModel({ - title: _.template(gettext('Upload a new PDF to “<%= name %>â€'))( - {name: course.escape('name')}), + title: _.template(gettext('Upload a new PDF to “<%- name %>â€'))( + {name: course.get('name')}), message: gettext('Please select a PDF file to upload.'), mimeTypes: ['application/pdf'] }); diff --git a/cms/static/js/views/modals/course_outline_modals.js b/cms/static/js/views/modals/course_outline_modals.js index 1d95a8e294ee7d2a952da44194a530d5136f8faf..7e5996b7c74a0bb29a35c785bffc072abd02824c 100644 --- a/cms/static/js/views/modals/course_outline_modals.js +++ b/cms/static/js/views/modals/course_outline_modals.js @@ -307,11 +307,26 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview', }, render: function() { + var xblockInfo = this.model; + var isTimeLimited = xblockInfo.get('is_time_limited'); + var isProctoredExam = xblockInfo.get('is_proctored_exam'); + var isPracticeExam = xblockInfo.get('is_practice_exam'); + var isOnboardingExam = xblockInfo.get('is_onboarding_exam'); var html = this.template($.extend({}, { - xblockInfo: this.model, + xblockInfo: xblockInfo, xblockType: this.options.xblockType, - enable_proctored_exam: this.options.enable_proctored_exams, - enable_timed_exam: this.options.enable_timed_exams + enableProctoredExams: this.options.enable_proctored_exams, + enableTimedExams: this.options.enable_timed_exams, + isSpecialExam: isTimeLimited, + isProctoredExam: isProctoredExam, + isPracticeExam: isPracticeExam, + isOnboardingExam: isOnboardingExam, + isTimedExam: isTimeLimited && !( + isProctoredExam || isPracticeExam || isOnboardingExam + ), + specialExamLockedIn: ( + xblockInfo.get('released_to_students') && xblockInfo.get('was_ever_special_exam') + ) }, this.getContext())); HtmlUtils.setHtml(this.$el, HtmlUtils.HTML(html)); diff --git a/cms/static/js/views/previous_video_upload.js b/cms/static/js/views/previous_video_upload.js index 1f7a46b38dd4b19c1b728ebfe000eb929f9f402a..d0a6862a32a9d6cc5e06c2953886bb4dd14533f6 100644 --- a/cms/static/js/views/previous_video_upload.js +++ b/cms/static/js/views/previous_video_upload.js @@ -1,10 +1,10 @@ define( ['underscore', 'gettext', 'js/utils/date_utils', 'js/views/baseview', 'common/js/components/views/feedback_prompt', 'common/js/components/views/feedback_notification', 'js/views/video_thumbnail', 'js/views/video_transcripts', - 'common/js/components/utils/view_utils', 'edx-ui-toolkit/js/utils/html-utils', + 'js/views/video_status', 'common/js/components/utils/view_utils', 'edx-ui-toolkit/js/utils/html-utils', 'text!templates/previous-video-upload.underscore'], function(_, gettext, DateUtils, BaseView, PromptView, NotificationView, VideoThumbnailView, VideoTranscriptsView, - ViewUtils, HtmlUtils, previousVideoUploadTemplate) { + VideoStatusView, ViewUtils, HtmlUtils, previousVideoUploadTemplate) { 'use strict'; var PreviousVideoUploadView = BaseView.extend({ @@ -34,10 +34,17 @@ define( edxVideoID: this.model.get('edx_video_id'), clientVideoID: this.model.get('client_video_id'), transcriptionStatus: this.model.get('transcription_status'), + errorDescription: this.model.get('error_description'), transcriptAvailableLanguages: options.transcriptAvailableLanguages, videoSupportedFileFormats: options.videoSupportedFileFormats, videoTranscriptSettings: options.videoTranscriptSettings }); + + this.VideoStatusView = new VideoStatusView({ + status: this.model.get('status'), + showError: !this.model.get('transcription_status'), + errorDescription: this.model.get('error_description') + }); }, render: function() { @@ -57,6 +64,7 @@ define( this.videoThumbnailView.setElement(this.$('.thumbnail-col')).render(); } this.videoTranscriptsView.setElement(this.$('.transcripts-col')).render(); + this.VideoStatusView.setElement(this.$('.status-col')).render(); return this; }, diff --git a/cms/static/js/views/utils/create_course_utils.js b/cms/static/js/views/utils/create_course_utils.js index 14f0327cfdfd8e30f9249fc96c1ade15c1977ad4..77799da1dfd6645a7bb89b6ea291b0953c11e509 100644 --- a/cms/static/js/views/utils/create_course_utils.js +++ b/cms/static/js/views/utils/create_course_utils.js @@ -5,7 +5,8 @@ define(['jquery', 'gettext', 'common/js/components/utils/view_utils', 'js/views/ function($, gettext, ViewUtils, CreateUtilsFactory) { 'use strict'; return function(selectors, classes) { - var keyLengthViolationMessage = gettext('The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.'); + var keyLengthViolationMessage = gettext('The combined length of the organization, course number, ' + + 'and course run fields cannot be more than <%- limit %> characters.'); var keyFieldSelectors = [selectors.org, selectors.number, selectors.run]; var nonEmptyCheckFieldSelectors = [selectors.name, selectors.org, selectors.number, selectors.run]; diff --git a/cms/static/js/views/utils/create_library_utils.js b/cms/static/js/views/utils/create_library_utils.js index f024580b429dce1b18ebf77f3d9517fcd0ce4044..11f17dbc0315e25667bc0859f729d88cac8f8693 100644 --- a/cms/static/js/views/utils/create_library_utils.js +++ b/cms/static/js/views/utils/create_library_utils.js @@ -5,7 +5,8 @@ define(['jquery', 'gettext', 'common/js/components/utils/view_utils', 'js/views/ function($, gettext, ViewUtils, CreateUtilsFactory) { 'use strict'; return function(selectors, classes) { - var keyLengthViolationMessage = gettext('The combined length of the organization and library code fields cannot be more than <%=limit%> characters.'); + var keyLengthViolationMessage = gettext('The combined length of the organization and library code fields' + + ' cannot be more than <%- limit %> characters.'); var keyFieldSelectors = [selectors.org, selectors.number]; var nonEmptyCheckFieldSelectors = [selectors.name, selectors.org, selectors.number]; diff --git a/cms/static/js/views/video_status.js b/cms/static/js/views/video_status.js new file mode 100644 index 0000000000000000000000000000000000000000..03713826b393ce3b821fccdcc9148e083ebcef89 --- /dev/null +++ b/cms/static/js/views/video_status.js @@ -0,0 +1,37 @@ +define( + [ + 'js/views/baseview', 'edx-ui-toolkit/js/utils/html-utils', 'text!templates/video-status.underscore' + ], + function(BaseView, HtmlUtils, videoStatusTemplate) { + 'use strict'; + + var VideoStatusView = BaseView.extend({ + tagName: 'div', + + initialize: function(options) { + this.status = options.status; + this.showError = options.showError; + this.errorDescription = options.errorDescription; + this.template = HtmlUtils.template(videoStatusTemplate); + }, + + /* + Renders status view. + */ + render: function() { + HtmlUtils.setHtml( + this.$el, + this.template({ + status: this.status, + show_error: this.showError, + error_description: this.errorDescription + }) + ); + + return this; + } + }); + + return VideoStatusView; + } +); diff --git a/cms/static/js/views/video_transcripts.js b/cms/static/js/views/video_transcripts.js index 8af5ae17bffc4d3b3c09f7d1fd72caaece125bff..a7109e613b7ee69a5aa9294ed0a2309ad6cd3e51 100644 --- a/cms/static/js/views/video_transcripts.js +++ b/cms/static/js/views/video_transcripts.js @@ -23,6 +23,7 @@ define( this.edxVideoID = options.edxVideoID; this.clientVideoID = options.clientVideoID; this.transcriptionStatus = options.transcriptionStatus; + this.errorDescription = options.errorDescription; this.transcriptAvailableLanguages = options.transcriptAvailableLanguages; this.videoSupportedFileFormats = options.videoSupportedFileFormats; this.videoTranscriptSettings = options.videoTranscriptSettings; @@ -338,6 +339,7 @@ define( this.$el, this.template({ transcripts: this.transcripts, + error_description: this.errorDescription, transcription_status: this.transcriptionStatus, transcriptAvailableLanguages: this.transcriptAvailableLanguages, edxVideoID: this.edxVideoID, diff --git a/cms/static/sass/_base-v2.scss b/cms/static/sass/_base-v2.scss index bc2648872c0046cbe12a3e60fbad7c28c0847a5c..640d799fe524707239258315e056a2de75eebadc 100644 --- a/cms/static/sass/_base-v2.scss +++ b/cms/static/sass/_base-v2.scss @@ -10,6 +10,6 @@ body { color: $gray-d3; } -footer.primary{ +footer.primary { font-size: font-size(x-small); } diff --git a/cms/static/sass/_base.scss b/cms/static/sass/_base.scss index 07b33a715aa911d425c24586bd515b74dd7ae64f..464f6869068880039bffa8e0b4e8e8c49329c2b2 100644 --- a/cms/static/sass/_base.scss +++ b/cms/static/sass/_base.scss @@ -70,8 +70,8 @@ h1 { .wrapper { @include clearfix(); - @include box-sizing(border-box); + box-sizing: border-box; width: 100%; } @@ -257,7 +257,8 @@ dl { padding: 0 $baseline; position: relative; - .mast, .metadata { + .mast, + .metadata { @include clearfix(); position: relative; @@ -383,11 +384,6 @@ dl { font-weight: 600; } } - - // page metadata/action bar - .metadata { - - } } // +Layout - Basic Page Content @@ -434,8 +430,9 @@ dl { } } -.content-primary, .content-supplementary { - @include box-sizing(border-box); +.content-primary, +.content-supplementary { + box-sizing: border-box; } // +Layout - Primary Content @@ -630,7 +627,8 @@ hr.divide { // ==================== // UI - semantically hide text -.sr, .sr-only { +.sr, +.sr-only { @extend %cont-text-sr; } @@ -676,8 +674,8 @@ hr.divider { // lean/simple modal window .content-modal { @include border-bottom-radius(2px); - @include box-sizing(border-box); + box-sizing: border-box; position: relative; display: none; width: 700px; @@ -716,8 +714,7 @@ hr.divider { } img { - @include box-sizing(border-box); - + box-sizing: border-box; width: 100%; overflow-y: scroll; padding: ($baseline/10); diff --git a/cms/static/sass/_reset.scss b/cms/static/sass/_reset.scss index 5f4aeed37ae912a144813f6c614921ffc8e98670..daaf34d842d3b3d8d6eb340ea17d5e3ca37462fa 100644 --- a/cms/static/sass/_reset.scss +++ b/cms/static/sass/_reset.scss @@ -3,7 +3,7 @@ // not ready for this yet, but this should be done as things get cleaner // * { -// @include box-sizing(border-box); +// box-sizing: border-box; // } // better text rendering/kerning through SVG @@ -92,8 +92,8 @@ video { padding: 0; border: 0; outline: 0; - font-size: 100%; font: inherit; + font-size: 100%; vertical-align: baseline; } diff --git a/cms/static/sass/contexts/_ie.scss b/cms/static/sass/contexts/_ie.scss index c7945043bf30cb7de19dedab406666648e5fd108..825507631e720320df8cdb4850cb907192de9401 100644 --- a/cms/static/sass/contexts/_ie.scss +++ b/cms/static/sass/contexts/_ie.scss @@ -15,17 +15,3 @@ } } } - -// ==================== - -// CASE: less than or equal to IE8 -.lte8 { - -} - -// ==================== - -// CASE: less than or equal to IE7 -.lte7 { - -} diff --git a/cms/static/sass/elements-v2/_controls.scss b/cms/static/sass/elements-v2/_controls.scss index 464db54981df36ce8fa968469d5b6dcf859d1513..a8ea745432001f1ebc7dad6d68e40a73c03bb903 100644 --- a/cms/static/sass/elements-v2/_controls.scss +++ b/cms/static/sass/elements-v2/_controls.scss @@ -4,19 +4,22 @@ @extend %ui-btn; @extend %ui-btn-pill; - padding:($baseline/4) ($baseline/2); + padding: ($baseline/4) ($baseline/2); border-width: 1px; border-style: solid; border-color: transparent; text-align: center; - &:hover, &:active { + &:hover, + &:active { @extend %ui-fake-link; border-color: $gray-l3; } - &.current, &.active, &.is-selected { + &.current, + &.active, + &.is-selected { box-shadow: inset 0 1px 2px 1px $shadow-l1; border-color: $gray-l3; } @@ -31,16 +34,19 @@ border-color: $white; color: $gray-d1; - &:hover, &:active { + &:hover, + &:active { background: $white; color: $blue-s1; } - &.current, &.active { + &.current, + &.active { background: $white; color: $gray-d4; - &:hover, &:active { + &:hover, + &:active { color: $blue-s1; } } diff --git a/cms/static/sass/elements-v2/_header.scss b/cms/static/sass/elements-v2/_header.scss index 0643599505d7da92ed6c728304291191dc3bd77d..2798102bdcb8091b23aedcdac19680d44d6661d5 100644 --- a/cms/static/sass/elements-v2/_header.scss +++ b/cms/static/sass/elements-v2/_header.scss @@ -23,7 +23,8 @@ // ==================== // basic layout - .wrapper-l, .wrapper-r { + .wrapper-l, + .wrapper-r { background: $white; } @@ -36,7 +37,11 @@ @include text-align(right); } - .branding, .info-course, .nav-course, .nav-account, .nav-pitch { + .branding, + .info-course, + .nav-course, + .nav-account, + .nav-pitch { box-sizing: border-box; display: inline-block; vertical-align: middle; @@ -67,7 +72,7 @@ margin-right: 0; } - .title{ + .title { @extend %ui-btn-dd-nav-primary; @include transition(all $tmg-f2 ease-in-out 0s); @@ -132,7 +137,6 @@ .nav-account-user { .title { - max-width: ($baseline*10.5); display: inline-block; max-width: 84%; overflow: hidden; diff --git a/cms/static/sass/elements/_creative-commons.scss b/cms/static/sass/elements/_creative-commons.scss index b575e3ac011fb47918ea918ef24d95cbfe867cf3..2fde86fb9b4ddfb121b782897398ec871ea54a3f 100644 --- a/cms/static/sass/elements/_creative-commons.scss +++ b/cms/static/sass/elements/_creative-commons.scss @@ -1,7 +1,8 @@ @font-face { font-family: 'CreativeCommons'; src: url('#{$static-path}/fonts/CreativeCommons/cc.eot'); - src: url('#{$static-path}/fonts/CreativeCommons/cc.eot#iefix') format('embedded-opentype'), + src: + url('#{$static-path}/fonts/CreativeCommons/cc.eot#iefix') format('embedded-opentype'), url('#{$static-path}/fonts/CreativeCommons/cc.woff') format('woff'), url('#{$static-path}/fonts/CreativeCommons/cc.ttf') format('truetype'), url('#{$static-path}/fonts/CreativeCommons/cc.svg#CreativeCommons') format('svg'); diff --git a/cms/static/sass/elements/_forms.scss b/cms/static/sass/elements/_forms.scss index b11a5c1af8d631baf26f54c048824a16506c2ce7..4bcf30b30a9882560e26bd8e1347684c67205415 100644 --- a/cms/static/sass/elements/_forms.scss +++ b/cms/static/sass/elements/_forms.scss @@ -33,7 +33,8 @@ input[type="text"], input[type="email"], input[type="password"], textarea.text { - @include box-sizing(border-box); + box-sizing: border-box; + @include linear-gradient($gray-l5, $white); @extend %t-copy-sub2; @@ -143,7 +144,7 @@ form { } .note { - @include box-sizing(border-box); + box-sizing: border-box; // note with actions &.has-actions { @@ -448,9 +449,7 @@ form { // ==================== input.search { padding: 6px 15px 8px 30px; - - @include box-sizing(border-box); - + box-sizing: border-box; border: 1px solid $darkGrey; border-radius: 20px; background: url('#{$static-path}/images/search-icon.png') no-repeat 8px 7px #edf1f5; @@ -485,9 +484,7 @@ code { width: 100%; min-height: 80px; padding: 10px; - - @include box-sizing(border-box); - + box-sizing: border-box; border: 1px solid $mediumGrey; @include linear-gradient(top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.3)); diff --git a/cms/static/sass/elements/_header.scss b/cms/static/sass/elements/_header.scss index 5f905413e60f5c59c3cd8643f7829e247e58bc68..c17338acade3b1676b4e0c03fe00c2a72000b887 100644 --- a/cms/static/sass/elements/_header.scss +++ b/cms/static/sass/elements/_header.scss @@ -12,7 +12,8 @@ background: $white; header.primary { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); max-width: $fg-max-width; @@ -48,8 +49,7 @@ .nav-course, .nav-account, .nav-pitch { - @include box-sizing(border-box); - + box-sizing: border-box; display: inline-block; vertical-align: middle; } diff --git a/cms/static/sass/elements/_icons.scss b/cms/static/sass/elements/_icons.scss index e7e560965156598d1b827e3d26dd7976e5ba9303..14c5ac1b88a945220b3ab774f1eb5f40fd8f4496 100644 --- a/cms/static/sass/elements/_icons.scss +++ b/cms/static/sass/elements/_icons.scss @@ -37,7 +37,7 @@ // OPTION: add this class for a visual hanging display &.is-hanging { - @include box-sizing(border-box); + box-sizing: border-box; @extend %ui-depth2; diff --git a/cms/static/sass/elements/_layout.scss b/cms/static/sass/elements/_layout.scss index 61396b4ab3a70e9559bc7bbda7ae3c609c0f63a9..97ec2401e9a4af090639cd7dd37ef15d3f5170d7 100644 --- a/cms/static/sass/elements/_layout.scss +++ b/cms/static/sass/elements/_layout.scss @@ -209,7 +209,7 @@ .content-primary, .content-supplementary { - @include box-sizing(border-box); + box-sizing: border-box; } // 3/4 - 1/4 two col layout diff --git a/cms/static/sass/elements/_modal-window.scss b/cms/static/sass/elements/_modal-window.scss index 25f655257421c1e01b078e6194648c580b8c68fa..6eeb1000435d18f0c7d8c9cac8163ae8b703764c 100644 --- a/cms/static/sass/elements/_modal-window.scss +++ b/cms/static/sass/elements/_modal-window.scss @@ -11,8 +11,7 @@ .modal-window { @extend %ui-depth3; - @include box-sizing(border-box); - + box-sizing: border-box; position: absolute; width: 50%; box-shadow: 0 0 7px $shadow-d1; @@ -219,6 +218,7 @@ color: $blue-d4; } } + .clipboard-button { position: absolute; right: 30px; diff --git a/cms/static/sass/elements/_modules.scss b/cms/static/sass/elements/_modules.scss index 401a16b08a2442ebccbabb6c90ec89c308736b0b..d3898968ea4f639e65085f881ae806a18edf147e 100644 --- a/cms/static/sass/elements/_modules.scss +++ b/cms/static/sass/elements/_modules.scss @@ -150,8 +150,7 @@ @extend %btn-primary-green; .name { - @include box-sizing(border-box); - + box-sizing: border-box; display: block; color: $white; } diff --git a/cms/static/sass/elements/_navigation.scss b/cms/static/sass/elements/_navigation.scss index a275c549e2e491e6eef420b615ff83381b31b20f..84cc7d9e03a278fefc13ded8e0148a68ddc8db2c 100644 --- a/cms/static/sass/elements/_navigation.scss +++ b/cms/static/sass/elements/_navigation.scss @@ -100,9 +100,7 @@ nav { .nav-sub { border-radius: 2px; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 1px $shadow-l1; position: relative; width: 100%; diff --git a/cms/static/sass/elements/_sock.scss b/cms/static/sass/elements/_sock.scss index acd7e12d67f477b9283162e6d8b60123a746f49b..b35356c3684ad2f244c424191d834f69b3412aa7 100644 --- a/cms/static/sass/elements/_sock.scss +++ b/cms/static/sass/elements/_sock.scss @@ -74,7 +74,7 @@ // shared elements .support, .feedback { - @include box-sizing(border-box); + box-sizing: border-box; .title { @extend %t-title6; diff --git a/cms/static/sass/elements/_system-feedback.scss b/cms/static/sass/elements/_system-feedback.scss index cb161eb75fc99ad24d2a8954aa74e63083b613a4..5585c20977a061a497e3188d9caf63f8794520a1 100644 --- a/cms/static/sass/elements/_system-feedback.scss +++ b/cms/static/sass/elements/_system-feedback.scss @@ -10,7 +10,8 @@ .message-status { @include border-top-radius(2px); - @include box-sizing(border-box); + + box-sizing: border-box; @extend %t-strong; @@ -52,7 +53,7 @@ .wrapper-notification, .wrapper-alert, .prompt { - @include box-sizing(border-box); + box-sizing: border-box; .copy { @extend %t-copy-sub1; @@ -415,7 +416,8 @@ padding: ($baseline/2) $baseline; .notification { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); width: 100%; @@ -448,7 +450,8 @@ padding: $baseline; .notification { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); width: 100%; @@ -472,7 +475,8 @@ } .notification { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); margin: 0 auto; @@ -602,8 +606,7 @@ .wrapper-alert { @extend %ui-depth2; - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 1px $white, inset 0 2px 2px $shadow-d1, inset 0 -4px 1px $blue; position: relative; overflow: hidden; @@ -663,7 +666,8 @@ // adopted alerts .alert { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); margin: 0 auto; @@ -921,8 +925,7 @@ body.uxdesign.alerts { .content-primary, .content-supplementary { - @include box-sizing(border-box); - + box-sizing: border-box; float: left; } diff --git a/cms/static/sass/elements/_system-help.scss b/cms/static/sass/elements/_system-help.scss index 5ff9a0f48a9a6886648149a21f8ae5421f283035..2f66913fc087af4759a141d4a9ddd97a8b3e0958 100644 --- a/cms/static/sass/elements/_system-help.scss +++ b/cms/static/sass/elements/_system-help.scss @@ -3,8 +3,7 @@ // view introductions - common greeting/starting points for the UI .content .introduction { - @include box-sizing(border-box); - + box-sizing: border-box; margin-bottom: $baseline; .title { diff --git a/cms/static/sass/elements/_uploaded-assets.scss b/cms/static/sass/elements/_uploaded-assets.scss index 0b1d4617e071ded3630dacf6b3e7c12a72bf462d..32dbc1aedd5ed53035a66c14a012c99962f7d171 100644 --- a/cms/static/sass/elements/_uploaded-assets.scss +++ b/cms/static/sass/elements/_uploaded-assets.scss @@ -87,7 +87,7 @@ @extend %t-strong; } - .status-col { + .video-status { text-transform: uppercase; } diff --git a/cms/static/sass/elements/_xblocks.scss b/cms/static/sass/elements/_xblocks.scss index 1f1ce3fc99b10c1eb7026770239cdd5225cd8867..d6e8aff5d66a86e2962063a4b698450355b1001c 100644 --- a/cms/static/sass/elements/_xblocks.scss +++ b/cms/static/sass/elements/_xblocks.scss @@ -34,8 +34,7 @@ // UI: xblock header primary for main title and xblock actions .xblock-header-primary { - @include box-sizing(border-box); - + box-sizing: border-box; border-bottom: 1px solid $gray-l4; border-radius: ($baseline/5) ($baseline/5) 0 0; min-height: ($baseline*2.5); @@ -541,8 +540,7 @@ @extend %t-action3; @extend %t-strong; - @include box-sizing(border-box); - + box-sizing: border-box; display: inline-block; padding: ($baseline/2); width: 49%; @@ -554,8 +552,7 @@ @extend %t-action4; @extend %t-strong; - @include box-sizing(border-box); - + box-sizing: border-box; display: inline-block; padding: ($baseline/2); width: 49%; @@ -749,7 +746,7 @@ // TYPE: enumerated lists of metadata sets .metadata-list-enum { * { - @include box-sizing(border-box); + box-sizing: border-box; } // label @@ -819,7 +816,7 @@ // TYPE: Dict .metadata-dict { * { - @include box-sizing(border-box); + box-sizing: border-box; } // label diff --git a/cms/static/sass/elements/_xmodules.scss b/cms/static/sass/elements/_xmodules.scss index 067a77266f843c7c2e1c5da9f3972d7ddc06463c..b3681d771e936487d2c65a30cdc524680310ea9d 100644 --- a/cms/static/sass/elements/_xmodules.scss +++ b/cms/static/sass/elements/_xmodules.scss @@ -188,7 +188,7 @@ // TYPE: enumerated video lists of metadata sets .metadata-videolist-enum { * { - @include box-sizing(border-box); + box-sizing: border-box; } } @@ -233,7 +233,7 @@ .list-input.settings-list { .metadata-video-translations { * { - @include box-sizing(border-box); + box-sizing: border-box; } // label diff --git a/cms/static/sass/views/_account.scss b/cms/static/sass/views/_account.scss index 70d07c933c2a49586ccec95cf24eafc6db760477..4ff3ff0d3ca1fb25b04fb032e5590d3f94e7b9fe 100644 --- a/cms/static/sass/views/_account.scss +++ b/cms/static/sass/views/_account.scss @@ -54,16 +54,16 @@ } } - .content-primary, .content-supplementary { - @include box-sizing(border-box); + .content-primary, + .content-supplementary { + box-sizing: border-box; } .content-primary { @extend .ui-col-wide; form { - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 2px $shadow-l1; border-radius: 2px; width: 100%; @@ -109,7 +109,9 @@ } } - label, input, textarea { + label, + input, + textarea { display: block; } @@ -125,7 +127,8 @@ } } - input, textarea { + input, + textarea { @extend %t-copy-base; height: 100%; @@ -218,7 +221,8 @@ margin-right: 0; } - input, textarea { + input, + textarea { width: 100%; } } @@ -251,7 +255,6 @@ margin: 0 0 ($baseline/4) 0; color: $gray-d2; } - } } diff --git a/cms/static/sass/views/_assets.scss b/cms/static/sass/views/_assets.scss index ab4b10dc7835ed60ad17558228685bbc28461bb9..144e5dffd82ea3e21c1703f2711a795fa5a483a3 100644 --- a/cms/static/sass/views/_assets.scss +++ b/cms/static/sass/views/_assets.scss @@ -2,8 +2,9 @@ // ==================== .view-uploads { - .content-primary, .content-supplementary { - @include box-sizing(border-box); + .content-primary, + .content-supplementary { + box-sizing: border-box; } .content-primary { @@ -210,7 +211,8 @@ text-align: left; color: $gray; - .column-sort-link, .column-selected-link { + .column-sort-link, + .column-selected-link { cursor: pointer; color: $blue; } @@ -266,7 +268,7 @@ .nav-item { &.reset-filter { - display:none; + display: none; } a { diff --git a/cms/static/sass/views/_certificates.scss b/cms/static/sass/views/_certificates.scss index 124840a7af157923f9895b8dd4e4eb757316d6a5..7c7eb3fa5f3e3bffa0bd5345d6b42a926f11741a 100644 --- a/cms/static/sass/views/_certificates.scss +++ b/cms/static/sass/views/_certificates.scss @@ -13,8 +13,7 @@ .view-certificates { .content-primary, .content-supplementary { - @include box-sizing(border-box); - + box-sizing: border-box; float: left; } @@ -115,8 +114,7 @@ margin: ($baseline/4) 0 ($baseline/2) $baseline; li { - @include box-sizing(border-box); - + box-sizing: border-box; display: table-cell; margin-right: 1%; padding: ($baseline/4) 0; @@ -215,8 +213,7 @@ } .collection-edit { - @include box-sizing(border-box); - + box-sizing: border-box; border-radius: 2px; width: 100%; background: $white; diff --git a/cms/static/sass/views/_container.scss b/cms/static/sass/views/_container.scss index d433eff5a18b18f8c4a103d474d8b22863478682..c9d593defcfbba92d3d3f3de93e4486414ab64f2 100644 --- a/cms/static/sass/views/_container.scss +++ b/cms/static/sass/views/_container.scss @@ -267,13 +267,16 @@ } // location widget - .unit-location, .library-location { + .unit-location, + .library-location { @extend %bar-module; border-top: none; - .wrapper-unit-id, .wrapper-library-id { - .unit-id-value, .library-id-value { + .wrapper-unit-id, + .wrapper-library-id { + .unit-id-value, + .library-id-value { @extend %status-value-base; display: inline-block; @@ -315,7 +318,8 @@ } // typographical overrides (based off of outline-simple) - .section-header, .subsection-header { + .section-header, + .subsection-header { line-height: 0; margin-bottom: ($baseline/2); } @@ -377,7 +381,8 @@ } .bc-container:not(.last) { - button, .parent-displayname { + button, + .parent-displayname { text-decoration: underline; color: $ui-link-color; } @@ -412,7 +417,8 @@ @include float(left); } - .button-forward, .component { + .button-forward, + .component { border: none; } diff --git a/cms/static/sass/views/_course-create.scss b/cms/static/sass/views/_course-create.scss index 48fed97374f70b45bffeca340a9ac686afb0974d..96301540c705e1d5c50fec5b29921dc7f2d5804c 100644 --- a/cms/static/sass/views/_course-create.scss +++ b/cms/static/sass/views/_course-create.scss @@ -7,8 +7,7 @@ // -------------------- .content-primary, .content-supplementary { - @include box-sizing(border-box); - + box-sizing: border-box; float: left; } diff --git a/cms/static/sass/views/_dashboard.scss b/cms/static/sass/views/_dashboard.scss index 1239c915593df7082e384b44890fad68a1523d1b..27e62c0c6e6d6edeb427efe649f82320bd69182a 100644 --- a/cms/static/sass/views/_dashboard.scss +++ b/cms/static/sass/views/_dashboard.scss @@ -17,7 +17,7 @@ // basic layout .content-primary, .content-supplementary { - @include box-sizing(border-box); + box-sizing: border-box; } .content-primary { @@ -365,8 +365,7 @@ // CASE: has status &.has-status { .course-status { - @include box-sizing(border-box); - + box-sizing: border-box; display: inline-block; vertical-align: middle; width: flex-grid(3, 9); @@ -444,8 +443,7 @@ // UI: individual course listings .course-item { - @include box-sizing(border-box); - + box-sizing: border-box; width: flex-grid(9, 9); position: relative; border-bottom: 1px solid $gray-l2; @@ -458,8 +456,7 @@ .course-link, .course-actions { - @include box-sizing(border-box); - + box-sizing: border-box; display: inline-block; vertical-align: middle; } @@ -535,8 +532,7 @@ // view live button .view-button { - @include box-sizing(border-box); - + box-sizing: border-box; padding: ($baseline/2); } diff --git a/cms/static/sass/views/_export-git.scss b/cms/static/sass/views/_export-git.scss index f1de2bb64f5b6d4ed23baa39777d1e94bf0e2896..b091a7b8d9cecaf432c0e6cacf6e65f5428a901f 100644 --- a/cms/static/sass/views/_export-git.scss +++ b/cms/static/sass/views/_export-git.scss @@ -4,9 +4,9 @@ .view-export-git { // UI: basic layout - .content-primary, .content-supplementary { - @include box-sizing(border-box); - + .content-primary, + .content-supplementary { + box-sizing: border-box; float: left; } @@ -60,7 +60,7 @@ // UI: export controls .export-git-controls { - @include box-sizing(border-box); + box-sizing: border-box; @extend %ui-window; diff --git a/cms/static/sass/views/_export.scss b/cms/static/sass/views/_export.scss index 60627568dba694689aae90110ea648e323208f0d..fb14a5f63f4b4c5a7d51d75bb7e8dcc6af5e99f9 100644 --- a/cms/static/sass/views/_export.scss +++ b/cms/static/sass/views/_export.scss @@ -4,8 +4,9 @@ .view-export { // UI: basic layout - .content-primary, .content-supplementary { - @include box-sizing(border-box); + .content-primary, + .content-supplementary { + box-sizing: border-box; } .content-primary { @@ -26,7 +27,7 @@ // UI: export controls .export-controls { - @include box-sizing(border-box); + box-sizing: border-box; @extend %ui-window; @@ -68,7 +69,8 @@ margin: ($baseline*2) 0; - .export-includes, .export-excludes { + .export-includes, + .export-excludes { width: flex-grid(4, 9); .item-detail { @@ -210,7 +212,7 @@ // STATE: started &.is-started { - .fa-warning { + .fa-warning { visibility: hidden; opacity: 0; } @@ -264,7 +266,8 @@ color: $red; } - .status-detail .title, .status-detail .copy { + .status-detail .title, + .status-detail .copy { color: $red; } } diff --git a/cms/static/sass/views/_group-configuration.scss b/cms/static/sass/views/_group-configuration.scss index 9fdc308bb6d59fed40504dedfd910761b7e15a1e..95d332de78ea0259e7888a849d004daeac33a932 100644 --- a/cms/static/sass/views/_group-configuration.scss +++ b/cms/static/sass/views/_group-configuration.scss @@ -1,8 +1,10 @@ // studio - views - group-configurations // ==================== .view-group-configurations { - .content-primary, .content-supplementary { - @include box-sizing(border-box); + .content-primary, + .content-supplementary { + box-sizing: border-box; + @include float(left); } @@ -128,7 +130,8 @@ width: 70%; li { - @include box-sizing(border-box); + box-sizing: border-box; + @include margin-right(1%); display: table-cell; @@ -152,7 +155,8 @@ width: 70%; li { - @include box-sizing(border-box); + box-sizing: border-box; + @include margin-right(1%); display: table-cell; @@ -287,8 +291,7 @@ } .collection-edit { - @include box-sizing(border-box); - + box-sizing: border-box; border-radius: 2px; width: 100%; background: $white; @@ -341,7 +344,9 @@ } } - label, input, textarea { + label, + input, + textarea { display: block; } @@ -361,7 +366,8 @@ } //this section is borrowed from _account.scss - we should clean up and unify later - input, textarea { + input, + textarea { @extend %t-copy-base; height: 100%; @@ -536,7 +542,7 @@ // specific group-type styles .content-groups { - .collection-header{ + .collection-header { .title { margin-bottom: 0; } diff --git a/cms/static/sass/views/_import.scss b/cms/static/sass/views/_import.scss index 60d785713284c7fb6d92c52ce7846d1e4ab89ab5..a861afdcfa95d175e390b9188c2557d888b5e3c8 100644 --- a/cms/static/sass/views/_import.scss +++ b/cms/static/sass/views/_import.scss @@ -2,8 +2,9 @@ // ==================== .view-import { - .content-primary, .content-supplementary { - @include box-sizing(border-box); + .content-primary, + .content-supplementary { + box-sizing: border-box; } .content-primary { @@ -25,7 +26,7 @@ // UI: import form .import-form { - @include box-sizing(border-box); + box-sizing: border-box; @extend %ui-window; @@ -233,7 +234,7 @@ // STATE: started &.is-started { - .fa-warning { + .fa-warning { visibility: hidden; opacity: 0; } @@ -287,7 +288,8 @@ color: $red; } - .status-detail .title, .status-detail .copy { + .status-detail .title, + .status-detail .copy { color: $red; } } diff --git a/cms/static/sass/views/_index.scss b/cms/static/sass/views/_index.scss index 1f209bf3936c88bcb6a06b88336756d8c1419d9c..7f7525aca4274f0252e2b020408a9fd21b63a6c4 100644 --- a/cms/static/sass/views/_index.scss +++ b/cms/static/sass/views/_index.scss @@ -7,9 +7,10 @@ margin-bottom: 0; } - .wrapper-content-header, .wrapper-content-features, .wrapper-content-cta { - @include box-sizing(border-box); - + .wrapper-content-header, + .wrapper-content-features, + .wrapper-content-cta { + box-sizing: border-box; margin: 0; padding: 0 $baseline; position: relative; @@ -33,21 +34,14 @@ margin-bottom: 0; } - h1, h2, h3, h4, h5, h6 { + h1, + h2, + h3, + h4, + h5, + h6 { color: $gray-d3; } - - h2 { - - } - - h3 { - - } - - h4 { - - } } // welcome content @@ -74,7 +68,8 @@ color: $white; } - .wrapper-text-welcome, .logo { + .wrapper-text-welcome, + .logo { display: inline-block; } @@ -98,7 +93,8 @@ border: 4px solid $black; } - .arrow_box::after, .arrow_box::before { + .arrow_box::after, + .arrow_box::before { top: 100%; border: solid transparent; content: " "; @@ -133,10 +129,6 @@ } .content-features { - .list-features { - - } - // indiv features .feature { @include clearfix(); @@ -146,15 +138,13 @@ padding: 0 0 ($baseline*2) 0; .img { - @include box-sizing(border-box); - + box-sizing: border-box; float: left; width: flex-grid(3, 12); margin-right: flex-gutter(); a { - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px ($baseline/10) $shadow-l1; position: relative; top: 0; @@ -235,7 +225,8 @@ margin: ($baseline*1.5) 0 0 0; .proofpoint { - @include box-sizing(border-box); + box-sizing: border-box; + @include transition(all $tmg-f2 ease-in-out 0s); border-radius: ($baseline/4); diff --git a/cms/static/sass/views/_maintenance.scss b/cms/static/sass/views/_maintenance.scss index ec1903edbf49b9fa0c89e9679696251e5c6767f4..58d1b7494751b0bfba400f112881356d36e0c750 100644 --- a/cms/static/sass/views/_maintenance.scss +++ b/cms/static/sass/views/_maintenance.scss @@ -46,7 +46,7 @@ overflow: auto; } - .result{ + .result { box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2); margin-top: 15px; padding: 15px 30px; diff --git a/cms/static/sass/views/_outline.scss b/cms/static/sass/views/_outline.scss index d11417f2d101b8743b5513a26cdcdc2b86414188..01534b54808e5d8b607f4d11a30f358ca38026e8 100644 --- a/cms/static/sass/views/_outline.scss +++ b/cms/static/sass/views/_outline.scss @@ -11,7 +11,8 @@ // CASE: is-editable // TODO: abstract out .is-editable { - .incontext-editor-value, .incontext-editor-action-wrapper { + .incontext-editor-value, + .incontext-editor-action-wrapper { vertical-align: top; } @@ -71,7 +72,7 @@ // -------------------- .content-primary, .content-supplementary { - @include box-sizing(border-box); + box-sizing: border-box; } .content-primary { @@ -226,9 +227,9 @@ margin-left: $baseline / 2; } - .status-release-label, - .status-highlights-enabled-label { - margin-right: ($baseline/4); + .status-release-label, + .status-highlights-enabled-label { + margin-right: ($baseline/4); } .status-highlights-enabled-value.button { @@ -251,12 +252,6 @@ // outline // -------------------- - - // UI: simple version of the outline - .outline-simple { - - } - // UI: complex version of the outline .outline-complex { .outline-content { @@ -270,10 +265,12 @@ &.is-collapsible { // only select the current item's toggle expansion controls - &:nth-child(1) .ui-toggle-expansion, &:nth-child(1) .item-title { + &:nth-child(1) .ui-toggle-expansion, + &:nth-child(1) .item-title { // STATE: hover/active - &:hover, &:active { + &:hover, + &:active { color: $blue; } } @@ -331,7 +328,8 @@ width: flex-grid(6, 9); - .icon, .wrapper-section-title { + .icon, + .wrapper-section-title { display: inline-block; vertical-align: top; } @@ -431,7 +429,8 @@ width: flex-grid(5, 9); - .icon, .wrapper-subsection-title { + .icon, + .wrapper-subsection-title { display: inline-block; vertical-align: top; } @@ -571,10 +570,6 @@ margin-bottom: $baseline; } - .add-subsection { - - } - .add-unit { margin-left: $outline-indent-width; } @@ -716,7 +711,9 @@ // TODO: refactor the _forms.scss partial to allow for this area to inherit from it - label, input, textarea { + label, + input, + textarea { display: block; } @@ -734,7 +731,8 @@ } - input, textarea { + input, + textarea { @extend %t-copy-base; @include transition(all $tmg-f2 ease-in-out 0s); @@ -765,7 +763,8 @@ // CASE: select input .field-select { - .label, .input { + .label, + .input { display: inline-block; vertical-align: middle; } @@ -816,7 +815,8 @@ text-transform: uppercase; } - .outline-unit .unit-title, .outline-unit .unit-status { + .outline-unit .unit-title, + .outline-unit .unit-status { display: inline-block; vertical-align: middle; } @@ -832,7 +832,6 @@ text-align: right; } - } // it is the only element there @@ -841,5 +840,4 @@ margin-bottom: 0; } } - } diff --git a/cms/static/sass/views/_settings.scss b/cms/static/sass/views/_settings.scss index 822b365b4cbcc8c7ada1184cd841f6897df2e65d..de7c156cd9e96e5e591c093ed3dcace70bf045d5 100644 --- a/cms/static/sass/views/_settings.scss +++ b/cms/static/sass/views/_settings.scss @@ -10,8 +10,9 @@ @include text-align(left); @include direction(); - .content-primary, .content-supplementary { - @include box-sizing(border-box); + .content-primary, + .content-supplementary { + box-sizing: border-box; } .content-primary { @@ -30,7 +31,8 @@ .message-status { @include border-top-radius(2px); - @include box-sizing(border-box); + + box-sizing: border-box; @extend %t-strong; @@ -71,11 +73,8 @@ // course details that should appear more like content than elements to change .is-not-editable { - label { - - } - - input, textarea { + input, + textarea { @extend %t-copy-lead1; @extend %t-strong; @@ -122,15 +121,6 @@ width: 100%; } - // basic layout/elements - .title-2 { - - } - - .title-3 { - - } - // in form -UI hints/tips/messages .header-help { margin: 0 0 $baseline 0; @@ -183,27 +173,30 @@ .list-input { @extend %cont-no-list; - .show-data{ - .heading{ + .show-data { + .heading { border: 1px solid #e0e0e0; padding: 5px 15px; margin-top: 5px; } - .div-grade-requirements{ + .div-grade-requirements { border: 1px solid #e0e0e0; border-top: none; padding: 10px 15px; - label{font-weight: 600;} - input#entrance-exam-minimum-score-pct{ + label { + font-weight: 600; + } + + input#entrance-exam-minimum-score-pct { height: 40px; font-size: 18px; } } } - #heading-entrance-exam{ + #heading-entrance-exam { font-weight: 600; } @@ -229,7 +222,9 @@ } } - label, input, textarea { + label, + input, + textarea { display: block; } @@ -246,7 +241,8 @@ } } - input, textarea { + input, + textarea { @extend %t-copy-base; @include placeholder($gray-l4); @@ -254,12 +250,6 @@ padding: ($baseline/2); - &.long { - } - - &.short { - } - &.error { border-color: $red; } @@ -279,7 +269,7 @@ .minimum-grade-percentage-sign { @include line-height(30); - padding-left: ($baseline/4);; + padding-left: ($baseline/4); } textarea.long { @@ -307,8 +297,7 @@ // enumerated/grouped lists &.enum { .field-group { - @include box-sizing(border-box); - + box-sizing: border-box; border-radius: 3px; background: $gray-l5; padding: $baseline; @@ -354,7 +343,8 @@ } .is-not-editable { - input, textarea { + input, + textarea { padding: 0; } } @@ -420,8 +410,7 @@ .link-courseURL { @extend %t-copy-lead1; - @include box-sizing(border-box); - + box-sizing: border-box; display: block; width: 100%; overflow: hidden; @@ -438,7 +427,7 @@ .list-actions { box-shadow: inset 0 1px 1px $shadow-l1; border-top: 1px solid $gray-l2; - padding: ($baseline/2); + padding: ($baseline/2); background: $gray-l5; .action-primary { @@ -480,7 +469,8 @@ } .is-not-editable { - input, textarea { + input, + textarea { padding: 10px; } } @@ -523,8 +513,7 @@ // specific fields - video #field-course-introduction-video { .input-existing { - @include box-sizing(border-box); - + box-sizing: border-box; border-radius: 3px; background: $gray-l5; padding: ($baseline/2); @@ -550,7 +539,9 @@ } // specific fields - course image - #field-course-image, #field-banner-image, #field-video-thumbnail-image { + #field-course-image, + #field-banner-image, + #field-video-thumbnail-image { .current-course-image { margin-bottom: ($baseline/2); padding: ($baseline/2) $baseline; @@ -625,7 +616,8 @@ } .new-grade-button { - @include box-sizing(border-box); + box-sizing: border-box; + @include linear-gradient(top, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0)); box-shadow: 0 1px 0 rgba(255, 255, 255, 0.3) inset; @@ -651,8 +643,7 @@ } .grade-slider { - @include box-sizing(border-box); - + box-sizing: border-box; width: flex-grid(8, 9); display: inline-block; vertical-align: middle; @@ -743,10 +734,6 @@ } } - &.is-dragging { - - } - .remove-button { @extend %t-action5; @@ -826,7 +813,6 @@ #field-course-minimum_grade_credit { width: flex-grid(4, 9); } - } &.assignment-types { @@ -1101,7 +1087,8 @@ } } - .key, .value { + .key, + .value { float: left; margin: 0 0 ($baseline/2) 0; } @@ -1142,8 +1129,7 @@ .CodeMirror { @extend %t-copy-base; - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 2px $shadow-l1 inset; @include linear-gradient($lightGrey, tint($lightGrey, 90%)); @@ -1219,7 +1205,7 @@ } .error-item-message { - width:100%; + width: 100%; border: none; resize: none; diff --git a/cms/static/sass/views/_static-pages.scss b/cms/static/sass/views/_static-pages.scss index 42afef651abf8be04d4cf272b3465388c14fd29b..4854736342fe7a66bc25c4c0b6d5aff9282672e9 100644 --- a/cms/static/sass/views/_static-pages.scss +++ b/cms/static/sass/views/_static-pages.scss @@ -6,8 +6,7 @@ // page structure .content-primary, .content-supplementary { - @include box-sizing(border-box); - + box-sizing: border-box; float: left; } @@ -233,8 +232,7 @@ // uses similar styling as assets.scss, unit.scss .wrapper-component-action-header { - @include box-sizing(border-box); - + box-sizing: border-box; position: absolute; width: 100%; padding: $baseline/4 $baseline/2; @@ -293,7 +291,8 @@ vertical-align: bottom; } - &.action-duplicate, &.action-move { + &.action-duplicate, + &.action-move { display: none; } } @@ -315,7 +314,7 @@ .course-nav-item-header { display: inline-block; - width:80%; + width: 80%; .title { @extend %t-title4; @@ -399,7 +398,8 @@ } .page-contents { - @include box-sizing(border-box); + box-sizing: border-box; + @include linear-gradient(top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.3)); @extend %t-copy-sub1; diff --git a/cms/static/sass/views/_textbooks.scss b/cms/static/sass/views/_textbooks.scss index 9836ccd8efaf60812ac9b7dbcc36440aa57fb4d7..47abc978a03e8002291ceba295fd5c5233c5bc0c 100644 --- a/cms/static/sass/views/_textbooks.scss +++ b/cms/static/sass/views/_textbooks.scss @@ -2,8 +2,9 @@ // ==================== .view-textbooks { - .content-primary, .content-supplementary { - @include box-sizing(border-box); + .content-primary, + .content-supplementary { + box-sizing: border-box; } .content-primary { @@ -113,9 +114,7 @@ @extend %ui-btn-non; } } - } - } &:hover .actions { @@ -123,8 +122,7 @@ } .edit-textbook { - @include box-sizing(border-box); - + box-sizing: border-box; border-radius: 2px; width: 100%; background: $white; @@ -177,8 +175,6 @@ padding: ($baseline/5) $baseline; text-transform: uppercase; } - - } .copy { @@ -187,12 +183,9 @@ margin: ($baseline) 0 ($baseline/2) 0; color: $gray; - strong { @extend %t-strong; } - - } .chapters-fields, @@ -217,7 +210,9 @@ } } - label, input, textarea { + label, + input, + textarea { display: block; } @@ -239,7 +234,8 @@ //this section is borrowed from _account.scss - we should clean up and unify later - input, textarea { + input, + textarea { @extend %t-copy-base; height: 100%; @@ -331,7 +327,8 @@ position: relative; - input, textarea { + input, + textarea { width: 100%; } @@ -343,7 +340,6 @@ @include right(0); } - } .action-close { diff --git a/cms/static/sass/views/_updates.scss b/cms/static/sass/views/_updates.scss index 6371f25d28613c17d9e632d0894ad988ed113295..96e3129c328ad477a7247a0a74ef58fffb855be2 100644 --- a/cms/static/sass/views/_updates.scss +++ b/cms/static/sass/views/_updates.scss @@ -112,7 +112,8 @@ padding: 20px; } - ol, ul { + ol, + ul { margin: 1em 0; padding: 0 0 0 1em; color: $body-color; diff --git a/cms/static/sass/views/_users.scss b/cms/static/sass/views/_users.scss index 98c93efa2a1a18650e3f908895af66d33a6ecd9b..0f3f587ce76d7c1904d3e25d9abd45df59ba0f10 100644 --- a/cms/static/sass/views/_users.scss +++ b/cms/static/sass/views/_users.scss @@ -4,8 +4,9 @@ .view-team { // LAYOUT: page - .content-primary, .content-supplementary { - @include box-sizing(border-box); + .content-primary, + .content-supplementary { + box-sizing: border-box; } .content-primary { @@ -32,7 +33,8 @@ // CASE: notice has actions { &.has-actions { - .msg, .list-actions { + .msg, + .list-actions { display: inline-block; vertical-align: middle; } @@ -47,10 +49,6 @@ text-align: right; margin-top: 0; - .action-item { - - } - .action-primary { @extend %btn-primary-green; @@ -69,8 +67,11 @@ } // ELEM: listing of users - .user-list, .user-item, .item-metadata, .item-actions { - @include box-sizing(border-box); + .user-list, + .user-item, + .item-metadata, + .item-actions { + box-sizing: border-box; } .user-list { @@ -88,7 +89,8 @@ margin-bottom: 0; } - .item-metadata, .item-actions { + .item-metadata, + .item-actions { display: inline-block; vertical-align: middle; } @@ -133,7 +135,8 @@ @include margin-right(flex-gutter()); - .user-username, .user-email { + .user-username, + .user-email { display: inline-block; vertical-align: middle; } @@ -220,20 +223,6 @@ color: inherit; } } - - // STATE: hover - &:hover { - .user-username { - } - - .user-email { - - } - - .item-actions { - - } - } } } } diff --git a/cms/static/sass/views/_video-upload.scss b/cms/static/sass/views/_video-upload.scss index 0b8c2a3c47646966f2409bbbfdbe8b0f15876e1b..aef3803015e1041d506f418d7662e41bc108eab2 100644 --- a/cms/static/sass/views/_video-upload.scss +++ b/cms/static/sass/views/_video-upload.scss @@ -1,7 +1,7 @@ .view-video-uploads { .content-primary, .content-supplementary { - @include box-sizing(border-box); + box-sizing: border-box; } .nav-actions { @@ -27,6 +27,10 @@ cursor: pointer; } + .message-error { + color: $red; + } + .video-transcripts-wrapper { display: block; @@ -486,7 +490,7 @@ } .name-col { - width: 25%; + width: 23%; } .transcripts-col { @@ -500,7 +504,7 @@ .date-col, .status-col { - width: 10%; + width: 15%; } .actions-col { diff --git a/cms/templates/404.html b/cms/templates/404.html index e1ad0ac38b2757e2a2aafa525808c71cc0693a7b..582c6f66eb96f47872746bbd4346bb3dffd209b9 100644 --- a/cms/templates/404.html +++ b/cms/templates/404.html @@ -17,11 +17,8 @@ from openedx.core.djangolib.markup import HTML, Text <article class="content-primary" role="main"> <p> ${_('The page that you were looking for was not found.')} - ${Text(_('Go back to the {homepage} or let us know about any pages that may have been moved at {email}.')).format( + ${Text(_('Go back to the {homepage}.')).format( homepage=HTML('<a href="/">homepage</a>'), - email=HTML('<a href="mailto:{address}">{address}</a>').format( - address=Text(settings.TECH_SUPPORT_EMAIL) - ) )} </p> </article> diff --git a/cms/templates/500.html b/cms/templates/500.html index bdebc79c13e109fd2961c5c64e4e06986093b018..ea99d6d03620ebc17509c91928724d3d8f09bba5 100644 --- a/cms/templates/500.html +++ b/cms/templates/500.html @@ -29,10 +29,6 @@ ${Text(_("{studio_name} Server Error")).format( studio_name=Text(settings.STUDIO_SHORT_NAME), )} ${_("We've logged the error and our staff is currently working to resolve this error as soon as possible.")} - ${Text(_(u'If the problem persists, please email us at {email_link}.')).format( - email_link=HTML(u'<a href="mailto:{email_address}">{email_address}</a>').format( - email_address=Text(settings.TECH_SUPPORT_EMAIL), - ) )} </p> </article> diff --git a/cms/templates/error.html b/cms/templates/error.html index 25aed65f8840f45dfe85bfee720d118dc565add9..30ec62df8f0f3a19bf277d7b7f2062ae794bdcea 100644 --- a/cms/templates/error.html +++ b/cms/templates/error.html @@ -14,26 +14,17 @@ from django.conf import settings % endif </%block> -<%! -help_link_start = '<a href="mailto:{email}">'.format(email=settings.TECH_SUPPORT_EMAIL) -help_link_end = '</a>' -%> - <%block name="content"> <article class="error-prompt"> % if error == '404': <h1>${_("The Page You Requested Page Cannot be Found")}</h1> - <p class="description">${Text(_("We're sorry. We couldn't find the {studio_name} page you're looking for. You may want to return to the {studio_name} Dashboard and try again. If you are still having problems accessing things, please feel free to {link_start}contact {studio_name} support{link_end} for further help.")).format( - studio_name=settings.STUDIO_SHORT_NAME, - link_start=HTML(help_link_start), - link_end=HTML(help_link_end), + <p class="description">${Text(_("We're sorry. We couldn't find the {studio_name} page you're looking for. You may want to return to the {studio_name} Dashboard and try again.")).format( + studio_name=settings.STUDIO_SHORT_NAME )}</p> % elif error == '500': <h1>${_("The Server Encountered an Error")}</h1> - <p class="description">${Text(_("We're sorry. There was a problem with the server while trying to process your last request. You may want to return to the {studio_name} Dashboard or try this request again. If you are still having problems accessing things, please feel free to {link_start}contact {studio_name} support{link_end} for further help.")).format( + <p class="description">${Text(_("We're sorry. There was a problem with the server while trying to process your last request. You may want to return to the {studio_name} Dashboard or try this request again.")).format( studio_name=settings.STUDIO_SHORT_NAME, - link_start=HTML(help_link_start), - link_end=HTML(help_link_end), )}</p> % endif <a href="/" class="back-button">${_("Back to dashboard")}</a> diff --git a/cms/templates/js/previous-video-upload.underscore b/cms/templates/js/previous-video-upload.underscore index 4ab630d5fd2dffad8969356a0c1c6ea68bac4701..a4cd993235a3120ee557afdb25685622c332b1ce 100644 --- a/cms/templates/js/previous-video-upload.underscore +++ b/cms/templates/js/previous-video-upload.underscore @@ -6,7 +6,7 @@ <div class="video-col date-col"><%- created %></div> <div class="video-col video-id-col"><%- edx_video_id %></div> <div class="video-col transcripts-col"></div> - <div class="video-col status-col"><%- status %></div> + <div class="video-col status-col"></div> <div class="video-col actions-col"> <ul class="actions-list"> <li class="action-item action-remove"> diff --git a/cms/templates/js/timed-examination-preference-editor.underscore b/cms/templates/js/timed-examination-preference-editor.underscore index 6c2f480f877613d68e23b60a560c92f63f92719a..e5ae66cfc58424fe3613495e163546fa0b546f7e 100644 --- a/cms/templates/js/timed-examination-preference-editor.underscore +++ b/cms/templates/js/timed-examination-preference-editor.underscore @@ -2,36 +2,60 @@ <h3 class="modal-section-title"><%- gettext('Set as a Special Exam') %></h3> <div class="modal-section-content has-actions"> <div class="list-fields list-input exam-types" role="group" aria-label="<%- gettext('Exam Types') %>"> + <% if (specialExamLockedIn && !isSpecialExam) { %> + <div class="summary-message summary-message-warning"> + <span class="icon fa fa-exclamation-triangle" aria-hidden="true"></span> + <p class="copy"> + <%- gettext("This subsection was released to learners as a special exam, but was reverted back to a basic exam. You may not configure it as a special exam now. Contact edX Support for assistance.") %> + </p> + </div> + <% } %> + <% if (specialExamLockedIn && isSpecialExam) { %> + <div class="summary-message summary-message-warning"> + <span class="icon fa fa-exclamation-triangle" aria-hidden="true"></span> + <p class="copy"> + <%- gettext("This special exam has been released to learners. You may not convert it to another type of special exam. You may revert this subsection back to being a basic exam by selecting 'None', but you will NOT be able to configure it as a special exam in the future.") %> + </p> + </div> + <% } %> <label class="label no-descriptive-text"> <input type="radio" name="exam_type" class="input input-radio no_special_exam" checked="checked"/> <%- gettext('None') %> </label> <label class="label"> <input type="radio" name="exam_type" class="input input-radio timed_exam" - aria-describedby="timed-exam-description" /> + aria-describedby="timed-exam-description" + <%- specialExamLockedIn && !isTimedExam ? 'disabled' : '' %> + /> <%- gettext('Timed') %> </label> <p class='field-message' id='timed-exam-description'> <%- gettext('Use a timed exam to limit the time learners can spend on problems in this subsection. Learners must submit answers before the time expires. You can allow additional time for individual learners through the Instructor Dashboard.') %> </p> - <% if (enable_proctored_exam) { %> + <% if (enableProctoredExams) { %> <label class="label"> <input type="radio" name="exam_type" class="input input-radio proctored_exam" - aria-describedby="proctored-exam-description" /> + aria-describedby="proctored-exam-description" + <%- specialExamLockedIn && (!isProctoredExam || isOnboardingExam) ? 'disabled' : '' %> + /> <%- gettext('Proctored') %> </label> <p class='field-message' id='proctored-exam-description'> <%- gettext('Proctored exams are timed and they record video of each learner taking the exam. The videos are then reviewed to ensure that learners follow all examination rules.') %> </p> - + <% var supports_onboarding = xblockInfo.get('supports_onboarding'); %> <% if (supports_onboarding) { %> <label class="label"> <input type="radio" name="exam_type" class="input input-radio onboarding_exam" - aria-describedby="onboarding-exam-description"/> + aria-describedby="onboarding-exam-description" + <%- specialExamLockedIn && !isOnboardingExam ? 'disabled' : '' %> + /> <%- gettext('Onboarding') %> </label> <p class='field-message' id='onboarding-exam-description'> <%- gettext("Use Onboarding to introduce learners to proctoring, verify their identity, and create an onboarding profile. Learners must complete the onboarding profile step prior to taking a proctored exam. Profile reviews take 2+ business days.") %> </p> <% } else { %> <label class="label"> <input type="radio" name="exam_type" class="input input-radio practice_exam" - aria-describedby="practice-exam-description"/> + aria-describedby="practice-exam-description" + <%- specialExamLockedIn && !isPracticeExam ? 'disabled' : '' %> + /> <%- gettext('Practice Proctored') %> </label> <p class='field-message' id='practice-exam-description'> <%- gettext("Use a practice proctored exam to introduce learners to the proctoring tools and processes. Results of a practice exam do not affect a learner's grade.") %> </p> diff --git a/cms/templates/js/video-status.underscore b/cms/templates/js/video-status.underscore new file mode 100644 index 0000000000000000000000000000000000000000..e2a24faf1d787e941ffbd422adca73792652fd3d --- /dev/null +++ b/cms/templates/js/video-status.underscore @@ -0,0 +1,5 @@ +<span class='video-status'><%- status %></span> +<% if (show_error && error_description) { %> + </br> + <span class='message-error'><%- error_description %></span> +<% }%> diff --git a/cms/templates/js/video-transcripts.underscore b/cms/templates/js/video-transcripts.underscore index 408deba30743db63809a9c27cdd7b9776c1af06c..290291db4979f7f5fac7d9052c3bfe275261d4e7 100644 --- a/cms/templates/js/video-transcripts.underscore +++ b/cms/templates/js/video-transcripts.underscore @@ -1,4 +1,14 @@ <div class='video-transcripts-header'> +<% if (transcription_status) { %> + <span class='transcripts-empty-text'><%- transcription_status %></span> + <% if (error_description) { %> + </br> + <span class='message-error'><%- error_description %></span> + <% }%> +<% } else if (!transcripts.length){ %> + <span class='transcripts-empty-text'><%- gettext('No transcript uploaded.') %></span> +<% }%> +</br> <% if (transcripts.length) { %> <button class="button-link toggle-show-transcripts-button"> <strong> @@ -8,10 +18,6 @@ </span> </strong> </button> -<% } else if (transcription_status) { %> - <span class='transcripts-empty-text'><%- transcription_status %></span> -<% } else { %> - <span class='transcripts-empty-text'><%- gettext('No transcript uploaded.') %></span> <% }%> <div class='video-transcripts-wrapper'> <% _.each(transcripts, function(transcriptLanguageCode){ %> diff --git a/cms/templates/widgets/source-edit.html b/cms/templates/widgets/source-edit.html index ac58fe9ceb6cfb75a1f5902c5dac7b8007c84842..bb201e5f39a8b3222fa0dd7e6319c4127bbe8916 100644 --- a/cms/templates/widgets/source-edit.html +++ b/cms/templates/widgets/source-edit.html @@ -1,7 +1,9 @@ +<%page expression_filter="h"/> <% import hashlib + from openedx.core.djangolib.js_utils import js_escaped_string from six import text_type - hlskey = hashlib.md5(text_type(module.location)).hexdigest() + hlskey = hashlib.md5(text_type(module.location).encode('utf-8')).hexdigest() %> <section id="hls-modal-${hlskey}" class="upload-modal modal" style="overflow:scroll; background:#ddd; padding: 10px 0;box-shadow: 0 0 5px 0 #555;" > @@ -13,7 +15,7 @@ <form id="hls-form" enctype="multipart/form-data"> <section class="source-edit"> - <textarea name="" data-metadata-name="source_code" class="source-edit-box hls-data" rows="8" cols="40">${editable_metadata_fields['source_code']['value']|h}</textarea> + <textarea name="" data-metadata-name="source_code" class="source-edit-box hls-data" rows="8" cols="40">${editable_metadata_fields['source_code']['value']}</textarea> </section> <div class="submit"> <button type="reset" class="hls-compile">Save & Compile to edX XML</button> @@ -30,8 +32,8 @@ <script type = "text/javascript"> require(["jquery", "jquery.leanModal", "codemirror/stex"], function($) { - hlstrig = $('#hls-trig-${hlskey}'); - hlsmodal = $('#hls-modal-${hlskey}'); + hlstrig = $('#hls-trig-${hlskey | n, js_escaped_string}'); + hlsmodal = $('#hls-modal-${hlskey | n, js_escaped_string}'); hlstrig.leanModal({ top: 0, @@ -44,27 +46,26 @@ require(["jquery", "jquery.leanModal", "codemirror/stex"], function($) { mode: 'stex' })); - $('#hls-trig-${hlskey}').click(function() { + hlstrig.click(function() { - ## cannot do this with css or it gets overwritten + // cannot do this with css or it gets overwritten var editorH = $( window ).height() - 100; var editorW = $( window ).innerWidth() - 70; hlsmodal.attr('style', function(i,s) { return s + 'margin: 2% 0 0 10% !important; left:10%; height:' + editorH + 'px;'}); - ## setup file input - ## need to insert this only after hls triggered, because otherwise it - ## causes other <form> elements to become multipart/form-data, - ## thus breaking multiple-choice input forms, for example. - $('#hls-finput').html('<input type="file" name="hlsfile" id="hlsfile" />'); - - var el = $('#hls-modal-${hlskey}'); - setup_autoupload(el); - slow_refresh_hls(el); + // setup file input + // need to insert this only after hls triggered, because otherwise it + // causes other <form> elements to become multipart/form-data, + // thus breaking multiple-choice input forms, for example. + edx.HtmlUtils.setHtml($('#hls-finput'),edx.HtmlUtils.HTML('<input type="file" name="hlsfile" id="hlsfile" />')); + // var el = $('#hls-modal-${hlskey | n, js_escaped_string}'); + setup_autoupload(hlsmodal); + slow_refresh_hls(hlsmodal); }); // file upload button hlsmodal.find('.hls-upload').click(function() { - $('#hls-modal-${hlskey}').find('#hlsfile').trigger('click'); + hlsmodal.find('#hlsfile').trigger('click'); }); // auto-upload after file is chosen @@ -105,9 +106,8 @@ require(["jquery", "jquery.leanModal", "codemirror/stex"], function($) { // compile & save button hlsmodal.find('.hls-compile').click(function() { - var el = $('#hls-modal-${hlskey}'); - compile_hls(el); - $(el).css('display', 'none') + compile_hls(hlsmodal); + $(hlsmodal).css('display', 'none') }); // connect to server using POST (requires cross-domain-access) @@ -146,25 +146,6 @@ require(["jquery", "jquery.leanModal", "codemirror/stex"], function($) { }); } - function process_return_${hlskey}(datadict) { - // datadict is json of array with "xml" and "message" - // if "xml" value is '' then the conversion failed - var xml = datadict.xml; - if (xml.length == 0) { - alert('Conversion failed! error:' + datadict.message); - } else { - set_raw_edit_box(xml, '${hlskey}'); - save_hls($('#hls-modal-${hlskey}')); - } - } - - - function set_raw_edit_box(data, key) { - // get the codemirror editor for the raw-edit-box - // it's a CodeMirror-wrap class element - $('#hls-modal-' + key).closest('.xblock-studio_view').find('.CodeMirror-wrap')[0].CodeMirror.setValue(data); - } - // save button hlsmodal.find('.hls-save').click(function() { diff --git a/cms/urls.py b/cms/urls.py index 76a739d3e4966694bf7895c06735c3efe89aec7d..3bf3901bc2d2274afab69cd8b12df7acf7105037 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -274,6 +274,16 @@ if 'debug_toolbar' in settings.INSTALLED_APPS: urlpatterns.append(url(r'^template/(?P<template>.+)$', openedx.core.djangoapps.debug.views.show_reference_template, name='openedx.core.djangoapps.debug.views.show_reference_template')) +urlpatterns.append( + url( + r'^api/learning_sequences/', + include( + ('openedx.core.djangoapps.content.learning_sequences.urls', 'learning_sequences'), + namespace='learning_sequences' + ), + ), +) + # display error page templates, for testing purposes urlpatterns += [ url(r'^404$', handler404), diff --git a/common/djangoapps/course_action_state/managers.py b/common/djangoapps/course_action_state/managers.py index a43e5a68c1d9bd52eb0ed19686b7abaef076e221..e50eb9c78c50097e3de44a99e8ac6ae437efac7a 100644 --- a/common/djangoapps/course_action_state/managers.py +++ b/common/djangoapps/course_action_state/managers.py @@ -22,7 +22,7 @@ class CourseActionStateManager(models.Manager): Finds and returns all entries for this action and the given field names-and-values in kwargs. The exclude_args dict allows excluding entries with the field names-and-values in exclude_args. """ - return self.filter(action=self.ACTION, **kwargs).exclude(**(exclude_args or {})) # pylint: disable=no-member + return self.filter(action=self.ACTION, **kwargs).exclude(**(exclude_args or {})) def find_first(self, exclude_args=None, **kwargs): """ @@ -37,7 +37,7 @@ class CourseActionStateManager(models.Manager): if len(objects) == 0: raise CourseActionStateItemNotFoundError( "No entry found for action {action} with filter {filter}, excluding {exclude}".format( - action=self.ACTION, # pylint: disable=no-member + action=self.ACTION, filter=kwargs, exclude=exclude_args, )) @@ -68,7 +68,7 @@ class CourseActionUIStateManager(CourseActionStateManager): Raises CourseActionStateException if allow_not_found is False and an entry for the given course for this Action doesn't exist. """ - state_object, created = self.get_or_create(course_key=course_key, action=self.ACTION) # pylint: disable=no-member + state_object, created = self.get_or_create(course_key=course_key, action=self.ACTION) if created: if allow_not_found: @@ -76,7 +76,7 @@ class CourseActionUIStateManager(CourseActionStateManager): else: raise CourseActionStateItemNotFoundError( "Cannot update non-existent entry for course_key {course_key} and action {action}".format( - action=self.ACTION, # pylint: disable=no-member + action=self.ACTION, course_key=course_key, )) diff --git a/common/djangoapps/course_modes/admin.py b/common/djangoapps/course_modes/admin.py index cb9da9b41bbb5082ec591d3c8894a4d80871a350..3138ea989caf6db2983c4a465f2309750d4d169a 100644 --- a/common/djangoapps/course_modes/admin.py +++ b/common/djangoapps/course_modes/admin.py @@ -76,10 +76,10 @@ class CourseModeForm(forms.ModelForm): default_tz = timezone(settings.TIME_ZONE) - if self.instance._expiration_datetime: # pylint: disable=protected-access + if self.instance._expiration_datetime: # django admin is using default timezone. To avoid time conversion from db to form # convert the UTC object to naive and then localize with default timezone. - _expiration_datetime = self.instance._expiration_datetime.replace( # pylint: disable=protected-access + _expiration_datetime = self.instance._expiration_datetime.replace( tzinfo=None ) self.initial["_expiration_datetime"] = default_tz.localize(_expiration_datetime) diff --git a/common/djangoapps/course_modes/apps.py b/common/djangoapps/course_modes/apps.py index fa8422150801bddc3980aeede2411f61c0d32b94..e0420ea199a0b3ac9d2bc56815cfc6a2499aca49 100644 --- a/common/djangoapps/course_modes/apps.py +++ b/common/djangoapps/course_modes/apps.py @@ -9,4 +9,4 @@ class CourseModesConfig(AppConfig): verbose_name = "Course Modes" def ready(self): - import course_modes.signals # pylint: disable=unused-variable + import course_modes.signals # pylint: disable=unused-import diff --git a/common/djangoapps/course_modes/migrations/0011_change_regex_for_comma_separated_ints.py b/common/djangoapps/course_modes/migrations/0011_change_regex_for_comma_separated_ints.py index cc6c0db2d9462b67c471cd90af42d56ea67f7ce9..6d3c9d288580bac62ce5aa7cca98572e5771ca1a 100644 --- a/common/djangoapps/course_modes/migrations/0011_change_regex_for_comma_separated_ints.py +++ b/common/djangoapps/course_modes/migrations/0011_change_regex_for_comma_separated_ints.py @@ -18,11 +18,11 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='coursemode', name='suggested_prices', - field=models.CharField(blank=True, default=u'', max_length=255, validators=[django.core.validators.RegexValidator(re.compile('^\d+(?:\,\d+)*\Z'), code='invalid', message='Enter only digits separated by commas.')]), + field=models.CharField(blank=True, default=u'', max_length=255, validators=[django.core.validators.RegexValidator(re.compile('^\d+(?:{escaped_comma}\d+)*\Z'.format(escaped_comma=re.escape(','))), code='invalid', message='Enter only digits separated by commas.')]), ), migrations.AlterField( model_name='coursemodesarchive', name='suggested_prices', - field=models.CharField(blank=True, default=u'', max_length=255, validators=[django.core.validators.RegexValidator(re.compile('^\d+(?:\,\d+)*\Z'), code='invalid', message='Enter only digits separated by commas.')]), + field=models.CharField(blank=True, default=u'', max_length=255, validators=[django.core.validators.RegexValidator(re.compile('^\d+(?:{escaped_comma}\d+)*\Z'.format(escaped_comma=re.escape(','))), code='invalid', message='Enter only digits separated by commas.')]), ), ] diff --git a/common/djangoapps/course_modes/migrations/0012_historicalcoursemode.py b/common/djangoapps/course_modes/migrations/0012_historicalcoursemode.py index 5885baa80636d15a5026b981aacc858a77924c1b..e59956d9448672a9ce3de71dfd116a957b0cb822 100644 --- a/common/djangoapps/course_modes/migrations/0012_historicalcoursemode.py +++ b/common/djangoapps/course_modes/migrations/0012_historicalcoursemode.py @@ -30,7 +30,7 @@ class Migration(migrations.Migration): ('_expiration_datetime', models.DateTimeField(blank=True, db_column=u'expiration_datetime', default=None, help_text='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.', null=True, verbose_name='Upgrade Deadline')), ('expiration_datetime_is_explicit', models.BooleanField(default=False)), ('expiration_date', models.DateField(blank=True, default=None, null=True)), - ('suggested_prices', models.CharField(blank=True, default=u'', max_length=255, validators=[django.core.validators.RegexValidator(re.compile('^\\d+(?:\\,\\d+)*\\Z'), code='invalid', message='Enter only digits separated by commas.')])), + ('suggested_prices', models.CharField(blank=True, default=u'', max_length=255, validators=[django.core.validators.RegexValidator(re.compile('^\\d+(?:{escaped_comma}\\d+)*\\Z'.format(escaped_comma=re.escape(','))), code='invalid', message='Enter only digits separated by commas.')])), ('description', models.TextField(blank=True, null=True)), ('sku', models.CharField(blank=True, help_text='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.', max_length=255, null=True, verbose_name=u'SKU')), ('bulk_sku', models.CharField(blank=True, default=None, help_text='This is the bulk SKU (stock keeping unit) of this mode in the external ecommerce service.', max_length=255, null=True, verbose_name=u'Bulk SKU')), diff --git a/common/djangoapps/course_modes/models.py b/common/djangoapps/course_modes/models.py index deaf47510c12921b5921d32318771635ca3259ae..6152033f2101b6137f2f876f08357ef5348b453a 100644 --- a/common/djangoapps/course_modes/models.py +++ b/common/djangoapps/course_modes/models.py @@ -191,13 +191,6 @@ class CourseMode(models.Model): unique_together = ('course', 'mode_slug', 'currency') def __init__(self, *args, **kwargs): - if 'course_id' in kwargs: - course_id = kwargs['course_id'] - if isinstance(course_id, str): - kwargs['course_id'] = CourseKey.from_string(course_id) - call_location = "\n".join("%30s : %s:%d" % (t[3], t[1], t[2]) for t in inspect.stack()[::-1]) - log.warning("Forced to coerce course_id in CourseMode instantiation: %s", call_location) - super(CourseMode, self).__init__(*args, **kwargs) def clean(self): @@ -545,6 +538,19 @@ class CourseMode(models.Model): """ return cls.PROFESSIONAL in modes_dict or cls.NO_ID_PROFESSIONAL_MODE in modes_dict + @classmethod + def contains_audit_mode(cls, modes_dict): + """ + Check whether the modes_dict contains an audit mode. + + Args: + modes_dict (dict): a dict of course modes + + Returns: + bool: whether modes_dict contains an audit mode + """ + return cls.AUDIT in modes_dict + @classmethod def is_professional_mode(cls, course_mode_tuple): """ diff --git a/common/djangoapps/course_modes/tests/factories.py b/common/djangoapps/course_modes/tests/factories.py index 01031d99cd8c1e2dc50d5551e074d4d5f8d905f7..dbd7c0bb0d7a5b5ee9b82d8a2646e69bec0926df 100644 --- a/common/djangoapps/course_modes/tests/factories.py +++ b/common/djangoapps/course_modes/tests/factories.py @@ -16,7 +16,6 @@ from openedx.core.djangoapps.content.course_overviews.tests.factories import Cou # Factories are self documenting -# pylint: disable=missing-docstring class CourseModeFactory(DjangoModelFactory): class Meta(object): model = CourseMode diff --git a/common/djangoapps/entitlements/api.py b/common/djangoapps/entitlements/api.py new file mode 100644 index 0000000000000000000000000000000000000000..bf55a8e0d577b7a056f86dbe2b3b7024943fea12 --- /dev/null +++ b/common/djangoapps/entitlements/api.py @@ -0,0 +1,16 @@ +""" +Python APIs exposed by the Entitlements app to other in-process apps. +""" + +from .models import CourseEntitlement as _CourseEntitlement + + +def get_active_entitlement_list_for_user(user): + """ + Arguments: + user (User): The user we are looking at the entitlements of. + + Returns: + List: Active entitlements for the provided User. + """ + return _CourseEntitlement.get_active_entitlements_for_user(user) diff --git a/common/djangoapps/entitlements/api/urls.py b/common/djangoapps/entitlements/api/urls.py deleted file mode 100644 index d3d5a52d63322ce4487956745b9f0b224456ffdf..0000000000000000000000000000000000000000 --- a/common/djangoapps/entitlements/api/urls.py +++ /dev/null @@ -1,8 +0,0 @@ - - -from django.conf.urls import include, url - -app_name = 'entitlements' -urlpatterns = [ - url(r'^v1/', include('entitlements.api.v1.urls')), -] diff --git a/common/djangoapps/entitlements/apps.py b/common/djangoapps/entitlements/apps.py index 9f158cc7bd40061cfde24cf26077b2586011d311..50a8d9a5258c0fef3a18ebb05a9b6b9b555a4ff6 100644 --- a/common/djangoapps/entitlements/apps.py +++ b/common/djangoapps/entitlements/apps.py @@ -18,5 +18,5 @@ class EntitlementsConfig(AppConfig): """ Connect handlers to signals. """ - from . import signals # pylint: disable=unused-variable + from . import signals # pylint: disable=unused-import from .tasks import expire_old_entitlements diff --git a/common/djangoapps/entitlements/models.py b/common/djangoapps/entitlements/models.py index 348c87f92afa06b6f7cb46afc588b9f2a320c06f..4041f02bc2483a9b08c75cc2a247455ef727990f 100644 --- a/common/djangoapps/entitlements/models.py +++ b/common/djangoapps/entitlements/models.py @@ -76,14 +76,14 @@ class CourseEntitlementPolicy(models.Model): days_since_entitlement_created = (now_timestamp - entitlement.created).days # We want to return whichever days value is less since it is then the more recent one - days_until_regain_ends = (self.regain_period.days - # pylint: disable=no-member + days_until_regain_ends = (self.regain_period.days - min(days_since_course_start, days_since_enrollment, days_since_entitlement_created)) # If the base days until expiration is less than the days until the regain period ends, use that instead if days_until_expiry < days_until_regain_ends: return days_until_expiry - return days_until_regain_ends # pylint: disable=no-member + return days_until_regain_ends def is_entitlement_regainable(self, entitlement): """ @@ -120,7 +120,7 @@ class CourseEntitlementPolicy(models.Model): # This is > because a get_days_since_created of refund_period means that that many days have passed, # which should then make the entitlement no longer refundable - if entitlement.get_days_since_created() > self.refund_period.days: # pylint: disable=no-member + if entitlement.get_days_since_created() > self.refund_period.days: return False if entitlement.enrollment_course_run: @@ -135,7 +135,7 @@ class CourseEntitlementPolicy(models.Model): """ # This is < because a get_days_since_created of expiration_period means that that many days have passed, # which should then expire the entitlement - return (entitlement.get_days_since_created() < self.expiration_period.days # pylint: disable=no-member + return (entitlement.get_days_since_created() < self.expiration_period.days and not entitlement.enrollment_course_run and not entitlement.expired_at) diff --git a/common/djangoapps/entitlements/api/__init__.py b/common/djangoapps/entitlements/rest_api/__init__.py similarity index 100% rename from common/djangoapps/entitlements/api/__init__.py rename to common/djangoapps/entitlements/rest_api/__init__.py diff --git a/common/djangoapps/entitlements/rest_api/urls.py b/common/djangoapps/entitlements/rest_api/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..cda3bb602e499a904e5e1b8c7973c40e5e8be0bc --- /dev/null +++ b/common/djangoapps/entitlements/rest_api/urls.py @@ -0,0 +1,10 @@ +""" +URLs file for the Entitlements API. +""" + +from django.conf.urls import include, url + +app_name = 'entitlements' +urlpatterns = [ + url(r'^v1/', include('entitlements.rest_api.v1.urls')), +] diff --git a/common/djangoapps/entitlements/api/v1/__init__.py b/common/djangoapps/entitlements/rest_api/v1/__init__.py similarity index 100% rename from common/djangoapps/entitlements/api/v1/__init__.py rename to common/djangoapps/entitlements/rest_api/v1/__init__.py diff --git a/common/djangoapps/entitlements/api/v1/filters.py b/common/djangoapps/entitlements/rest_api/v1/filters.py similarity index 91% rename from common/djangoapps/entitlements/api/v1/filters.py rename to common/djangoapps/entitlements/rest_api/v1/filters.py index 295bbaeba6fdcf6dc6146174e5ec4240233527b0..984b7464013f6fcf43c70468502d63bc61d36bb9 100644 --- a/common/djangoapps/entitlements/api/v1/filters.py +++ b/common/djangoapps/entitlements/rest_api/v1/filters.py @@ -1,4 +1,6 @@ - +""" +Filters for the Entitlements API. +""" from django_filters import rest_framework as filters @@ -8,7 +10,7 @@ from entitlements.models import CourseEntitlement class CharListFilter(filters.CharFilter): """ Filters a field via a comma-delimited list of values. """ - def filter(self, qs, value): # pylint: disable=method-hidden + def filter(self, qs, value): if value not in (None, ''): value = value.split(',') @@ -34,6 +36,7 @@ class UUIDListFilter(CharListFilter): class CourseEntitlementFilter(filters.FilterSet): + """Filter for CourseEntitlements""" uuid = UUIDListFilter() user = filters.CharFilter(field_name='user__username') diff --git a/common/djangoapps/entitlements/api/v1/permissions.py b/common/djangoapps/entitlements/rest_api/v1/permissions.py similarity index 100% rename from common/djangoapps/entitlements/api/v1/permissions.py rename to common/djangoapps/entitlements/rest_api/v1/permissions.py diff --git a/common/djangoapps/entitlements/api/v1/serializers.py b/common/djangoapps/entitlements/rest_api/v1/serializers.py similarity index 100% rename from common/djangoapps/entitlements/api/v1/serializers.py rename to common/djangoapps/entitlements/rest_api/v1/serializers.py diff --git a/common/djangoapps/entitlements/api/v1/tests/__init__.py b/common/djangoapps/entitlements/rest_api/v1/tests/__init__.py similarity index 100% rename from common/djangoapps/entitlements/api/v1/tests/__init__.py rename to common/djangoapps/entitlements/rest_api/v1/tests/__init__.py diff --git a/common/djangoapps/entitlements/api/v1/tests/test_serializers.py b/common/djangoapps/entitlements/rest_api/v1/tests/test_serializers.py similarity index 88% rename from common/djangoapps/entitlements/api/v1/tests/test_serializers.py rename to common/djangoapps/entitlements/rest_api/v1/tests/test_serializers.py index 88831aa4d4294b92228c45b5bd7632d0a6a3993e..c1e9a70b348ef2a6ddd6b90240dccd11c9985b70 100644 --- a/common/djangoapps/entitlements/api/v1/tests/test_serializers.py +++ b/common/djangoapps/entitlements/rest_api/v1/tests/test_serializers.py @@ -1,4 +1,6 @@ - +""" +Tests for the API Serializers. +""" import unittest @@ -9,14 +11,15 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # Entitlements is not in CMS' INSTALLED_APPS so these imports will error during test collection if settings.ROOT_URLCONF == 'lms.urls': - from entitlements.api.v1.serializers import CourseEntitlementSerializer + from entitlements.rest_api.v1.serializers import CourseEntitlementSerializer from entitlements.tests.factories import CourseEntitlementFactory @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') class EntitlementsSerializerTests(ModuleStoreTestCase): - def setUp(self): - super(EntitlementsSerializerTests, self).setUp() + """ + Tests for the Entitlement Serializers. + """ def test_data(self): entitlement = CourseEntitlementFactory() diff --git a/common/djangoapps/entitlements/api/v1/tests/test_views.py b/common/djangoapps/entitlements/rest_api/v1/tests/test_views.py similarity index 93% rename from common/djangoapps/entitlements/api/v1/tests/test_views.py rename to common/djangoapps/entitlements/rest_api/v1/tests/test_views.py index 3428ce72ebf07ff743cbcf00e60e5e18f17581b3..3ba57fe7a296ef39fb7ff65ce3dcb7f993d570d0 100644 --- a/common/djangoapps/entitlements/api/v1/tests/test_views.py +++ b/common/djangoapps/entitlements/rest_api/v1/tests/test_views.py @@ -1,4 +1,6 @@ - +""" +Test file to test the Entitlement API Views. +""" import json import logging @@ -30,12 +32,15 @@ log = logging.getLogger(__name__) if settings.ROOT_URLCONF == 'lms.urls': from entitlements.tests.factories import CourseEntitlementFactory from entitlements.models import CourseEntitlement, CourseEntitlementPolicy, CourseEntitlementSupportDetail - from entitlements.api.v1.serializers import CourseEntitlementSerializer - from entitlements.api.v1.views import set_entitlement_policy + from entitlements.rest_api.v1.serializers import CourseEntitlementSerializer + from entitlements.rest_api.v1.views import set_entitlement_policy @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') class EntitlementViewSetTest(ModuleStoreTestCase): + """ + Tests for the Entitlements API Views. + """ ENTITLEMENTS_DETAILS_PATH = 'entitlements_api:v1:entitlements-detail' def setUp(self): @@ -44,7 +49,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase): self.client.login(username=self.user.username, password=TEST_PASSWORD) self.course = CourseFactory() self.course_mode = CourseModeFactory( - course_id=self.course.id, + course_id=self.course.id, # pylint: disable=no-member mode_slug=CourseMode.VERIFIED, # This must be in the future to ensure it is returned by downstream code. expiration_datetime=now() + timedelta(days=1) @@ -363,7 +368,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase): ) assert course_entitlement.policy == policy - @patch("entitlements.api.v1.views.get_owners_for_course") + @patch("entitlements.rest_api.v1.views.get_owners_for_course") def test_email_opt_in_single_org(self, mock_get_owners): course_uuid = uuid.uuid4() entitlement_data = self._get_data_set(self.user, str(course_uuid)) @@ -382,7 +387,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase): result_obj = UserOrgTag.objects.get(user=self.user, org=org, key='email-optin') self.assertEqual(result_obj.value, u"True") - @patch("entitlements.api.v1.views.get_owners_for_course") + @patch("entitlements.rest_api.v1.views.get_owners_for_course") def test_email_opt_in_multiple_orgs(self, mock_get_owners): course_uuid = uuid.uuid4() entitlement_data = self._get_data_set(self.user, str(course_uuid)) @@ -431,7 +436,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase): ) assert results == CourseEntitlementSerializer(course_entitlement).data - @patch("entitlements.api.v1.views.get_course_runs_for_course") + @patch("entitlements.rest_api.v1.views.get_course_runs_for_course") def test_add_entitlement_and_upgrade_audit_enrollment(self, mock_get_course_runs): """ Verify that if an entitlement is added for a user, if the user has one upgradeable enrollment @@ -439,10 +444,13 @@ class EntitlementViewSetTest(ModuleStoreTestCase): """ course_uuid = uuid.uuid4() entitlement_data = self._get_data_set(self.user, str(course_uuid)) - mock_get_course_runs.return_value = [{'key': str(self.course.id)}] + mock_get_course_runs.return_value = [{'key': str(self.course.id)}] # pylint: disable=no-member # Add an audit course enrollment for user. - enrollment = CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.AUDIT) + enrollment = CourseEnrollment.enroll( + self.user, + self.course.id, # pylint: disable=no-member + mode=CourseMode.AUDIT) response = self.client.post( self.entitlements_list_url, @@ -457,12 +465,15 @@ class EntitlementViewSetTest(ModuleStoreTestCase): course_uuid=course_uuid ) # Assert that enrollment mode is now verified - enrollment_mode = CourseEnrollment.enrollment_mode_for_user(self.user, self.course.id)[0] + enrollment_mode = CourseEnrollment.enrollment_mode_for_user( + self.user, + self.course.id # pylint: disable=no-member + )[0] assert enrollment_mode == course_entitlement.mode assert course_entitlement.enrollment_course_run == enrollment assert results == CourseEntitlementSerializer(course_entitlement).data - @patch("entitlements.api.v1.views.get_course_runs_for_course") + @patch("entitlements.rest_api.v1.views.get_course_runs_for_course") def test_add_entitlement_and_upgrade_audit_enrollment_with_dynamic_deadline(self, mock_get_course_runs): """ Verify that if an entitlement is added for a user, if the user has one upgradeable enrollment @@ -511,7 +522,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase): assert course_entitlement.enrollment_course_run == enrollment assert results == CourseEntitlementSerializer(course_entitlement).data - @patch("entitlements.api.v1.views.get_course_runs_for_course") + @patch("entitlements.rest_api.v1.views.get_course_runs_for_course") def test_add_entitlement_inactive_audit_enrollment(self, mock_get_course_runs): """ Verify that if an entitlement is added for a user, if the user has an inactive audit enrollment @@ -519,10 +530,14 @@ class EntitlementViewSetTest(ModuleStoreTestCase): """ course_uuid = uuid.uuid4() entitlement_data = self._get_data_set(self.user, str(course_uuid)) - mock_get_course_runs.return_value = [{'key': str(self.course.id)}] + mock_get_course_runs.return_value = [{'key': str(self.course.id)}] # pylint: disable=no-member # Add an audit course enrollment for user. - enrollment = CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.AUDIT) + enrollment = CourseEnrollment.enroll( + self.user, + self.course.id, # pylint: disable=no-member + mode=CourseMode.AUDIT + ) enrollment.update_enrollment(is_active=False) response = self.client.post( self.entitlements_list_url, @@ -537,7 +552,10 @@ class EntitlementViewSetTest(ModuleStoreTestCase): course_uuid=course_uuid ) # Assert that enrollment mode is now verified - enrollment_mode, enrollment_active = CourseEnrollment.enrollment_mode_for_user(self.user, self.course.id) + enrollment_mode, enrollment_active = CourseEnrollment.enrollment_mode_for_user( + self.user, + self.course.id # pylint: disable=no-member + ) assert enrollment_mode == CourseMode.AUDIT assert enrollment_active is False assert course_entitlement.enrollment_course_run is None @@ -554,7 +572,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase): ) assert response.status_code == 200 - results = response.data.get('results', []) # pylint: disable=no-member + results = response.data.get('results', []) assert results == CourseEntitlementSerializer([entitlement], many=True).data def test_staff_get_only_staff_entitlements(self): @@ -583,7 +601,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase): content_type='application/json', ) assert response.status_code == 200 - results = response.data.get('results', []) # pylint: disable=no-member + results = response.data.get('results', []) # Make sure that the first result isn't expired, and the second one is also not for staff users assert results[0].get('expired_at') is None and results[1].get('expired_at') is None @@ -605,7 +623,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase): ) assert response.status_code == 200 - results = response.data.get('results', []) # pylint: disable=no-member + results = response.data.get('results', []) assert results[0].get('expired_at') is None and results[1].get('expired_at') def test_get_user_entitlements(self): @@ -652,7 +670,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase): ) assert response.status_code == 200 - results = response.data # pylint: disable=no-member + results = response.data assert results.get('expired_at') def test_delete_and_revoke_entitlement(self): @@ -669,7 +687,11 @@ class EntitlementViewSetTest(ModuleStoreTestCase): @patch("entitlements.models.get_course_uuid_for_course") def test_revoke_unenroll_entitlement(self, mock_course_uuid): - enrollment = CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id, is_active=True) + enrollment = CourseEnrollmentFactory.create( + user=self.user, + course_id=self.course.id, # pylint: disable=no-member + is_active=True + ) course_entitlement = CourseEntitlementFactory.create(user=self.user, enrollment_course_run=enrollment) mock_course_uuid.return_value = course_entitlement.course_uuid url = reverse(self.ENTITLEMENTS_DETAILS_PATH, args=[str(course_entitlement.uuid)]) @@ -822,7 +844,7 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase): {'key': str(self.course2.id)} ] - @patch("entitlements.api.v1.views.get_course_runs_for_course") + @patch("entitlements.rest_api.v1.views.get_course_runs_for_course") def test_user_can_enroll(self, mock_get_course_runs): course_entitlement = CourseEntitlementFactory.create(user=self.user, mode=CourseMode.VERIFIED) mock_get_course_runs.return_value = self.return_values @@ -847,7 +869,7 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase): assert course_entitlement.enrollment_course_run is not None @patch("entitlements.models.get_course_uuid_for_course") - @patch("entitlements.api.v1.views.get_course_runs_for_course") + @patch("entitlements.rest_api.v1.views.get_course_runs_for_course") def test_user_can_unenroll(self, mock_get_course_runs, mock_get_course_uuid): course_entitlement = CourseEntitlementFactory.create(user=self.user, mode=CourseMode.VERIFIED) mock_get_course_runs.return_value = self.return_values @@ -882,7 +904,7 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase): assert not CourseEnrollment.is_enrolled(self.user, self.course.id) assert course_entitlement.enrollment_course_run is None - @patch("entitlements.api.v1.views.get_course_runs_for_course") + @patch("entitlements.rest_api.v1.views.get_course_runs_for_course") def test_user_can_switch(self, mock_get_course_runs): mock_get_course_runs.return_value = self.return_values course_entitlement = CourseEntitlementFactory.create(user=self.user, mode=CourseMode.VERIFIED) @@ -920,7 +942,7 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase): assert CourseEnrollment.is_enrolled(self.user, self.course2.id) assert course_entitlement.enrollment_course_run is not None - @patch("entitlements.api.v1.views.get_course_runs_for_course") + @patch("entitlements.rest_api.v1.views.get_course_runs_for_course") def test_user_already_enrolled(self, mock_get_course_runs): course_entitlement = CourseEntitlementFactory.create(user=self.user, mode=CourseMode.VERIFIED) mock_get_course_runs.return_value = self.return_values @@ -945,7 +967,7 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase): assert CourseEnrollment.is_enrolled(self.user, self.course.id) assert course_entitlement.enrollment_course_run is not None - @patch("entitlements.api.v1.views.get_course_runs_for_course") + @patch("entitlements.rest_api.v1.views.get_course_runs_for_course") def test_user_already_enrolled_in_unpaid_mode(self, mock_get_course_runs): course_entitlement = CourseEntitlementFactory.create(user=self.user, mode=CourseMode.VERIFIED) mock_get_course_runs.return_value = self.return_values @@ -972,7 +994,7 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase): assert is_active and (enrolled_mode == course_entitlement.mode) assert course_entitlement.enrollment_course_run is not None - @patch("entitlements.api.v1.views.get_course_runs_for_course") + @patch("entitlements.rest_api.v1.views.get_course_runs_for_course") def test_user_cannot_enroll_in_unknown_course_run_id(self, mock_get_course_runs): fake_course_str = str(self.course.id) + 'fake' fake_course_key = CourseKey.from_string(fake_course_str) @@ -995,11 +1017,11 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase): expected_message = 'The Course Run ID is not a match for this Course Entitlement.' assert response.status_code == 400 - assert response.data['message'] == expected_message # pylint: disable=no-member + assert response.data['message'] == expected_message assert not CourseEnrollment.is_enrolled(self.user, fake_course_key) @patch('entitlements.models.refund_entitlement', return_value=True) - @patch('entitlements.api.v1.views.get_course_runs_for_course') + @patch('entitlements.rest_api.v1.views.get_course_runs_for_course') @patch("entitlements.models.get_course_uuid_for_course") def test_user_can_revoke_and_refund(self, mock_course_uuid, mock_get_course_runs, mock_refund_entitlement): course_entitlement = CourseEntitlementFactory.create(user=self.user, mode=CourseMode.VERIFIED) @@ -1040,14 +1062,14 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase): assert course_entitlement.enrollment_course_run is None assert course_entitlement.expired_at is not None - @patch('entitlements.api.v1.views.CourseEntitlement.is_entitlement_refundable', return_value=False) + @patch('entitlements.rest_api.v1.views.CourseEntitlement.is_entitlement_refundable', return_value=False) @patch('entitlements.models.refund_entitlement', return_value=True) - @patch('entitlements.api.v1.views.get_course_runs_for_course') + @patch('entitlements.rest_api.v1.views.get_course_runs_for_course') def test_user_can_revoke_and_no_refund_available( self, mock_get_course_runs, - mock_refund_entitlement, - mock_is_refundable + mock_refund_entitlement, # pylint: disable=unused-argument + mock_is_refundable # pylint: disable=unused-argument ): course_entitlement = CourseEntitlementFactory.create(user=self.user, mode=CourseMode.VERIFIED) mock_get_course_runs.return_value = self.return_values @@ -1084,14 +1106,14 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase): assert course_entitlement.enrollment_course_run is not None assert course_entitlement.expired_at is None - @patch('entitlements.api.v1.views.CourseEntitlement.is_entitlement_refundable', return_value=True) + @patch('entitlements.rest_api.v1.views.CourseEntitlement.is_entitlement_refundable', return_value=True) @patch('entitlements.models.refund_entitlement', return_value=False) - @patch("entitlements.api.v1.views.get_course_runs_for_course") + @patch("entitlements.rest_api.v1.views.get_course_runs_for_course") def test_user_is_not_unenrolled_on_failed_refund( self, mock_get_course_runs, - mock_refund_entitlement, - mock_is_refundable + mock_refund_entitlement, # pylint: disable=unused-argument + mock_is_refundable # pylint: disable=unused-argument ): course_entitlement = CourseEntitlementFactory.create(user=self.user, mode=CourseMode.VERIFIED) mock_get_course_runs.return_value = self.return_values diff --git a/common/djangoapps/entitlements/api/v1/urls.py b/common/djangoapps/entitlements/rest_api/v1/urls.py similarity index 92% rename from common/djangoapps/entitlements/api/v1/urls.py rename to common/djangoapps/entitlements/rest_api/v1/urls.py index 78444019fbd10dd42a80dd67a1d52f35296f29a7..35a204df09eaa5e15d445558149589e29f5f9b77 100644 --- a/common/djangoapps/entitlements/api/v1/urls.py +++ b/common/djangoapps/entitlements/rest_api/v1/urls.py @@ -1,4 +1,6 @@ - +""" +URLs for the V1 of the Entitlements API. +""" from django.conf.urls import include, url from rest_framework.routers import DefaultRouter diff --git a/common/djangoapps/entitlements/api/v1/views.py b/common/djangoapps/entitlements/rest_api/v1/views.py similarity index 98% rename from common/djangoapps/entitlements/api/v1/views.py rename to common/djangoapps/entitlements/rest_api/v1/views.py index 4d0f6bd3121c261ad2e9ebe603c4b194182cb01b..63b27718b210ec6b4ecd1b98e8b163a977151b5c 100644 --- a/common/djangoapps/entitlements/api/v1/views.py +++ b/common/djangoapps/entitlements/rest_api/v1/views.py @@ -1,4 +1,6 @@ - +""" +Views for the Entitlements v1 API. +""" import logging @@ -15,9 +17,9 @@ from rest_framework.authentication import SessionAuthentication from rest_framework.response import Response from course_modes.models import CourseMode -from entitlements.api.v1.filters import CourseEntitlementFilter -from entitlements.api.v1.permissions import IsAdminOrSupportOrAuthenticatedReadOnly -from entitlements.api.v1.serializers import CourseEntitlementSerializer +from entitlements.rest_api.v1.filters import CourseEntitlementFilter +from entitlements.rest_api.v1.permissions import IsAdminOrSupportOrAuthenticatedReadOnly +from entitlements.rest_api.v1.serializers import CourseEntitlementSerializer from entitlements.models import CourseEntitlement, CourseEntitlementPolicy, CourseEntitlementSupportDetail from entitlements.utils import is_course_run_entitlement_fulfillable from openedx.core.djangoapps.catalog.utils import get_course_runs_for_course, get_owners_for_course @@ -102,6 +104,9 @@ def set_entitlement_policy(entitlement, site): class EntitlementViewSet(viewsets.ModelViewSet): + """ + ViewSet for the Entitlements API. + """ ENTITLEMENT_UUID4_REGEX = '[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}' authentication_classes = (JwtAuthentication, SessionAuthenticationCrossDomainCsrf,) @@ -295,7 +300,7 @@ class EntitlementViewSet(viewsets.ModelViewSet): ) CourseEntitlementSupportDetail.objects.create(**support_detail) - return super(EntitlementViewSet, self).partial_update(request, *args, **kwargs) + return super(EntitlementViewSet, self).partial_update(request, *args, **kwargs) # pylint: disable=no-member class EntitlementEnrollmentViewSet(viewsets.GenericViewSet): diff --git a/common/djangoapps/pipeline_mako/__init__.py b/common/djangoapps/pipeline_mako/__init__.py index 0ce62943092744812ca9f11650545b43932652f3..8c82533ad897dd5681b3aa3f3b5e2c02e954f6f4 100644 --- a/common/djangoapps/pipeline_mako/__init__.py +++ b/common/djangoapps/pipeline_mako/__init__.py @@ -85,7 +85,7 @@ def render_individual_js(package, paths, templates=None): return '\n'.join(tags) -def render_require_js_path_overrides(path_overrides): # pylint: disable=invalid-name +def render_require_js_path_overrides(path_overrides): """Render JavaScript to override default RequireJS paths. The Django pipeline appends a hash to JavaScript files, diff --git a/common/djangoapps/pipeline_mako/templates/mako/inline_js.html b/common/djangoapps/pipeline_mako/templates/mako/inline_js.html index 1a231e220b2b384e2e891ee3cdaba5f0a8f1985a..a9fbafc07c1290b8fafc4f3ab0f18805257b45ed 100644 --- a/common/djangoapps/pipeline_mako/templates/mako/inline_js.html +++ b/common/djangoapps/pipeline_mako/templates/mako/inline_js.html @@ -1,9 +1,13 @@ +<%page expression_filter="h"/> +<%! from openedx.core.djangolib.js_utils import dump_js_escaped_json %> <script \ -% if async: +% if context.get('async', default=None): async \ % endif -if defer: +% if defer: defer \ +% endif type="text/javascript" charset="utf-8"> - ${source | safe} + ## xss-lint: disable=mako-invalid-html-filter + ${source | n, dump_js_escaped_json} </script> diff --git a/common/djangoapps/pipeline_mako/templates/mako/js.html b/common/djangoapps/pipeline_mako/templates/mako/js.html index ffc9355675dbe8cebaebb7d176bd0375befc26f1..86c706f9ce2005680250786963955a8cd2ecfa59 100644 --- a/common/djangoapps/pipeline_mako/templates/mako/js.html +++ b/common/djangoapps/pipeline_mako/templates/mako/js.html @@ -1,5 +1,6 @@ +<%page expression_filter="h"/> <script \ -% if async: +% if context.get('async', default=None): async \ % endif % if defer: diff --git a/common/djangoapps/pipeline_mako/tests/test_render.py b/common/djangoapps/pipeline_mako/tests/test_render.py index 358d903395ce8061221ae14a1f7bacb2b68b1d6b..77aca11ec15cf0b9d070634efad5ce3d6455412f 100644 --- a/common/djangoapps/pipeline_mako/tests/test_render.py +++ b/common/djangoapps/pipeline_mako/tests/test_render.py @@ -17,8 +17,8 @@ class RequireJSPathOverridesTest(TestCase): OVERRIDES = { 'jquery': 'common/js/vendor/jquery.js', - 'backbone': 'common/js/vendor/backbone.js', - 'text': 'js/vendor/text.js' + 'text': 'js/vendor/text.js', + 'backbone': 'common/js/vendor/backbone.js' } OVERRIDES_JS = [ diff --git a/common/djangoapps/static_replace/test/test_static_replace.py b/common/djangoapps/static_replace/test/test_static_replace.py index 5a4a9541098d59e097d291ff833d3f83781e2b15..38c1f45f5e8c5bd2b8dcde134aa2a30fefe2c916 100644 --- a/common/djangoapps/static_replace/test/test_static_replace.py +++ b/common/djangoapps/static_replace/test/test_static_replace.py @@ -61,7 +61,7 @@ def test_multi_replace(): def test_process_url(): - def processor(__, prefix, quote, rest): # pylint: disable=missing-docstring + def processor(__, prefix, quote, rest): return quote + 'test' + prefix + rest + quote assert process_static_urls(STATIC_SOURCE, processor) == '"test/static/file.png"' @@ -70,7 +70,7 @@ def test_process_url(): def test_process_url_data_dir_exists(): base = '"/static/{data_dir}/file.png"'.format(data_dir=DATA_DIRECTORY) - def processor(original, prefix, quote, rest): # pylint: disable=unused-argument,missing-docstring + def processor(original, prefix, quote, rest): # pylint: disable=unused-argument return quote + 'test' + rest + quote assert process_static_urls(base, processor, data_dir=DATA_DIRECTORY) == base @@ -78,7 +78,7 @@ def test_process_url_data_dir_exists(): def test_process_url_no_match(): - def processor(__, prefix, quote, rest): # pylint: disable=missing-docstring + def processor(__, prefix, quote, rest): return quote + 'test' + prefix + rest + quote assert process_static_urls(STATIC_SOURCE, processor) == '"test/static/file.png"' diff --git a/common/djangoapps/student/admin.py b/common/djangoapps/student/admin.py index 2627db0e57d2e7b40ccad536af75ca2d1cb09304..5977062a1d0f2b55c468f87a3255bfef0ac12b9f 100644 --- a/common/djangoapps/student/admin.py +++ b/common/djangoapps/student/admin.py @@ -31,6 +31,7 @@ from student.models import ( CourseAccessRole, CourseEnrollment, CourseEnrollmentAllowed, + CourseEnrollmentCelebration, DashboardConfiguration, LinkedInAddToProfileConfiguration, LoginFailures, @@ -80,6 +81,44 @@ class _Check(object): return inner +class DisableEnrollmentAdminMixin: + """ Disables admin access to an admin page that scales with enrollments, as performance is poor at that size. """ + @_Check.is_enabled(COURSE_ENROLLMENT_ADMIN_SWITCH.is_enabled) + def has_view_permission(self, request, obj=None): + """ + Returns True if CourseEnrollment objects can be viewed via the admin view. + """ + return super().has_view_permission(request, obj) + + @_Check.is_enabled(COURSE_ENROLLMENT_ADMIN_SWITCH.is_enabled) + def has_add_permission(self, request): + """ + Returns True if CourseEnrollment objects can be added via the admin view. + """ + return super().has_add_permission(request) + + @_Check.is_enabled(COURSE_ENROLLMENT_ADMIN_SWITCH.is_enabled) + def has_change_permission(self, request, obj=None): + """ + Returns True if CourseEnrollment objects can be modified via the admin view. + """ + return super().has_change_permission(request, obj) + + @_Check.is_enabled(COURSE_ENROLLMENT_ADMIN_SWITCH.is_enabled) + def has_delete_permission(self, request, obj=None): + """ + Returns True if CourseEnrollment objects can be deleted via the admin view. + """ + return super().has_delete_permission(request, obj) + + @_Check.is_enabled(COURSE_ENROLLMENT_ADMIN_SWITCH.is_enabled) + def has_module_permission(self, request): + """ + Returns True if links to the CourseEnrollment admin view can be displayed. + """ + return super().has_module_permission(request) + + class CourseAccessRoleForm(forms.ModelForm): """Form for adding new Course Access Roles view the Django Admin Panel.""" @@ -238,7 +277,7 @@ class CourseEnrollmentForm(forms.ModelForm): @admin.register(CourseEnrollment) -class CourseEnrollmentAdmin(admin.ModelAdmin): +class CourseEnrollmentAdmin(DisableEnrollmentAdminMixin, admin.ModelAdmin): """ Admin interface for the CourseEnrollment model. """ list_display = ('id', 'course_id', 'mode', 'user', 'is_active',) list_filter = ('mode', 'is_active',) @@ -264,41 +303,6 @@ class CourseEnrollmentAdmin(admin.ModelAdmin): def queryset(self, request): return super(CourseEnrollmentAdmin, self).queryset(request).select_related('user') - @_Check.is_enabled(COURSE_ENROLLMENT_ADMIN_SWITCH.is_enabled) - def has_view_permission(self, request, obj=None): - """ - Returns True if CourseEnrollment objects can be viewed via the admin view. - """ - return super(CourseEnrollmentAdmin, self).has_view_permission(request, obj) # pylint: disable=no-member - - @_Check.is_enabled(COURSE_ENROLLMENT_ADMIN_SWITCH.is_enabled) - def has_add_permission(self, request): - """ - Returns True if CourseEnrollment objects can be added via the admin view. - """ - return super(CourseEnrollmentAdmin, self).has_add_permission(request) - - @_Check.is_enabled(COURSE_ENROLLMENT_ADMIN_SWITCH.is_enabled) - def has_change_permission(self, request, obj=None): - """ - Returns True if CourseEnrollment objects can be modified via the admin view. - """ - return super(CourseEnrollmentAdmin, self).has_change_permission(request, obj) - - @_Check.is_enabled(COURSE_ENROLLMENT_ADMIN_SWITCH.is_enabled) - def has_delete_permission(self, request, obj=None): - """ - Returns True if CourseEnrollment objects can be deleted via the admin view. - """ - return super(CourseEnrollmentAdmin, self).has_delete_permission(request, obj) - - @_Check.is_enabled(COURSE_ENROLLMENT_ADMIN_SWITCH.is_enabled) - def has_module_permission(self, request): - """ - Returns True if links to the CourseEnrollment admin view can be displayed. - """ - return super(CourseEnrollmentAdmin, self).has_module_permission(request) - class UserProfileInline(admin.StackedInline): """ Inline admin interface for UserProfile model. """ @@ -394,7 +398,7 @@ class LoginFailuresAdmin(admin.ModelAdmin): """ Only enabled if feature is enabled. """ - return super(LoginFailuresAdmin, self).has_view_permission(request, obj) # pylint: disable=no-member + return super(LoginFailuresAdmin, self).has_view_permission(request, obj) @_Check.is_enabled(LoginFailures.is_feature_enabled) def has_delete_permission(self, request, obj=None): @@ -511,6 +515,25 @@ class AllowedAuthUserAdmin(admin.ModelAdmin): model = AllowedAuthUser +@admin.register(CourseEnrollmentCelebration) +class CourseEnrollmentCelebrationAdmin(DisableEnrollmentAdminMixin, admin.ModelAdmin): + """Admin interface for the CourseEnrollmentCelebration model. """ + raw_id_fields = ('enrollment',) + list_display = ('id', 'course', 'user', 'celebrate_first_section') + search_fields = ('enrollment__course__id', 'enrollment__user__username') + + class Meta(object): + model = CourseEnrollmentCelebration + + def course(self, obj): + return obj.enrollment.course.id + course.short_description = 'Course' + + def user(self, obj): + return obj.enrollment.user.username + user.short_description = 'User' + + admin.site.register(UserTestGroup) admin.site.register(Registration) admin.site.register(PendingNameChange) diff --git a/common/djangoapps/student/apps.py b/common/djangoapps/student/apps.py index ff728cf38ad5df71126dc492c7057deac0abe8bc..83287fc4dd46420f228dfc505055aef3427b6f98 100644 --- a/common/djangoapps/student/apps.py +++ b/common/djangoapps/student/apps.py @@ -6,8 +6,6 @@ Configuration for the ``student`` Django application. import os from django.apps import AppConfig -from django.contrib.auth.signals import user_logged_in -from django.db.models.signals import pre_save class StudentConfig(AppConfig): @@ -17,10 +15,8 @@ class StudentConfig(AppConfig): name = 'student' def ready(self): - - from django.contrib.auth.models import User - from .signals.receivers import on_user_updated - pre_save.connect(on_user_updated, sender=User) + # Connect signal handlers. + from .signals import receivers # pylint: disable=unused-import # The django-simple-history model on CourseEnrollment creates performance # problems in testing, we mock it here so that the mock impacts all tests. diff --git a/common/djangoapps/student/helpers.py b/common/djangoapps/student/helpers.py index 934096c129c1f107c861ac8c30038199520642b1..a6abb093b9025425af662dfdf8b6ca9d6aa565f5 100644 --- a/common/djangoapps/student/helpers.py +++ b/common/djangoapps/student/helpers.py @@ -61,6 +61,7 @@ DISABLE_UNENROLL_CERT_STATES = [ 'generating', 'downloadable', ] +EMAIL_EXISTS_MSG_FMT = _("An account with the Email '{email}' already exists.") USERNAME_EXISTS_MSG_FMT = _("An account with the Public Username '{username}' already exists.") diff --git a/common/djangoapps/student/management/commands/manage_group.py b/common/djangoapps/student/management/commands/manage_group.py index 110b1e7d3e62005d1c1f48d01708cd02d0bf231a..368a0ec3fc00b578f6010df74320aea5248a468d 100644 --- a/common/djangoapps/student/management/commands/manage_group.py +++ b/common/djangoapps/student/management/commands/manage_group.py @@ -14,8 +14,6 @@ from django.utils.translation import gettext as _ class Command(BaseCommand): - # pylint: disable=missing-docstring - help = 'Creates the specified group, if it does not exist, and sets its permissions.' def add_arguments(self, parser): @@ -26,7 +24,7 @@ class Command(BaseCommand): def _handle_remove(self, group_name): try: - Group.objects.get(name=group_name).delete() # pylint: disable=no-member + Group.objects.get(name=group_name).delete() self.stderr.write(_('Removed group: "{}"').format(group_name)) except Group.DoesNotExist: self.stderr.write(_('Did not find a group with name "{}" - skipping.').format(group_name)) @@ -39,7 +37,7 @@ class Command(BaseCommand): return old_permissions = set() - group, created = Group.objects.get_or_create(name=group_name) # pylint: disable=no-member + group, created = Group.objects.get_or_create(name=group_name) if created: try: @@ -107,7 +105,7 @@ class Command(BaseCommand): content_type = ContentType.objects.get_for_model(model_class) try: - new_permission = Permission.objects.get( # pylint: disable=no-member + new_permission = Permission.objects.get( content_type=content_type, codename=codename, ) diff --git a/common/djangoapps/student/management/commands/manage_user.py b/common/djangoapps/student/management/commands/manage_user.py index 4c2a102322a417806f5a30662cf37dce94cc777a..80e2315dc8c749c86c7016966c339f0cb0b37bb0 100644 --- a/common/djangoapps/student/management/commands/manage_user.py +++ b/common/djangoapps/student/management/commands/manage_user.py @@ -30,8 +30,6 @@ def is_valid_django_hash(encoded): class Command(BaseCommand): - # pylint: disable=missing-docstring - help = 'Creates the specified user, if it does not exist, and sets its groups.' def add_arguments(self, parser): @@ -135,7 +133,7 @@ class Command(BaseCommand): for group_name in groups or set(): try: - group = Group.objects.get(name=group_name) # pylint: disable=no-member + group = Group.objects.get(name=group_name) new_groups.add(group) except Group.DoesNotExist: # warn, but move on. diff --git a/common/djangoapps/student/management/tests/test_bulk_change_enrollment.py b/common/djangoapps/student/management/tests/test_bulk_change_enrollment.py index 404f8b825381d13e3bf08c10ce1678adac4effc6..c2572f567822ba8f4d8d2a98fb5296ae491eb438 100644 --- a/common/djangoapps/student/management/tests/test_bulk_change_enrollment.py +++ b/common/djangoapps/student/management/tests/test_bulk_change_enrollment.py @@ -244,7 +244,7 @@ class BulkChangeEnrollmentTests(SharedModuleStoreTestCase): def _assert_mode_changed(self, mock_tracker, course, user, to_mode): """Confirm the analytics event was emitted.""" - mock_tracker.emit.assert_has_calls( # pylint: disable=maybe-no-member + mock_tracker.emit.assert_has_calls( [ call( EVENT_NAME_ENROLLMENT_MODE_CHANGED, diff --git a/common/djangoapps/student/management/tests/test_manage_group.py b/common/djangoapps/student/management/tests/test_manage_group.py index 92ffdea2d545eea03b10a01cdc06417b51097b48..4eef828a6761b7236d3e05c1ff2f4fdeb70f7b92 100644 --- a/common/djangoapps/student/management/tests/test_manage_group.py +++ b/common/djangoapps/student/management/tests/test_manage_group.py @@ -42,7 +42,7 @@ class TestManageGroupCommand(TestCase): group = Group.objects.create(name=group_name) for codename in permission_codenames: group.permissions.add( - Permission.objects.get(content_type=content_type, codename=codename) # pylint: disable=no-member + Permission.objects.get(content_type=content_type, codename=codename) ) def check_group_permissions(self, group_permissions): @@ -58,7 +58,7 @@ class TestManageGroupCommand(TestCase): """ DRY helper. """ - self.assertEqual(set(group_names), {g.name for g in Group.objects.all()}) # pylint: disable=no-member + self.assertEqual(set(group_names), {g.name for g in Group.objects.all()}) def check_permissions(self, group_name, permission_codenames): """ @@ -66,7 +66,7 @@ class TestManageGroupCommand(TestCase): """ self.assertEqual( set(permission_codenames), - {p.codename for p in Group.objects.get(name=group_name).permissions.all()} # pylint: disable=no-member + {p.codename for p in Group.objects.get(name=group_name).permissions.all()} ) @ddt.data( diff --git a/common/djangoapps/student/management/tests/test_manage_user.py b/common/djangoapps/student/management/tests/test_manage_user.py index 0298964d5b4112b1f6230b25916b192b4fb0b933..f6fc6d911f9f9eca1e218ab8a7fdb1b887ede653 100644 --- a/common/djangoapps/student/management/tests/test_manage_user.py +++ b/common/djangoapps/student/management/tests/test_manage_user.py @@ -27,7 +27,6 @@ class TestManageUserCommand(TestCase): """ Ensures that users are created if they don't exist and reused if they do. """ - # pylint: disable=no-member self.assertEqual([], list(User.objects.all())) call_command('manage_user', TEST_USERNAME, TEST_EMAIL) user = User.objects.get(username=TEST_USERNAME) @@ -43,7 +42,6 @@ class TestManageUserCommand(TestCase): """ Ensures that users are removed if they exist and exit cleanly otherwise. """ - # pylint: disable=no-member User.objects.create(username=TEST_USERNAME, email=TEST_EMAIL) self.assertEqual([(TEST_USERNAME, TEST_EMAIL)], [(u.username, u.email) for u in User.objects.all()]) call_command('manage_user', TEST_USERNAME, TEST_EMAIL, '--remove') @@ -108,7 +106,6 @@ class TestManageUserCommand(TestCase): Ensure that the operation is aborted if the username matches an existing user account but the supplied email doesn't match. """ - # pylint: disable=no-member User.objects.create(username=TEST_USERNAME, email=TEST_EMAIL) with self.assertRaises(CommandError) as exc_context: call_command('manage_user', TEST_USERNAME, 'other@example.com') @@ -150,7 +147,7 @@ class TestManageUserCommand(TestCase): expected_staff, expected_super = expected_bits args = [opt for bit, opt in ((expected_staff, '--staff'), (expected_super, '--superuser')) if bit] call_command('manage_user', TEST_USERNAME, TEST_EMAIL, *args) - user = User.objects.all().first() # pylint: disable=no-member + user = User.objects.all().first() self.assertEqual(user.is_staff, expected_staff) self.assertEqual(user.is_superuser, expected_super) diff --git a/common/djangoapps/student/management/tests/test_transfer_students.py b/common/djangoapps/student/management/tests/test_transfer_students.py index 05118b1146d3c018739d9480a743316766b89a1c..40696e5491e7f62c7f475955c247d441d5afa07d 100644 --- a/common/djangoapps/student/management/tests/test_transfer_students.py +++ b/common/djangoapps/student/management/tests/test_transfer_students.py @@ -13,7 +13,7 @@ from opaque_keys.edx import locator from six import text_type from course_modes.models import CourseMode -from shoppingcart.models import CertificateItem, Order # pylint: disable=import-error +from shoppingcart.models import CertificateItem, Order from student.models import ( EVENT_NAME_ENROLLMENT_ACTIVATED, EVENT_NAME_ENROLLMENT_DEACTIVATED, @@ -93,7 +93,7 @@ class TestTransferStudents(ModuleStoreTestCase): self.assertTrue(self.signal_fired) # Confirm the analytics event was emitted. - self.mock_tracker.emit.assert_has_calls( # pylint: disable=maybe-no-member + self.mock_tracker.emit.assert_has_calls( [ call( EVENT_NAME_ENROLLMENT_ACTIVATED, diff --git a/common/djangoapps/student/migrations/0001_squashed_0031_auto_20200317_1122.py b/common/djangoapps/student/migrations/0001_squashed_0031_auto_20200317_1122.py new file mode 100644 index 0000000000000000000000000000000000000000..22ef19f0c42a38e4f784812409302a484e44a6a0 --- /dev/null +++ b/common/djangoapps/student/migrations/0001_squashed_0031_auto_20200317_1122.py @@ -0,0 +1,525 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2020-04-13 17:34 +from __future__ import unicode_literals + +import course_modes.models +from django.conf import settings +import django.core.validators +from django.db import migrations, models +import django.db.migrations.operations.special +import django.db.models.deletion +import django.utils.timezone +import django_countries.fields +import model_utils.fields +import opaque_keys.edx.django.models +import openedx.core.djangolib.model_mixins +import simple_history.models +import uuid + +from experiments.models import ExperimentData +from openedx.features.course_duration_limits.config import EXPERIMENT_DATA_HOLDBACK_KEY, EXPERIMENT_ID +from student.models import CourseAccessRole, CourseEnrollment, FBEEnrollmentExclusion + +# These data migrations do not require changes when building from scratch. +# student.migrations.0029_add_data_researcher +# student.migrations.0011_course_key_field_to_foreign_key + +# student.migrations.0025_auto_20191101_1846 +def populate_fbeenrollmentexclusion(apps, schema_editor): + holdback_entries = ExperimentData.objects.filter( + experiment_id=EXPERIMENT_ID, + key=EXPERIMENT_DATA_HOLDBACK_KEY, + value='True' + ) + for holdback_entry in holdback_entries: + enrollments = [FBEEnrollmentExclusion(enrollment=enrollment) + for enrollment in CourseEnrollment.objects.filter(user=holdback_entry.user)] + if enrollments: + FBEEnrollmentExclusion.objects.bulk_create(enrollments) + + +class Migration(migrations.Migration): + + replaces = [('student', '0001_initial'), ('student', '0002_auto_20151208_1034'), ('student', '0003_auto_20160516_0938'), ('student', '0004_auto_20160531_1422'), ('student', '0005_auto_20160531_1653'), ('student', '0006_logoutviewconfiguration'), ('student', '0007_registrationcookieconfiguration'), ('student', '0008_auto_20161117_1209'), ('student', '0009_auto_20170111_0422'), ('student', '0010_auto_20170207_0458'), ('student', '0011_course_key_field_to_foreign_key'), ('student', '0012_sociallink'), ('student', '0013_delete_historical_enrollment_records'), ('student', '0014_courseenrollmentallowed_user'), ('student', '0015_manualenrollmentaudit_add_role'), ('student', '0016_coursenrollment_course_on_delete_do_nothing'), ('student', '0017_accountrecovery'), ('student', '0018_remove_password_history'), ('student', '0019_auto_20181221_0540'), ('student', '0020_auto_20190227_2019'), ('student', '0021_historicalcourseenrollment'), ('student', '0022_indexing_in_courseenrollment'), ('student', '0023_bulkunenrollconfiguration'), ('student', '0024_fbeenrollmentexclusion'), ('student', '0025_auto_20191101_1846'), ('student', '0026_allowedauthuser'), ('student', '0027_courseenrollment_mode_callable_default'), ('student', '0028_historicalmanualenrollmentaudit'), ('student', '0029_add_data_researcher'), ('student', '0030_userprofile_phone_number'), ('student', '0031_auto_20200317_1122')] + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('course_overviews', '0013_courseoverview_language'), + ('experiments', '0001_initial'), + ('sites', '0002_alter_domain_unique'), + ('course_overviews', '0014_courseoverview_certificate_available_date'), + ] + + operations = [ + migrations.CreateModel( + name='AnonymousUserId', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('anonymous_user_id', models.CharField(max_length=32, unique=True)), + ('course_id', opaque_keys.edx.django.models.CourseKeyField(blank=True, db_index=True, max_length=255)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='CourseAccessRole', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('org', models.CharField(blank=True, db_index=True, max_length=64)), + ('course_id', opaque_keys.edx.django.models.CourseKeyField(blank=True, db_index=True, max_length=255)), + ('role', models.CharField(db_index=True, max_length=64)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='CourseEnrollment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('course', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to='course_overviews.CourseOverview')), + ('created', models.DateTimeField(auto_now_add=True, db_index=True, null=True)), + ('is_active', models.BooleanField(default=True)), + ('mode', models.CharField(default=b'honor', max_length=100)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ('user', 'course_id'), + }, + ), + migrations.CreateModel( + name='CourseEnrollmentAllowed', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('email', models.CharField(db_index=True, max_length=255)), + ('course_id', opaque_keys.edx.django.models.CourseKeyField(db_index=True, max_length=255)), + ('auto_enroll', models.BooleanField(default=0)), + ('created', models.DateTimeField(auto_now_add=True, db_index=True, null=True)), + ], + ), + migrations.CreateModel( + name='CourseEnrollmentAttribute', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('namespace', models.CharField(help_text='Namespace of enrollment attribute', max_length=255)), + ('name', models.CharField(help_text='Name of the enrollment attribute', max_length=255)), + ('value', models.CharField(help_text='Value of the enrollment attribute', max_length=255)), + ('enrollment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attributes', to='student.CourseEnrollment')), + ], + ), + migrations.CreateModel( + name='DashboardConfiguration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('recent_enrollment_time_delta', models.PositiveIntegerField(default=0, help_text="The number of seconds in which a new enrollment is considered 'recent'. Used to display notifications.")), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'ordering': ('-change_date',), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='EnrollmentRefundConfiguration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('refund_window_microseconds', models.BigIntegerField(default=1209600000000, help_text='The window of time after enrolling during which users can be granted a refund, represented in microseconds. The default is 14 days.')), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'ordering': ('-change_date',), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='EntranceExamConfiguration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('course_id', opaque_keys.edx.django.models.CourseKeyField(db_index=True, max_length=255)), + ('created', models.DateTimeField(auto_now_add=True, db_index=True, null=True)), + ('updated', models.DateTimeField(auto_now=True, db_index=True)), + ('skip_entrance_exam', models.BooleanField(default=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='LanguageProficiency', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(choices=[['aa', 'Afar'], ['ab', 'Abkhazian'], ['af', 'Afrikaans'], ['ak', 'Akan'], ['sq', 'Albanian'], ['am', 'Amharic'], ['ar', 'Arabic'], ['an', 'Aragonese'], ['hy', 'Armenian'], ['as', 'Assamese'], ['av', 'Avaric'], ['ae', 'Avestan'], ['ay', 'Aymara'], ['az', 'Azerbaijani'], ['ba', 'Bashkir'], ['bm', 'Bambara'], ['eu', 'Basque'], ['be', 'Belarusian'], ['bn', 'Bengali'], ['bh', 'Bihari languages'], ['bi', 'Bislama'], ['bs', 'Bosnian'], ['br', 'Breton'], ['bg', 'Bulgarian'], ['my', 'Burmese'], ['ca', 'Catalan'], ['ch', 'Chamorro'], ['ce', 'Chechen'], ['zh', 'Chinese'], ['zh_HANS', 'Simplified Chinese'], ['zh_HANT', 'Traditional Chinese'], ['cu', 'Church Slavic'], ['cv', 'Chuvash'], ['kw', 'Cornish'], ['co', 'Corsican'], ['cr', 'Cree'], ['cs', 'Czech'], ['da', 'Danish'], ['dv', 'Divehi'], ['nl', 'Dutch'], ['dz', 'Dzongkha'], ['en', 'English'], ['eo', 'Esperanto'], ['et', 'Estonian'], ['ee', 'Ewe'], ['fo', 'Faroese'], ['fj', 'Fijian'], ['fi', 'Finnish'], ['fr', 'French'], ['fy', 'Western Frisian'], ['ff', 'Fulah'], ['ka', 'Georgian'], ['de', 'German'], ['gd', 'Gaelic'], ['ga', 'Irish'], ['gl', 'Galician'], ['gv', 'Manx'], ['el', 'Greek'], ['gn', 'Guarani'], ['gu', 'Gujarati'], ['ht', 'Haitian'], ['ha', 'Hausa'], ['he', 'Hebrew'], ['hz', 'Herero'], ['hi', 'Hindi'], ['ho', 'Hiri Motu'], ['hr', 'Croatian'], ['hu', 'Hungarian'], ['ig', 'Igbo'], ['is', 'Icelandic'], ['io', 'Ido'], ['ii', 'Sichuan Yi'], ['iu', 'Inuktitut'], ['ie', 'Interlingue'], ['ia', 'Interlingua'], ['id', 'Indonesian'], ['ik', 'Inupiaq'], ['it', 'Italian'], ['jv', 'Javanese'], ['ja', 'Japanese'], ['kl', 'Kalaallisut'], ['kn', 'Kannada'], ['ks', 'Kashmiri'], ['kr', 'Kanuri'], ['kk', 'Kazakh'], ['km', 'Central Khmer'], ['ki', 'Kikuyu'], ['rw', 'Kinyarwanda'], ['ky', 'Kirghiz'], ['kv', 'Komi'], ['kg', 'Kongo'], ['ko', 'Korean'], ['kj', 'Kuanyama'], ['ku', 'Kurdish'], ['lo', 'Lao'], ['la', 'Latin'], ['lv', 'Latvian'], ['li', 'Limburgan'], ['ln', 'Lingala'], ['lt', 'Lithuanian'], ['lb', 'Luxembourgish'], ['lu', 'Luba-Katanga'], ['lg', 'Ganda'], ['mk', 'Macedonian'], ['mh', 'Marshallese'], ['ml', 'Malayalam'], ['mi', 'Maori'], ['mr', 'Marathi'], ['ms', 'Malay'], ['mg', 'Malagasy'], ['mt', 'Maltese'], ['mn', 'Mongolian'], ['na', 'Nauru'], ['nv', 'Navajo'], ['nr', 'Ndebele, South'], ['nd', 'Ndebele, North'], ['ng', 'Ndonga'], ['ne', 'Nepali'], ['nn', 'Norwegian Nynorsk'], ['nb', 'BokmÃ¥l, Norwegian'], ['no', 'Norwegian'], ['ny', 'Chichewa'], ['oc', 'Occitan'], ['oj', 'Ojibwa'], ['or', 'Oriya'], ['om', 'Oromo'], ['os', 'Ossetian'], ['pa', 'Panjabi'], ['fa', 'Persian'], ['pi', 'Pali'], ['pl', 'Polish'], ['pt', 'Portuguese'], ['ps', 'Pushto'], ['qu', 'Quechua'], ['rm', 'Romansh'], ['ro', 'Romanian'], ['rn', 'Rundi'], ['ru', 'Russian'], ['sg', 'Sango'], ['sa', 'Sanskrit'], ['si', 'Sinhala'], ['sk', 'Slovak'], ['sl', 'Slovenian'], ['se', 'Northern Sami'], ['sm', 'Samoan'], ['sn', 'Shona'], ['sd', 'Sindhi'], ['so', 'Somali'], ['st', 'Sotho, Southern'], ['es', 'Spanish'], ['sc', 'Sardinian'], ['sr', 'Serbian'], ['ss', 'Swati'], ['su', 'Sundanese'], ['sw', 'Swahili'], ['sv', 'Swedish'], ['ty', 'Tahitian'], ['ta', 'Tamil'], ['tt', 'Tatar'], ['te', 'Telugu'], ['tg', 'Tajik'], ['tl', 'Tagalog'], ['th', 'Thai'], ['bo', 'Tibetan'], ['ti', 'Tigrinya'], ['to', 'Tonga (Tonga Islands)'], ['tn', 'Tswana'], ['ts', 'Tsonga'], ['tk', 'Turkmen'], ['tr', 'Turkish'], ['tw', 'Twi'], ['ug', 'Uighur'], ['uk', 'Ukrainian'], ['ur', 'Urdu'], ['uz', 'Uzbek'], ['ve', 'Venda'], ['vi', 'Vietnamese'], ['vo', 'Volapük'], ['cy', 'Welsh'], ['wa', 'Walloon'], ['wo', 'Wolof'], ['xh', 'Xhosa'], ['yi', 'Yiddish'], ['yo', 'Yoruba'], ['za', 'Zhuang'], ['zu', 'Zulu']], help_text='The ISO 639-1 language code for this language.', max_length=16)), + ], + ), + migrations.CreateModel( + name='LinkedInAddToProfileConfiguration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('company_identifier', models.TextField(help_text='The company identifier for the LinkedIn Add-to-Profile button e.g 0_0dPSPyS070e0HsE9HNz_13_d11_')), + ('dashboard_tracking_code', models.TextField(blank=True, default='')), + ('trk_partner_name', models.CharField(blank=True, default='', help_text="Short identifier for the LinkedIn partner used in the tracking code. (Example: 'edx') If no value is provided, tracking codes will not be sent to LinkedIn.", max_length=10)), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'ordering': ('-change_date',), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LoginFailures', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('failure_count', models.IntegerField(default=0)), + ('lockout_until', models.DateTimeField(null=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name_plural': 'Login Failures', + 'verbose_name': 'Login Failure', + }, + ), + migrations.CreateModel( + name='ManualEnrollmentAudit', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('enrolled_email', models.CharField(db_index=True, max_length=255)), + ('time_stamp', models.DateTimeField(auto_now_add=True, null=True)), + ('state_transition', models.CharField(choices=[('from unenrolled to allowed to enroll', 'from unenrolled to allowed to enroll'), ('from allowed to enroll to enrolled', 'from allowed to enroll to enrolled'), ('from enrolled to enrolled', 'from enrolled to enrolled'), ('from enrolled to unenrolled', 'from enrolled to unenrolled'), ('from unenrolled to enrolled', 'from unenrolled to enrolled'), ('from allowed to enroll to enrolled', 'from allowed to enroll to enrolled'), ('from unenrolled to unenrolled', 'from unenrolled to unenrolled'), ('N/A', 'N/A')], max_length=255)), + ('reason', models.TextField(null=True)), + ('enrolled_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('enrollment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='student.CourseEnrollment')), + ('role', models.CharField(blank=True, max_length=64, null=True)), + ], + ), + migrations.CreateModel( + name='PendingEmailChange', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('new_email', models.CharField(blank=True, db_index=True, max_length=255)), + ('activation_key', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='activation key')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='PendingNameChange', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('new_name', models.CharField(blank=True, max_length=255)), + ('rationale', models.CharField(blank=True, max_length=1024)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Registration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('activation_key', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='activation key')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'db_table': 'auth_registration', + }, + ), + migrations.CreateModel( + name='UserProfile', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(blank=True, db_index=True, max_length=255)), + ('meta', models.TextField(blank=True)), + ('courseware', models.CharField(blank=True, default='course.xml', max_length=255)), + ('language', models.CharField(blank=True, db_index=True, max_length=255)), + ('location', models.CharField(blank=True, db_index=True, max_length=255)), + ('year_of_birth', models.IntegerField(blank=True, db_index=True, null=True)), + ('gender', models.CharField(blank=True, choices=[('m', 'Male'), ('f', 'Female'), ('o', 'Other/Prefer Not to Say')], db_index=True, max_length=6, null=True)), + ('level_of_education', models.CharField(blank=True, choices=[('p', 'Doctorate'), ('m', "Master's or professional degree"), ('b', "Bachelor's degree"), ('a', 'Associate degree'), ('hs', 'Secondary/high school'), ('jhs', 'Junior secondary/junior high/middle school'), ('el', 'Elementary/primary school'), ('none', 'No formal education'), ('other', 'Other education')], db_index=True, max_length=6, null=True)), + ('mailing_address', models.TextField(blank=True, null=True)), + ('city', models.TextField(blank=True, null=True)), + ('country', django_countries.fields.CountryField(blank=True, max_length=2, null=True)), + ('goals', models.TextField(blank=True, null=True)), + ('allow_certificate', models.BooleanField(default=1)), + ('bio', models.CharField(blank=True, max_length=3000, null=True)), + ('profile_image_uploaded_at', models.DateTimeField(blank=True, null=True)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'db_table': 'auth_userprofile', + 'permissions': (('can_deactivate_users', 'Can deactivate, but NOT delete users'),), + }, + ), + migrations.CreateModel( + name='UserSignupSource', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('site', models.CharField(db_index=True, max_length=255)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='UserStanding', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('account_status', models.CharField(blank=True, choices=[('disabled', 'Account Disabled'), ('enabled', 'Account Enabled')], max_length=31)), + ('standing_last_changed_at', models.DateTimeField(auto_now=True)), + ('changed_by', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='standing', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='UserTestGroup', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(db_index=True, max_length=32)), + ('description', models.TextField(blank=True)), + ('users', models.ManyToManyField(db_index=True, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='languageproficiency', + name='user_profile', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='language_proficiencies', to='student.UserProfile'), + ), + migrations.AddField( + model_name='courseenrollmentallowed', + name='user', + field=models.ForeignKey(blank=True, help_text="First user which enrolled in the specified course through the specified e-mail. Once set, it won't change.", null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + migrations.AlterUniqueTogether( + name='courseenrollmentallowed', + unique_together=set([('email', 'course_id')]), + ), + migrations.AlterUniqueTogether( + name='languageproficiency', + unique_together=set([('code', 'user_profile')]), + ), + migrations.AlterUniqueTogether( + name='entranceexamconfiguration', + unique_together=set([('user', 'course_id')]), + ), + migrations.AlterField( + model_name='courseenrollment', + name='mode', + field=models.CharField(default='audit', max_length=100), + ), + migrations.AlterUniqueTogether( + name='courseenrollment', + unique_together=set([('user', 'course_id')]), + ), + migrations.AlterUniqueTogether( + name='courseaccessrole', + unique_together=set([('user', 'org', 'course_id', 'role')]), + ), + migrations.CreateModel( + name='UserAttribute', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ('name', models.CharField(help_text='Name of this user attribute.', max_length=255)), + ('value', models.CharField(help_text='Value of this user attribute.', max_length=255)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attributes', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AlterUniqueTogether( + name='userattribute', + unique_together=set([('user', 'name')]), + ), + migrations.AlterField( + model_name='userattribute', + name='name', + field=models.CharField(db_index=True, help_text='Name of this user attribute.', max_length=255), + ), + migrations.CreateModel( + name='LogoutViewConfiguration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'ordering': ('-change_date',), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='RegistrationCookieConfiguration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('utm_cookie_name', models.CharField(help_text='Name of the UTM cookie', max_length=255)), + ('affiliate_cookie_name', models.CharField(help_text='Name of the affiliate cookie', max_length=255)), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'ordering': ('-change_date',), + 'abstract': False, + }, + ), + migrations.AlterModelOptions( + name='courseenrollment', + options={'ordering': ('user', 'course')}, + ), + migrations.AlterUniqueTogether( + name='courseenrollment', + unique_together=set([('user', 'course')]), + ), + migrations.CreateModel( + name='SocialLink', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('platform', models.CharField(max_length=30)), + ('social_link', models.CharField(blank=True, max_length=100)), + ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='social_links', to='student.UserProfile')), + ], + ), + migrations.CreateModel( + name='AccountRecovery', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('secondary_email', models.EmailField(help_text='Secondary email address to recover linked account.', max_length=254, unique=True, verbose_name='Secondary email address')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='account_recovery', to=settings.AUTH_USER_MODEL)), + ('is_active', models.BooleanField(default=False)), + ], + options={ + 'db_table': 'auth_accountrecovery', + }, + ), + migrations.CreateModel( + name='PendingSecondaryEmailChange', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('new_secondary_email', models.CharField(blank=True, db_index=True, max_length=255)), + ('activation_key', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='activation key')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + bases=(openedx.core.djangolib.model_mixins.DeletableByUserValue, models.Model), + ), + migrations.CreateModel( + name='HistoricalCourseEnrollment', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('created', models.DateTimeField(blank=True, db_index=True, editable=False, null=True)), + ('is_active', models.BooleanField(default=True)), + ('mode', models.CharField(default='audit', max_length=100)), + ('history_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('history_date', models.DateTimeField()), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('course', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='course_overviews.CourseOverview')), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'get_latest_by': 'history_date', + 'ordering': ('-history_date', '-history_id'), + 'db_table': 'student_courseenrollment_history', + 'verbose_name': 'historical course enrollment', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.AddIndex( + model_name='courseenrollment', + index=models.Index(fields=['user', '-created'], name='student_cou_user_id_b19dcd_idx'), + ), + migrations.CreateModel( + name='BulkUnenrollConfiguration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('csv_file', models.FileField(help_text='It expect that the data will be provided in a csv file format with first row being the header and columns will be as follows: user_id, username, email, course_id, is_verified, verification_date', upload_to='', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['csv'])])), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'ordering': ('-change_date',), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='FBEEnrollmentExclusion', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('enrollment', models.OneToOneField(on_delete=django.db.models.deletion.DO_NOTHING, to='student.CourseEnrollment')), + ], + ), + migrations.RunPython( + code=populate_fbeenrollmentexclusion, + reverse_code=migrations.operations.special.RunPython.noop, + ), + migrations.CreateModel( + name='AllowedAuthUser', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ('email', models.EmailField(help_text="An employee (a user whose email has current site's domain name) whose email exists in this model, can be able to login from login screen through email and password. And if any employee's email doesn't exist in this model then that employee can login via third party authentication backend only.", max_length=254, unique=True)), + ('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='allowed_auth_users', to='sites.Site')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AlterField( + model_name='courseenrollment', + name='mode', + field=models.CharField(default=course_modes.models.CourseMode.get_default_mode_slug, max_length=100), + ), + migrations.AlterField( + model_name='historicalcourseenrollment', + name='mode', + field=models.CharField(default=course_modes.models.CourseMode.get_default_mode_slug, max_length=100), + ), + migrations.CreateModel( + name='HistoricalManualEnrollmentAudit', + fields=[ + ('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('enrolled_email', models.CharField(db_index=True, max_length=255)), + ('time_stamp', models.DateTimeField(blank=True, editable=False, null=True)), + ('state_transition', models.CharField(choices=[('from unenrolled to allowed to enroll', 'from unenrolled to allowed to enroll'), ('from allowed to enroll to enrolled', 'from allowed to enroll to enrolled'), ('from enrolled to enrolled', 'from enrolled to enrolled'), ('from enrolled to unenrolled', 'from enrolled to unenrolled'), ('from unenrolled to enrolled', 'from unenrolled to enrolled'), ('from allowed to enroll to enrolled', 'from allowed to enroll to enrolled'), ('from unenrolled to unenrolled', 'from unenrolled to unenrolled'), ('N/A', 'N/A')], max_length=255)), + ('reason', models.TextField(null=True)), + ('role', models.CharField(blank=True, max_length=64, null=True)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_date', models.DateTimeField()), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('enrolled_by', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ('enrollment', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='student.CourseEnrollment')), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'get_latest_by': 'history_date', + 'ordering': ('-history_date', '-history_id'), + 'verbose_name': 'historical manual enrollment audit', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.AddField( + model_name='userprofile', + name='phone_number', + field=models.CharField(blank=True, max_length=50, null=True, validators=[django.core.validators.RegexValidator(message='Phone number can only contain numbers.', regex='^\\+?1?\\d*$')]), + ), + migrations.CreateModel( + name='AccountRecoveryConfiguration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('csv_file', models.FileField(help_text='It expect that the data will be provided in a csv file format with first row being the header and columns will be as follows: username, email, new_email', upload_to='', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['csv'])])), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'ordering': ('-change_date',), + 'abstract': False, + }, + ), + migrations.AlterField( + model_name='courseenrollment', + name='course', + field=models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.DO_NOTHING, + to='course_overviews.CourseOverview'), + ), + ] diff --git a/common/djangoapps/student/migrations/0025_auto_20191101_1846.py b/common/djangoapps/student/migrations/0025_auto_20191101_1846.py index 5c82594324e6f0d975eaaa0c3675dfdb3986d349..e08a9afba3760c4d730d9f78484d551823f29970 100644 --- a/common/djangoapps/student/migrations/0025_auto_20191101_1846.py +++ b/common/djangoapps/student/migrations/0025_auto_20191101_1846.py @@ -26,6 +26,7 @@ class Migration(migrations.Migration): dependencies = [ ('student', '0024_fbeenrollmentexclusion'), + ('experiments', '0001_initial'), ] operations = [ diff --git a/common/djangoapps/student/migrations/0032_removed_logout_view_configuration.py b/common/djangoapps/student/migrations/0032_removed_logout_view_configuration.py new file mode 100644 index 0000000000000000000000000000000000000000..02d52a833310e9015fc27b948bd30272c817f0e3 --- /dev/null +++ b/common/djangoapps/student/migrations/0032_removed_logout_view_configuration.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2020-03-25 14:28 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('student', '0031_auto_20200317_1122'), + ] + + operations = [ + migrations.RemoveField( + model_name='logoutviewconfiguration', + name='changed_by', + ), + migrations.DeleteModel( + name='LogoutViewConfiguration', + ), + ] diff --git a/common/djangoapps/student/migrations/0033_userprofile_state.py b/common/djangoapps/student/migrations/0033_userprofile_state.py new file mode 100644 index 0000000000000000000000000000000000000000..3aaec78862584aaf873d1f2aca6108b0021be5a0 --- /dev/null +++ b/common/djangoapps/student/migrations/0033_userprofile_state.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-04-30 20:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('student', '0032_removed_logout_view_configuration'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='state', + field=models.CharField(blank=True, choices=[('AL', 'Alabama'), ('AK', 'Alaska'), ('AZ', 'Arizona'), ('AR', 'Arkansas'), ('AA', 'Armed Forces Americas'), ('AE', 'Armed Forces Europe'), ('AP', 'Armed Forces Pacific'), ('CA', 'California'), ('CO', 'Colorado'), ('CT', 'Connecticut'), ('DE', 'Delaware'), ('DC', 'District Of Columbia'), ('FL', 'Florida'), ('GA', 'Georgia'), ('HI', 'Hawaii'), ('ID', 'Idaho'), ('IL', 'Illinois'), ('IN', 'Indiana'), ('IA', 'Iowa'), ('KS', 'Kansas'), ('KY', 'Kentucky'), ('LA', 'Louisiana'), ('ME', 'Maine'), ('MD', 'Maryland'), ('MA', 'Massachusetts'), ('MI', 'Michigan'), ('MN', 'Minnesota'), ('MS', 'Mississippi'), ('MO', 'Missouri'), ('MT', 'Montana'), ('NE', 'Nebraska'), ('NV', 'Nevada'), ('NH', 'New Hampshire'), ('NJ', 'New Jersey'), ('NM', 'New Mexico'), ('NY', 'New York'), ('NC', 'North Carolina'), ('ND', 'North Dakota'), ('OH', 'Ohio'), ('OK', 'Oklahoma'), ('OR', 'Oregon'), ('PA', 'Pennsylvania'), ('RI', 'Rhode Island'), ('SC', 'South Carolina'), ('SD', 'South Dakota'), ('TN', 'Tennessee'), ('TX', 'Texas'), ('UT', 'Utah'), ('VT', 'Vermont'), ('VA', 'Virginia'), ('WA', 'Washington'), ('WV', 'West Virginia'), ('WI', 'Wisconsin'), ('WY', 'Wyoming')], max_length=2, null=True), + ), + ] diff --git a/common/djangoapps/student/migrations/0034_courseenrollmentcelebration.py b/common/djangoapps/student/migrations/0034_courseenrollmentcelebration.py new file mode 100644 index 0000000000000000000000000000000000000000..7bf6f3c857e0fcd8c0614617550545820f3d5e0f --- /dev/null +++ b/common/djangoapps/student/migrations/0034_courseenrollmentcelebration.py @@ -0,0 +1,29 @@ +# Generated by Django 2.2.12 on 2020-06-08 15:12 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import model_utils.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('student', '0033_userprofile_state'), + ] + + operations = [ + migrations.CreateModel( + name='CourseEnrollmentCelebration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ('celebrate_first_section', models.BooleanField(default=False)), + ('enrollment', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='celebration', to='student.CourseEnrollment')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index 2029b70693511a302c33fa286cb83f7ffa44ee0c..9f6c01996eb1e9ebd76a7bf068804e16b459919c 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -13,7 +13,6 @@ file and check it in at the same time as your model changes. To do that, import hashlib -import inspect import json import logging import uuid @@ -500,6 +499,64 @@ class UserProfile(models.Model): mailing_address = models.TextField(blank=True, null=True) city = models.TextField(blank=True, null=True) country = CountryField(blank=True, null=True) + COUNTRY_WITH_STATES = u'US' + STATE_CHOICES = ( + ('AL', 'Alabama'), + ('AK', 'Alaska'), + ('AZ', 'Arizona'), + ('AR', 'Arkansas'), + ('AA', 'Armed Forces Americas'), + ('AE', 'Armed Forces Europe'), + ('AP', 'Armed Forces Pacific'), + ('CA', 'California'), + ('CO', 'Colorado'), + ('CT', 'Connecticut'), + ('DE', 'Delaware'), + ('DC', 'District Of Columbia'), + ('FL', 'Florida'), + ('GA', 'Georgia'), + ('HI', 'Hawaii'), + ('ID', 'Idaho'), + ('IL', 'Illinois'), + ('IN', 'Indiana'), + ('IA', 'Iowa'), + ('KS', 'Kansas'), + ('KY', 'Kentucky'), + ('LA', 'Louisiana'), + ('ME', 'Maine'), + ('MD', 'Maryland'), + ('MA', 'Massachusetts'), + ('MI', 'Michigan'), + ('MN', 'Minnesota'), + ('MS', 'Mississippi'), + ('MO', 'Missouri'), + ('MT', 'Montana'), + ('NE', 'Nebraska'), + ('NV', 'Nevada'), + ('NH', 'New Hampshire'), + ('NJ', 'New Jersey'), + ('NM', 'New Mexico'), + ('NY', 'New York'), + ('NC', 'North Carolina'), + ('ND', 'North Dakota'), + ('OH', 'Ohio'), + ('OK', 'Oklahoma'), + ('OR', 'Oregon'), + ('PA', 'Pennsylvania'), + ('RI', 'Rhode Island'), + ('SC', 'South Carolina'), + ('SD', 'South Dakota'), + ('TN', 'Tennessee'), + ('TX', 'Texas'), + ('UT', 'Utah'), + ('VT', 'Vermont'), + ('VA', 'Virginia'), + ('WA', 'Washington'), + ('WV', 'West Virginia'), + ('WI', 'Wisconsin'), + ('WY', 'Wyoming'), + ) + state = models.CharField(blank=True, null=True, max_length=2, choices=STATE_CHOICES) goals = models.TextField(blank=True, null=True) allow_certificate = models.BooleanField(default=1) bio = models.CharField(blank=True, null=True, max_length=3000, db_index=False) @@ -535,7 +592,7 @@ class UserProfile(models.Model): if self.gender: return self.__enumerable_to_display(self.GENDER_CHOICES, self.gender) - def get_meta(self): # pylint: disable=missing-docstring + def get_meta(self): # pylint: disable=missing-function-docstring js_str = self.meta if not js_str: js_str = dict() @@ -544,7 +601,7 @@ class UserProfile(models.Model): return js_str - def set_meta(self, meta_json): # pylint: disable=missing-docstring + def set_meta(self, meta_json): self.meta = json.dumps(meta_json) def set_login_session(self, session_id=None): @@ -625,7 +682,7 @@ class UserProfile(models.Model): @receiver(models.signals.post_save, sender=UserProfile) -def invalidate_user_profile_country_cache(sender, instance, **kwargs): # pylint: disable=unused-argument, invalid-name +def invalidate_user_profile_country_cache(sender, instance, **kwargs): # pylint: disable=unused-argument """Invalidate the cache of country in UserProfile model. """ changed_fields = getattr(instance, '_changed_fields', {}) @@ -659,7 +716,6 @@ def user_profile_post_save_callback(sender, **kwargs): Emit analytics events after saving the UserProfile. """ user_profile = kwargs['instance'] - # pylint: disable=protected-access emit_field_changed_events( user_profile, user_profile.user, @@ -714,7 +770,6 @@ def user_post_save_callback(sender, **kwargs): # Because `emit_field_changed_events` removes the record of the fields that # were changed, wait to do that until after we've checked them as part of # the condition on whether we want to check for automatic enrollments. - # pylint: disable=protected-access emit_field_changed_events( user, user, @@ -914,6 +969,16 @@ class LoginFailures(models.Model): record.save() + @classmethod + def check_user_reset_password_threshold(cls, user): + """ + Checks if the user is above threshold for reset password message. + """ + record, _ = LoginFailures.objects.get_or_create(user=user) + max_failures_allowed = settings.MAX_FAILED_LOGIN_ATTEMPTS_ALLOWED + + return record.failure_count >= max_failures_allowed / 2, record.failure_count + @classmethod def clear_lockout_counter(cls, user): """ @@ -1126,13 +1191,6 @@ class CourseEnrollment(models.Model): ordering = ('user', 'course') def __init__(self, *args, **kwargs): - if 'course_id' in kwargs: - course_id = kwargs['course_id'] - if isinstance(course_id, str): - kwargs['course_id'] = CourseKey.from_string(course_id) - call_location = "\n".join("%30s : %s:%d" % (t[3], t[1], t[2]) for t in inspect.stack()[::-1]) - log.warning("Forced to coerce course_id in CourseEnrollment instantiation: %s", call_location) - super(CourseEnrollment, self).__init__(*args, **kwargs) # Private variable for storing course_overview to minimize calls to the database. @@ -1243,7 +1301,6 @@ class CourseEnrollment(models.Model): Returns a boolean value regarding whether the user has access to enroll in the course. Returns False if the enrollment has been closed. """ - # pylint: disable=import-error from openedx.core.djangoapps.enrollments.permissions import ENROLL_IN_COURSE return not user.has_perm(ENROLL_IN_COURSE, course) @@ -2055,7 +2112,7 @@ class FBEEnrollmentExclusion(models.Model): @receiver(models.signals.post_save, sender=CourseEnrollment) @receiver(models.signals.post_delete, sender=CourseEnrollment) -def invalidate_enrollment_mode_cache(sender, instance, **kwargs): # pylint: disable=unused-argument, invalid-name +def invalidate_enrollment_mode_cache(sender, instance, **kwargs): # pylint: disable=unused-argument """ Invalidate the cache of CourseEnrollment model. """ @@ -2259,7 +2316,7 @@ class CourseAccessRole(models.Model): """ Lexigraphic sort """ - return self._key < other._key # pylint: disable=protected-access + return self._key < other._key def __str__(self): return "[CourseAccessRole] user: {} role: {} org: {} course: {}".format(self.user.username, self.role, self.org, self.course_id) @@ -2396,7 +2453,7 @@ def create_comments_service_user(user): @receiver(user_logged_in) -def log_successful_login(sender, request, user, **kwargs): # pylint: disable=unused-argument +def log_successful_login(sender, request, user, **kwargs): """Handler to log when logins have occurred successfully.""" if settings.FEATURES['SQUELCH_PII_IN_LOGS']: AUDIT_LOG.info(u"Login success - user.id: {0}".format(user.id)) @@ -2405,7 +2462,7 @@ def log_successful_login(sender, request, user, **kwargs): # pylint: disable=un @receiver(user_logged_out) -def log_successful_logout(sender, request, user, **kwargs): # pylint: disable=unused-argument +def log_successful_logout(sender, request, user, **kwargs): """Handler to log when logouts have occurred successfully.""" if hasattr(request, 'user'): if settings.FEATURES['SQUELCH_PII_IN_LOGS']: @@ -2416,7 +2473,7 @@ def log_successful_logout(sender, request, user, **kwargs): # pylint: disable=u @receiver(user_logged_in) @receiver(user_logged_out) -def enforce_single_login(sender, request, user, signal, **kwargs): # pylint: disable=unused-argument +def enforce_single_login(sender, request, user, signal, **kwargs): """ Sets the current session id in the user profile, to prevent concurrent logins. @@ -2682,7 +2739,7 @@ class LanguageProficiency(models.Model): ) -class SocialLink(models.Model): # pylint: disable=model-missing-unicode +class SocialLink(models.Model): """ Represents a URL connecting a particular social platform to a user's social profile. @@ -2990,3 +3047,39 @@ class AccountRecoveryConfiguration(ConfigurationModel): first row being the header and columns will be as follows: \ username, email, new_email") ) + + +class CourseEnrollmentCelebration(TimeStampedModel): + """ + Keeps track of how we've celebrated a user's course progress. + + An example of a celebration is a dialog that pops up after you complete your first section + in a course saying "good job!". Just some positive feedback like that. (This specific example is + controlled by the celebrated_first_section field below.) + + In general, if a row does not exist for an enrollment, we don't want to show any celebrations. + We don't want to suddenly inject celebrations in the middle of a course, because they + might not make contextual sense and it's an inconsistent experience. The helper methods below + (starting with "should_") can help by looking up values with appropriate fallbacks. + + See the create_course_enrollment_celebration signal handler for how these get created. + + .. no_pii: + """ + enrollment = models.OneToOneField(CourseEnrollment, models.CASCADE, related_name='celebration') + celebrate_first_section = models.BooleanField(default=False) + + def __str__(self): + return ( + "[CourseEnrollmentCelebration] course: {}; user: {}; first_section: {}" + ).format(self.enrollment.course.id, self.enrollment.user.username, self.celebrate_first_section) + + @staticmethod + def should_celebrate_first_section(enrollment): + """ Returns the celebration value for first_section with appropriate fallback if it doesn't exist """ + if not enrollment: + return False + try: + return enrollment.celebration.celebrate_first_section + except CourseEnrollmentCelebration.DoesNotExist: + return False diff --git a/common/djangoapps/student/roles.py b/common/djangoapps/student/roles.py index 879d620bbade975834cd2bcf18e142f6f862eef8..9433022edf0c4722568fce7b7f95156dc757fd43 100644 --- a/common/djangoapps/student/roles.py +++ b/common/djangoapps/student/roles.py @@ -312,6 +312,7 @@ class CourseCcxCoachRole(CourseRole): super(CourseCcxCoachRole, self).__init__(self.ROLE, *args, **kwargs) +@register_access_role class CourseDataResearcherRole(CourseRole): """A Data Researcher""" ROLE = 'data_researcher' @@ -343,6 +344,14 @@ class OrgLibraryUserRole(OrgRole): super(OrgLibraryUserRole, self).__init__(self.ROLE, *args, **kwargs) +class OrgDataResearcherRole(OrgRole): + """A Data Researcher""" + ROLE = 'data_researcher' + + def __init__(self, *args, **kwargs): + super(OrgDataResearcherRole, self).__init__(self.ROLE, *args, **kwargs) + + @register_access_role class CourseCreatorRole(RoleBase): """ diff --git a/common/djangoapps/student/rules.py b/common/djangoapps/student/rules.py deleted file mode 100644 index c718d56af4f69fe7eb76b2b32b8cb3f993358fe9..0000000000000000000000000000000000000000 --- a/common/djangoapps/student/rules.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -Django rules for student roles -""" -from __future__ import absolute_import - -import rules - -from lms.djangoapps.courseware.access import has_access -from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag, WaffleFlag, WaffleFlagNamespace - -from .roles import CourseDataResearcherRole - -# Waffle flag to enable the separate course outline page and full width content. -RESEARCHER_ROLE = CourseWaffleFlag(WaffleFlagNamespace(name='instructor'), 'researcher') - - -@rules.predicate -def can_access_reports(user, course_id): - """ - Returns whether the user can access the course data downloads. - """ - is_staff = user.is_staff - if RESEARCHER_ROLE.is_enabled(course_id): - return is_staff or CourseDataResearcherRole(course_id).has_user(user) - else: - return is_staff or has_access(user, 'staff', course_id) - -rules.add_perm('student.can_research', can_access_reports) diff --git a/common/djangoapps/student/signals/receivers.py b/common/djangoapps/student/signals/receivers.py index bb0213a39b5ec56ad41e80799b736edffb3f413a..b6f0d6041517aaef9ad1f2a45f55d6427c3b4b47 100644 --- a/common/djangoapps/student/signals/receivers.py +++ b/common/djangoapps/student/signals/receivers.py @@ -2,14 +2,21 @@ Signal receivers for the "student" application. """ +# pylint: disable=unused-argument from django.conf import settings +from django.contrib.auth import get_user_model +from django.db import IntegrityError +from django.db.models.signals import post_save, pre_save +from django.dispatch import receiver -from student.helpers import USERNAME_EXISTS_MSG_FMT, AccountValidationError -from student.models import is_email_retired, is_username_retired +from lms.djangoapps.courseware.toggles import REDIRECT_TO_COURSEWARE_MICROFRONTEND +from student.helpers import EMAIL_EXISTS_MSG_FMT, USERNAME_EXISTS_MSG_FMT, AccountValidationError +from student.models import CourseEnrollment, CourseEnrollmentCelebration, is_email_retired, is_username_retired -def on_user_updated(sender, instance, **kwargs): # pylint: disable=unused-argument +@receiver(pre_save, sender=get_user_model()) +def on_user_updated(sender, instance, **kwargs): """ Check for retired usernames. """ @@ -34,6 +41,32 @@ def on_user_updated(sender, instance, **kwargs): # pylint: disable=unused-argum # Check for a retired email. if is_email_retired(instance.email): raise AccountValidationError( - EMAIL_EXISTS_MSG_FMT.format(username=instance.email), + EMAIL_EXISTS_MSG_FMT.format(email=instance.email), field="email" ) + + +@receiver(post_save, sender=CourseEnrollment) +def create_course_enrollment_celebration(sender, instance, created, **kwargs): + """ + Creates celebration rows when enrollments are created + + This is how we distinguish between new enrollments that we want to celebrate and old ones + that existed before we introduced a given celebration. + """ + if not created: + return + + # The UI for celebrations is only supported on the MFE right now, so don't turn on + # celebrations unless this enrollment's course is MFE-enabled. + if not REDIRECT_TO_COURSEWARE_MICROFRONTEND.is_enabled(instance.course_id): + return + + try: + CourseEnrollmentCelebration.objects.create( + enrollment=instance, + celebrate_first_section=True, + ) + except IntegrityError: + # A celebration object was already created. Shouldn't happen, but ignore it if it does. + pass diff --git a/common/djangoapps/student/tasks.py b/common/djangoapps/student/tasks.py index 56a7565ab5fcb8c4b2e937dae896af7fc1142596..30f00e92c44d6bb0a0fde8b854da32c75dee0f5a 100644 --- a/common/djangoapps/student/tasks.py +++ b/common/djangoapps/student/tasks.py @@ -6,7 +6,7 @@ This file contains celery tasks for sending email import logging from celery.exceptions import MaxRetriesExceededError -from celery.task import task # pylint: disable=no-name-in-module, import-error +from celery.task import task from django.conf import settings from django.contrib.auth.models import User from django.contrib.sites.models import Site @@ -58,7 +58,7 @@ def send_activation_email(self, msg_string, from_address=None): dest_addr, exc_info=True ) - except Exception: # pylint: disable=bare-except + except Exception: log.exception( 'Unable to send activation email to user from "%s" to "%s"', from_address, diff --git a/common/djangoapps/student/tests/factories.py b/common/djangoapps/student/tests/factories.py index f8649a33410178e92d58ef94120f2965e6dd9f58..51ab00825cdf75564588d6df81bd9068e41cc70b 100644 --- a/common/djangoapps/student/tests/factories.py +++ b/common/djangoapps/student/tests/factories.py @@ -19,6 +19,7 @@ from student.models import ( CourseAccessRole, CourseEnrollment, CourseEnrollmentAllowed, + CourseEnrollmentCelebration, PendingEmailChange, Registration, User, @@ -27,7 +28,6 @@ from student.models import ( ) # Factories are self documenting -# pylint: disable=missing-docstring TEST_PASSWORD = 'test' @@ -90,7 +90,7 @@ class UserFactory(DjangoModelFactory): date_joined = datetime(2011, 1, 1, tzinfo=UTC) @factory.post_generation - def profile(obj, create, extracted, **kwargs): # pylint: disable=unused-argument, no-self-argument + def profile(obj, create, extracted, **kwargs): # pylint: disable=unused-argument, missing-function-docstring if create: obj.save() return UserProfileFactory.create(user=obj, **kwargs) @@ -166,6 +166,13 @@ class CourseEnrollmentFactory(DjangoModelFactory): return manager.create(*args, **kwargs) +class CourseEnrollmentCelebrationFactory(DjangoModelFactory): + class Meta: + model = CourseEnrollmentCelebration + + enrollment = factory.SubFactory(CourseEnrollmentFactory) + + class CourseAccessRoleFactory(DjangoModelFactory): class Meta(object): model = CourseAccessRole diff --git a/common/djangoapps/student/tests/test_certificates.py b/common/djangoapps/student/tests/test_certificates.py index 29827969918513a1830b9e86cf3a55c63be08af5..f7d5c1d5b739a1ba340cffa8800790c9697a4952 100644 --- a/common/djangoapps/student/tests/test_certificates.py +++ b/common/djangoapps/student/tests/test_certificates.py @@ -13,9 +13,9 @@ from mock import patch from pytz import UTC from course_modes.models import CourseMode -from lms.djangoapps.certificates.api import get_certificate_url # pylint: disable=import-error -from lms.djangoapps.certificates.models import CertificateStatuses # pylint: disable=import-error -from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory # pylint: disable=import-error +from lms.djangoapps.certificates.api import get_certificate_url +from lms.djangoapps.certificates.models import CertificateStatuses +from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory from student.models import LinkedInAddToProfileConfiguration from student.tests.factories import CourseEnrollmentFactory, UserFactory from xmodule.modulestore import ModuleStoreEnum diff --git a/common/djangoapps/student/tests/test_credit.py b/common/djangoapps/student/tests/test_credit.py index 6c81125b4760d8a84fde2636ad9fc883d62e5a10..c3b5e218be510ca99b37dc77c02381c0c49314ca 100644 --- a/common/djangoapps/student/tests/test_credit.py +++ b/common/djangoapps/student/tests/test_credit.py @@ -189,7 +189,7 @@ class CreditCourseDashboardTest(ModuleStoreTestCase): def _purchase_credit(self): """Purchase credit from a provider in the course. """ self.enrollment.mode = "credit" - self.enrollment.save() # pylint: disable=no-member + self.enrollment.save() CourseEnrollmentAttribute.objects.create( enrollment=self.enrollment, diff --git a/common/djangoapps/student/tests/test_email.py b/common/djangoapps/student/tests/test_email.py index cf0e484e33db875abcbe5ca697e288981d2159f2..921d64869ab59922e6af09c8651a684911f9b8dc 100644 --- a/common/djangoapps/student/tests/test_email.py +++ b/common/djangoapps/student/tests/test_email.py @@ -14,6 +14,7 @@ from django.http import HttpResponse from django.test import TransactionTestCase, override_settings from django.test.client import RequestFactory from django.urls import reverse +from django.utils.html import escape from mock import Mock, patch from six import text_type @@ -600,9 +601,7 @@ class SecondaryEmailChangeRequestTests(EventTestMixin, EmailTemplateTagMixin, Ca self._assert_email( subject=u'Confirm your recovery email for édX', body_fragments=[ - u'You\'ve registered this recovery email address for édX.'.format( - new_email=new_email, - ), + u'You\'ve registered this recovery email address for édX.', u'If you set this email address, click "confirm email."', u'If you didn\'t request this change, you can disregard this email.', u'http://edx.org/activate_secondary_email/{key}'.format(key=registration_key), @@ -623,6 +622,6 @@ class SecondaryEmailChangeRequestTests(EventTestMixin, EmailTemplateTagMixin, Ca assert message.subject == subject - for body in text, html: - for fragment in body_fragments: - assert fragment in body + for fragment in body_fragments: + assert fragment in text + assert escape(fragment) in html diff --git a/common/djangoapps/student/tests/test_models.py b/common/djangoapps/student/tests/test_models.py index 072fdbfbec0930b4c41f395a1e86dac23c8ebbfe..fd18cbba392d1b893ef90657473aa39ac4568fd7 100644 --- a/common/djangoapps/student/tests/test_models.py +++ b/common/djangoapps/student/tests/test_models.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - import datetime import hashlib diff --git a/common/djangoapps/student/tests/test_receivers.py b/common/djangoapps/student/tests/test_receivers.py new file mode 100644 index 0000000000000000000000000000000000000000..07f65a8a03143854b501d99b4f3e0680c2e6e12d --- /dev/null +++ b/common/djangoapps/student/tests/test_receivers.py @@ -0,0 +1,34 @@ +""" Tests for student signal receivers. """ + +from lms.djangoapps.courseware.toggles import REDIRECT_TO_COURSEWARE_MICROFRONTEND +from student.models import CourseEnrollmentCelebration +from student.tests.factories import CourseEnrollmentFactory +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase + + +class ReceiversTest(SharedModuleStoreTestCase): + """ + Tests for dashboard utility functions + """ + @REDIRECT_TO_COURSEWARE_MICROFRONTEND.override(active=True) + def test_celebration_created(self): + """ Test that we make celebration objects when enrollments are created """ + self.assertEqual(CourseEnrollmentCelebration.objects.count(), 0) + + # Test initial creation upon an enrollment being made + enrollment = CourseEnrollmentFactory() + self.assertEqual(CourseEnrollmentCelebration.objects.count(), 1) + celebration = CourseEnrollmentCelebration.objects.get(enrollment=enrollment, celebrate_first_section=True) + + # Test nothing changes if we update that enrollment + celebration.celebrate_first_section = False + celebration.save() + enrollment.mode = 'test-mode' + enrollment.save() + self.assertEqual(CourseEnrollmentCelebration.objects.count(), 1) + CourseEnrollmentCelebration.objects.get(enrollment=enrollment, celebrate_first_section=False) + + def test_celebration_gated_by_waffle(self): + """ Test we don't make a celebration if the MFE redirect waffle flag is off """ + CourseEnrollmentFactory() + self.assertEqual(CourseEnrollmentCelebration.objects.count(), 0) diff --git a/common/djangoapps/student/tests/test_views.py b/common/djangoapps/student/tests/test_views.py index a77a49d7e0848d3cd7a5193e5776ebbe246dc1d0..bfdc87c662605fb93813e2f91b66f540728fbc0a 100644 --- a/common/djangoapps/student/tests/test_views.py +++ b/common/djangoapps/student/tests/test_views.py @@ -389,7 +389,7 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin, response = self.client.get(self.path) self.assertNotContains(response, '<li class="course-item">') - @patch('entitlements.api.v1.views.get_course_runs_for_course') + @patch('entitlements.rest_api.v1.views.get_course_runs_for_course') @patch.object(CourseOverview, 'get_from_id') def test_sessions_for_entitlement_course_runs(self, mock_course_overview, mock_course_runs): """ @@ -774,7 +774,7 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin, Links will be removed from the course title, course image and button (View Course/Resume Course). The course card should have an access expired message. """ - CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1)) + CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=self.THREE_YEARS_AGO - timedelta(days=30)) self.override_waffle_switch(True) course = CourseFactory.create(start=self.THREE_YEARS_AGO) @@ -783,9 +783,11 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin, user=self.user, course_id=course.id ) + enrollment.created = self.THREE_YEARS_AGO + timedelta(days=1) + enrollment.save() # pylint: disable=unused-variable - schedule = ScheduleFactory(start_date=self.THREE_YEARS_AGO + timedelta(days=1), enrollment=enrollment) + schedule = ScheduleFactory(enrollment=enrollment) response = self.client.get(reverse('dashboard')) dashboard_html = self._remove_whitespace_from_response(response) diff --git a/common/djangoapps/student/tests/tests.py b/common/djangoapps/student/tests/tests.py index c5953682ce7267019dfc0388b0122846f4bbc909..1fc4c6c45adc04b2426e0c798e5bd7afe69bf74e 100644 --- a/common/djangoapps/student/tests/tests.py +++ b/common/djangoapps/student/tests/tests.py @@ -26,12 +26,11 @@ from six import text_type from six.moves import range from six.moves.urllib.parse import quote -import shoppingcart # pylint: disable=import-error -from bulk_email.models import Optout # pylint: disable=import-error +from bulk_email.models import Optout from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory -from lms.djangoapps.certificates.models import CertificateStatuses # pylint: disable=import-error -from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory # pylint: disable=import-error +from lms.djangoapps.certificates.models import CertificateStatuses +from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory from lms.djangoapps.verify_student.tests import TestVerificationBase from openedx.core.djangoapps.catalog.tests.factories import CourseFactory as CatalogCourseFactory from openedx.core.djangoapps.catalog.tests.factories import CourseRunFactory, ProgramFactory, generate_course_run_key @@ -390,74 +389,6 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase): self.assertFalse(course_mode_info['show_upsell']) self.assertIsNone(course_mode_info['days_for_upsell']) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') - @patch('lms.djangoapps.courseware.views.index.log.warning') - @patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True}) - def test_blocked_course_scenario(self, log_warning): - - self.client.login(username="jack", password="test") - - #create testing invoice 1 - sale_invoice_1 = shoppingcart.models.Invoice.objects.create( - total_amount=1234.32, company_name='Test1', company_contact_name='Testw', - company_contact_email='test1@test.com', customer_reference_number='2Fwe23S', - recipient_name='Testw_1', recipient_email='test2@test.com', internal_reference="A", - course_id=self.course.id, is_valid=False - ) - invoice_item = shoppingcart.models.CourseRegistrationCodeInvoiceItem.objects.create( - invoice=sale_invoice_1, - qty=1, - unit_price=1234.32, - course_id=self.course.id - ) - course_reg_code = shoppingcart.models.CourseRegistrationCode( - code="abcde", - course_id=self.course.id, - created_by=self.user, - invoice=sale_invoice_1, - invoice_item=invoice_item, - mode_slug=CourseMode.DEFAULT_MODE_SLUG - ) - course_reg_code.save() - - cart = shoppingcart.models.Order.get_cart_for_user(self.user) - shoppingcart.models.PaidCourseRegistration.add_to_order(cart, self.course.id) - resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': course_reg_code.code}) - self.assertEqual(resp.status_code, 200) - - redeem_url = reverse('register_code_redemption', args=[course_reg_code.code]) - response = self.client.get(redeem_url) - self.assertEqual(response.status_code, 200) - # check button text - self.assertContains(response, 'Activate Course Enrollment') - - #now activate the user by enrolling him/her to the course - response = self.client.post(redeem_url) - self.assertEqual(response.status_code, 200) - response = self.client.get(reverse('dashboard')) - self.assertContains(response, 'You can no longer access this course because payment has not yet been received') - optout_object = Optout.objects.filter(user=self.user, course_id=self.course.id) - self.assertEqual(len(optout_object), 1) - - # Direct link to course redirect to user dashboard - self.client.get(reverse('courseware', kwargs={"course_id": text_type(self.course.id)})) - log_warning.assert_called_with( - u'User %s cannot access the course %s because payment has not yet been received', - self.user, - text_type(self.course.id), - ) - - # Now re-validating the invoice - invoice = shoppingcart.models.Invoice.objects.get(id=sale_invoice_1.id) - invoice.is_valid = True - invoice.save() - - response = self.client.get(reverse('dashboard')) - self.assertNotContains( - response, - 'You can no longer access this course because payment has not yet been received', - ) - @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') def test_linked_in_add_to_profile_btn_not_appearing_without_config(self): # Without linked-in config don't show Add Certificate to LinkedIn button @@ -715,7 +646,7 @@ class EnrollmentEventTestMixin(EventTestMixin): def assert_enrollment_mode_change_event_was_emitted(self, user, course_key, mode): """Ensures an enrollment mode change event was emitted""" - self.mock_tracker.emit.assert_called_once_with( # pylint: disable=maybe-no-member + self.mock_tracker.emit.assert_called_once_with( 'edx.course.enrollment.mode_changed', { 'course_id': text_type(course_key), @@ -727,7 +658,7 @@ class EnrollmentEventTestMixin(EventTestMixin): def assert_enrollment_event_was_emitted(self, user, course_key): """Ensures an enrollment event was emitted since the last event related assertion""" - self.mock_tracker.emit.assert_called_once_with( # pylint: disable=maybe-no-member + self.mock_tracker.emit.assert_called_once_with( 'edx.course.enrollment.activated', { 'course_id': text_type(course_key), @@ -739,7 +670,7 @@ class EnrollmentEventTestMixin(EventTestMixin): def assert_unenrollment_event_was_emitted(self, user, course_key): """Ensures an unenrollment event was emitted since the last event related assertion""" - self.mock_tracker.emit.assert_called_once_with( # pylint: disable=maybe-no-member + self.mock_tracker.emit.assert_called_once_with( 'edx.course.enrollment.deactivated', { 'course_id': text_type(course_key), diff --git a/common/djangoapps/student/views/__init__.py b/common/djangoapps/student/views/__init__.py index c11803e8f993472bdb1d41f1336427a8d58a3c26..e10dd7b8a8827c6db5815f8b5b88b965e4dc0a1f 100644 --- a/common/djangoapps/student/views/__init__.py +++ b/common/djangoapps/student/views/__init__.py @@ -3,5 +3,5 @@ Combines all of the broken out student views """ -from .dashboard import * # pylint: disable=wildcard-import -from .management import * # pylint: disable=wildcard-import +from .dashboard import * +from .management import * diff --git a/common/djangoapps/student/views/dashboard.py b/common/djangoapps/student/views/dashboard.py index 4d0f295c91f5a0b8adb7f0a5abac9c682ca6d1ed..513956d1010803f16e3616ffcc304ef1b33aedbc 100644 --- a/common/djangoapps/student/views/dashboard.py +++ b/common/djangoapps/student/views/dashboard.py @@ -25,7 +25,7 @@ from bulk_email.models import Optout from course_modes.models import CourseMode from edxmako.shortcuts import render_to_response, render_to_string from entitlements.models import CourseEntitlement -from lms.djangoapps.commerce.utils import EcommerceService # pylint: disable=import-error +from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.courseware.access import has_access from lms.djangoapps.experiments.utils import get_dashboard_course_info from lms.djangoapps.verify_student.services import IDVerificationService @@ -40,12 +40,12 @@ from openedx.core.djangoapps.plugins.plugin_contexts import get_plugins_view_con from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.programs.utils import ProgramDataExtender, ProgramProgressMeter from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled_for_user +from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled from openedx.core.djangoapps.util.maintenance_banner import add_maintenance_banner from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace from openedx.core.djangolib.markup import HTML, Text from openedx.features.enterprise_support.api import get_dashboard_consent_notification -from shoppingcart.models import CourseRegistrationCode, DonationConfiguration +from shoppingcart.models import DonationConfiguration from student.api import COURSE_DASHBOARD_PLUGIN_VIEW_NAME from student.helpers import cert_info, check_verify_status_by_course, get_resume_urls_for_enrollments from student.models import ( @@ -150,7 +150,7 @@ def _allow_donation(course_modes, course_id, enrollment): ) -def _create_recent_enrollment_message(course_enrollments, course_modes): # pylint: disable=invalid-name +def _create_recent_enrollment_message(course_enrollments, course_modes): """ Builds a recent course enrollment message. @@ -315,37 +315,6 @@ def complete_course_mode_info(course_id, enrollment, modes=None): return mode_info -def is_course_blocked(request, redeemed_registration_codes, course_key): - """ - Checking if registration is blocked or not. - """ - blocked = False - for redeemed_registration in redeemed_registration_codes: - # registration codes may be generated via Bulk Purchase Scenario - # we have to check only for the invoice generated registration codes - # that their invoice is valid or not - if redeemed_registration.invoice_item: - if not redeemed_registration.invoice_item.invoice.is_valid: - blocked = True - # disabling email notifications for unpaid registration courses - Optout.objects.get_or_create(user=request.user, course_id=course_key) - log.info( - u"User %s (%s) opted out of receiving emails from course %s", - request.user.username, - request.user.email, - course_key, - ) - track.views.server_track( - request, - "change-email1-settings", - {"receive_emails": "no", "course": text_type(course_key)}, - page='dashboard', - ) - break - - return blocked - - def get_verification_error_reasons_for_display(verification_error_codes): """ Returns the display text for the given verification error codes. @@ -655,7 +624,7 @@ def student_dashboard(request): enterprise_message = get_dashboard_consent_notification(request, user, course_enrollments) recovery_email_message = recovery_email_activation_message = None - if is_secondary_email_feature_enabled_for_user(user=user): + if is_secondary_email_feature_enabled(): try: pending_email = PendingSecondaryEmailChange.objects.get(user=user) except PendingSecondaryEmailChange.DoesNotExist: @@ -776,18 +745,6 @@ def student_dashboard(request): statuses = ["approved", "denied", "pending", "must_reverify"] reverifications = reverification_info(statuses) - block_courses = frozenset( - enrollment.course_id for enrollment in course_enrollments - if is_course_blocked( - request, - CourseRegistrationCode.objects.filter( - course_id=enrollment.course_id, - registrationcoderedemption__redeemed_by=request.user - ), - enrollment.course_id - ) - ) - enrolled_courses_either_paid = frozenset( enrollment.course_id for enrollment in course_enrollments if enrollment.is_paid_course() @@ -828,6 +785,14 @@ def student_dashboard(request): enr for enr in course_enrollments if entitlement.enrollment_course_run.course_id != enr.course_id ] + # Collect all program types the user is enrolled in + enrolled_program_types = [] + if getattr(settings, 'ENABLE_DEMOGRAPHICS_COLLECTION', False): + enrolled_program_types = { + _program.get('type_attrs', {}).get('slug') + for _program in meter.engaged_programs + if _program.get('type_attrs', {}).get('slug') is not None + } context = { 'urls': urls, 'programs_data': programs_data, @@ -856,7 +821,6 @@ def student_dashboard(request): 'verification_expiry': verification_status['verification_expiry'], 'verification_status_by_course': verify_status_by_course, 'verification_errors': verification_errors, - 'block_courses': block_courses, 'denied_banner': denied_banner, 'billing_email': settings.PAYMENT_SUPPORT_EMAIL, 'user': user, @@ -878,6 +842,7 @@ def student_dashboard(request): 'recovery_email_message': recovery_email_message, 'recovery_email_activation_message': recovery_email_activation_message, 'show_load_all_courses_link': show_load_all_courses_link(user, course_limit, course_enrollments), + 'enrolled_program_types': enrolled_program_types, # TODO START: clean up as part of REVEM-199 (START) 'course_info': get_dashboard_course_info(user, course_enrollments), # TODO START: clean up as part of REVEM-199 (END) diff --git a/common/djangoapps/student/views/management.py b/common/djangoapps/student/views/management.py index 7b4fec74c7fc81491ee7c40e0c82a14947bf7e7a..24f4bb1a33f6efd1b268204097218aeaeebe6ceb 100644 --- a/common/djangoapps/student/views/management.py +++ b/common/djangoapps/student/views/management.py @@ -692,7 +692,7 @@ def do_email_change_request(user, new_email, activation_key=None, secondary_emai @ensure_csrf_cookie -def activate_secondary_email(request, key): # pylint: disable=unused-argument +def activate_secondary_email(request, key): """ This is called when the activation link is clicked. We activate the secondary email for the requested user. @@ -720,7 +720,7 @@ def activate_secondary_email(request, key): # pylint: disable=unused-argument @ensure_csrf_cookie -def confirm_email_change(request, key): # pylint: disable=unused-argument +def confirm_email_change(request, key): """ User requested a new e-mail. This is called when the activation link is clicked. We confirm with the old e-mail, and update diff --git a/common/djangoapps/terrain/stubs/catalog.py b/common/djangoapps/terrain/stubs/catalog.py index 7ec477a6c0e0ab6df4bc671736012f65639e73df..d2cdebe5dcb1aedd555fb7bc7b264c91bb4d9048 100644 --- a/common/djangoapps/terrain/stubs/catalog.py +++ b/common/djangoapps/terrain/stubs/catalog.py @@ -1,12 +1,12 @@ """ Stub implementation of catalog service for acceptance tests """ -# pylint: disable=invalid-name, missing-docstring +# pylint: disable=invalid-name import re -import six.moves.urllib.parse # pylint: disable=import-error +import six.moves.urllib.parse from .http import StubHttpRequestHandler, StubHttpService diff --git a/common/djangoapps/terrain/stubs/comments.py b/common/djangoapps/terrain/stubs/comments.py index 57f022f97462d4636e7790907795d39876badb75..4d46e0081c72e31d07334040f831d292b2c310bd 100644 --- a/common/djangoapps/terrain/stubs/comments.py +++ b/common/djangoapps/terrain/stubs/comments.py @@ -6,7 +6,7 @@ Stub implementation of cs_comments_service for acceptance tests import re from collections import OrderedDict -import six.moves.urllib.parse # pylint: disable=import-error +import six.moves.urllib.parse from .http import StubHttpRequestHandler, StubHttpService diff --git a/common/djangoapps/terrain/stubs/ecommerce.py b/common/djangoapps/terrain/stubs/ecommerce.py index bda35a7ae060a56a2d7af5d9dd32ff33083de87c..96835ab0c171b2fba3bd03515e71aad2e4d932cf 100644 --- a/common/djangoapps/terrain/stubs/ecommerce.py +++ b/common/djangoapps/terrain/stubs/ecommerce.py @@ -5,14 +5,15 @@ Stub implementation of ecommerce service for acceptance tests import re -import six.moves.urllib.parse # pylint: disable=import-error +import six.moves.urllib.parse from .http import StubHttpRequestHandler, StubHttpService -class StubEcommerceServiceHandler(StubHttpRequestHandler): # pylint: disable=missing-docstring +class StubEcommerceServiceHandler(StubHttpRequestHandler): # pylint: disable=missing-class-docstring - def do_GET(self): # pylint: disable=invalid-name, missing-docstring + # pylint: disable=missing-function-docstring + def do_GET(self): pattern_handlers = { '/api/v2/orders/$': self.get_orders_list, } @@ -59,5 +60,5 @@ class StubEcommerceServiceHandler(StubHttpRequestHandler): # pylint: disable=mi self.send_json_response(orders) -class StubEcommerceService(StubHttpService): # pylint: disable=missing-docstring +class StubEcommerceService(StubHttpService): HANDLER_CLASS = StubEcommerceServiceHandler diff --git a/common/djangoapps/terrain/stubs/edxnotes.py b/common/djangoapps/terrain/stubs/edxnotes.py index b32f3b174f10d375d5b22375153a719b84c5a648..9d1b83697a81074a13af7f791935b10e5b39d01c 100644 --- a/common/djangoapps/terrain/stubs/edxnotes.py +++ b/common/djangoapps/terrain/stubs/edxnotes.py @@ -11,7 +11,7 @@ from math import ceil from uuid import uuid4 import six -from six.moves.urllib.parse import urlencode # pylint: disable=import-error +from six.moves.urllib.parse import urlencode from .http import StubHttpRequestHandler, StubHttpService diff --git a/common/djangoapps/terrain/stubs/http.py b/common/djangoapps/terrain/stubs/http.py index cf3523f230d0ba9aa5680ebedcacb5116229eb90..7cf277b89ff01e53273e608a47052129d6e0411d 100644 --- a/common/djangoapps/terrain/stubs/http.py +++ b/common/djangoapps/terrain/stubs/http.py @@ -10,8 +10,8 @@ from logging import getLogger import six from lazy import lazy -from six.moves.BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer # pylint: disable=import-error -from six.moves.socketserver import ThreadingMixIn # pylint: disable=import-error +from six.moves.BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer +from six.moves.socketserver import ThreadingMixIn LOGGER = getLogger(__name__) diff --git a/common/djangoapps/terrain/stubs/tests/test_edxnotes.py b/common/djangoapps/terrain/stubs/tests/test_edxnotes.py index 3a76a875bb7784f6a4409f10d8b56568ef3292ab..340038b609885c9331c89a4513318c76eb704af4 100644 --- a/common/djangoapps/terrain/stubs/tests/test_edxnotes.py +++ b/common/djangoapps/terrain/stubs/tests/test_edxnotes.py @@ -34,7 +34,7 @@ class StubEdxNotesServiceTest(unittest.TestCase): """ Returns a list of dummy notes. """ - return [self._get_dummy_note(i) for i in range(count)] # pylint: disable=unused-variable + return [self._get_dummy_note(i) for i in range(count)] def _get_dummy_note(self, uid=0): """ diff --git a/common/djangoapps/third_party_auth/admin.py b/common/djangoapps/third_party_auth/admin.py index bbb4c5ea16d2574e7c5021e42ea8e6f8c87dcac4..305b0daef757b886008267ba55602bc71c5e8227 100644 --- a/common/djangoapps/third_party_auth/admin.py +++ b/common/djangoapps/third_party_auth/admin.py @@ -9,10 +9,9 @@ from django import forms from django.contrib import admin from django.db import transaction from django.urls import reverse +from django.utils.html import format_html from django.utils.translation import ugettext_lazy as _ -from openedx.core.djangolib.markup import HTML - from .models import ( _PSA_OAUTH2_BACKENDS, _PSA_SAML_BACKENDS, @@ -102,9 +101,8 @@ class SAMLProviderConfigAdmin(KeyedConfigurationModelAdmin): update_url = reverse('admin:{}_{}_add'.format(self.model._meta.app_label, self.model._meta.model_name)) update_url += '?source={}'.format(instance.pk) - return HTML(u'<a href="{}">{}</a>').format(update_url, instance.name) + return format_html(u'<a href="{}">{}</a>', update_url, instance.name) - name_with_update_link.allow_tags = True name_with_update_link.short_description = u'Name' def has_data(self, inst): @@ -119,9 +117,8 @@ class SAMLProviderConfigAdmin(KeyedConfigurationModelAdmin): def mode(self, inst): """ Indicate if debug_mode is enabled or not""" if inst.debug_mode: - return '<span style="color: red;">Debug</span>' + return format_html('<span style="color: red;">Debug</span>') return "Normal" - mode.allow_tags = True def save_model(self, request, obj, form, change): """ @@ -151,11 +148,10 @@ class SAMLConfigurationAdmin(KeyedConfigurationModelAdmin): public_key = inst.get_setting('SP_PUBLIC_CERT') private_key = inst.get_setting('SP_PRIVATE_KEY') if not public_key or not private_key: - return HTML(u'<em>Key pair incomplete/missing</em>') + return format_html(u'<em>Key pair incomplete/missing</em>') pub1, pub2 = public_key[0:10], public_key[-10:] priv1, priv2 = private_key[0:10], private_key[-10:] - return HTML(u'Public: {}…{}<br>Private: {}…{}').format(pub1, pub2, priv1, priv2) - key_summary.allow_tags = True + return format_html(u'Public: {}…{}<br>Private: {}…{}', pub1, pub2, priv1, priv2) admin.site.register(SAMLConfiguration, SAMLConfigurationAdmin) diff --git a/common/djangoapps/third_party_auth/api/views.py b/common/djangoapps/third_party_auth/api/views.py index b9d4705f0b46bdb795531aa800108fe7ccc6b768..52c49ea092fd20e8a4bb8aa12f3073f51caba018 100644 --- a/common/djangoapps/third_party_auth/api/views.py +++ b/common/djangoapps/third_party_auth/api/views.py @@ -399,6 +399,7 @@ class ThirdPartyAuthUserStatusView(APIView): GET /api/third_party_auth/v0/providers/user_status/ **GET Response Values** + ``` { "accepts_logins": true, "name": "Google", @@ -407,6 +408,7 @@ class ThirdPartyAuthUserStatusView(APIView): "connected": false, "id": "oa2-google-oauth2" } + ``` """ tpa_states = [] for state in pipeline.get_provider_user_states(request.user): diff --git a/common/djangoapps/third_party_auth/middleware.py b/common/djangoapps/third_party_auth/middleware.py index 836eab3a064bcfe92bb28c79ece1500f408ecb71..6a94eb9e44497f37ae51d722cd25d5de7415b0ca 100644 --- a/common/djangoapps/third_party_auth/middleware.py +++ b/common/djangoapps/third_party_auth/middleware.py @@ -1,7 +1,7 @@ """Middleware classes for third_party_auth.""" -import six.moves.urllib.parse # pylint: disable=import-error +import six.moves.urllib.parse from django.contrib import messages from django.shortcuts import redirect from django.urls import reverse diff --git a/common/djangoapps/third_party_auth/migrations/0001_squashed_0026_auto_20200401_1932.py b/common/djangoapps/third_party_auth/migrations/0001_squashed_0026_auto_20200401_1932.py new file mode 100644 index 0000000000000000000000000000000000000000..43d63f5670e1c02c36a13f7d4ec45db262df6a8b --- /dev/null +++ b/common/djangoapps/third_party_auth/migrations/0001_squashed_0026_auto_20200401_1932.py @@ -0,0 +1,175 @@ +# Generated by Django 2.2.12 on 2020-04-21 20:52 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import openedx.core.lib.hash_utils +import third_party_auth.models + +# These should be no-ops, becuse we don't need to migrate any data on initial creation. +# third_party_auth.migrations.0019_consolidate_slug +# third_party_auth.migrations.0005_add_site_field + + +class Migration(migrations.Migration): + + replaces = [('third_party_auth', '0001_initial'), ('third_party_auth', '0002_schema__provider_icon_image'), ('third_party_auth', '0003_samlproviderconfig_debug_mode'), ('third_party_auth', '0004_add_visible_field'), ('third_party_auth', '0005_add_site_field'), ('third_party_auth', '0006_samlproviderconfig_automatic_refresh_enabled'), ('third_party_auth', '0007_auto_20170406_0912'), ('third_party_auth', '0008_auto_20170413_1455'), ('third_party_auth', '0009_auto_20170415_1144'), ('third_party_auth', '0010_add_skip_hinted_login_dialog_field'), ('third_party_auth', '0011_auto_20170616_0112'), ('third_party_auth', '0012_auto_20170626_1135'), ('third_party_auth', '0013_sync_learner_profile_data'), ('third_party_auth', '0014_auto_20171222_1233'), ('third_party_auth', '0015_samlproviderconfig_archived'), ('third_party_auth', '0016_auto_20180130_0938'), ('third_party_auth', '0017_remove_icon_class_image_secondary_fields'), ('third_party_auth', '0018_auto_20180327_1631'), ('third_party_auth', '0019_consolidate_slug'), ('third_party_auth', '0020_cleanup_slug_fields'), ('third_party_auth', '0021_sso_id_verification'), ('third_party_auth', '0022_auto_20181012_0307'), ('third_party_auth', '0023_auto_20190418_2033'), ('third_party_auth', '0024_fix_edit_disallowed'), ('third_party_auth', '0025_auto_20200303_1448'), ('third_party_auth', '0026_auto_20200401_1932')] + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('organizations', '0006_auto_20171207_0259'), + ('sites', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='SAMLProviderData', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('fetched_at', models.DateTimeField(db_index=True)), + ('expires_at', models.DateTimeField(db_index=True, null=True)), + ('entity_id', models.CharField(db_index=True, max_length=255)), + ('sso_url', models.URLField(verbose_name='SSO URL')), + ('public_key', models.TextField()), + ], + options={ + 'verbose_name_plural': 'SAML Provider Data', + 'verbose_name': 'SAML Provider Data', + 'ordering': ('-fetched_at',), + }, + ), + migrations.CreateModel( + name='SAMLConfiguration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('private_key', models.TextField(blank=True, help_text='To generate a key pair as two files, run "openssl req -new -x509 -days 3652 -nodes -out saml.crt -keyout saml.key". Paste the contents of saml.key here. For increased security, you can avoid storing this in your database by leaving this field blank and setting it via the SOCIAL_AUTH_SAML_SP_PRIVATE_KEY setting in your instance\'s Django settings (or lms.auth.json).')), + ('public_key', models.TextField(blank=True, help_text="Public key certificate. For increased security, you can avoid storing this in your database by leaving this field blank and setting it via the SOCIAL_AUTH_SAML_SP_PUBLIC_CERT setting in your instance's Django settings (or lms.auth.json).")), + ('entity_id', models.CharField(default='http://saml.example.com', max_length=255, verbose_name='Entity ID')), + ('org_info_str', models.TextField(default='{"en-US": {"url": "http://www.example.com", "displayname": "Example Inc.", "name": "example"}}', help_text="JSON dictionary of 'url', 'displayname', and 'name' for each language", verbose_name='Organization Info')), + ('other_config_str', models.TextField(default='{\n"SECURITY_CONFIG": {"metadataCacheDuration": 604800, "signMetadata": false}\n}', help_text='JSON object defining advanced settings that are passed on to python-saml. Valid keys that can be set here include: SECURITY_CONFIG and SP_EXTRA')), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ('site', models.ForeignKey(default=1, help_text='The Site that this SAML configuration belongs to.', on_delete=django.db.models.deletion.CASCADE, related_name='samlconfigurations', to='sites.Site')), + ('slug', models.SlugField(default='default', help_text='A short string uniquely identifying this configuration. Cannot contain spaces. Examples: "ubc", "mit-staging"', max_length=30)), + ], + options={ + 'verbose_name_plural': 'SAML Configuration', + 'verbose_name': 'SAML Configuration', + }, + ), + migrations.CreateModel( + name='OAuth2ProviderConfig', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('icon_class', models.CharField(blank=True, default='fa-sign-in', help_text='The Font Awesome (or custom) icon class to use on the login button for this provider. Examples: fa-google-plus, fa-facebook, fa-linkedin, fa-sign-in, fa-university', max_length=50)), + ('name', models.CharField(help_text='Name of this provider (shown to users)', max_length=50)), + ('secondary', models.BooleanField(default=False, help_text='Secondary providers are displayed less prominently, in a separate list of "Institution" login providers.')), + ('skip_registration_form', models.BooleanField(default=False, help_text='If this option is enabled, users will not be asked to confirm their details (name, email, etc.) during the registration process. Only select this option for trusted providers that are known to provide accurate user information.')), + ('skip_email_verification', models.BooleanField(default=False, help_text='If this option is selected, users will not be required to confirm their email, and their account will be activated immediately upon registration.')), + ('backend_name', models.CharField(db_index=True, help_text='Which python-social-auth OAuth2 provider backend to use. The list of backend choices is determined by the THIRD_PARTY_AUTH_BACKENDS setting.', max_length=50)), + ('key', models.TextField(blank=True, verbose_name='Client ID')), + ('secret', models.TextField(blank=True, help_text='For increased security, you can avoid storing this in your database by leaving this field blank and setting SOCIAL_AUTH_OAUTH_SECRETS = {"(backend name)": "secret", ...} in your instance\'s Django settings (or lms.auth.json)', verbose_name='Client Secret')), + ('other_settings', models.TextField(blank=True, help_text='Optional JSON object with advanced settings, if any.')), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ('icon_image', models.FileField(blank=True, help_text='If there is no Font Awesome icon available for this provider, upload a custom image. SVG images are recommended as they can scale to any size.', upload_to='')), + ('visible', models.BooleanField(default=False, help_text='If this option is not selected, users will not be presented with the provider as an option to authenticate with on the login screen, but manual authentication using the correct link is still possible.')), + ('site', models.ForeignKey(default=1, help_text='The Site that this provider configuration belongs to.', on_delete=django.db.models.deletion.CASCADE, related_name='oauth2providerconfigs', to='sites.Site')), + ('max_session_length', models.PositiveIntegerField(blank=True, default=None, help_text='If this option is set, then users logging in using this SSO provider will have their session length limited to no longer than this value. If set to 0 (zero), the session will expire upon the user closing their browser. If left blank, the Django platform session default length will be used.', null=True, verbose_name='Max session length (seconds)')), + ('skip_hinted_login_dialog', models.BooleanField(default=False, help_text='If this option is enabled, users that visit a "TPA hinted" URL for this provider (e.g. a URL ending with `?tpa_hint=[provider_name]`) will be forwarded directly to the login URL of the provider instead of being first prompted with a login dialog.')), + ('send_to_registration_first', models.BooleanField(default=False, help_text='If this option is selected, users will be directed to the registration page immediately after authenticating with the third party instead of the login page.')), + ('sync_learner_profile_data', models.BooleanField(default=False, help_text='Synchronize user profile data received from the identity provider with the edX user account on each SSO login. The user will be notified if the email address associated with their account is changed as a part of this synchronization.')), + ('send_welcome_email', models.BooleanField(default=False, help_text='If this option is selected, users will be sent a welcome email upon registration.')), + ('slug', models.SlugField(default='default', help_text='A short string uniquely identifying this provider. Cannot contain spaces and should be a usable as a CSS class. Examples: "ubc", "mit-staging"', max_length=30)), + ('enable_sso_id_verification', models.BooleanField(default=False, help_text='Use the presence of a profile from a trusted third party as proof of identity verification.')), + ('organization', models.ForeignKey(blank=True, help_text='optional. If this provider is an Organization, this attribute can be used reference users in that Organization', null=True, on_delete=django.db.models.deletion.CASCADE, to='organizations.Organization')), + ], + options={ + 'verbose_name_plural': 'Provider Configuration (OAuth)', + 'verbose_name': 'Provider Configuration (OAuth)', + }, + ), + migrations.CreateModel( + name='LTIProviderConfig', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('name', models.CharField(help_text='Name of this provider (shown to users)', max_length=50)), + ('skip_registration_form', models.BooleanField(default=False, help_text='If this option is enabled, users will not be asked to confirm their details (name, email, etc.) during the registration process. Only select this option for trusted providers that are known to provide accurate user information.')), + ('skip_email_verification', models.BooleanField(default=False, help_text='If this option is selected, users will not be required to confirm their email, and their account will be activated immediately upon registration.')), + ('lti_consumer_key', models.CharField(help_text='The name that the LTI Tool Consumer will use to identify itself', max_length=255)), + ('lti_hostname', models.CharField(db_index=True, default='localhost', help_text='The domain that will be acting as the LTI consumer.', max_length=255)), + ('lti_consumer_secret', models.CharField(blank=True, default=openedx.core.lib.hash_utils.create_hash256, help_text='The shared secret that the LTI Tool Consumer will use to authenticate requests. Only this edX instance and this tool consumer instance should know this value. For increased security, you can avoid storing this in your database by leaving this field blank and setting SOCIAL_AUTH_LTI_CONSUMER_SECRETS = {"consumer key": "secret", ...} in your instance\'s Django setttigs (or lms.auth.json)', max_length=255)), + ('lti_max_timestamp_age', models.IntegerField(default=10, help_text='The maximum age of oauth_timestamp values, in seconds.')), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ('visible', models.BooleanField(default=False, help_text='If this option is not selected, users will not be presented with the provider as an option to authenticate with on the login screen, but manual authentication using the correct link is still possible.')), + ('site', models.ForeignKey(default=1, help_text='The Site that this provider configuration belongs to.', on_delete=django.db.models.deletion.CASCADE, related_name='ltiproviderconfigs', to='sites.Site')), + ('max_session_length', models.PositiveIntegerField(blank=True, default=None, help_text='If this option is set, then users logging in using this SSO provider will have their session length limited to no longer than this value. If set to 0 (zero), the session will expire upon the user closing their browser. If left blank, the Django platform session default length will be used.', null=True, verbose_name='Max session length (seconds)')), + ('skip_hinted_login_dialog', models.BooleanField(default=False, help_text='If this option is enabled, users that visit a "TPA hinted" URL for this provider (e.g. a URL ending with `?tpa_hint=[provider_name]`) will be forwarded directly to the login URL of the provider instead of being first prompted with a login dialog.')), + ('send_to_registration_first', models.BooleanField(default=False, help_text='If this option is selected, users will be directed to the registration page immediately after authenticating with the third party instead of the login page.')), + ('sync_learner_profile_data', models.BooleanField(default=False, help_text='Synchronize user profile data received from the identity provider with the edX user account on each SSO login. The user will be notified if the email address associated with their account is changed as a part of this synchronization.')), + ('send_welcome_email', models.BooleanField(default=False, help_text='If this option is selected, users will be sent a welcome email upon registration.')), + ('slug', models.SlugField(default='default', help_text='A short string uniquely identifying this provider. Cannot contain spaces and should be a usable as a CSS class. Examples: "ubc", "mit-staging"', max_length=30)), + ('enable_sso_id_verification', models.BooleanField(default=False, help_text='Use the presence of a profile from a trusted third party as proof of identity verification.')), + ('organization', models.ForeignKey(blank=True, help_text='optional. If this provider is an Organization, this attribute can be used reference users in that Organization', null=True, on_delete=django.db.models.deletion.CASCADE, to='organizations.Organization')), + ], + options={ + 'verbose_name_plural': 'Provider Configuration (LTI)', + 'verbose_name': 'Provider Configuration (LTI)', + }, + ), + migrations.CreateModel( + name='SAMLProviderConfig', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('icon_class', models.CharField(blank=True, default='fa-sign-in', help_text='The Font Awesome (or custom) icon class to use on the login button for this provider. Examples: fa-google-plus, fa-facebook, fa-linkedin, fa-sign-in, fa-university', max_length=50)), + ('name', models.CharField(help_text='Name of this provider (shown to users)', max_length=50)), + ('secondary', models.BooleanField(default=False, help_text='Secondary providers are displayed less prominently, in a separate list of "Institution" login providers.')), + ('skip_registration_form', models.BooleanField(default=False, help_text='If this option is enabled, users will not be asked to confirm their details (name, email, etc.) during the registration process. Only select this option for trusted providers that are known to provide accurate user information.')), + ('skip_email_verification', models.BooleanField(default=False, help_text='If this option is selected, users will not be required to confirm their email, and their account will be activated immediately upon registration.')), + ('backend_name', models.CharField(default='tpa-saml', help_text="Which python-social-auth provider backend to use. 'tpa-saml' is the standard edX SAML backend.", max_length=50)), + ('entity_id', models.CharField(help_text='Example: https://idp.testshib.org/idp/shibboleth', max_length=255, verbose_name='Entity ID')), + ('metadata_source', models.CharField(help_text="URL to this provider's XML metadata. Should be an HTTPS URL. Example: https://www.testshib.org/metadata/testshib-providers.xml", max_length=255)), + ('attr_user_permanent_id', models.CharField(blank=True, help_text='URN of the SAML attribute that we can use as a unique, persistent user ID. Leave blank for default.', max_length=128, verbose_name='User ID Attribute')), + ('attr_full_name', models.CharField(blank=True, help_text="URN of SAML attribute containing the user's full name. Leave blank for default.", max_length=128, verbose_name='Full Name Attribute')), + ('attr_first_name', models.CharField(blank=True, help_text="URN of SAML attribute containing the user's first name. Leave blank for default.", max_length=128, verbose_name='First Name Attribute')), + ('attr_last_name', models.CharField(blank=True, help_text="URN of SAML attribute containing the user's last name. Leave blank for default.", max_length=128, verbose_name='Last Name Attribute')), + ('attr_username', models.CharField(blank=True, help_text='URN of SAML attribute to use as a suggested username for this user. Leave blank for default.', max_length=128, verbose_name='Username Hint Attribute')), + ('attr_email', models.CharField(blank=True, help_text="URN of SAML attribute containing the user's email address[es]. Leave blank for default.", max_length=128, verbose_name='Email Attribute')), + ('other_settings', models.TextField(blank=True, help_text='For advanced use cases, enter a JSON object with addtional configuration. The tpa-saml backend supports {"requiredEntitlements": ["urn:..."]}, which can be used to require the presence of a specific eduPersonEntitlement, and {"extra_field_definitions": [{"name": "...", "urn": "..."},...]}, which can be used to define registration form fields and the URNs that can be used to retrieve the relevant values from the SAML response. Custom provider types, as selected in the "Identity Provider Type" field, may make use of the information stored in this field for additional configuration.', verbose_name='Advanced settings')), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ('icon_image', models.FileField(blank=True, help_text='If there is no Font Awesome icon available for this provider, upload a custom image. SVG images are recommended as they can scale to any size.', upload_to='')), + ('debug_mode', models.BooleanField(default=False, help_text='In debug mode, all SAML XML requests and responses will be logged. This is helpful for testing/setup but should always be disabled before users start using this provider.', verbose_name='Debug Mode')), + ('visible', models.BooleanField(default=False, help_text='If this option is not selected, users will not be presented with the provider as an option to authenticate with on the login screen, but manual authentication using the correct link is still possible.')), + ('site', models.ForeignKey(default=1, help_text='The Site that this provider configuration belongs to.', on_delete=django.db.models.deletion.CASCADE, related_name='samlproviderconfigs', to='sites.Site')), + ('automatic_refresh_enabled', models.BooleanField(default=True, help_text="When checked, the SAML provider's metadata will be included in the automatic refresh job, if configured.", verbose_name='Enable automatic metadata refresh')), + ('identity_provider_type', models.CharField(choices=[('standard_saml_provider', 'Standard SAML provider'), ('sap_success_factors', 'SAP SuccessFactors provider')], default='standard_saml_provider', help_text='Some SAML providers require special behavior. For example, SAP SuccessFactors SAML providers require an additional API call to retrieve user metadata not provided in the SAML response. Select the provider type which best matches your use case. If in doubt, choose the Standard SAML Provider type.', max_length=128, verbose_name='Identity Provider Type')), + ('max_session_length', models.PositiveIntegerField(blank=True, default=None, help_text='If this option is set, then users logging in using this SSO provider will have their session length limited to no longer than this value. If set to 0 (zero), the session will expire upon the user closing their browser. If left blank, the Django platform session default length will be used.', null=True, verbose_name='Max session length (seconds)')), + ('skip_hinted_login_dialog', models.BooleanField(default=False, help_text='If this option is enabled, users that visit a "TPA hinted" URL for this provider (e.g. a URL ending with `?tpa_hint=[provider_name]`) will be forwarded directly to the login URL of the provider instead of being first prompted with a login dialog.')), + ('send_to_registration_first', models.BooleanField(default=False, help_text='If this option is selected, users will be directed to the registration page immediately after authenticating with the third party instead of the login page.')), + ('sync_learner_profile_data', models.BooleanField(default=False, help_text='Synchronize user profile data received from the identity provider with the edX user account on each SSO login. The user will be notified if the email address associated with their account is changed as a part of this synchronization.')), + ('archived', models.BooleanField(default=False)), + ('saml_configuration', models.ForeignKey(blank=True, limit_choices_to=third_party_auth.models.active_saml_configurations_filter, null=True, on_delete=django.db.models.deletion.SET_NULL, to='third_party_auth.SAMLConfiguration')), + ('send_welcome_email', models.BooleanField(default=False, help_text='If this option is selected, users will be sent a welcome email upon registration.')), + ('slug', models.SlugField(default='default', help_text='A short string uniquely identifying this provider. Cannot contain spaces and should be a usable as a CSS class. Examples: "ubc", "mit-staging"', max_length=30)), + ('enable_sso_id_verification', models.BooleanField(default=False, help_text='Use the presence of a profile from a trusted third party as proof of identity verification.')), + ('default_email', models.CharField(blank=True, help_text='Default value for email to be used if not present in SAML response.', max_length=255, verbose_name='Default Value for Email')), + ('default_first_name', models.CharField(blank=True, help_text='Default value for first name to be used if not present in SAML response.', max_length=255, verbose_name='Default Value for First Name')), + ('default_full_name', models.CharField(blank=True, help_text='Default value for full name to be used if not present in SAML response.', max_length=255, verbose_name='Default Value for Full Name')), + ('default_last_name', models.CharField(blank=True, help_text='Default value for last name to be used if not present in SAML response.', max_length=255, verbose_name='Default Value for Last Name')), + ('default_username', models.CharField(blank=True, help_text='Default value for username to be used if not present in SAML response.', max_length=255, verbose_name='Default Value for Username')), + ('organization', models.ForeignKey(blank=True, help_text='optional. If this provider is an Organization, this attribute can be used reference users in that Organization', null=True, on_delete=django.db.models.deletion.CASCADE, to='organizations.Organization')), + ], + options={ + 'verbose_name_plural': 'Provider Configuration (SAML IdPs)', + 'verbose_name': 'Provider Configuration (SAML IdP)', + }, + ), + ] diff --git a/common/djangoapps/third_party_auth/models.py b/common/djangoapps/third_party_auth/models.py index 48a29ffa612398288d654fd313574a185650bff0..8edc0d9d2d7666108090db97bb388018c0116bb5 100644 --- a/common/djangoapps/third_party_auth/models.py +++ b/common/djangoapps/third_party_auth/models.py @@ -332,7 +332,7 @@ class ProviderConfig(ConfigurationModel): """ Determines if the provider is able to be used with the current site. """ - return self.enabled and self.site == Site.objects.get_current(get_current_request()) + return self.enabled and self.site_id == Site.objects.get_current(get_current_request()).id class OAuth2ProviderConfig(ProviderConfig): @@ -366,7 +366,7 @@ class OAuth2ProviderConfig(ProviderConfig): help_text=( u'For increased security, you can avoid storing this in your database by leaving ' ' this field blank and setting ' - 'SOCIAL_AUTH_OAUTH_SECRETS = {"(backend name)": "secret", ...} ' # pylint: disable=unicode-format-string + 'SOCIAL_AUTH_OAUTH_SECRETS = {"(backend name)": "secret", ...} ' 'in your instance\'s Django settings (or lms.auth.json)' ) ) @@ -622,9 +622,9 @@ class SAMLProviderConfig(ProviderConfig): verbose_name=u"Advanced settings", blank=True, help_text=( u'For advanced use cases, enter a JSON object with addtional configuration. ' - 'The tpa-saml backend supports {"requiredEntitlements": ["urn:..."]}, ' # pylint: disable=unicode-format-string + 'The tpa-saml backend supports {"requiredEntitlements": ["urn:..."]}, ' 'which can be used to require the presence of a specific eduPersonEntitlement, ' - 'and {"extra_field_definitions": [{"name": "...", "urn": "..."},...]}, which can be ' # pylint: disable=unicode-format-string + 'and {"extra_field_definitions": [{"name": "...", "urn": "..."},...]}, which can be ' 'used to define registration form fields and the URNs that can be used to retrieve ' 'the relevant values from the SAML response. Custom provider types, as selected ' 'in the "Identity Provider Type" field, may make use of the information stored ' @@ -718,7 +718,7 @@ class SAMLProviderConfig(ProviderConfig): data = SAMLProviderData.current(self.entity_id) if not data or not data.is_valid(): log.error( - 'No SAMLProviderData found for provider "%s" with entity id "%s" and IdP slug "%s". ' # pylint: disable=unicode-format-string + 'No SAMLProviderData found for provider "%s" with entity id "%s" and IdP slug "%s". ' 'Run "manage.py saml pull" to fix or debug.', self.name, self.entity_id, self.slug ) @@ -833,7 +833,7 @@ class LTIProviderConfig(ProviderConfig): 'tool consumer instance should know this value. ' 'For increased security, you can avoid storing this in ' 'your database by leaving this field blank and setting ' - 'SOCIAL_AUTH_LTI_CONSUMER_SECRETS = {"consumer key": "secret", ...} ' # pylint: disable=unicode-format-string + 'SOCIAL_AUTH_LTI_CONSUMER_SECRETS = {"consumer key": "secret", ...} ' 'in your instance\'s Django setttigs (or lms.auth.json)' ), blank=True, diff --git a/common/djangoapps/third_party_auth/pipeline.py b/common/djangoapps/third_party_auth/pipeline.py index 84ecefabec3e6e115bdd8c64c3089b014f7a9e21..18924f21ce894694e8a90170eeaf69bc8839bc38 100644 --- a/common/djangoapps/third_party_auth/pipeline.py +++ b/common/djangoapps/third_party_auth/pipeline.py @@ -85,6 +85,7 @@ from edxmako.shortcuts import render_to_string from lms.djangoapps.verify_student.models import SSOVerification from lms.djangoapps.verify_student.utils import earliest_allowed_verification_date from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers +from openedx.core.djangoapps.user_api import accounts from openedx.core.djangoapps.user_authn import cookies as user_authn_cookies from third_party_auth.utils import user_exists from track import segment @@ -850,7 +851,10 @@ def set_id_verification_status(auth_entry, strategy, details, user=None, *args, def get_username(strategy, details, backend, user=None, *args, **kwargs): """ - Copy of social_core.pipeline.user.get_username with additional logging and case insensitive username checks. + Copy of social_core.pipeline.user.get_username to achieve + 1. additional logging + 2. case insensitive username checks + 3. enforce same maximum and minimum length restrictions we have in `user_api/accounts` """ if 'username' not in backend.setting('USER_FIELDS', USER_FIELDS): return @@ -859,7 +863,8 @@ def get_username(strategy, details, backend, user=None, *args, **kwargs): if not user: email_as_username = strategy.setting('USERNAME_IS_FULL_EMAIL', False) uuid_length = strategy.setting('UUID_LENGTH', 16) - max_length = storage.user.username_max_length() + min_length = strategy.setting('USERNAME_MIN_LENGTH', accounts.USERNAME_MIN_LENGTH) + max_length = strategy.setting('USERNAME_MAX_LENGTH', accounts.USERNAME_MAX_LENGTH) do_slugify = strategy.setting('SLUGIFY_USERNAMES', False) do_clean = strategy.setting('CLEAN_USERNAMES', True) @@ -898,7 +903,7 @@ def get_username(strategy, details, backend, user=None, *args, **kwargs): # username is cut to avoid any field max_length. # The final_username may be empty and will skip the loop. # We are using our own version of user_exists to avoid possible case sensitivity issues. - while not final_username or user_exists({'username': final_username}): + while not final_username or len(final_username) < min_length or user_exists({'username': final_username}): username = short_username + uuid4().hex[:uuid_length] final_username = slug_func(clean_func(username[:max_length])) logger.info(u'[THIRD_PARTY_AUTH] New username generated. Username: {username}'.format( diff --git a/common/djangoapps/third_party_auth/saml.py b/common/djangoapps/third_party_auth/saml.py index a475e4924f521f1ebdb32efe5f064e73ec726ee5..6a06a86d46194971bd97450544a64ce247701a39 100644 --- a/common/djangoapps/third_party_auth/saml.py +++ b/common/djangoapps/third_party_auth/saml.py @@ -169,19 +169,24 @@ class SAMLAuthBackend(SAMLAuth): # pylint: disable=abstract-method from .models import SAMLProviderConfig if SAMLProviderConfig.current(idp.name).debug_mode: - def wrap_with_logging(method_name, action_description, xml_getter): + def wrap_with_logging(method_name, action_description, xml_getter, request_data, next_url): """ Wrap the request and response handlers to add debug mode logging """ method = getattr(auth_inst, method_name) def wrapped_method(*args, **kwargs): """ Wrapped login or process_response method """ result = method(*args, **kwargs) - log.info(u"SAML login %s for IdP %s. XML is:\n%s", action_description, idp.name, xml_getter()) + log.info( + u"SAML login %s for IdP %s. Data: %s. Next url %s. XML is:\n%s", + action_description, idp.name, request_data, next_url, xml_getter() + ) return result setattr(auth_inst, method_name, wrapped_method) - wrap_with_logging("login", "request", auth_inst.get_last_request_xml) - wrap_with_logging("process_response", "response", auth_inst.get_last_response_xml) + request_data = self.strategy.request_data() + next_url = self.strategy.session_get('next') + wrap_with_logging("login", "request", auth_inst.get_last_request_xml, request_data, next_url) + wrap_with_logging("process_response", "response", auth_inst.get_last_response_xml, request_data, next_url) return auth_inst diff --git a/common/djangoapps/third_party_auth/settings.py b/common/djangoapps/third_party_auth/settings.py index 0f6a4536c3f835e15b8a3d8f5fc93c191dc45ad5..b28f810df6d3fde52ec4b97bad440453b960eb3f 100644 --- a/common/djangoapps/third_party_auth/settings.py +++ b/common/djangoapps/third_party_auth/settings.py @@ -81,6 +81,9 @@ def apply_settings(django_settings): # enable this when you want to get stack traces rather than redirections. django_settings.SOCIAL_AUTH_RAISE_EXCEPTIONS = False + # Clean username to make sure username is compatible with our system requirements + django_settings.SOCIAL_AUTH_CLEAN_USERNAME_FUNCTION = 'third_party_auth.models.clean_username' + # Allow users to login using social auth even if their account is not verified yet # This is required since we [ab]use django's 'is_active' flag to indicate verified # accounts; without this set to True, python-social-auth won't allow us to link the diff --git a/common/djangoapps/third_party_auth/tests/specs/test_testshib.py b/common/djangoapps/third_party_auth/tests/specs/test_testshib.py index 8018bc1068a7e2c1f9ccba5a340d5fee1081ba35..a4a154f822101e21d4144f8c7c54a70860c1c9a4 100644 --- a/common/djangoapps/third_party_auth/tests/specs/test_testshib.py +++ b/common/djangoapps/third_party_auth/tests/specs/test_testshib.py @@ -308,16 +308,25 @@ class TestShibIntegrationTest(SamlIntegrationTestUtilities, IntegrationTestMixin # logs - one for the request and one for the response self.assertEqual(mock_log.call_count, 4) - (msg, action_type, idp_name, xml), _kwargs = mock_log.call_args_list[0] + expected_next_url = "/dashboard" + (msg, action_type, idp_name, request_data, next_url, xml), _kwargs = mock_log.call_args_list[0] self.assertTrue(msg.startswith(u"SAML login %s")) self.assertEqual(action_type, "request") self.assertEqual(idp_name, self.PROVIDER_IDP_SLUG) + self.assertDictContainsSubset( + {"idp": idp_name, "auth_entry": "login", "next": expected_next_url}, + request_data + ) + self.assertEqual(next_url, expected_next_url) self.assertIn('<samlp:AuthnRequest', xml) - (msg, action_type, idp_name, xml), _kwargs = mock_log.call_args_list[1] + (msg, action_type, idp_name, response_data, next_url, xml), _kwargs = mock_log.call_args_list[1] self.assertTrue(msg.startswith(u"SAML login %s")) self.assertEqual(action_type, "response") self.assertEqual(idp_name, self.PROVIDER_IDP_SLUG) + self.assertDictContainsSubset({"RelayState": idp_name}, response_data) + self.assertIn('SAMLResponse', response_data) + self.assertEqual(next_url, expected_next_url) self.assertIn('<saml2p:Response', xml) else: self.assertFalse(mock_log.called) @@ -454,7 +463,7 @@ class SuccessFactorsIntegrationTest(SamlIntegrationTestUtilities, IntegrationTes Mock an error response when calling the OData API for user details. """ - def callback(request, uri, headers): # pylint: disable=unused-argument + def callback(request, uri, headers): """ Return a 500 error when someone tries to call the URL. """ diff --git a/common/djangoapps/third_party_auth/tests/test_identityserver3.py b/common/djangoapps/third_party_auth/tests/test_identityserver3.py index fa958356461017fa88219c07c1ffd4d0465a6d5e..7c3c6d54672a604c6a18205c219239147a56ddff 100644 --- a/common/djangoapps/third_party_auth/tests/test_identityserver3.py +++ b/common/djangoapps/third_party_auth/tests/test_identityserver3.py @@ -47,7 +47,7 @@ class IdentityServer3Test(testutil.TestCase): test that a KeyError is thrown if the "sub" claim does not exist """ response = {"id": 1} - self.assertRaises(KeyError, self.id3_instance.get_user_id({}, response)) + self.assertRaises(TypeError, self.id3_instance.get_user_id({}, response)) def test_proper_config_access(self): """ diff --git a/common/djangoapps/third_party_auth/tests/test_pipeline.py b/common/djangoapps/third_party_auth/tests/test_pipeline.py index 2374c4827e7d4fd819b828ba8d65c6f50f00ba1f..9613706cf65d1a5a78154668856f40bc2d333817 100644 --- a/common/djangoapps/third_party_auth/tests/test_pipeline.py +++ b/common/djangoapps/third_party_auth/tests/test_pipeline.py @@ -9,6 +9,8 @@ import mock from third_party_auth import pipeline from third_party_auth.tests import testutil +from third_party_auth.tests.specs.base import IntegrationTestMixin +from third_party_auth.tests.specs.test_testshib import SamlIntegrationTestUtilities from third_party_auth.tests.testutil import simulate_running_pipeline @@ -50,3 +52,49 @@ class ProviderUserStateTestCase(testutil.TestCase): with simulate_running_pipeline("third_party_auth.pipeline", backend_name, **kwargs): logout_url = pipeline.get_idp_logout_url_from_running_pipeline(request) self.assertEqual(idp_config['logout_url'], logout_url) + + +@unittest.skipUnless(testutil.AUTH_FEATURE_ENABLED, testutil.AUTH_FEATURES_KEY + ' not enabled') +@ddt.ddt +class PipelineOverridesTest(SamlIntegrationTestUtilities, IntegrationTestMixin, testutil.SAMLTestCase): + """ + Tests for pipeline overrides + """ + + def setUp(self): + super(PipelineOverridesTest, self).setUp() + self.enable_saml() + self.provider = self.configure_saml_provider( + enabled=True, + name="Test Provider", + slug='test', + backend_name='tpa-saml' + ) + + @ddt.data( + ('S', 'S9fe2', False), + ('S', 'S9fe2', True), + ('S.K', 'S_K', False), + ('S.K.', 'S_K_', False), + ('S.K.', 'S_K_9fe2', True), + ('usernamewithcharacterlengthofmorethan30chars', 'usernamewithcharacterlengthofm', False), + ('usernamewithcharacterlengthofmorethan30chars', 'usernamewithcharacterlengt9fe2', True), + ) + @ddt.unpack + @mock.patch('third_party_auth.pipeline.user_exists') + def test_get_username_in_pipeline(self, idp_username, expected_username, already_exists, mock_user_exists): + """ + Test get_username method of running pipeline + """ + details = { + "username": idp_username, + "email": "test@example.com" + } + mock_user_exists.side_effect = [already_exists, False] + __, strategy = self.get_request_and_strategy() + with mock.patch('third_party_auth.pipeline.uuid4') as mock_uuid: + uuid4 = mock.Mock() + type(uuid4).hex = mock.PropertyMock(return_value='9fe2c4e93f654fdbb24c02b15259716c') + mock_uuid.return_value = uuid4 + final_username = pipeline.get_username(strategy, details, self.provider.backend_class()) + self.assertEqual(expected_username, final_username['username']) diff --git a/common/djangoapps/third_party_auth/tests/test_provider.py b/common/djangoapps/third_party_auth/tests/test_provider.py index b1a3deaa2ca5ad35818102d9ad3f585a163874be..36497bef005687fa0f800e08991f1ab3f798e192 100644 --- a/common/djangoapps/third_party_auth/tests/test_provider.py +++ b/common/djangoapps/third_party_auth/tests/test_provider.py @@ -1,9 +1,12 @@ """Unit tests for provider.py.""" +import re import unittest from django.contrib.sites.models import Site +from django.db import connections, DEFAULT_DB_ALIAS +from django.test.utils import CaptureQueriesContext from mock import Mock, patch from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration @@ -75,6 +78,24 @@ class RegistryTest(testutil.TestCase): with patch('third_party_auth.provider._PSA_OAUTH2_BACKENDS', backend_names): self.assertEqual(sorted(provider_names), [prov.name for prov in provider.Registry.enabled()]) + def test_enabled_doesnt_query_site(self): + """Regression test for 1+N queries for django_site (ARCHBOM-1139)""" + re_django_site_query = re.compile(r'FROM\s+"django_site"') + + self.enable_saml() + provider_count = 5 + for i in range(provider_count): + self.configure_saml_provider(enabled=True, slug="saml-slug-%s" % i) + + with CaptureQueriesContext(connections[DEFAULT_DB_ALIAS]) as cq: + enabled_slugs = {p.slug for p in provider.Registry.enabled()} + + self.assertEqual(len(enabled_slugs), provider_count) + # Should not involve any queries for Site, or at least should not *scale* with number of providers + all_queries = [q['sql'] for q in cq.captured_queries] + django_site_queries = list(filter(re_django_site_query.search, all_queries)) + self.assertEqual(len(django_site_queries), 0) # previously was == provider_count (1 for each provider) + def test_providers_displayed_for_login(self): """ Tests to ensure that only providers that we can use to log in are presented diff --git a/common/djangoapps/third_party_auth/tests/test_views.py b/common/djangoapps/third_party_auth/tests/test_views.py index 2f2687db8897ca723414d0a37aadd76c36d9358f..7bc3248161ef9ebb98a02115f98ac7711aefee65 100644 --- a/common/djangoapps/third_party_auth/tests/test_views.py +++ b/common/djangoapps/third_party_auth/tests/test_views.py @@ -56,8 +56,8 @@ class SAMLMetadataTest(SAMLTestCase): self.enable_saml( other_config_str=( '{' - '"TECHNICAL_CONTACT": {"givenName": "Jane Tech", "emailAddress": "jane@example.com"},' # pylint: disable=unicode-format-string - '"SUPPORT_CONTACT": {"givenName": "Joe Support", "emailAddress": "joe@example.com"}' # pylint: disable=unicode-format-string + '"TECHNICAL_CONTACT": {"givenName": "Jane Tech", "emailAddress": "jane@example.com"},' + '"SUPPORT_CONTACT": {"givenName": "Joe Support", "emailAddress": "joe@example.com"}' '}' ) ) diff --git a/common/djangoapps/track/tests/test_contexts.py b/common/djangoapps/track/tests/test_contexts.py index 4c633b36123d0f1b91258daa7a0a7c79ba34a4a3..c1fad8838cba555e29b2ec605775005b56ee56ee 100644 --- a/common/djangoapps/track/tests/test_contexts.py +++ b/common/djangoapps/track/tests/test_contexts.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - from unittest import TestCase import ddt diff --git a/common/djangoapps/track/tests/test_middleware.py b/common/djangoapps/track/tests/test_middleware.py index 3f3b823b04e3ff4b63e851d54269b9de57ed00ef..7de0cda2f75008e5ae0730cd8d320fbe869bcc7f 100644 --- a/common/djangoapps/track/tests/test_middleware.py +++ b/common/djangoapps/track/tests/test_middleware.py @@ -45,8 +45,7 @@ class TrackMiddlewareTestCase(TestCase): When HTTP headers contains latin1 characters. """ request = self.request_factory.get('/somewhere') - # pylint: disable=no-member - request.META[meta_key] = 'test latin1 \xd3 \xe9 \xf1' # pylint: disable=no-member + request.META[meta_key] = 'test latin1 \xd3 \xe9 \xf1' context = self.get_context_for_request(request) self.assertEqual(context[context_key], u'test latin1 Ó é ñ') diff --git a/common/djangoapps/track/tracker.py b/common/djangoapps/track/tracker.py index e6f2e9552467e153053283116ecd0e3012053d03..67cd9d33fedd34ff59dc8a94755b258684eff0cd 100644 --- a/common/djangoapps/track/tracker.py +++ b/common/djangoapps/track/tracker.py @@ -1,4 +1,5 @@ """ +WARNING! track.tracker module is deprecated please use eventtracking app to track events Module that tracks analytics events by sending them to different configurable backends. @@ -20,6 +21,7 @@ below:: import inspect +import warnings from importlib import import_module import six @@ -87,7 +89,9 @@ def send(event): Send an event object to all the initialized backends. """ - + warnings.warn( + 'track.tracker module is deprecated. Please use eventtracking to send events.', DeprecationWarning + ) for name, backend in six.iteritems(backends): backend.send(event) diff --git a/common/djangoapps/track/views/__init__.py b/common/djangoapps/track/views/__init__.py index a434a1dc43b598a4f99719ee1f78129342f2ca8d..dd975e3b2c15ebf437824ea3760c9b9233e9d52e 100644 --- a/common/djangoapps/track/views/__init__.py +++ b/common/djangoapps/track/views/__init__.py @@ -1,27 +1,16 @@ -import datetime import json - -import pytz import six -from django.contrib.auth.decorators import login_required + from django.contrib.auth.models import User from django.http import HttpResponse -from django.shortcuts import redirect -from django.views.decorators.csrf import ensure_csrf_cookie from eventtracking import tracker as eventtracker from ipware.ip import get_ip -from edxmako.shortcuts import render_to_response from track import contexts, shim, tracker -def log_event(event): - """Capture a event by sending it to the register trackers""" - tracker.send(event) - - def _get_request_header(request, header_name, default=''): """Helper method to get header values from a request's META dict, if present.""" if request is not None and hasattr(request, 'META') and header_name in request.META: @@ -48,6 +37,18 @@ def _get_request_value(request, value_name, default=''): return default +def _get_course_context(page): + """Return the course context from the provided page. + + If the context has no/empty course_id, return empty context + """ + course_context = contexts.course_context_from_url(page) + if course_context.get('course_id', '') == '': + course_context = {} + + return course_context + + def _add_user_id_for_username(data): """ If data contains a username, adds the corresponding user_id to the data. @@ -111,27 +112,16 @@ def server_track(request, event_type, event, page=None): except: username = "anonymous" - # define output: - event = { - "username": username, - "ip": _get_request_ip(request), - "referer": _get_request_header(request, 'HTTP_REFERER'), - "accept_language": _get_request_header(request, 'HTTP_ACCEPT_LANGUAGE'), - "event_source": "server", - "event_type": event_type, - "event": event, - "agent": _get_request_header(request, 'HTTP_USER_AGENT').encode().decode('latin1'), - "page": page, - "time": datetime.datetime.utcnow().replace(tzinfo=pytz.utc), - "host": _get_request_header(request, 'SERVER_NAME'), - "context": eventtracker.get_tracker().resolve_context(), - } - - # Some duplicated fields are passed into event-tracking via the context by track.middleware. - # Remove them from the event here since they are captured elsewhere. - shim.remove_shim_context(event) - - log_event(event) + context_override = _get_course_context(page) + context_override.update({ + 'username': username, + 'event_source': 'server', + 'page': page + }) + + event_tracker = eventtracker.get_tracker() + with event_tracker.context('edx.course.server', context_override): + eventtracker.emit(name=event_type, data=event) def task_track(request_info, task_info, event_type, event, page=None): @@ -156,22 +146,17 @@ def task_track(request_info, task_info, event_type, event, page=None): # supplement event information with additional information # about the task in which it is running. - full_event = dict(event, **task_info) - - # Get values from the task-level - # information, or just add placeholder values. - with eventtracker.get_tracker().context('edx.course.task', contexts.course_context_from_url(page)): - event = { - "username": request_info.get('username', 'unknown'), - "ip": request_info.get('ip', 'unknown'), - "event_source": "task", - "event_type": event_type, - "event": full_event, - "agent": request_info.get('agent', 'unknown'), - "page": page, - "time": datetime.datetime.utcnow().replace(tzinfo=pytz.utc), - "host": request_info.get('host', 'unknown'), - "context": eventtracker.get_tracker().resolve_context(), - } - - log_event(event) + data = dict(event, **task_info) + + context_override = contexts.course_context_from_url(page) + context_override.update({ + 'username': request_info.get('username', 'unknown'), + 'ip': request_info.get('ip', 'unknown'), + 'agent': request_info.get('agent', 'unknown'), + 'host': request_info.get('host', 'unknown'), + 'event_source': 'task', + 'page': page, + }) + + with eventtracker.get_tracker().context('edx.course.task', context_override): + eventtracker.emit(name=event_type, data=data) diff --git a/common/djangoapps/track/views/tests/test_views.py b/common/djangoapps/track/views/tests/test_views.py index 44cb9e0ffbc6ccff4aff7deabb9c8b47ae78d4f7..c9cb595b75c0b2b2b89738e0f325bea63671c5b8 100644 --- a/common/djangoapps/track/views/tests/test_views.py +++ b/common/djangoapps/track/views/tests/test_views.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring,maybe-no-member - - import ddt import six from django.contrib.auth.models import User @@ -31,6 +28,7 @@ class TestTrackViews(EventTrackingTestCase): self.request_factory = RequestFactory() patcher = patch('track.views.tracker', autospec=True) + self.mock_tracker = patcher.start() self.addCleanup(patcher.stop) @@ -198,24 +196,18 @@ class TestTrackViews(EventTrackingTestCase): views.server_track(request, str(sentinel.event_type), '{}') expected_event = { - 'accept_language': '', - 'referer': '', - 'username': 'anonymous', - 'ip': '127.0.0.1', - 'event_source': 'server', - 'event_type': str(sentinel.event_type), - 'event': '{}', - 'agent': '', - 'page': None, - 'time': FROZEN_TIME, - 'host': 'testserver', - 'context': {}, + 'timestamp': FROZEN_TIME, + 'data': '{}', + 'name': str(sentinel.event_type), + 'context': + { + 'username': 'anonymous', + 'page': None, + 'event_source': 'server' + } } - self.assert_mock_tracker_call_matches(expected_event) - def assert_mock_tracker_call_matches(self, expected_event): - self.assertEqual(len(self.mock_tracker.send.mock_calls), 1) - actual_event = self.mock_tracker.send.mock_calls[0][1][0] + actual_event = self.get_event() assert_event_matches(expected_event, actual_event) def test_server_track_with_middleware(self): @@ -228,28 +220,35 @@ class TestTrackViews(EventTrackingTestCase): views.server_track(request, str(sentinel.event_type), '{}') expected_event = { - 'accept_language': '', - 'referer': '', - 'username': 'anonymous', - 'ip': '127.0.0.1', - 'event_source': 'server', - 'event_type': str(sentinel.event_type), - 'event': '{}', - 'agent': '', - 'page': None, - 'time': FROZEN_TIME, - 'host': 'testserver', + 'timestamp': FROZEN_TIME, + 'data': '{"GET": {}, "POST": {}}', + 'name': self.path_with_course, 'context': { + 'username': 'anonymous', 'user_id': '', - 'course_id': u'foo/bar/baz', + 'accept_language': '', + 'ip': '127.0.0.1', 'org_id': 'foo', - 'path': u'/courses/foo/bar/baz/xmod/' - }, + 'agent': '', + 'event_source': 'server', + 'host': 'testserver', + 'session': '', + 'referer': '', + 'client_id': None, + 'course_id': 'foo/bar/baz', + 'path': self.path_with_course, + 'page': None + } } finally: middleware.process_response(request, None) - self.assert_mock_tracker_call_matches(expected_event) + actual_event = self.get_event() + assert_event_matches( + expected_event, + actual_event, + tolerate={'string_payload'} + ) def test_server_track_with_middleware_and_google_analytics_cookie(self): middleware = TrackMiddleware() @@ -262,48 +261,50 @@ class TestTrackViews(EventTrackingTestCase): views.server_track(request, str(sentinel.event_type), '{}') expected_event = { - 'accept_language': '', - 'referer': '', - 'username': 'anonymous', - 'ip': '127.0.0.1', - 'event_source': 'server', - 'event_type': str(sentinel.event_type), - 'event': '{}', - 'agent': '', - 'page': None, - 'time': FROZEN_TIME, - 'host': 'testserver', + 'timestamp': FROZEN_TIME, + 'data': '{"GET": {}, "POST": {}}', + 'name': self.path_with_course, 'context': { + 'username': 'anonymous', 'user_id': '', - 'course_id': u'foo/bar/baz', + 'accept_language': '', + 'ip': '127.0.0.1', 'org_id': 'foo', - 'path': u'/courses/foo/bar/baz/xmod/' - }, + 'agent': '', + 'event_source': 'server', + 'host': 'testserver', + 'session': '', + 'referer': '', + 'client_id': '1033501218.1368477899', + 'course_id': 'foo/bar/baz', + 'path': self.path_with_course, + 'page': None + } } + finally: middleware.process_response(request, None) - self.assert_mock_tracker_call_matches(expected_event) + actual_event = self.get_event() + assert_event_matches(expected_event, actual_event, tolerate={'string_payload', }) def test_server_track_with_no_request(self): request = None views.server_track(request, str(sentinel.event_type), '{}') expected_event = { - 'accept_language': '', - 'referer': '', - 'username': 'anonymous', - 'ip': '', - 'event_source': 'server', - 'event_type': str(sentinel.event_type), - 'event': '{}', - 'agent': '', - 'page': None, - 'time': FROZEN_TIME, - 'host': '', - 'context': {}, + 'timestamp': FROZEN_TIME, + 'data': '{}', + 'name': str(sentinel.event_type), + 'context': { + 'username': 'anonymous', + 'page': None, + 'event_source': + 'server' + } } - self.assert_mock_tracker_call_matches(expected_event) + actual_event = self.get_event() + assert_event_matches(expected_event, actual_event) def test_task_track(self): request_info = { @@ -324,18 +325,18 @@ class TestTrackViews(EventTrackingTestCase): views.task_track(request_info, task_info, str(sentinel.event_type), self.event) expected_event = { - 'username': 'anonymous', - 'ip': '127.0.0.1', - 'event_source': 'task', - 'event_type': str(sentinel.event_type), - 'event': expected_event_data, - 'agent': 'agent', - 'page': None, - 'time': FROZEN_TIME, - 'host': 'testserver', + 'timestamp': FROZEN_TIME, + 'data': expected_event_data, + 'name': str(sentinel.event_type), 'context': { - 'course_id': '', - 'org_id': '' - }, + 'username': 'anonymous', + 'ip': '127.0.0.1', + 'agent': 'agent', + 'host': 'testserver', + 'page': None, + 'event_source': 'task' + } } - self.assert_mock_tracker_call_matches(expected_event) + + actual_event = self.get_event() + assert_event_matches(expected_event, actual_event) diff --git a/common/djangoapps/util/cache.py b/common/djangoapps/util/cache.py index a08221224695bd7a202d9855319e9a133c40010a..083638dca4499da2fbea1a22fe30610c9e92a45e 100644 --- a/common/djangoapps/util/cache.py +++ b/common/djangoapps/util/cache.py @@ -72,7 +72,7 @@ def cache_if_anonymous(*get_parameters): get_parameter: six.text_type(parameter_value).encode('utf-8') }) - response = cache.get(cache_key) # pylint: disable=maybe-no-member + response = cache.get(cache_key) if response: # A hack to ensure that the response data is a valid text type for both Python 2 and 3. @@ -82,7 +82,7 @@ def cache_if_anonymous(*get_parameters): response.write(item) else: response = view_func(request, *args, **kwargs) - cache.set(cache_key, response, 60 * 3) # pylint: disable=maybe-no-member + cache.set(cache_key, response, 60 * 3) return response diff --git a/common/djangoapps/util/file.py b/common/djangoapps/util/file.py index ac0ab235be75ab3a7ce75f30c05fe9bb65d5bc58..5ee3f958df1ffcda07f6a72cf59941bf852c60b9 100644 --- a/common/djangoapps/util/file.py +++ b/common/djangoapps/util/file.py @@ -88,7 +88,6 @@ def store_uploaded_file( return file_storage, stored_file_name -# pylint: disable=invalid-name def course_filename_prefix_generator(course_id, separator='_'): """ Generates a course-identifying unicode string for use in a file @@ -103,7 +102,6 @@ def course_filename_prefix_generator(course_id, separator='_'): return get_valid_filename(six.text_type(separator).join([course_id.org, course_id.course, course_id.run])) -# pylint: disable=invalid-name def course_and_time_based_filename_generator(course_id, base_name): """ Generates a filename (without extension) based on the current time and the supplied filename. diff --git a/common/djangoapps/util/milestones_helpers.py b/common/djangoapps/util/milestones_helpers.py index 7e3f3a451e34c2af168413a112be8f8ffae8955f..5ce13c674ad54bc83411f2da2e000233755f8e50 100644 --- a/common/djangoapps/util/milestones_helpers.py +++ b/common/djangoapps/util/milestones_helpers.py @@ -1,4 +1,3 @@ -# pylint: disable=invalid-name """ Utility library for working with the edx-milestones app """ @@ -107,7 +106,7 @@ def set_prerequisite_courses(course_key, prerequisite_course_keys): add_prerequisite_course(course_key, prerequisite_course_key) -def get_pre_requisite_courses_not_completed(user, enrolled_courses): # pylint: disable=invalid-name +def get_pre_requisite_courses_not_completed(user, enrolled_courses): """ Makes a dict mapping courses to their unfulfilled milestones using the fulfillment API of the milestones app. diff --git a/common/djangoapps/util/model_utils.py b/common/djangoapps/util/model_utils.py index f6a33f4ef5874bc58260fcc0d7e4b0348f7bc7ae..66e92374986b2c6bb6092f5c00510a5c18b11115 100644 --- a/common/djangoapps/util/model_utils.py +++ b/common/djangoapps/util/model_utils.py @@ -42,7 +42,7 @@ def get_changed_fields_dict(instance, model_class): else: # We want to compare all of the scalar fields on the model, but none of # the relations. - field_names = [f.name for f in model_class._meta.get_fields() if not f.is_relation] # pylint: disable=protected-access + field_names = [f.name for f in model_class._meta.get_fields() if not f.is_relation] changed_fields = { field_name: getattr(old_model, field_name) for field_name in field_names if getattr(old_model, field_name) != getattr(instance, field_name) diff --git a/common/djangoapps/util/module_utils.py b/common/djangoapps/util/module_utils.py index 9ed3e84f70d401d1b2e40aeafe7395620bafea06..bb51521a89686118536b5b4c8ae3cd4191a17383 100644 --- a/common/djangoapps/util/module_utils.py +++ b/common/djangoapps/util/module_utils.py @@ -3,7 +3,7 @@ Utility library containing operations used/shared by multiple courseware modules """ -def yield_dynamic_descriptor_descendants(descriptor, user_id, module_creator=None): # pylint: disable=invalid-name +def yield_dynamic_descriptor_descendants(descriptor, user_id, module_creator=None): """ This returns all of the descendants of a descriptor. If the descriptor has dynamic children, the module will be created using module_creator diff --git a/common/djangoapps/util/request_rate_limiter.py b/common/djangoapps/util/request_rate_limiter.py index cb292ea1b24bcddfbccfaec7af13bc9c0d43839f..384ac28276935d6742c62a4b594484e42bc57383 100644 --- a/common/djangoapps/util/request_rate_limiter.py +++ b/common/djangoapps/util/request_rate_limiter.py @@ -3,6 +3,7 @@ A utility class which wraps the RateLimitMixin 3rd party class to do bad request which can be used for rate limiting """ +from datetime import datetime, timedelta from django.conf import settings from ratelimitbackend.backends import RateLimitMixin @@ -44,7 +45,7 @@ class PasswordResetEmailRateLimiter(RequestRateLimiter): def key(self, request, dt): """ - Returns cache key. + Returns IP based cache key. """ return '%s-%s-%s' % ( self.reset_email_cache_prefix, @@ -52,8 +53,51 @@ class PasswordResetEmailRateLimiter(RequestRateLimiter): dt.strftime('%Y%m%d%H%M'), ) + def email_key(self, request, dt): + """ + Returns email based cache key. + """ + return '%s-%s-%s' % ( + self.reset_email_cache_prefix, + self.get_email(request), + dt.strftime('%Y%m%d%H%M'), + ) + def expire_after(self): """ Returns timeout for cache keys. """ return self.cache_timeout_seconds + + def get_email(self, request): + """ + Returns email id for cache key. + """ + user = request.user + # Prefer logged-in user's email + email = user.email if user.is_authenticated else request.POST.get('email') + return email + + def keys_to_check(self, request): + """ + Return list of IP and email based keys. + """ + keys = super(PasswordResetEmailRateLimiter, self).keys_to_check(request) + + now = datetime.now() + email_keys = [ + self.email_key( + request, + now - timedelta(minutes=minute), + ) for minute in range(self.minutes + 1) + ] + keys.extend(email_keys) + + return keys + + def tick_request_counter(self, request): + """ + Ticks any counters used to compute when rate limit has been reached. + """ + for key in self.keys_to_check(request): + self.cache_incr(key) diff --git a/common/djangoapps/util/testing.py b/common/djangoapps/util/testing.py index 33169cf90c07fb6cbc886e2135156e17f57cb083..3218f51708d28f6c247bdef8eb2f90201dcff228 100644 --- a/common/djangoapps/util/testing.py +++ b/common/djangoapps/util/testing.py @@ -15,7 +15,7 @@ from mock import patch from util.db import OuterAtomic if six.PY3: - from importlib import reload # pylint: disable=no-name-in-module,redefined-builtin + from importlib import reload class UrlResetMixin(object): diff --git a/common/djangoapps/util/tests/test_date_utils.py b/common/djangoapps/util/tests/test_date_utils.py index e0e0ef66d3b6d72ddc40f3cd72d207621344af61..8e42299d69dd027ae0931aa23b709f65fd9a336f 100644 --- a/common/djangoapps/util/tests/test_date_utils.py +++ b/common/djangoapps/util/tests/test_date_utils.py @@ -102,7 +102,7 @@ def fake_ugettext(translations): """ Create a fake implementation of ugettext, for testing. """ - def _ugettext(text): # pylint: disable=missing-docstring + def _ugettext(text): return translations.get(text, text) return _ugettext @@ -111,7 +111,7 @@ def fake_pgettext(translations): """ Create a fake implementation of pgettext, for testing. """ - def _pgettext(context, text): # pylint: disable=missing-docstring + def _pgettext(context, text): return translations.get((context, text), text) return _pgettext diff --git a/common/djangoapps/util/tests/test_db.py b/common/djangoapps/util/tests/test_db.py index adaee8c789eb770448a217a8f5b8e57856294c23..108b66a82798b8ed7972d590fdce6b6079875019 100644 --- a/common/djangoapps/util/tests/test_db.py +++ b/common/djangoapps/util/tests/test_db.py @@ -198,7 +198,6 @@ class MigrationTests(TestCase): """ @override_settings(MIGRATION_MODULES={}) - @unittest.skip("Migration will delete several models. Need to ship not referencing it first. LEARNER-2041") def test_migrations_are_in_sync(self): """ Tests that the migration files are in sync with the models. diff --git a/common/djangoapps/util/url.py b/common/djangoapps/util/url.py index b9ea4c3c19642ee478aac4a4bdab064e28d2cc64..1240791cd137d083a18980d095626617569b94fa 100644 --- a/common/djangoapps/util/url.py +++ b/common/djangoapps/util/url.py @@ -11,7 +11,7 @@ from django.conf import settings from django.urls import set_urlconf if six.PY3: - from importlib import reload # pylint: disable=no-name-in-module,redefined-builtin + from importlib import reload def reload_django_url_config(): diff --git a/common/djangoapps/util/views.py b/common/djangoapps/util/views.py index a3e007843646a5ba25f71ba1c139ff811d880b81..af4e115b52c9952373dae1b44685f34bb7acdae7 100644 --- a/common/djangoapps/util/views.py +++ b/common/djangoapps/util/views.py @@ -21,6 +21,7 @@ from six.moves import map from lms.djangoapps.courseware.access import has_access from lms.djangoapps.courseware.masquerade import setup_masquerade from openedx.core.djangoapps.schedules.utils import reset_self_paced_schedule +from openedx.features.course_experience.utils import dates_banner_should_display import track.views from edxmako.shortcuts import render_to_response @@ -55,7 +56,7 @@ def ensure_valid_usage_key(view_func): If usage_key_string is not valid raise 404. """ @wraps(view_func) - def inner(request, *args, **kwargs): # pylint: disable=missing-docstring + def inner(request, *args, **kwargs): usage_key = kwargs.get('usage_key_string') if usage_key is not None: try: @@ -72,7 +73,7 @@ def ensure_valid_usage_key(view_func): def require_global_staff(func): """View decorator that requires that the user have global staff permissions. """ @wraps(func) - def wrapped(request, *args, **kwargs): # pylint: disable=missing-docstring + def wrapped(request, *args, **kwargs): if GlobalStaff().has_user(request.user): return func(request, *args, **kwargs) else: @@ -171,8 +172,7 @@ def calculate(request): def info(request): - ''' Info page (link from main header) ''' - # pylint: disable=unused-argument + """ Info page (link from main header) """ return render_to_response("info.html", {}) @@ -219,7 +219,10 @@ def reset_course_deadlines(request): user = masquerade_user else: user = request.user - reset_self_paced_schedule(user, course_key) + + missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, user) + if missed_deadlines and not missed_gated_content: + reset_self_paced_schedule(user, course_key) if redirect_url == RENDER_XBLOCK_NAME: detail_id_dict.pop('course_id') return redirect(reverse(redirect_url, kwargs=detail_id_dict)) diff --git a/common/djangoapps/xblock_django/api.py b/common/djangoapps/xblock_django/api.py index b9cb2f3a53e724d4e319e264c65f954719342db8..c591ce0361639920709d2075ae2b664ce45ff58e 100644 --- a/common/djangoapps/xblock_django/api.py +++ b/common/djangoapps/xblock_django/api.py @@ -3,8 +3,8 @@ API methods related to xblock state. """ -from xblock_django.models import XBlockConfiguration, XBlockStudioConfiguration from openedx.core.lib.cache_utils import CacheInvalidationManager +from xblock_django.models import XBlockConfiguration, XBlockStudioConfiguration cacher = CacheInvalidationManager(model=XBlockConfiguration) diff --git a/common/djangoapps/xblock_django/tests/test_user_service.py b/common/djangoapps/xblock_django/tests/test_user_service.py index e894fa5e28f1757ef5c9d031443298a2e84ac5f2..2a41eb86f184996977e1386e58fa055960a7e07e 100644 --- a/common/djangoapps/xblock_django/tests/test_user_service.py +++ b/common/djangoapps/xblock_django/tests/test_user_service.py @@ -7,6 +7,7 @@ from django.test import TestCase from opaque_keys.edx.keys import CourseKey from openedx.core.djangoapps.user_api.preferences.api import set_user_preference +from openedx.core.djangoapps.external_user_ids.models import ExternalIdType from student.models import anonymous_id_for_user from student.tests.factories import AnonymousUserFactory, UserFactory from xblock_django.user_service import ( @@ -82,7 +83,10 @@ class UserServiceTestCase(TestCase): """ django_user_service = DjangoXBlockUserService(self.user, user_is_staff=False) - anonymous_user_id = django_user_service.get_anonymous_user_id(username=self.user.username, course_id='edx/toy/2012_Fall') + anonymous_user_id = django_user_service.get_anonymous_user_id( + username=self.user.username, + course_id='edx/toy/2012_Fall' + ) self.assertIsNone(anonymous_user_id) def test_get_anonymous_user_id_returns_none_for_non_existing_users(self): @@ -112,3 +116,16 @@ class UserServiceTestCase(TestCase): ) self.assertEqual(anonymous_user_id, anon_user_id) + + def test_external_id(self): + """ + Tests that external ids differ based on type. + """ + ExternalIdType.objects.create(name='test1', description='Test type 1') + ExternalIdType.objects.create(name='test2', description='Test type 2') + django_user_service = DjangoXBlockUserService(self.user, user_is_staff=True) + ext_id1 = django_user_service.get_external_user_id('test1') + ext_id2 = django_user_service.get_external_user_id('test2') + assert ext_id1 != ext_id2 + with self.assertRaises(ValueError): + django_user_service.get_external_user_id('unknown') diff --git a/common/djangoapps/xblock_django/user_service.py b/common/djangoapps/xblock_django/user_service.py index 2145463eb05c6b58db7b8fc1d21d5579fb04690d..f09757677aef3a0a366eb67926dd5090492e505d 100644 --- a/common/djangoapps/xblock_django/user_service.py +++ b/common/djangoapps/xblock_django/user_service.py @@ -7,10 +7,10 @@ from django.contrib.auth.models import User from opaque_keys.edx.keys import CourseKey from xblock.reference.user_service import UserService, XBlockUser +from openedx.core.djangoapps.external_user_ids.models import ExternalId from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences from student.models import anonymous_id_for_user, get_user_by_username_or_email - ATTR_KEY_IS_AUTHENTICATED = 'edx-platform.is_authenticated' ATTR_KEY_USER_ID = 'edx-platform.user_id' ATTR_KEY_USERNAME = 'edx-platform.username' @@ -35,6 +35,16 @@ class DjangoXBlockUserService(UserService): """ return self._convert_django_user_to_xblock_user(self._django_user) + def get_external_user_id(self, type_name): + """ + Returns an external user id of the given type. + Raises ValueError if the type doesn't exist. + """ + external_id, _ = ExternalId.add_new_user_id(self._django_user, type_name) + if not external_id: + raise ValueError("External ID type: %s does not exist" % type_name) + return str(external_id.external_user_id) + def get_anonymous_user_id(self, username, course_id): """ Get the anonymous user id for a user. diff --git a/common/lib/capa/capa/capa_problem.py b/common/lib/capa/capa/capa_problem.py index 5eb1e5e3ed47efd50277a4412299ec062dde2c54..a3354b47c65e8c72c122a1b44927273249fef4e4 100644 --- a/common/lib/capa/capa/capa_problem.py +++ b/common/lib/capa/capa/capa_problem.py @@ -95,20 +95,20 @@ class LoncapaSystem(object): See :class:`ModuleSystem` for documentation of other attributes. """ - def __init__( # pylint: disable=invalid-name + def __init__( self, ajax_url, anonymous_student_id, cache, can_execute_unsafe_code, get_python_lib_zip, - DEBUG, # pylint: disable=invalid-name + DEBUG, filestore, i18n, node_path, render_template, seed, # Why do we do this if we have self.seed? - STATIC_URL, # pylint: disable=invalid-name + STATIC_URL, xqueue, matlab_api_key=None ): diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py index 38479f4b77c9ac4297047548bfa36c6cb32746fe..e6bf7a97639ca688043f683bcafe6bd01c880c63 100644 --- a/common/lib/capa/capa/responsetypes.py +++ b/common/lib/capa/capa/responsetypes.py @@ -8,7 +8,6 @@ of a variety of types. Used by capa_problem.py """ -# pylint: disable=attribute-defined-outside-init # standard library imports diff --git a/common/lib/capa/capa/safe_exec/tests/test_safe_exec.py b/common/lib/capa/capa/safe_exec/tests/test_safe_exec.py index 147ef5208cb933e00536bc68b58c48859eaad51b..15e37e869b2ffe400ed4b1f1eeae959660f54845 100644 --- a/common/lib/capa/capa/safe_exec/tests/test_safe_exec.py +++ b/common/lib/capa/capa/safe_exec/tests/test_safe_exec.py @@ -199,7 +199,10 @@ class TestUpdateHash(unittest.TestCase): """ d1 = {k: 1 for k in "abcdefghijklmnopqrstuvwxyz"} - d2 = dict(d1) + d2 = {k: 1 for k in "bcdefghijklmnopqrstuvwxyza"} + # TODO: remove the next lines once we are in python3.8 + # since python3.8 dict preserve the order of insertion + # and therefore d2 and d1 keys are already in different order. for i in range(10000): d2[i] = 1 for i in range(10000): diff --git a/common/lib/capa/capa/tests/test_responsetypes.py b/common/lib/capa/capa/tests/test_responsetypes.py index 2b918d462a27bdec29d083399730e4132c3fa044..50370a9586c040c8356c5181532d83c32e941c73 100644 --- a/common/lib/capa/capa/tests/test_responsetypes.py +++ b/common/lib/capa/capa/tests/test_responsetypes.py @@ -57,11 +57,12 @@ class ResponseTest(unittest.TestCase): if self.xml_factory_class: self.xml_factory = self.xml_factory_class() - def build_problem(self, capa_system=None, **kwargs): # pylint: disable=missing-docstring + def build_problem(self, capa_system=None, **kwargs): xml = self.xml_factory.build_xml(**kwargs) return new_loncapa_problem(xml, capa_system=capa_system) - def assert_grade(self, problem, submission, expected_correctness, msg=None): # pylint: disable=missing-docstring + # pylint: disable=missing-function-docstring + def assert_grade(self, problem, submission, expected_correctness, msg=None): input_dict = {'1_2_1': submission} correct_map = problem.grade_answers(input_dict) if msg is None: @@ -69,11 +70,12 @@ class ResponseTest(unittest.TestCase): else: self.assertEqual(correct_map.get_correctness('1_2_1'), expected_correctness, msg) - def assert_answer_format(self, problem): # pylint: disable=missing-docstring + def assert_answer_format(self, problem): answers = problem.get_question_answers() self.assertIsNotNone(answers['1_2_1']) - def assert_multiple_grade(self, problem, correct_answers, incorrect_answers): # pylint: disable=missing-docstring + # pylint: disable=missing-function-docstring + def assert_multiple_grade(self, problem, correct_answers, incorrect_answers): for input_str in correct_answers: result = problem.grade_answers({'1_2_1': input_str}).get_correctness('1_2_1') self.assertEqual(result, 'correct') @@ -109,7 +111,7 @@ class ResponseTest(unittest.TestCase): return str(rand.randint(0, 1e9)) -class MultiChoiceResponseTest(ResponseTest): # pylint: disable=missing-docstring +class MultiChoiceResponseTest(ResponseTest): # pylint: disable=missing-class-docstring xml_factory_class = MultipleChoiceResponseXMLFactory def test_multiple_choice_grade(self): @@ -199,7 +201,7 @@ class MultiChoiceResponseTest(ResponseTest): # pylint: disable=missing-docstrin self.assert_grade(problem, 'choice_infinity may be both ... (should be partial)', 'partially-correct') -class TrueFalseResponseTest(ResponseTest): # pylint: disable=missing-docstring +class TrueFalseResponseTest(ResponseTest): # pylint: disable=missing-class-docstring xml_factory_class = TrueFalseResponseXMLFactory def test_true_false_grade(self): @@ -243,7 +245,7 @@ class TrueFalseResponseTest(ResponseTest): # pylint: disable=missing-docstring self.assert_grade(problem, ['choice_0'], 'correct') -class ImageResponseTest(ResponseTest): # pylint: disable=missing-docstring +class ImageResponseTest(ResponseTest): # pylint: disable=missing-class-docstring xml_factory_class = ImageResponseXMLFactory def test_rectangle_grade(self): @@ -306,7 +308,7 @@ class ImageResponseTest(ResponseTest): # pylint: disable=missing-docstring self.assert_answer_format(problem) -class SymbolicResponseTest(ResponseTest): # pylint: disable=missing-docstring +class SymbolicResponseTest(ResponseTest): # pylint: disable=missing-class-docstring xml_factory_class = SymbolicResponseXMLFactory def test_grade_single_input_incorrect(self): @@ -378,7 +380,7 @@ class SymbolicResponseTest(ResponseTest): # pylint: disable=missing-docstring ) -class OptionResponseTest(ResponseTest): # pylint: disable=missing-docstring +class OptionResponseTest(ResponseTest): # pylint: disable=missing-class-docstring xml_factory_class = OptionResponseXMLFactory def test_grade(self): @@ -576,7 +578,7 @@ class FormulaResponseTest(ResponseTest): self.assertFalse(list(problem.responders.values())[0].validate_answer('3*y+2*x')) -class StringResponseTest(ResponseTest): # pylint: disable=missing-docstring +class StringResponseTest(ResponseTest): # pylint: disable=missing-class-docstring xml_factory_class = StringResponseXMLFactory def test_backward_compatibility_for_multiple_answers(self): @@ -938,7 +940,7 @@ class StringResponseTest(ResponseTest): # pylint: disable=missing-docstring self.assert_grade(problem, u" ", "incorrect") -class CodeResponseTest(ResponseTest): # pylint: disable=missing-docstring +class CodeResponseTest(ResponseTest): # pylint: disable=missing-class-docstring xml_factory_class = CodeResponseXMLFactory def setUp(self): @@ -1129,7 +1131,7 @@ class CodeResponseTest(ResponseTest): # pylint: disable=missing-docstring self.assertEqual(output[answer_id]['msg'], u'Invalid grader reply. Please contact the course staff.') -class ChoiceResponseTest(ResponseTest): # pylint: disable=missing-docstring +class ChoiceResponseTest(ResponseTest): # pylint: disable=missing-class-docstring xml_factory_class = ChoiceResponseXMLFactory def test_radio_group_grade(self): @@ -1297,7 +1299,7 @@ class ChoiceResponseTest(ResponseTest): # pylint: disable=missing-docstring self.assert_grade(problem, ['choice_1', 'choice_3'], 'incorrect') -class NumericalResponseTest(ResponseTest): # pylint: disable=missing-docstring +class NumericalResponseTest(ResponseTest): # pylint: disable=missing-class-docstring xml_factory_class = NumericalResponseXMLFactory # We blend the line between integration (using evaluator) and exclusively @@ -1662,7 +1664,7 @@ class NumericalResponseTest(ResponseTest): # pylint: disable=missing-docstring self.assertFalse(responder.validate_answer('fish')) -class CustomResponseTest(ResponseTest): # pylint: disable=missing-docstring +class CustomResponseTest(ResponseTest): # pylint: disable=missing-class-docstring xml_factory_class = CustomResponseXMLFactory def test_inline_code(self): diff --git a/common/lib/symmath/symmath/formula.py b/common/lib/symmath/symmath/formula.py index 355dbfd57dad1cd80684faa5d12df16eae24c914..e82d361d7c5f0ad568386af93df8bb808bca7b42 100644 --- a/common/lib/symmath/symmath/formula.py +++ b/common/lib/symmath/symmath/formula.py @@ -84,7 +84,7 @@ def to_latex(expr): # sometimes get 'script(N)__B' or more complicated terms expr_s = re.sub( r'script([a-zA-Z0-9]+)', - '\\mathcal{\\1}', + r'\\mathcal{\\1}', expr_s ) diff --git a/common/lib/xmodule/xmodule/capa_base.py b/common/lib/xmodule/xmodule/capa_base.py index 9de45d785b317dde7ae80123a6f3c6b9b88e0caa..53b87d659f291aed9df1e5dd36f6a942b40c7c4e 100644 --- a/common/lib/xmodule/xmodule/capa_base.py +++ b/common/lib/xmodule/xmodule/capa_base.py @@ -725,6 +725,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields): html = self.handle_problem_html_error(err) html = self.remove_tags_from_html(html) + _ = self.runtime.service(self, "i18n").ugettext # Enable/Disable Submit button if should_enable_submit_button returns True/False. submit_button = self.submit_button_name() @@ -821,6 +822,7 @@ class CapaMixin(ScorableXBlockMixin, CapaFields): # Build the notification message based on the notification type and translate it. ungettext = self.runtime.service(self, "i18n").ungettext + _ = self.runtime.service(self, "i18n").ugettext if answer_notification_type == 'incorrect': if progress is not None: answer_notification_message = ungettext( @@ -1212,6 +1214,12 @@ class CapaMixin(ScorableXBlockMixin, CapaFields): # Too late. Cannot submit if self.closed(): + problem_location = text_type(self.location) + if 'HarvardX+MCB80.1x+3T2019' in problem_location: + log.info( + 'Problem %s closed, close date: %s, attempts: %s/%s, is_past_due: %s', + problem_location, self.close_date, self.attempts, self.max_attempts, self.is_past_due() + ) event_info['failure'] = 'closed' self.track_function_unmask('problem_check_fail', event_info) raise NotFoundError(_("Problem is closed.")) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index 3677b756690134615f56a6f7de1eef1a154150eb..1dbfa7429f0422d5e587017fc686f929e7d32ed3 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -35,7 +35,7 @@ from .capa_base import CapaMixin, ComplexEncoder, _ log = logging.getLogger("edx.courseware") -@XBlock.wants('user') # pylint: disable=abstract-method +@XBlock.wants('user') @XBlock.needs('i18n') class ProblemBlock( CapaMixin, RawMixin, XmlMixin, EditingMixin, @@ -203,7 +203,7 @@ class ProblemBlock( self.scope_ids.usage_id, self.scope_ids.user_id ) - _, _, traceback_obj = sys.exc_info() # pylint: disable=redefined-outer-name + _, _, traceback_obj = sys.exc_info() six.reraise(ProcessingError, ProcessingError(not_found_error_message), traceback_obj) except Exception: @@ -213,7 +213,7 @@ class ProblemBlock( self.scope_ids.usage_id, self.scope_ids.user_id ) - _, _, traceback_obj = sys.exc_info() # pylint: disable=redefined-outer-name + _, _, traceback_obj = sys.exc_info() six.reraise(ProcessingError, ProcessingError(generic_error_message), traceback_obj) after = self.get_progress() diff --git a/common/lib/xmodule/xmodule/contentstore/content.py b/common/lib/xmodule/xmodule/contentstore/content.py index 5810a4c0dd783bff494bbb56b5c70352a0a4e6ca..15dd1122dc3c64cfadda1d559d1659c3d0396911 100644 --- a/common/lib/xmodule/xmodule/contentstore/content.py +++ b/common/lib/xmodule/xmodule/contentstore/content.py @@ -11,7 +11,7 @@ from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import AssetKey, CourseKey from opaque_keys.edx.locator import AssetLocator from PIL import Image -from six.moves.urllib.parse import parse_qsl, quote_plus, urlencode, urlparse, urlunparse # pylint: disable=import-error +from six.moves.urllib.parse import parse_qsl, quote_plus, urlencode, urlparse, urlunparse from xmodule.assetstore.assetmgr import AssetManager from xmodule.exceptions import NotFoundError @@ -61,7 +61,7 @@ class StaticContent(object): name_root = name_root + ext.replace(u'.', u'-') if dimensions: - width, height = dimensions # pylint: disable=unpacking-non-sequence + width, height = dimensions name_root += "-{}x{}".format(width, height) return u"{name_root}{extension}".format( diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index 8710255c286237cde4351e4edfbd1cbe75ec112f..1fd2c6342f5b1ae5071156feb318500b0c2efd3b 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -12,6 +12,7 @@ import dateutil.parser import requests import six from django.conf import settings +from django.core.validators import validate_email from lazy import lazy from lxml import etree from path import Path as path @@ -83,6 +84,18 @@ class StringOrDate(Date): return result +class EmailString(String): + """ + Parse String with email validation + """ + def from_json(self, value): + if value: + validate_email(value) + return value + else: + return None + + edx_xml_parser = etree.XMLParser(dtd_validation=False, load_dtd=False, remove_comments=True, remove_blank_text=True) @@ -876,6 +889,17 @@ class CourseFields(object): scope=Scope.settings, ) + proctoring_escalation_email = EmailString( + display_name=_("Proctortrack Exam Escalation Contact"), + help=_( + "Required if 'proctortrack' is selected as your proctoring provider. " + "Enter an email address to be contacted by the support team whenever there are escalations " + "(e.g. appeals, delayed reviews, etc.)." + ), + default=None, + scope=Scope.settings + ) + allow_proctoring_opt_out = Boolean( display_name=_("Allow Opting Out of Proctored Exams"), help=_( diff --git a/common/lib/xmodule/xmodule/css/capa/display.scss b/common/lib/xmodule/xmodule/css/capa/display.scss index 32bba7cda7826b685f6766bdb7a0e3d7809c560c..2f1a8eda13e53bc4807582c2d3145e00cacd1dd0 100644 --- a/common/lib/xmodule/xmodule/css/capa/display.scss +++ b/common/lib/xmodule/xmodule/css/capa/display.scss @@ -130,10 +130,10 @@ h2 { display: block; } -iframe[seamless]{ +iframe[seamless] { overflow: hidden; padding: 0; - border: 0px none transparent; + border: 0 none transparent; background-color: transparent; } @@ -157,7 +157,8 @@ div.problem { padding: 0; width: auto; - canvas, img { + canvas, + img { page-break-inside: avoid; } } @@ -209,7 +210,7 @@ div.problem { width: 100px; label { - @include box-sizing(border-box); + box-sizing: border-box; display: inline-block; clear: both; @@ -231,7 +232,7 @@ div.problem { } fieldset { - @include box-sizing(border-box); + box-sizing: border-box; } input[type="radio"], @@ -775,7 +776,7 @@ div.problem { .problem { .capa_inputtype.textline, .inputtype.formulaequationinput { input { - @include box-sizing(border-box); + box-sizing: border-box; border: 2px solid $gray-l4; border-radius: 3px; @@ -1284,7 +1285,7 @@ div.problem { a.full { @include position(absolute, 0 0 1px 0); - @include box-sizing(border-box); + box-sizing: border-box; display: block; padding: ($baseline/5); diff --git a/common/lib/xmodule/xmodule/css/html/edit.scss b/common/lib/xmodule/xmodule/css/html/edit.scss index 2c7b4542b4154ac80f48fef72717b0bf1c8d78a4..bf47a0f5d372e42aa56e63db7e837a7c9c55b4f1 100644 --- a/common/lib/xmodule/xmodule/css/html/edit.scss +++ b/common/lib/xmodule/xmodule/css/html/edit.scss @@ -3,7 +3,7 @@ @include clearfix(); .CodeMirror { - @include box-sizing(border-box); + box-sizing: border-box; height: 435px; } diff --git a/common/lib/xmodule/xmodule/css/tabs/codemirror.scss b/common/lib/xmodule/xmodule/css/tabs/codemirror.scss index 9678958b2bc7ea397d8f9813dbd998f9ee8468fa..237d1850332a86baf9565de2382503d2fb5a3060 100644 --- a/common/lib/xmodule/xmodule/css/tabs/codemirror.scss +++ b/common/lib/xmodule/xmodule/css/tabs/codemirror.scss @@ -2,7 +2,7 @@ @include clearfix(); .CodeMirror { - @include box-sizing(border-box); + box-sizing: border-box; width: 100%; position: relative; diff --git a/common/lib/xmodule/xmodule/css/tabs/tabs.scss b/common/lib/xmodule/xmodule/css/tabs/tabs.scss index f49e65e2642de1ad379fc8af2bb42e9345f7b915..277462675f1ff31f5478b0e84d3d82301abb40e5 100644 --- a/common/lib/xmodule/xmodule/css/tabs/tabs.scss +++ b/common/lib/xmodule/xmodule/css/tabs/tabs.scss @@ -23,7 +23,7 @@ .edit-header { - @include box-sizing(border-box); + box-sizing: border-box; padding: 18px $baseline; top: 0 !important; // ugly override for second level tab override diff --git a/common/lib/xmodule/xmodule/css/video/display.scss b/common/lib/xmodule/xmodule/css/video/display.scss index de10657d24095283578db3311c156872263286f1..93a8f2f5a328057e18e50d2f51e0fce683eced2d 100644 --- a/common/lib/xmodule/xmodule/css/video/display.scss +++ b/common/lib/xmodule/xmodule/css/video/display.scss @@ -928,7 +928,7 @@ $cool-dark: rgb(79, 89, 93); // UXPL cool dark width: 25%; padding: lh(); - @include box-sizing(border-box); + box-sizing: border-box; @include transition(none); background: $black; diff --git a/common/lib/xmodule/xmodule/edxnotes_utils.py b/common/lib/xmodule/xmodule/edxnotes_utils.py index 8da0e832522e713b45add7fe89eb5a3b7afdd1e6..c4010bed3c5527c33e7363f2f72cc2716fc71714 100644 --- a/common/lib/xmodule/xmodule/edxnotes_utils.py +++ b/common/lib/xmodule/xmodule/edxnotes_utils.py @@ -11,7 +11,7 @@ def edxnotes(cls): Conditional decorator that loads edxnotes only when they exist. """ if "edxnotes" in sys.modules: - from edxnotes.decorators import edxnotes as notes # pylint: disable=import-error + from edxnotes.decorators import edxnotes as notes return notes(cls) else: return cls diff --git a/common/lib/xmodule/xmodule/graders.py b/common/lib/xmodule/xmodule/graders.py index 9a1c15c3ef24118fd0a967fcc375b3253715b84c..503935c181422b3e1709775932cdaf232f89aab5 100644 --- a/common/lib/xmodule/xmodule/graders.py +++ b/common/lib/xmodule/xmodule/graders.py @@ -15,7 +15,7 @@ import six from contracts import contract from pytz import UTC from django.utils.translation import ugettext_lazy as _ -from six.moves import range # pylint: disable=ungrouped-imports +from six.moves import range from xmodule.util.misc import get_short_labeler diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py index 70346486d1cf5ea8f2f2b8cbcb3bbb1309ad675d..202d9d7e51624f47c98394e4c288ebb06f63c7a5 100644 --- a/common/lib/xmodule/xmodule/html_module.py +++ b/common/lib/xmodule/xmodule/html_module.py @@ -116,7 +116,6 @@ class HtmlBlock( def get_html(self): """ Returns html required for rendering the block. """ - # pylint: disable=no-member if self.data is not None and getattr(self.system, 'anonymous_student_id', None) is not None: return self.data.replace("%%USER_ID%%", self.system.anonymous_student_id) return self.data @@ -460,7 +459,6 @@ class CourseInfoBlock(CourseInfoFields, HtmlBlock): # When we switch this to an XBlock, we can merge this with student_view, # but for now the XModule mixin requires that this method be defined. - # pylint: disable=no-member if self.data != "": if self.system.anonymous_student_id: return self.data.replace("%%USER_ID%%", self.system.anonymous_student_id) diff --git a/common/lib/xmodule/xmodule/js/src/capa/schematic.js b/common/lib/xmodule/xmodule/js/src/capa/schematic.js index 63edb278d87381868666d5039c875a9e047dadd2..92c274c7bce219d99ef648092fe5bc0efc5048c5 100644 --- a/common/lib/xmodule/xmodule/js/src/capa/schematic.js +++ b/common/lib/xmodule/xmodule/js/src/capa/schematic.js @@ -2810,7 +2810,7 @@ schematic = (function() { // for each requested freq, interpolate response value for (var k = 1; k < flist.length; k++) { var f = flist[k]; - var v = interpolate(f,x_values,values); //xss-lint: disable=javascript-interpolate + var v = interpolate(f,x_values,values); // convert to dB fvlist.push([f,v == undefined ? 'undefined' : 20.0 * Math.log(v)/Math.LN10]); } @@ -2932,7 +2932,7 @@ schematic = (function() { // for each requested time, interpolate waveform value for (var k = 1; k < tlist.length; k++) { var t = tlist[k]; - var v = interpolate(t,times,values); // xss-lint: disable=javascript-interpolate + var v = interpolate(t,times,values); tvlist.push([t,v == undefined ? 'undefined' : v]); } // save results as list of [t,value] pairs @@ -2978,7 +2978,7 @@ schematic = (function() { // t is the time at which we want a value // times is a list of timepoints from the simulation - function interpolate(t,times,values) { // xss-lint: disable=javascript-interpolate + function interpolate(t,times,values) { if (values == undefined) return undefined; for (var i = 0; i < times.length; i++) @@ -5219,7 +5219,7 @@ schematic = (function() { } Wire.prototype = new Component(); Wire.prototype.constructor = Wire; - + Wire.prototype.toString = function() { return edx.StringUtils.interpolate( '<Wire ({x},{y}) ({x_plus_dx},{y_plus_dy})>', @@ -5348,7 +5348,7 @@ schematic = (function() { y: this.y }); } - + Ground.prototype.draw = function(c) { Component.prototype.draw.call(this,c); // give superclass a shot this.draw_line(c,0,0,0,8); diff --git a/common/lib/xmodule/xmodule/js/src/sequence/display.js b/common/lib/xmodule/xmodule/js/src/sequence/display.js index 06f519bd3508ce5ee689876439e13f106417ccea..1a283e55b8450545f8b4ed2b831b0b0bd3baabf8 100644 --- a/common/lib/xmodule/xmodule/js/src/sequence/display.js +++ b/common/lib/xmodule/xmodule/js/src/sequence/display.js @@ -329,7 +329,6 @@ this.render(newPosition); } else { alertTemplate = gettext('Sequence error! Cannot navigate to %(tab_name)s in the current SequenceModule. Please contact the course staff.'); // eslint-disable-line max-len - // xss-lint: disable=javascript-interpolate alertText = interpolate(alertTemplate, { tab_name: newPosition }, true); diff --git a/common/lib/xmodule/xmodule/js/src/video/02_html5_hls_video.js b/common/lib/xmodule/xmodule/js/src/video/02_html5_hls_video.js index d241e3b90b5387b10fbeebe668c881a08fe60582..f8df889d135f7291aa97eef9a98e152c4d78fcc9 100644 --- a/common/lib/xmodule/xmodule/js/src/video/02_html5_hls_video.js +++ b/common/lib/xmodule/xmodule/js/src/video/02_html5_hls_video.js @@ -42,7 +42,12 @@ if (config.browserIsSafari) { this.videoEl.attr('src', config.videoSources[0]); } else { - this.hls = new HLS({autoStartLoad: false}); + // load auto start if auto_advance is enabled + if (config.state.auto_advance) { + this.hls = new HLS({autoStartLoad: true}); + } else { + this.hls = new HLS({autoStartLoad: false}); + } this.hls.loadSource(config.videoSources[0]); this.hls.attachMedia(this.video); diff --git a/common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js b/common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js index df7ac15e0829460c035b459808ac04aeb27303ed..3179e8b1534ceab555c4f7d5fd796e32560fb679 100644 --- a/common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js +++ b/common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js @@ -329,7 +329,6 @@ function() { msg = ngettext('%(value)s second', '%(value)s seconds', value); break; } - // xss-lint: disable=javascript-interpolate return interpolate(msg, {value: value}, true); }; diff --git a/common/lib/xmodule/xmodule/library_content_module.py b/common/lib/xmodule/xmodule/library_content_module.py index b31f5d355ce3bf0897e05f2f19ef48b069797466..077d457fce6816ddcc42bce4949e086bc4e13d6b 100644 --- a/common/lib/xmodule/xmodule/library_content_module.py +++ b/common/lib/xmodule/xmodule/library_content_module.py @@ -418,7 +418,7 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe return user_id @XBlock.handler - def refresh_children(self, request=None, suffix=None): # pylint: disable=unused-argument + def refresh_children(self, request=None, suffix=None): """ Refresh children: This method is to be used when any of the libraries that this block @@ -649,7 +649,7 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe for child in self.get_children(): self.runtime.add_block_as_child_node(child, xml_object) # Set node attributes based on our fields. - for field_name, field in six.iteritems(self.fields): # pylint: disable=no-member + for field_name, field in six.iteritems(self.fields): if field_name in ('children', 'parent', 'content'): continue if field.is_set_on(self): diff --git a/common/lib/xmodule/xmodule/lti_2_util.py b/common/lib/xmodule/xmodule/lti_2_util.py index 2fee600dadb28a38b00b5b882da720bd1c348326..f6a389b2e8113cae2c226ccd2d0ffca0eeff2ab5 100644 --- a/common/lib/xmodule/xmodule/lti_2_util.py +++ b/common/lib/xmodule/xmodule/lti_2_util.py @@ -1,4 +1,3 @@ -# pylint: disable=attribute-defined-outside-init """ A mixin class for LTI 2.0 functionality. This is really just done to refactor the code to keep the LTIModule class from getting too big @@ -156,7 +155,7 @@ class LTI20ModuleMixin(object): log.info("[LTI]: {}".format(msg)) raise LTIError(msg) - def _lti_2_0_result_get_handler(self, request, real_user): # pylint: disable=unused-argument + def _lti_2_0_result_get_handler(self, request, real_user): """ Helper request handler for GET requests to LTI 2.0 result endpoint @@ -182,7 +181,7 @@ class LTI20ModuleMixin(object): base_json_obj['comment'] = self.score_comment return Response(json.dumps(base_json_obj).encode('utf-8'), content_type=LTI_2_0_JSON_CONTENT_TYPE) - def _lti_2_0_result_del_handler(self, request, real_user): # pylint: disable=unused-argument + def _lti_2_0_result_del_handler(self, request, real_user): """ Helper request handler for DELETE requests to LTI 2.0 result endpoint diff --git a/common/lib/xmodule/xmodule/lti_module.py b/common/lib/xmodule/xmodule/lti_module.py index bfaea0a037fbd07be30a6ad98892c6b06b564267..39a85d0ed42651529f55bb5203a9b43953c7ada1 100644 --- a/common/lib/xmodule/xmodule/lti_module.py +++ b/common/lib/xmodule/xmodule/lti_module.py @@ -345,7 +345,7 @@ class LTIModule(LTIFields, LTI20ModuleMixin, XModule): ] } css = {'scss': [resource_string(__name__, 'css/lti/lti.scss')]} - js_module_name = "LTI" + js_module_name = 'LTI' def get_input_fields(self): # LTI provides a list of default parameters that might be passed as @@ -557,6 +557,12 @@ class LTIModule(LTIFields, LTI20ModuleMixin, XModule): } return roles.get(self.system.get_user_role(), u'Student') + def get_icon_class(self): + """ Returns the icon class """ + if self.graded and self.has_score: # pylint: disable=no-member + return 'problem' + return 'other' + def oauth_params(self, custom_parameters, client_key, client_secret): """ Signs request and returns signature and OAuth parameters. @@ -662,7 +668,7 @@ oauth_consumer_key="", oauth_signature="frVp4JuvT1mVXlxktiAUjQ7%2F1cw%3D"'} return params @XBlock.handler - def grade_handler(self, request, suffix): # pylint: disable=unused-argument + def grade_handler(self, request, suffix): """ This is called by courseware.module_render, to handle an AJAX call. diff --git a/common/lib/xmodule/xmodule/modulestore/__init__.py b/common/lib/xmodule/xmodule/modulestore/__init__.py index 785beb955666adf2ae41c2412262347f41e361f9..27aa5573eb24dcd4eea6424ccdb4b31fc6cc06f9 100644 --- a/common/lib/xmodule/xmodule/modulestore/__init__.py +++ b/common/lib/xmodule/xmodule/modulestore/__init__.py @@ -26,12 +26,18 @@ from xblock.runtime import Mixologist # The below import is not used within this module, but ir is still needed becuase # other modules are imorting EdxJSONEncoder from here -from openedx.core.lib.json_utils import EdxJSONEncoder # pylint: disable=unused-import +from openedx.core.lib.json_utils import EdxJSONEncoder from xmodule.assetstore import AssetMetadata from xmodule.errortracker import make_error_tracker from .exceptions import InsufficientSpecificationError, InvalidLocationError +# The name of the type for patterns in re changed in Python 3.7. +try: + Pattern = re._pattern_type # pylint: disable=protected-access +except AttributeError: + Pattern = re.Pattern # pylint: disable=no-member + log = logging.getLogger('edx.modulestore') new_contract('CourseKey', CourseKey) @@ -387,7 +393,7 @@ class EditInfo(object): self.original_usage_version = edit_info.get('original_usage_version', None) def __repr__(self): - # pylint: disable=bad-continuation, redundant-keyword-arg + # pylint: disable=bad-continuation return ("{classname}(previous_version={self.previous_version}, " "update_version={self.update_version}, " "source_version={source_version}, " @@ -474,7 +480,7 @@ class BlockData(object): return self.asides def __repr__(self): - # pylint: disable=bad-continuation, redundant-keyword-arg + # pylint: disable=bad-continuation return ("{classname}(fields={self.fields}, " "block_type={self.block_type}, " "definition={self.definition}, " @@ -899,7 +905,7 @@ class ModuleStoreRead(six.with_metaclass(ABCMeta, ModuleStoreAssetBase)): """ if isinstance(target, list): return any(self._value_matches(ele, criteria) for ele in target) - elif isinstance(criteria, re._pattern_type): # pylint: disable=protected-access + elif isinstance(criteria, Pattern): return criteria.search(target) is not None elif callable(criteria): return criteria(target) @@ -1157,11 +1163,9 @@ class ModuleStoreWrite(six.with_metaclass(ABCMeta, ModuleStoreRead, ModuleStoreA # pylint: disable=abstract-method class ModuleStoreReadBase(BulkOperationsMixin, ModuleStoreRead): - ''' + """ Implement interface functionality that can be shared. - ''' - - # pylint: disable=invalid-name + """ def __init__( self, contentstore=None, @@ -1178,7 +1182,6 @@ class ModuleStoreReadBase(BulkOperationsMixin, ModuleStoreRead): ''' super(ModuleStoreReadBase, self).__init__(**kwargs) self._course_errors = defaultdict(make_error_tracker) # location -> ErrorLog - # pylint: disable=fixme # TODO move the inheritance_cache_subsystem to classes which use it self.metadata_inheritance_cache_subsystem = metadata_inheritance_cache_subsystem self.request_cache = request_cache @@ -1194,7 +1197,6 @@ class ModuleStoreReadBase(BulkOperationsMixin, ModuleStoreRead): errors as get_item if course_key isn't present. """ # check that item is present and raise the promised exceptions if needed - # pylint: disable=fixme # TODO (vshnayder): post-launch, make errors properties of items # self.get_item(location) assert isinstance(course_key, CourseKey) diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/base.py b/common/lib/xmodule/xmodule/modulestore/mongo/base.py index 2a6a0336d90f1265e7aebf7ee45b91d255a055d7..2aedf6f1e63611a00a447588f84bbcd03d6cc911 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/base.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/base.py @@ -228,7 +228,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin): self.course_id = course_key self.cached_metadata = cached_metadata - def load_item(self, location, for_parent=None): # pylint: disable=method-hidden + def load_item(self, location, for_parent=None): """ Return an XModule instance for the specified location """ @@ -515,7 +515,6 @@ class ParentLocationCache(dict): """ Dict-based object augmented with a more cache-like interface, for internal use. """ - # pylint: disable=missing-docstring @contract(key=six.text_type) def has(self, key): @@ -1653,7 +1652,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo if revision == ModuleStoreEnum.RevisionOption.published_only: query['_id.revision'] = MongoRevisionKey.published - def cache_and_return(parent_loc): # pylint:disable=missing-docstring + def cache_and_return(parent_loc): parent_cache.set(six.text_type(location), parent_loc) return parent_loc diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py index adc98e70eab9923babca6cb59a6fa6fb9db2d80e..a382b08feb40b2de9c1104ab8befdbd1b5285963 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py @@ -196,7 +196,7 @@ class DraftModuleStore(MongoModuleStore): # b/c we don't want the payload, I'm copying the guts of get_items here query = self._course_key_to_son(dest_course_id) query['_id.category'] = {'$nin': ['course', 'about']} - if self.collection.find(query).limit(1).count() > 0: + if self.collection.count_documents(query, limit=1) > 0: raise DuplicateCourseError( dest_course_id, "Course at destination {0} is not an empty course. " diff --git a/common/lib/xmodule/xmodule/modulestore/perf_tests/generate_asset_xml.py b/common/lib/xmodule/xmodule/modulestore/perf_tests/generate_asset_xml.py index 6afcb998d436759c9fef32123b194c083b0109cb..ff8bd47cf386d0ec1428ef89dd702b5e8548c509 100644 --- a/common/lib/xmodule/xmodule/modulestore/perf_tests/generate_asset_xml.py +++ b/common/lib/xmodule/xmodule/modulestore/perf_tests/generate_asset_xml.py @@ -205,7 +205,6 @@ def validate_xml(xsd_filename, xml_filename): etree.fromstring(f.read(), xmlparser) if click is not None: - # pylint: disable=bad-continuation @click.command() @click.option('--num_assets', type=click.INT, diff --git a/common/lib/xmodule/xmodule/modulestore/perf_tests/generate_report.py b/common/lib/xmodule/xmodule/modulestore/perf_tests/generate_report.py index c5bf85901959bc0206dc9f5c3e7d9312d11a21a6..6471c004ea765a3678e49009a3b3a659ee12505d 100644 --- a/common/lib/xmodule/xmodule/modulestore/perf_tests/generate_report.py +++ b/common/lib/xmodule/xmodule/modulestore/perf_tests/generate_report.py @@ -50,7 +50,7 @@ class HTMLTable(object): th, td { padding: 5px; }""" - ) # pylint: disable=bad-continuation + ) class HTMLDocument(object): diff --git a/common/lib/xmodule/xmodule/modulestore/perf_tests/test_asset_import_export.py b/common/lib/xmodule/xmodule/modulestore/perf_tests/test_asset_import_export.py index c6642201729434edafb9f6f44cf7e7f066f0baab..f177ac01c8173eec84f928696d9ad6894d7f6621 100644 --- a/common/lib/xmodule/xmodule/modulestore/perf_tests/test_asset_import_export.py +++ b/common/lib/xmodule/xmodule/modulestore/perf_tests/test_asset_import_export.py @@ -37,7 +37,6 @@ ALL_SORTS = ( ('uploadDate', ModuleStoreEnum.SortOrder.descending), ) -# pylint: disable=invalid-name TEST_DIR = path(__file__).dirname() PLATFORM_ROOT = TEST_DIR.parent.parent.parent.parent.parent.parent TEST_DATA_ROOT = PLATFORM_ROOT / TEST_DATA_DIR diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py index c537bc024477a77cb71318a36e521107c39cf106..cfa85d27c96469e6ed76e3e56fe834d94af7421d 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py @@ -160,7 +160,7 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli descriptor.location = old_descriptor_locn return item - def create_item(self, user_id, course_key, block_type, block_id=None, # pylint: disable=too-many-statements + def create_item(self, user_id, course_key, block_type, block_id=None, # pylint: disable=W0221 definition_locator=None, fields=None, asides=None, force=False, skip_auto_publish=False, **kwargs): """ See :py:meth `ModuleStoreDraftAndPublished.create_item` diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index 2cc310abe077cbd949ec6e74b3ccee3a0d7cac3e..1544a69ef3493000c2edc50889cee90f78eb398e 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -18,7 +18,7 @@ from mock import patch from six.moves import range from lms.djangoapps.courseware.tests.factories import StaffFactory -from lms.djangoapps.courseware.field_overrides import OverrideFieldData # pylint: disable=import-error +from lms.djangoapps.courseware.field_overrides import OverrideFieldData from openedx.core.djangolib.testing.utils import CacheIsolationMixin, CacheIsolationTestCase, FilteredQueryCountMixin from openedx.core.lib.tempdir import mkdtemp_clean from student.models import CourseEnrollment diff --git a/common/lib/xmodule/xmodule/modulestore/tests/factories.py b/common/lib/xmodule/xmodule/modulestore/tests/factories.py index 9e12e02d29058df07e54f503d7b907581225c496..1d33d9c3069068071050f69186cbea3de5d6b232 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/factories.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/factories.py @@ -542,7 +542,6 @@ class StackTraceCounter(object): """ stacks = StackTraceCounter(stack_depth, include_arguments) - # pylint: disable=missing-docstring @functools.wraps(func) def capture(*args, **kwargs): stacks.capture_stack(args, kwargs) diff --git a/common/lib/xmodule/xmodule/modulestore/tests/sample_courses.py b/common/lib/xmodule/xmodule/modulestore/tests/sample_courses.py index c2ac366b3d1f224d0386a268afc28b848bc6609b..4a9e027f6ed193fb4745dba5f0b9e977f71a9d00 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/sample_courses.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/sample_courses.py @@ -55,7 +55,12 @@ TOY_BLOCK_INFO_TREE = [ }, [ BlockInfo( "secret:toylab", "html", { - "data": "<b>Lab 2A: Superposition Experiment</b>\n\n\n<p>Isn't the toy course great?</p>\n\n<p>Let's add some markup that uses non-ascii characters.\n'For example, we should be able to write words like encyclopædia, or foreign words like français.\nLooking beyond latin-1, we should handle math symbols: πr² ≤ ∞.\nAnd it shouldn't matter if we use entities or numeric codes — Ω ≠ π ≡ Ω ≠ π.\n</p>\n\n", # pylint: disable=line-too-long + "data": "<b>Lab 2A: Superposition Experiment</b>\n\n\n<p>Isn't the toy course great?</p>\n" + "\n<p>Let's add some markup that uses non-ascii characters.\n'For example," + " we should be able to write words like encyclopædia, or foreign words like " + "français.\nLooking beyond latin-1, we should handle math symbols: " + " πr² ≤ ∞.\nAnd it shouldn't matter if we use entities or numeric" + " codes — Ω ≠ π ≡ Ω ≠ π.\n</p>\n\n", "xml_attributes": {"filename": ["html/secret/toylab.xml", "html/secret/toylab.xml"]}, "display_name": "Toy lab" }, [] 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 ba94a058f97308bb201f1cad3d6884ecc0b4c04a..d023e5c99a248ced1fdcf3541b17513af6d076d1 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py @@ -155,7 +155,6 @@ class CommonMixedModuleStoreSetup(CourseComparisonTest): self.user_id = ModuleStoreEnum.UserID.test - # pylint: disable=invalid-name def _create_course(self, course_key, asides=None): """ Create a course w/ one item in the persistence store using the given course & item location. @@ -249,7 +248,6 @@ class CommonMixedModuleStoreSetup(CourseComparisonTest): """ return self.store.has_changes(self.store.get_item(location)) - # pylint: disable=dangerous-default-value def _initialize_mixed(self, mappings=None, contentstore=None): """ initializes the mixed modulestore. @@ -3571,7 +3569,7 @@ class TestAsidesWithMixedModuleStore(CommonMixedModuleStoreSetup): super(TestAsidesWithMixedModuleStore, self).setUp() key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) - self.runtime = TestRuntime(services={'field-data': field_data}) # pylint: disable=abstract-class-instantiated + self.runtime = TestRuntime(services={'field-data': field_data}) @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) @XBlockAside.register_temp_plugin(AsideFoo, 'test_aside1') diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py index 4220f83edfe85f8a73194e459ea0869d3e17dee6..a381d2f63fcae5c520839ba3b76dbbd94763a657 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py @@ -13,7 +13,6 @@ import pymongo import pytest import six -# pylint: disable=no-name-in-module # pylint: disable=bad-continuation # pylint: disable=protected-access from django.test import TestCase diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_semantics.py b/common/lib/xmodule/xmodule/modulestore/tests/test_semantics.py index 98ed3263c1516a14d5a3e13dc5698968665d33a6..a8bc3c35543c362773501eea48e16ff9db20f322 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_semantics.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_semantics.py @@ -234,7 +234,7 @@ class DirectOnlyCategorySemantics(PureModulestoreTestCase): key_store = DictKeyValueStore() field_data = KvsFieldData(key_store) - aside = AsideTest(scope_ids=scope_ids, runtime=TestRuntime(services={'field-data': field_data})) # pylint: disable=abstract-class-instantiated + aside = AsideTest(scope_ids=scope_ids, runtime=TestRuntime(services={'field-data': field_data})) aside.fields[self.ASIDE_DATA_FIELD.field_name].write_to(aside, self.ASIDE_DATA_FIELD.initial) return [aside] diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py index 788be2a601a4c945021c1658d6d46df1eb89af41..c0559a4c64a9be43b9ad8bf48affc47b65100882 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py @@ -2235,12 +2235,12 @@ class TestSchema(SplitModuleTest): db_connection = modulestore().db_connection for collection in [db_connection.course_index, db_connection.structures, db_connection.definitions]: self.assertEqual( - collection.find({'schema_version': {'$exists': False}}).count(), + collection.count_documents({'schema_version': {'$exists': False}}), 0, "{0.name} has records without schema_version".format(collection) ) self.assertEqual( - collection.find({'schema_version': {'$ne': SplitMongoModuleStore.SCHEMA_VERSION}}).count(), + collection.count_documents({'schema_version': {'$ne': SplitMongoModuleStore.SCHEMA_VERSION}}), 0, "{0.name} has records with wrong schema_version".format(collection) ) @@ -2278,6 +2278,6 @@ def modulestore(): return SplitModuleTest.modulestore -# pylint: disable=unused-argument, missing-docstring +# pylint: disable=unused-argument def render_to_template_mock(*args): pass diff --git a/common/lib/xmodule/xmodule/modulestore/tests/utils.py b/common/lib/xmodule/xmodule/modulestore/tests/utils.py index 830953c238b6a5b6485453b3d5ee6192621bd32b..91f141d17c54084a1f0179f4f2ca359aef2b607e 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/utils.py @@ -171,9 +171,9 @@ class ProceduralCourseTestMixin(object): Add k chapters, k^2 sections, k^3 verticals, k^4 problems to self.course (where k = branching) """ user_id = self.user.id - self.populated_usage_keys = {} # pylint: disable=attribute-defined-outside-init + self.populated_usage_keys = {} - def descend(parent, stack): # pylint: disable=missing-docstring + def descend(parent, stack): if not stack: return diff --git a/common/lib/xmodule/xmodule/modulestore/xml.py b/common/lib/xmodule/xmodule/modulestore/xml.py index 012fb780e2c5febcae809b64425909d31a258289..8680ea7d9c25dab7dd6b0c4321d71be9c5bcd26c 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml.py +++ b/common/lib/xmodule/xmodule/modulestore/xml.py @@ -842,7 +842,7 @@ class XMLModuleStore(ModuleStoreReadBase): return {'xml': True} @contextmanager - def branch_setting(self, branch_setting, course_id=None): # pylint: disable=unused-argument + def branch_setting(self, branch_setting, course_id=None): """ A context manager for temporarily setting the branch value for the store to the given branch_setting. """ diff --git a/common/lib/xmodule/xmodule/modulestore/xml_importer.py b/common/lib/xmodule/xmodule/modulestore/xml_importer.py index 74da12bf138a253a790eec0ea91ccb1b71b91d5c..ee7864e9d39b60dc4465759ab7944419571b6fe0 100644 --- a/common/lib/xmodule/xmodule/modulestore/xml_importer.py +++ b/common/lib/xmodule/xmodule/modulestore/xml_importer.py @@ -460,15 +460,19 @@ class ImportManager(object): if self.verbose: log.debug('importing module location %s', child.location) - _update_and_import_module( - child, - self.store, - self.user_id, - courselike_key, - dest_id, - do_import_static=self.do_import_static, - runtime=courselike.runtime, - ) + try: + _update_and_import_module( + child, + self.store, + self.user_id, + courselike_key, + dest_id, + do_import_static=self.do_import_static, + runtime=courselike.runtime, + ) + except Exception: + log.error('failed to import module location %s', child.location) + raise depth_first(child) @@ -478,15 +482,19 @@ class ImportManager(object): if self.verbose: log.debug('importing module location %s', leftover) - _update_and_import_module( - self.xml_module_store.get_item(leftover), - self.store, - self.user_id, - courselike_key, - dest_id, - do_import_static=self.do_import_static, - runtime=courselike.runtime, - ) + try: + _update_and_import_module( + self.xml_module_store.get_item(leftover), + self.store, + self.user_id, + courselike_key, + dest_id, + do_import_static=self.do_import_static, + runtime=courselike.runtime, + ) + except Exception: + log.error('failed to import module location %s', leftover) + raise def run_imports(self): """ @@ -689,7 +697,7 @@ class LibraryImportManager(ImportManager): """ Get the descriptor of the library from the XML import modulestore. """ - source_library = self.xml_module_store.get_library(courselike_key) # pylint: disable=no-member + source_library = self.xml_module_store.get_library(courselike_key) library, library_data_path = self.import_courselike( runtime, courselike_key, dest_id, source_library, ) @@ -745,7 +753,7 @@ def _update_and_import_module( """ Move the module to a new course. """ - def _convert_ref_fields_to_new_namespace(reference): # pylint: disable=invalid-name + def _convert_ref_fields_to_new_namespace(reference): """ Convert a reference to the new namespace, but only if the original namespace matched the original course. diff --git a/common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py b/common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py new file mode 100644 index 0000000000000000000000000000000000000000..d5c0b3011e30500a1b935241218b62ed91771792 --- /dev/null +++ b/common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py @@ -0,0 +1,54 @@ +""" +The enrollment_track dynamic partition generation to be part of the +openedx.dynamic_partition plugin. +""" +import logging + +import six +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ + +from xmodule.partitions.partitions import ( + get_partition_from_id, + ENROLLMENT_TRACK_PARTITION_ID, + UserPartition, + UserPartitionError +) + +log = logging.getLogger(__name__) + +FEATURES = getattr(settings, 'FEATURES', {}) + + +def create_enrollment_track_partition(course): + """ + Create and return the dynamic enrollment track user partition. + If it cannot be created, None is returned. + """ + if not FEATURES.get('ENABLE_ENROLLMENT_TRACK_USER_PARTITION'): + return None + + try: + enrollment_track_scheme = UserPartition.get_scheme("enrollment_track") + except UserPartitionError: + log.warning("No 'enrollment_track' scheme registered, EnrollmentTrackUserPartition will not be created.") + return None + + used_ids = set(p.id for p in course.user_partitions) + if ENROLLMENT_TRACK_PARTITION_ID in used_ids: + log.warning( + "Can't add 'enrollment_track' partition, as ID {id} is assigned to {partition} in course {course}.".format( + id=ENROLLMENT_TRACK_PARTITION_ID, + partition=get_partition_from_id(course.user_partitions, ENROLLMENT_TRACK_PARTITION_ID).name, + course=six.text_type(course.id) + ) + ) + return None + + partition = enrollment_track_scheme.create_user_partition( + id=ENROLLMENT_TRACK_PARTITION_ID, + name=_(u"Enrollment Track Groups"), + description=_(u"Partition for segmenting users by enrollment track"), + parameters={"course_id": six.text_type(course.id)} + ) + return partition diff --git a/common/lib/xmodule/xmodule/partitions/partitions.py b/common/lib/xmodule/xmodule/partitions/partitions.py index 891f5a208241723cd94ae6f421e76242d58f1afa..61f6000d2e441b1523ab211556244d99b20c8dff 100644 --- a/common/lib/xmodule/xmodule/partitions/partitions.py +++ b/common/lib/xmodule/xmodule/partitions/partitions.py @@ -126,7 +126,8 @@ class UserPartition(namedtuple("UserPartition", "id name description groups sche # The default scheme to be used when upgrading version 1 partitions. VERSION_1_SCHEME = "random" - def __new__(cls, id, name, description, groups, scheme=None, parameters=None, active=True, scheme_id=VERSION_1_SCHEME): # pylint: disable=line-too-long + def __new__(cls, id, name, description, groups, scheme=None, parameters=None, active=True, + scheme_id=VERSION_1_SCHEME): if not scheme: scheme = UserPartition.get_scheme(scheme_id) if parameters is None: @@ -280,3 +281,17 @@ class UserPartition(namedtuple("UserPartition", "id name description groups sche Returns: :class:`.Fragment` """ return None + + +def get_partition_from_id(partitions, user_partition_id): + """ + Look for a user partition with a matching id in the provided list of partitions. + + Returns: + A UserPartition, or None if not found. + """ + for partition in partitions: + if partition.id == user_partition_id: + return partition + + return None diff --git a/common/lib/xmodule/xmodule/partitions/partitions_service.py b/common/lib/xmodule/xmodule/partitions/partitions_service.py index 79eee7f3730dd8a5a94b9e08d6b9335dfc14b905..4db503eaa897f2acb366a05f8cda16dd412b705a 100644 --- a/common/lib/xmodule/xmodule/partitions/partitions_service.py +++ b/common/lib/xmodule/xmodule/partitions/partitions_service.py @@ -9,12 +9,11 @@ import logging import six from django.conf import settings -from django.utils.translation import ugettext_lazy as _ from openedx.core.lib.cache_utils import request_cached -from openedx.features.content_type_gating.partitions import create_content_gating_partition +from openedx.core.lib.dynamic_partitions_generators import DynamicPartitionGeneratorsPluginManager from xmodule.modulestore.django import modulestore -from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID, UserPartition, UserPartitionError +from xmodule.partitions.partitions import get_partition_from_id log = logging.getLogger(__name__) @@ -74,48 +73,14 @@ def _get_dynamic_partitions(course): Return the dynamic user partitions for this course. If none exists, returns an empty array. """ - return [ - partition - for partition in [ - _create_enrollment_track_partition(course), - create_content_gating_partition(course), - ] - if partition - ] + dynamic_partition_generators = DynamicPartitionGeneratorsPluginManager.get_available_plugins().values() + generated_partitions = [] + for generator in dynamic_partition_generators: + generated_partition = generator(course) + if generated_partition: + generated_partitions.append(generated_partition) - -def _create_enrollment_track_partition(course): - """ - Create and return the dynamic enrollment track user partition. - If it cannot be created, None is returned. - """ - if not FEATURES.get('ENABLE_ENROLLMENT_TRACK_USER_PARTITION'): - return None - - try: - enrollment_track_scheme = UserPartition.get_scheme("enrollment_track") - except UserPartitionError: - log.warning("No 'enrollment_track' scheme registered, EnrollmentTrackUserPartition will not be created.") - return None - - used_ids = set(p.id for p in course.user_partitions) - if ENROLLMENT_TRACK_PARTITION_ID in used_ids: - log.warning( - "Can't add 'enrollment_track' partition, as ID {id} is assigned to {partition} in course {course}.".format( - id=ENROLLMENT_TRACK_PARTITION_ID, - partition=get_partition_from_id(course.user_partitions, ENROLLMENT_TRACK_PARTITION_ID).name, - course=six.text_type(course.id) - ) - ) - return None - - partition = enrollment_track_scheme.create_user_partition( - id=ENROLLMENT_TRACK_PARTITION_ID, - name=_(u"Enrollment Track Groups"), - description=_(u"Partition for segmenting users by enrollment track"), - parameters={"course_id": six.text_type(course.id)} - ) - return partition + return generated_partitions class PartitionService(object): @@ -124,16 +89,17 @@ class PartitionService(object): with a given course. """ - def __init__(self, course_id, cache=None): + def __init__(self, course_id, cache=None, course=None): self._course_id = course_id self._cache = cache + self.course = course def get_course(self): """ Return the course instance associated with this PartitionService. This default implementation looks up the course from the modulestore. """ - return modulestore().get_course(self._course_id) + return self.course or modulestore().get_course(self._course_id) @property def course_partitions(self): @@ -203,17 +169,3 @@ class PartitionService(object): return user_partition.scheme.get_group_for_user( self._course_id, user, user_partition, assign=assign, ) - - -def get_partition_from_id(partitions, user_partition_id): - """ - Look for a user partition with a matching id in the provided list of partitions. - - Returns: - A UserPartition, or None if not found. - """ - for partition in partitions: - if partition.id == user_partition_id: - return partition - - return None diff --git a/common/lib/xmodule/xmodule/partitions/tests/test_partitions.py b/common/lib/xmodule/xmodule/partitions/tests/test_partitions.py index a21c57da23204d0d43c9b50b4fd8c969cdbcc8da..f2a57ede35426d658e53a8f7c9fb380f512964ca 100644 --- a/common/lib/xmodule/xmodule/partitions/tests/test_partitions.py +++ b/common/lib/xmodule/xmodule/partitions/tests/test_partitions.py @@ -118,7 +118,7 @@ class MockUserPartitionScheme(object): class MockEnrollmentTrackUserPartitionScheme(MockUserPartitionScheme): - def create_user_partition(self, id, name, description, groups=None, parameters=None, active=True): # pylint: disable=redefined-builtin, invalid-name, unused-argument + def create_user_partition(self, id, name, description, groups=None, parameters=None, active=True): # pylint: disable=redefined-builtin, invalid-name """ The EnrollmentTrackPartitionScheme provides this method to return a subclass of UserPartition. """ diff --git a/common/lib/xmodule/xmodule/poll_module.py b/common/lib/xmodule/xmodule/poll_module.py index db96ccbb70086f8cf6a3a5e423aac7bcc8305e2a..d8b2e078b1927980901da3e30dcd2a91bff83f6e 100644 --- a/common/lib/xmodule/xmodule/poll_module.py +++ b/common/lib/xmodule/xmodule/poll_module.py @@ -7,7 +7,7 @@ If student have answered - Question with statistics for each answers. """ -import cgi +import html import json import logging from collections import OrderedDict @@ -17,7 +17,7 @@ from pkg_resources import resource_string import six from lxml import etree -from openedx.core.djangolib.markup import Text +from openedx.core.djangolib.markup import Text, HTML from xblock.fields import Boolean, Dict, List, Scope, String from xmodule.mako_module import MakoModuleDescriptor from xmodule.stringify import stringify_children @@ -152,12 +152,12 @@ class PollModule(PollFields, XModule): # Set default count for answer = 0. if answer['id'] not in temp_poll_answers: temp_poll_answers[answer['id']] = 0 - answers_to_json[answer['id']] = cgi.escape(answer['text']) + answers_to_json[answer['id']] = html.escape(answer['text'], quote=False) self.poll_answers = temp_poll_answers return json.dumps({ 'answers': answers_to_json, - 'question': cgi.escape(self.question), + 'question': html.escape(self.question, quote=False), # to show answered poll after reload: 'poll_answer': self.poll_answer, 'poll_answers': self.poll_answers if self.voted else {}, @@ -215,17 +215,22 @@ class PollDescriptor(PollFields, MakoModuleDescriptor, XmlDescriptor): def definition_to_xml(self, resource_fs): """Return an xml element representing to this definition.""" - poll_str = u'<{tag_name}>{text}</{tag_name}>'.format( + poll_str = HTML('<{tag_name}>{text}</{tag_name}>').format( tag_name=self._tag_name, text=self.question) xml_object = etree.fromstring(poll_str) xml_object.set('display_name', self.display_name) def add_child(xml_obj, answer): # Escape answer text before adding to xml tree. - answer_text = six.text_type(Text(answer['text'])) - child_str = u'<{tag_name} id="{id}">{text}</{tag_name}>'.format( - tag_name=self._child_tag_name, id=answer['id'], - text=answer_text) + answer_text = str(answer['text']) + child_str = Text('{tag_begin}{text}{tag_end}').format( + tag_begin=HTML('<{tag_name} id="{id}">').format( + tag_name=self._child_tag_name, + id=answer['id'] + ), + text=answer_text, + tag_end=HTML('</{tag_name}>').format(tag_name=self._child_tag_name) + ) child_node = etree.fromstring(child_str) xml_object.append(child_node) diff --git a/common/lib/xmodule/xmodule/raw_module.py b/common/lib/xmodule/xmodule/raw_module.py index 4d802453577c6bdf5a5299db8b32f356ace79c12..9f5b3c9b56372ae3592407dca5d48ef244348e55 100644 --- a/common/lib/xmodule/xmodule/raw_module.py +++ b/common/lib/xmodule/xmodule/raw_module.py @@ -1,5 +1,3 @@ - - import logging import re @@ -12,7 +10,7 @@ from .exceptions import SerializationError log = logging.getLogger(__name__) -PRE_TAG_REGEX = re.compile(r'<pre>[\s\S]*?</pre>') +PRE_TAG_REGEX = re.compile(r'<pre\b[^>]*>(?:(?=([^<]+))\1|<(?!pre\b[^>]*>))*?</pre>') class RawMixin(object): @@ -25,12 +23,21 @@ class RawMixin(object): @classmethod def definition_from_xml(cls, xml_object, system): - pre_tag_data = [etree.tostring(pre_tag_info) for pre_tag_info in xml_object.findall('.//pre')] - data = etree.tostring(xml_object, pretty_print=True, encoding='unicode') - if pre_tag_data: - for index, pre_tag in enumerate(re.findall(PRE_TAG_REGEX, data)): - data = re.sub(pre_tag, pre_tag_data[index].decode(), data) - return {'data': data}, [] + try: + data = etree.tostring(xml_object, pretty_print=True, encoding='unicode') + pre_tag_data = [] + for pre_tag_info in xml_object.findall('.//pre'): + if len(pre_tag_info.findall('.//pre')) == 0: + pre_tag_data.append(etree.tostring(pre_tag_info)) + + if pre_tag_data: + matches = re.finditer(PRE_TAG_REGEX, data) + for match_num, match in enumerate(matches): + data = re.sub(match.group(), pre_tag_data[match_num].decode(), data) + etree.XML(data) # it just checks if generated string is valid xml + return {'data': data}, [] + except etree.XMLSyntaxError: + return {'data': etree.tostring(xml_object, pretty_print=True, encoding='unicode')}, [] def definition_to_xml(self, resource_fs): """ diff --git a/common/lib/xmodule/xmodule/seq_module.py b/common/lib/xmodule/xmodule/seq_module.py index 9275c396df90759aa5825d12bd0b702e9105b1a8..06ebbaff699c7769bfd8a1a90fef5ae7309192af 100644 --- a/common/lib/xmodule/xmodule/seq_module.py +++ b/common/lib/xmodule/xmodule/seq_module.py @@ -14,6 +14,7 @@ from functools import reduce from pkg_resources import resource_string import six +from django.contrib.auth.models import User from lxml import etree from opaque_keys.edx.keys import UsageKey from pytz import UTC @@ -196,6 +197,7 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): def __init__(self, *args, **kwargs): super(SequenceModule, self).__init__(*args, **kwargs) + self.gated_sequence_fragment = None # If position is specified in system, then use that instead. position = getattr(self.system, 'position', None) if position is not None: @@ -277,6 +279,30 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): prereq_met = True prereq_meta_info = {} + # Content type gating for FBE previously only gated individual blocks + # This was an issue because audit learners could start a timed exam and then be unable to complete the exam + # even if they later upgrade because the timer would have expired. + # For this reason we check if content gating is enabled for the user and gate the entire sequence in that case + # This functionality still needs to be replicated in the frontend-app-learning courseware MFE + # The ticket to track this is https://openedx.atlassian.net/browse/REV-1220 + # Note that this will break compatability with using sequences outside of edx-platform + # but we are ok with this for now + if self.is_time_limited: + try: + user = User.objects.get(id=self.runtime.user_id) + # importing here to avoid a circular import + from openedx.features.content_type_gating.models import ContentTypeGatingConfig + from openedx.features.content_type_gating.helpers import CONTENT_GATING_PARTITION_ID + if ContentTypeGatingConfig.enabled_for_enrollment(user=user, course_key=self.runtime.course_id): + # Get the content type gating locked content fragment to render for this sequence + partition = self.descriptor._get_user_partition(CONTENT_GATING_PARTITION_ID) # pylint: disable=protected-access + user_group = partition.scheme.get_group_for_user(self.runtime.course_id, user, partition) + self.gated_sequence_fragment = partition.access_denied_fragment( + self.descriptor, user, user_group, [] + ) + except User.DoesNotExist: + pass + if self._required_prereq(): if self.runtime.user_is_staff: banner_text = _('This subsection is unlocked for learners when they meet the prerequisite requirements.') @@ -290,6 +316,7 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): banner_text, special_html = special_html_view if special_html and not masquerading_as_specific_student: return Fragment(special_html) + return self._student_or_public_view(context, prereq_met, prereq_meta_info, banner_text) def public_view(self, context): @@ -317,7 +344,7 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): staff is masquerading. """ _ = self.runtime.service(self, "i18n").ugettext - if self.is_time_limited: + if self.is_time_limited and not self.gated_sequence_fragment: special_exam_html = self._time_limited_student_view() if special_exam_html: banner_text = _("This exam is hidden from the learner.") @@ -369,6 +396,7 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): ) items = self._render_student_view_for_items(context, display_items, fragment, view) if prereq_met else [] + params = { 'items': items, 'element_id': self.location.html_id(), @@ -383,8 +411,12 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): 'save_position': view != PUBLIC_VIEW, 'show_completion': view != PUBLIC_VIEW, 'gated_content': self._get_gated_content_info(prereq_met, prereq_meta_info), + 'sequence_name': self.display_name, 'exclude_units': context.get('exclude_units', False) } + if self.gated_sequence_fragment: + params['gated_sequence_fragment'] = self.gated_sequence_fragment.content + return params def _student_or_public_view(self, context, prereq_met, prereq_meta_info, banner_text=None, view=STUDENT_VIEW): @@ -529,6 +561,7 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): context['show_bookmark_button'] = show_bookmark_button context['bookmarked'] = is_bookmarked + context['format'] = getattr(self, 'format', '') if render_items: rendered_item = item.render(view, context) diff --git a/common/lib/xmodule/xmodule/split_test_module.py b/common/lib/xmodule/xmodule/split_test_module.py index b3c0102bb03e413ac33d39cfb51eb6e5fa66ec6c..5855e3aeb237cd9717263108139a7179c3f37fac 100644 --- a/common/lib/xmodule/xmodule/split_test_module.py +++ b/common/lib/xmodule/xmodule/split_test_module.py @@ -329,7 +329,7 @@ class SplitTestModule(SplitTestFields, XModule, StudioEditableModule): return fragment @XBlock.handler - def log_child_render(self, request, suffix=''): # pylint: disable=unused-argument + def log_child_render(self, request, suffix=''): """ Record in the tracking logs which child was rendered """ @@ -382,9 +382,10 @@ class SplitTestModule(SplitTestFields, XModule, StudioEditableModule): return self.descriptor.validate() -@XBlock.needs('user_tags') # pylint: disable=abstract-method +@XBlock.needs('user_tags') @XBlock.needs('partitions') @XBlock.needs('user') +# pylint: disable=missing-class-docstring class SplitTestDescriptor(SplitTestFields, SequenceDescriptor, StudioEditableDescriptor): # the editing interface can be the same as for sequences -- just a container module_class = SplitTestModule @@ -648,7 +649,7 @@ class SplitTestDescriptor(SplitTestFields, SequenceDescriptor, StudioEditableDes return None @XBlock.handler - def add_missing_groups(self, request, suffix=''): # pylint: disable=unused-argument + def add_missing_groups(self, request, suffix=''): """ Create verticals for any missing groups in the split test instance. diff --git a/common/lib/xmodule/xmodule/tabs.py b/common/lib/xmodule/xmodule/tabs.py index 8a8f123c86fa1c0d17a61e6f09e30adf290607b7..71be05141796e50f79448c41d687fa468f3eb4e3 100644 --- a/common/lib/xmodule/xmodule/tabs.py +++ b/common/lib/xmodule/xmodule/tabs.py @@ -414,7 +414,6 @@ class CourseTabList(List): discussion_tab, CourseTab.load('wiki'), CourseTab.load('progress'), - CourseTab.load('dates'), ]) @staticmethod diff --git a/common/lib/xmodule/xmodule/tests/__init__.py b/common/lib/xmodule/xmodule/tests/__init__.py index 33cbda76e79359d8fafaa9a9e123818b1f2a4e49..8c2d9fe6106542cb501ecb1bba5023f20ebd6817 100644 --- a/common/lib/xmodule/xmodule/tests/__init__.py +++ b/common/lib/xmodule/xmodule/tests/__init__.py @@ -47,7 +47,7 @@ class TestModuleSystem(ModuleSystem): # pylint: disable=abstract-method """ ModuleSystem for testing """ - def __init__(self, **kwargs): # pylint: disable=unused-argument + def __init__(self, **kwargs): id_manager = CourseLocationManager(kwargs['course_id']) kwargs.setdefault('id_reader', id_manager) kwargs.setdefault('id_generator', id_manager) @@ -107,7 +107,6 @@ def get_test_system(course_id=CourseKey.from_string('/'.join(['org', 'course', ' def get_module(descriptor): """Mocks module_system get_module function""" - # pylint: disable=protected-access # Unlike XBlock Runtimes or DescriptorSystems, # each XModule is provided with a new ModuleSystem. diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py index f48da0c915903a943daf43b577ec1cc4bc5b2be9..aead4e88089f9841fe85869ef0bddf2e9c8d7892 100644 --- a/common/lib/xmodule/xmodule/tests/test_capa_module.py +++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py @@ -2,7 +2,6 @@ """ Tests of the Capa XModule """ -# pylint: disable=missing-docstring # pylint: disable=invalid-name @@ -861,7 +860,7 @@ class ProblemBlockTest(unittest.TestCase): # pylint: enable=line-too-long self.assertEqual(xqueue_interface._http_post.call_count, 1) - _, kwargs = xqueue_interface._http_post.call_args # pylint: disable=unpacking-non-sequence + _, kwargs = xqueue_interface._http_post.call_args six.assertCountEqual(self, fpaths, list(kwargs['files'].keys())) for fpath, fileobj in six.iteritems(kwargs['files']): self.assertEqual(fpath, fileobj.name) @@ -894,7 +893,7 @@ class ProblemBlockTest(unittest.TestCase): module.handle('xmodule_handler', request, 'problem_check') self.assertEqual(xqueue_interface._http_post.call_count, 1) - _, kwargs = xqueue_interface._http_post.call_args # pylint: disable=unpacking-non-sequence + _, kwargs = xqueue_interface._http_post.call_args six.assertCountEqual(self, fnames, list(kwargs['files'].keys())) for fpath, fileobj in six.iteritems(kwargs['files']): self.assertEqual(fpath, fileobj.name) diff --git a/common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py b/common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py index 5e5e56fdf39bf0a114040f56eea47edb8bee0fee..b4dacc247593bdb81f24d12165891e577a5af03a 100644 --- a/common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py +++ b/common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py @@ -112,8 +112,8 @@ class CourseMetadataUtilsTestCase(TestCase): test_datetime = datetime(1945, 2, 6, 4, 20, 00, tzinfo=utc) advertised_start_parsable = "2038-01-19 03:14:07" - FunctionTest = namedtuple('FunctionTest', 'function scenarios') # pylint: disable=invalid-name - TestScenario = namedtuple('TestScenario', 'arguments expected_return') # pylint: disable=invalid-name + FunctionTest = namedtuple('FunctionTest', 'function scenarios') + TestScenario = namedtuple('TestScenario', 'arguments expected_return') function_tests = [ FunctionTest(clean_course_key, [ diff --git a/common/lib/xmodule/xmodule/tests/test_course_module.py b/common/lib/xmodule/xmodule/tests/test_course_module.py index 771a1e1ba475aa7580a377770f265c3af2ff0b9d..84c1be9a85089eefc5317eb131da1c9a8f957e47 100644 --- a/common/lib/xmodule/xmodule/tests/test_course_module.py +++ b/common/lib/xmodule/xmodule/tests/test_course_module.py @@ -295,7 +295,13 @@ class TeamsConfigurationTestCase(unittest.TestCase): topic_id = "topic_id_{}".format(next_num) name = "Name {}".format(next_num) description = "Description {}".format(next_num) - return {"name": name, "description": description, "id": topic_id} + return { + "name": name, + "description": description, + "id": topic_id, + "type": "open", + "max_team_size": None + } def test_teams_enabled_new_course(self): # Make sure we can detect when no teams exist. @@ -341,7 +347,7 @@ class TeamsConfigurationTestCase(unittest.TestCase): self.add_team_configuration(max_team_size=4, topics=topics) self.assertTrue(self.course.teams_enabled) expected_teamsets_data = [ - teamset.cleaned_data_old_format + teamset.cleaned_data for teamset in self.course.teamsets ] self.assertEqual(expected_teamsets_data, topics) @@ -463,14 +469,14 @@ class ProctoringProviderTestCase(unittest.TestCase): throws a ValueError with the correct error message. """ provider = 'invalid-provider' - proctoring_provider_whitelist = [u'mock', u'mock_proctoring_without_rules'] + allowed_proctoring_providers = [u'mock', u'mock_proctoring_without_rules'] with self.assertRaises(ValueError) as context_manager: self.proctoring_provider.from_json(provider) self.assertEqual( context_manager.exception.args[0], ['The selected proctoring provider, {}, is not a valid provider. Please select from one of {}.' - .format(provider, proctoring_provider_whitelist)] + .format(provider, allowed_proctoring_providers)] ) def test_from_json_adds_platform_default_for_missing_provider(self): diff --git a/common/lib/xmodule/xmodule/tests/test_lti_unit.py b/common/lib/xmodule/xmodule/tests/test_lti_unit.py index ebed5e6cad5596815415d9737eec7c51bb206cbb..0c18c5bea7f4568dde8138159ce6dbf99848c931 100644 --- a/common/lib/xmodule/xmodule/tests/test_lti_unit.py +++ b/common/lib/xmodule/xmodule/tests/test_lti_unit.py @@ -416,7 +416,8 @@ class LTIModuleTest(LogicTest): u'<imsx_POXHeader><imsx_POXRequestHeaderInfo><imsx_version>V1.0</imsx_version>' u'<imsx_messageIdentifier>edX_fix</imsx_messageIdentifier></imsx_POXRequestHeaderInfo>' u'</imsx_POXHeader><imsx_POXBody><replaceResultRequest><resultRecord><sourcedGUID>' - u'<sourcedId>MITxLTI/MITxLTI/201x:localhost%3A8000-i4x-MITxLTI-MITxLTI-lti-3751833a214a4f66a0d18f63234207f2:363979ef768ca171b50f9d1bfb322131</sourcedId>' # pylint: disable=line-too-long + u'<sourcedId>MITxLTI/MITxLTI/201x:localhost%3A8000-i4x-MITxLTI-MITxLTI-lti-3751833a214a4f66a0d18f63234207f2' + u':363979ef768ca171b50f9d1bfb322131</sourcedId>' u'</sourcedGUID><result><resultScore><language>en</language><textString>0.32</textString></resultScore>' u'</result></resultRecord></replaceResultRequest></imsx_POXBody></imsx_POXEnvelopeRequest>' ).encode('utf-8') diff --git a/common/lib/xmodule/xmodule/tests/test_sequence.py b/common/lib/xmodule/xmodule/tests/test_sequence.py index 323d301b5f59bae0a55720a87bbae52cb92d6022..cded440e51e7ef742c4cdb6e3190f1539824cdfb 100644 --- a/common/lib/xmodule/xmodule/tests/test_sequence.py +++ b/common/lib/xmodule/xmodule/tests/test_sequence.py @@ -88,7 +88,7 @@ class SequenceBlockTestCase(XModuleXmlImportTest): return_value=Mock(vertical_is_complete=Mock(return_value=True)) ) block.xmodule_runtime._services['user'] = StubUserService() # pylint: disable=protected-access - block.xmodule_runtime.xmodule_instance = getattr(block, '_xmodule', None) # pylint: disable=protected-access + block.xmodule_runtime.xmodule_instance = getattr(block, '_xmodule', None) block.parent = parent.location return block diff --git a/common/lib/xmodule/xmodule/tests/test_split_test_module.py b/common/lib/xmodule/xmodule/tests/test_split_test_module.py index 14408c4e6bb25f95bd3e8dd16668b380ea61c407..44308770671bd5d49eafe044b2a95c941962f97f 100644 --- a/common/lib/xmodule/xmodule/tests/test_split_test_module.py +++ b/common/lib/xmodule/xmodule/tests/test_split_test_module.py @@ -72,7 +72,8 @@ class SplitTestModuleTest(XModuleXmlImportTest, PartitionTestCase): parent=sequence, attribs={ 'user_partition_id': '0', - 'group_id_to_child': '{"0": "i4x://edX/xml_test_course/html/split_test_cond0", "1": "i4x://edX/xml_test_course/html/split_test_cond1"}' # pylint: disable=line-too-long + 'group_id_to_child': '{"0": "i4x://edX/xml_test_course/html/split_test_cond0", "1":' + ' "i4x://edX/xml_test_course/html/split_test_cond1"}' } ) xml.HtmlFactory(parent=split_test, url_name='split_test_cond0', text='HTML FOR GROUP 0') diff --git a/common/lib/xmodule/xmodule/tests/test_vertical.py b/common/lib/xmodule/xmodule/tests/test_vertical.py index dd0e187d1fda80320dc063d947d73c5e9ecc847b..3287d884d7b09a8b3c3b2e61e1e87eb0cb5ca005 100644 --- a/common/lib/xmodule/xmodule/tests/test_vertical.py +++ b/common/lib/xmodule/xmodule/tests/test_vertical.py @@ -6,7 +6,9 @@ Tests for vertical module. from collections import namedtuple +from datetime import datetime, timedelta import json +import pytz import six import ddt @@ -67,6 +69,11 @@ class StubCompletionService(object): def blocks_to_mark_complete_on_view(self, blocks): return {} if self._completion_value == 1.0 else blocks + def vertical_is_complete(self, item): + if item.scope_ids.block_type != 'vertical': + raise ValueError('The passed in xblock is not a vertical type!') + return self._completion_value + class BaseVerticalBlockTest(XModuleXmlImportTest): """ @@ -120,18 +127,24 @@ class VerticalBlockTestCase(BaseVerticalBlockTest): @ddt.unpack @ddt.data( - {'context': None, 'view': STUDENT_VIEW}, - {'context': {}, 'view': STUDENT_VIEW}, - {'context': {}, 'view': PUBLIC_VIEW}, + {'context': None, 'view': STUDENT_VIEW, 'completion_value': 0.0, 'days': 1}, + {'context': {}, 'view': STUDENT_VIEW, 'completion_value': 0.0, 'days': 1}, + {'context': {}, 'view': PUBLIC_VIEW, 'completion_value': 0.0, 'days': 1}, + {'context': {'format': 'Quiz'}, 'view': STUDENT_VIEW, 'completion_value': 1.0, 'days': 1}, # completed + {'context': {'format': 'Exam'}, 'view': STUDENT_VIEW, 'completion_value': 0.0, 'days': 1}, # upcoming + {'context': {'format': 'Homework'}, 'view': STUDENT_VIEW, 'completion_value': 0.0, 'days': -1}, # past due ) - def test_render_student_preview_view(self, context, view): + def test_render_student_preview_view(self, context, view, completion_value, days): """ Test the rendering of the student and public view. """ self.module_system._services['bookmarks'] = Mock() + now = datetime.now(pytz.UTC) + self.vertical.due = now + timedelta(days=days) if view == STUDENT_VIEW: self.module_system._services['user'] = StubUserService() - self.module_system._services['completion'] = StubCompletionService(enabled=True, completion_value=0.0) + self.module_system._services['completion'] = StubCompletionService(enabled=True, + completion_value=completion_value) elif view == PUBLIC_VIEW: self.module_system._services['user'] = StubUserService(is_anonymous=True) @@ -140,10 +153,16 @@ class VerticalBlockTestCase(BaseVerticalBlockTest): ).content self.assertIn(self.test_html_1, html) self.assertIn(self.test_html_2, html) + self.assertIn("'due': datetime.datetime({year}, {month}, {day}".format( + year=self.vertical.due.year, month=self.vertical.due.month, day=self.vertical.due.day), html) if view == STUDENT_VIEW: self.assert_bookmark_info(self.assertIn, html) else: self.assert_bookmark_info(self.assertNotIn, html) + if context: + self.assertIn("'subsection_format': '{}'".format(context['format']), html) + self.assertIn("'completed': {}".format(completion_value), html) + self.assertIn("'past_due': {}".format(self.vertical.due < now), html) @ddt.unpack @ddt.data( @@ -163,7 +182,7 @@ class VerticalBlockTestCase(BaseVerticalBlockTest): completion_value=completion_value, ) self.module_system.render(self.vertical, STUDENT_VIEW, self.default_context) - if (mark_completed_enabled): + if mark_completed_enabled: self.assertEqual( mock_student_view.call_args[0][1]['wrap_xblock_data']['mark-completed-on-view-after-delay'], 9876 ) diff --git a/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py b/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py index 34b800b3b7caf5a02d3e110dbeb40a649a298ce6..29c5806aaad27c743212ce7a5e18da729c089132 100644 --- a/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py +++ b/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py @@ -184,7 +184,6 @@ class LeafDescriptorFactory(Factory): """ Factory to generate leaf XModuleDescriptors. """ - # pylint: disable=missing-docstring class Meta(object): model = XModuleDescriptor @@ -276,7 +275,7 @@ class XBlockWrapperTestMixin(object): """ pass - def check_property(self, descriptor): # pylint: disable=unused-argument + def check_property(self, descriptor): """ Execute assertions to verify that the property under test is true for the supplied descriptor. @@ -306,20 +305,19 @@ class XBlockWrapperTestMixin(object): descriptor_cls, fields = cls_and_fields self.skip_if_invalid(descriptor_cls) descriptor = ContainerModuleFactory(descriptor_cls=descriptor_cls, depth=2, **fields) - # pylint: disable=no-member descriptor.runtime.id_reader.get_definition_id = Mock(return_value='a') self.check_property(descriptor) # Test that when an xmodule is generated from descriptor_cls # with mixed xmodule and xblock children, the test property holds @ddt.data(*flatten(CONTAINER_XMODULES)) - def test_container_node_mixed(self, cls_and_fields): # pylint: disable=unused-argument + def test_container_node_mixed(self, cls_and_fields): raise SkipTest("XBlock support in XDescriptor not yet fully implemented") # Test that when an xmodule is generated from descriptor_cls # with only xblock children, the test property holds @ddt.data(*flatten(CONTAINER_XMODULES)) - def test_container_node_xblocks_only(self, cls_and_fields): # pylint: disable=unused-argument + def test_container_node_xblocks_only(self, cls_and_fields): raise SkipTest("XBlock support in XModules not yet fully implemented") diff --git a/common/lib/xmodule/xmodule/vertical_block.py b/common/lib/xmodule/xmodule/vertical_block.py index 08cfc2e7ee2858df71de3f5074b307a6c28a6da2..9654d912e3c6232f608ecdea61078b054c0daaa5 100644 --- a/common/lib/xmodule/xmodule/vertical_block.py +++ b/common/lib/xmodule/xmodule/vertical_block.py @@ -5,8 +5,10 @@ VerticalBlock - an XBlock which renders its children in a column. import logging from copy import copy +from datetime import datetime from functools import reduce +import pytz import six from lxml import etree from web_fragments.fragment import Fragment @@ -89,10 +91,16 @@ class VerticalBlock(SequenceFields, XModuleFields, StudioEditableBlock, XmlParse 'content': rendered_child.content }) + completed = completion_service and completion_service.vertical_is_complete(self) + past_due = not completed and self.due and self.due < datetime.now(pytz.UTC) fragment_context = { 'items': contents, 'xblock_context': context, 'unit_title': self.display_name_with_default if not is_child_of_vertical else None, + 'due': self.due, + 'completed': completed, + 'past_due': past_due, + 'subsection_format': context.get('format', ''), } if view == STUDENT_VIEW: diff --git a/common/lib/xmodule/xmodule/video_module/__init__.py b/common/lib/xmodule/xmodule/video_module/__init__.py index cbee7351b9a3746cc72e42e9366525b347f01f37..8c132b766dcd9014caee51d091401a9c692507b2 100644 --- a/common/lib/xmodule/xmodule/video_module/__init__.py +++ b/common/lib/xmodule/xmodule/video_module/__init__.py @@ -2,8 +2,6 @@ Container for video module and its utils. """ -# pylint: disable=wildcard-import - from .bumper_utils import * from .transcripts_utils import * from .video_module import * diff --git a/common/lib/xmodule/xmodule/video_module/transcripts_utils.py b/common/lib/xmodule/xmodule/video_module/transcripts_utils.py index 09a14f809f1f593ef5c184c463fd02b731957643..fca01d7352f9788b11b4f5681d3b64b3746fab18 100644 --- a/common/lib/xmodule/xmodule/video_module/transcripts_utils.py +++ b/common/lib/xmodule/xmodule/video_module/transcripts_utils.py @@ -19,7 +19,7 @@ from pysrt import SubRipFile, SubRipItem, SubRipTime from pysrt.srtexc import Error from six import text_type from six.moves import range, zip -from six.moves.html_parser import HTMLParser # pylint: disable=import-error +from six.moves.html_parser import HTMLParser from openedx.core.djangolib import blockstore_cache from openedx.core.lib import blockstore_api @@ -40,19 +40,19 @@ log = logging.getLogger(__name__) NON_EXISTENT_TRANSCRIPT = 'non_existent_dummy_file_name' -class TranscriptException(Exception): # pylint: disable=missing-docstring +class TranscriptException(Exception): pass -class TranscriptsGenerationException(Exception): # pylint: disable=missing-docstring +class TranscriptsGenerationException(Exception): pass -class GetTranscriptsFromYouTubeException(Exception): # pylint: disable=missing-docstring +class GetTranscriptsFromYouTubeException(Exception): pass -class TranscriptsRequestValidationException(Exception): # pylint: disable=missing-docstring +class TranscriptsRequestValidationException(Exception): pass diff --git a/common/lib/xmodule/xmodule/video_module/video_handlers.py b/common/lib/xmodule/xmodule/video_module/video_handlers.py index bde727a7ea1a54a81f536b0cd78cf3d01e15eb5f..037ec75e00dc17e4ff756119acc325a2bc6bd476 100644 --- a/common/lib/xmodule/xmodule/video_module/video_handlers.py +++ b/common/lib/xmodule/xmodule/video_module/video_handlers.py @@ -391,7 +391,11 @@ class VideoStudentViewHandlers(object): runtime uses a similar REST API that's not an XBlock handler. """ from lms.djangoapps.courseware.views.views import load_metadata_from_youtube - metadata, status_code = load_metadata_from_youtube(video_id=self.youtube_id_1_0) + if not self.youtube_id_1_0: + # TODO: more informational response to explain that yt_video_metadata not supported for non-youtube videos. + return Response('{}', status=400) + + metadata, status_code = load_metadata_from_youtube(video_id=self.youtube_id_1_0, request=request) response = Response(json.dumps(metadata), status=status_code) response.content_type = 'application/json' return response diff --git a/common/lib/xmodule/xmodule/video_module/video_module.py b/common/lib/xmodule/xmodule/video_module/video_module.py index 870f2b2e4d4b0c3109b3eca0b0580f2ea928dfbb..27b61934f7f87d38f2dba59928f22b37926ac271 100644 --- a/common/lib/xmodule/xmodule/video_module/video_module.py +++ b/common/lib/xmodule/xmodule/video_module/video_module.py @@ -394,47 +394,7 @@ class VideoBlock( autoadvance_this_video = self.auto_advance and autoadvance_enabled metadata = { - 'saveStateEnabled': view != PUBLIC_VIEW, - 'saveStateUrl': self.ajax_url + '/save_user_state', - 'autoplay': settings.FEATURES.get('AUTOPLAY_VIDEOS', False), - 'streams': self.youtube_streams, - 'sources': sources, - 'poster': poster, - 'duration': video_duration, - # This won't work when we move to data that - # isn't on the filesystem - 'captionDataDir': getattr(self, 'data_dir', None), - - 'showCaptions': json.dumps(self.show_captions), - 'generalSpeed': self.global_speed, - 'speed': self.speed, 'autoAdvance': autoadvance_this_video, - 'savedVideoPosition': self.saved_video_position.total_seconds(), - 'start': self.start_time.total_seconds(), - 'end': self.end_time.total_seconds(), - 'completionEnabled': completion_enabled, - 'completionPercentage': settings.COMPLETION_VIDEO_COMPLETE_PERCENTAGE, - 'transcriptLanguage': transcript_language, - 'transcriptLanguages': sorted_languages, - 'ytTestTimeout': settings.YOUTUBE['TEST_TIMEOUT'], - 'ytApiUrl': settings.YOUTUBE['API'], - 'lmsRootURL': settings.LMS_ROOT_URL, - 'ytMetadataEndpoint': ( - # In the new runtime, get YouTube metadata via a handler. The handler supports anonymous users and - # can work in sandboxed iframes. In the old runtime, the JS will call the LMS's yt_video_metadata - # API endpoint directly (not an XBlock handler). - self.runtime.handler_url(self, 'yt_video_metadata') - if getattr(self.runtime, 'suppports_state_for_anonymous_users', False) else '' - ), - - 'transcriptTranslationUrl': self.runtime.handler_url( - self, 'transcript', 'translation/__lang__' - ).rstrip('/?'), - 'transcriptAvailableTranslationsUrl': self.runtime.handler_url( - self, 'transcript', 'available_translations' - ).rstrip('/?'), - 'publishCompletionUrl': self.runtime.handler_url(self, 'publish_completion', '').rstrip('?'), - # For now, the option "data-autohide-html5" is hard coded. This option # either enables or disables autohiding of controls and captions on mouse # inactivity. If set to true, controls and captions will autohide for @@ -447,12 +407,48 @@ class VideoBlock( # this option will have an effect if changed to "True". The code on # front-end exists. 'autohideHtml5': False, - + 'autoplay': settings.FEATURES.get('AUTOPLAY_VIDEOS', False), + # This won't work when we move to data that + # isn't on the filesystem + 'captionDataDir': getattr(self, 'data_dir', None), + 'completionEnabled': completion_enabled, + 'completionPercentage': settings.COMPLETION_VIDEO_COMPLETE_PERCENTAGE, + 'duration': video_duration, + 'end': self.end_time.total_seconds(), # pylint: disable=no-member + 'generalSpeed': self.global_speed, + 'lmsRootURL': settings.LMS_ROOT_URL, + 'poster': poster, + 'prioritizeHls': self.prioritize_hls(self.youtube_streams, sources), + 'publishCompletionUrl': self.runtime.handler_url(self, 'publish_completion', '').rstrip('?'), # This is the server's guess at whether youtube is available for # this user, based on what was recorded the last time we saw the # user, and defaulting to True. 'recordedYoutubeIsAvailable': self.youtube_is_available, - 'prioritizeHls': self.prioritize_hls(self.youtube_streams, sources), + 'savedVideoPosition': self.saved_video_position.total_seconds(), # pylint: disable=no-member + 'saveStateEnabled': view != PUBLIC_VIEW, + 'saveStateUrl': self.ajax_url + '/save_user_state', + 'showCaptions': json.dumps(self.show_captions), + 'sources': sources, + 'speed': self.speed, + 'start': self.start_time.total_seconds(), # pylint: disable=no-member + 'streams': self.youtube_streams, + 'transcriptAvailableTranslationsUrl': self.runtime.handler_url( + self, 'transcript', 'available_translations' + ).rstrip('/?'), + 'transcriptLanguage': transcript_language, + 'transcriptLanguages': sorted_languages, + 'transcriptTranslationUrl': self.runtime.handler_url( + self, 'transcript', 'translation/__lang__' + ).rstrip('/?'), + 'ytApiUrl': settings.YOUTUBE['API'], + 'ytMetadataEndpoint': ( + # In the new runtime, get YouTube metadata via a handler. The handler supports anonymous users and + # can work in sandboxed iframes. In the old runtime, the JS will call the LMS's yt_video_metadata + # API endpoint directly (not an XBlock handler). + self.runtime.handler_url(self, 'yt_video_metadata') + if getattr(self.runtime, 'suppports_state_for_anonymous_users', False) else '' + ), + 'ytTestTimeout': settings.YOUTUBE['TEST_TIMEOUT'], } bumperize(self) @@ -821,7 +817,8 @@ class VideoBlock( _ = self.runtime.service(self, "i18n").ugettext video_url.update({ - 'help': _('The URL for your video. This can be a YouTube URL or a link to an .mp4, .ogg, or .webm video file hosted elsewhere on the Internet.'), # pylint: disable=line-too-long + 'help': _('The URL for your video. This can be a YouTube URL or a link to an .mp4, .ogg, or ' + '.webm video file hosted elsewhere on the Internet.'), 'display_name': _('Default Video URL'), 'field_name': 'video_url', 'type': 'VideoList', diff --git a/common/lib/xmodule/xmodule/video_module/video_utils.py b/common/lib/xmodule/xmodule/video_module/video_utils.py index 8b6f0e3bee1576aad1b6c289f171bcd39b7af2ba..19e27d4865c636329e7c24958c451034c3b9a2db 100644 --- a/common/lib/xmodule/xmodule/video_module/video_utils.py +++ b/common/lib/xmodule/xmodule/video_module/video_utils.py @@ -12,7 +12,7 @@ from django.conf import settings from django.core.exceptions import ValidationError from django.core.validators import URLValidator from six.moves import zip -from six.moves.urllib.parse import parse_qs, urlencode, urlparse, urlsplit, urlunsplit # pylint: disable=import-error +from six.moves.urllib.parse import parse_qs, urlencode, urlparse, urlsplit, urlunsplit log = logging.getLogger(__name__) diff --git a/common/lib/xmodule/xmodule/video_module/video_xfields.py b/common/lib/xmodule/xmodule/video_module/video_xfields.py index c18c55464916342faa6f98e0acfb51a1bdbff18d..60f257130bba205cb6cc2c155b4a5a04595616a8 100644 --- a/common/lib/xmodule/xmodule/video_module/video_xfields.py +++ b/common/lib/xmodule/xmodule/video_module/video_xfields.py @@ -77,24 +77,36 @@ class VideoFields(object): #front-end code of video player checks logical validity of (start_time, end_time) pair. download_video = Boolean( - help=_("Allow students to download versions of this video in different formats if they cannot use the edX video player or do not have access to YouTube. You must add at least one non-YouTube URL in the Video File URLs field."), # pylint: disable=line-too-long + help=_("Allow students to download versions of this video in different formats if they cannot use the edX video" + " player or do not have access to YouTube. You must add at least one non-YouTube URL " + "in the Video File URLs field."), display_name=_("Video Download Allowed"), scope=Scope.settings, default=False ) html5_sources = List( - help=_("The URL or URLs where you've posted non-YouTube versions of the video. Each URL must end in .mpeg, .mp4, .ogg, or .webm and cannot be a YouTube URL. (For browser compatibility, we strongly recommend .mp4 and .webm format.) Students will be able to view the first listed video that's compatible with the student's computer. To allow students to download these videos, set Video Download Allowed to True."), # pylint: disable=line-too-long + help=_("The URL or URLs where you've posted non-YouTube versions of the video. Each URL must end in .mpeg," + " .mp4, .ogg, or .webm and cannot be a YouTube URL. (For browser compatibility, we strongly recommend" + " .mp4 and .webm format.) Students will be able to view the first listed video that's compatible with" + " the student's computer. To allow students to download these videos, " + "set Video Download Allowed to True."), display_name=_("Video File URLs"), scope=Scope.settings, ) track = String( - help=_("By default, students can download an .srt or .txt transcript when you set Download Transcript Allowed to True. If you want to provide a downloadable transcript in a different format, we recommend that you upload a handout by using the Upload a Handout field. If this isn't possible, you can post a transcript file on the Files & Uploads page or on the Internet, and then add the URL for the transcript here. Students see a link to download that transcript below the video."), # pylint: disable=line-too-long + help=_("By default, students can download an .srt or .txt transcript when you set Download Transcript " + "Allowed to True. If you want to provide a downloadable transcript in a different format, we recommend " + "that you upload a handout by using the Upload a Handout field. If this isn't possible, you can post a " + "transcript file on the Files & Uploads page or on the Internet, and then add the URL for the " + "transcript here. Students see a link to download that transcript below the video."), display_name=_("Downloadable Transcript URL"), scope=Scope.settings, default='' ) download_track = Boolean( - help=_("Allow students to download the timed transcript. A link to download the file appears below the video. By default, the transcript is an .srt or .txt file. If you want to provide the transcript for download in a different format, upload a file by using the Upload Handout field."), # pylint: disable=line-too-long + help=_("Allow students to download the timed transcript. A link to download the file appears below the video." + " By default, the transcript is an .srt or .txt file. If you want to provide the transcript for " + "download in a different format, upload a file by using the Upload Handout field."), display_name=_("Download Transcript Allowed"), scope=Scope.settings, default=False @@ -102,7 +114,8 @@ class VideoFields(object): # `sub` is deprecated field and should not be used in future. Now, transcripts are primarily handled in VAL and # backward compatibility for the video modules already using this field has been ensured. sub = String( - help=_("The default transcript for the video, from the Default Timed Transcript field on the Basic tab. This transcript should be in English. You don't have to change this setting."), # pylint: disable=line-too-long + help=_("The default transcript for the video, from the Default Timed Transcript field on the Basic tab. " + "This transcript should be in English. You don't have to change this setting."), display_name=_("Default Timed Transcript"), scope=Scope.settings, default="" @@ -115,7 +128,8 @@ class VideoFields(object): ) # Data format: {'de': 'german_translation', 'uk': 'ukrainian_translation'} transcripts = Dict( - help=_("Add transcripts in different languages. Click below to specify a language and upload an .srt transcript file for that language."), # pylint: disable=line-too-long + help=_("Add transcripts in different languages." + " Click below to specify a language and upload an .srt transcript file for that language."), display_name=_("Transcript Languages"), scope=Scope.settings, default={} @@ -160,7 +174,8 @@ class VideoFields(object): default=True ) handout = String( - help=_("Upload a handout to accompany this video. Students can download the handout by clicking Download Handout under the video."), # pylint: disable=line-too-long + help=_("Upload a handout to accompany this video. Students can download the handout by " + "clicking Download Handout under the video."), display_name=_("Upload Handout"), scope=Scope.settings, ) @@ -174,7 +189,10 @@ class VideoFields(object): default=False ) edx_video_id = String( - help=_("If you were assigned a Video ID by edX for the video to play in this component, enter the ID here. In this case, do not enter values in the Default Video URL, the Video File URLs, and the YouTube ID fields. If you were not assigned a Video ID, enter values in those other fields and ignore this field."), # pylint: disable=line-too-long + help=_("If you were assigned a Video ID by edX for the video to play in this component, enter the ID here." + " In this case, do not enter values in the Default Video URL, the Video File URLs, " + "and the YouTube ID fields. If you were not assigned a Video ID," + " enter values in those other fields and ignore this field."), display_name=_("Video ID"), scope=Scope.settings, default="", diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 11a94ef42fe728ea0f8e2d1198c7b4dc6cab5026..308bd90779148bd1fa552264cfad899bf0be7853 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -672,7 +672,6 @@ class XModuleMixin(XModuleFields, XBlock): Note that the functions will be applied in the order in which they're listed. So [f1, f2] -> f2(f1(field_data)) """ - # pylint: disable=attribute-defined-outside-init # Skip rebinding if we're already bound a user, and it's this user. if self.scope_ids.user_id is not None and user_id == self.scope_ids.user_id: @@ -964,7 +963,7 @@ class XModule(XModuleToXBlockMixin, HTMLSnippet, XModuleMixin): return CombinedSystem(self._runtime, self.descriptor._runtime) # pylint: disable=protected-access @runtime.setter - def runtime(self, value): # pylint: disable=arguments-differ + def runtime(self, value): self._runtime = value def __str__(self): @@ -1393,7 +1392,7 @@ class ConfigurableFragmentWrapper(object): # Runtime.handler_url interface. # # The monkey-patching happens in cms/djangoapps/xblock_config/apps.py and lms/djangoapps/lms_xblock/apps.py -def descriptor_global_handler_url(block, handler_name, suffix='', query='', thirdparty=False): # pylint: disable=unused-argument +def descriptor_global_handler_url(block, handler_name, suffix='', query='', thirdparty=False): """ See :meth:`xblock.runtime.Runtime.handler_url`. """ @@ -1405,7 +1404,7 @@ def descriptor_global_handler_url(block, handler_name, suffix='', query='', thir # the Runtime part of its interface. This function matches the Runtime.local_resource_url interface # # The monkey-patching happens in cms/djangoapps/xblock_config/apps.py and lms/djangoapps/lms_xblock/apps.py -def descriptor_global_local_resource_url(block, uri): # pylint: disable=invalid-name, unused-argument +def descriptor_global_local_resource_url(block, uri): """ See :meth:`xblock.runtime.Runtime.local_resource_url`. """ diff --git a/common/static/common/js/discussion/utils.js b/common/static/common/js/discussion/utils.js index 20ee03cb90c25f824a95d04ffafb85abc6764489..1d544807c671fc4c32bb5b02cdee8f2a353c0cc2 100644 --- a/common/static/common/js/discussion/utils.js +++ b/common/static/common/js/discussion/utils.js @@ -485,7 +485,7 @@ }; DiscussionUtil.typesetMathJax = function(element) { - if (typeof MathJax !== 'undefined' && MathJax !== null && MathJax.Hub !== 'undefined') { + if (typeof MathJax !== 'undefined' && MathJax !== null && typeof MathJax.Hub !== 'undefined') { MathJax.Hub.Queue(['Typeset', MathJax.Hub, element[0]]); } }; diff --git a/common/static/common/templates/discussion/templates.underscore b/common/static/common/templates/discussion/templates.underscore index 273cc679dbea2a9d85098220a5511fce40b407d3..0ddb6f2e539d72b9ead33696c0a9073a1a0d2f50 100644 --- a/common/static/common/templates/discussion/templates.underscore +++ b/common/static/common/templates/discussion/templates.underscore @@ -140,7 +140,7 @@ <input id='edit-discussion-forum-title' aria-describedby="field_help_title" type="text" class="edit-post-title field-input" name="title" value="<%- title %>"> </label> </div> -<div class="form-row post-field"> +<div class="post-field"> <p class="sr-only field-help" id="edit-post-editor-description"><%- gettext('Edit your post below.') %></p> <div class="edit-post-body" aria-describedby="edit-post-editor-description" name="body"><%- body %></div> </div> @@ -241,9 +241,7 @@ <div class="edit-post-form"> <h<%- startHeader %>><%- gettext("Editing response") %></h<%- startHeader %>> <ul class="edit-post-form-errors"></ul> - <div class="form-row"> - <div class="edit-post-body" name="body" data-id="<%- id %>"><%- body %></div> - </div> + <div class="edit-post-body" name="body" data-id="<%- id %>"><%- body %></div> <button type="submit" id="edit-response-submit"class="btn btn-primary post-update"><%- gettext("Update response") %></button> <button class="btn btn-outline-primary post-cancel"><%- gettext("Cancel") %></button> </div> @@ -290,9 +288,7 @@ <div class="edit-post-form" id="comment_<%- id %>"> <h<%- startHeader %> ><%- gettext("Editing comment") %></h<%- startHeader%>> <ul class="edit-comment-form-errors"></ul> - <div class="form-row"> - <div class="edit-comment-body" name="body" data-id="<%- id %>"><%- body %></div> - </div> + <div class="edit-comment-body" name="body" data-id="<%- id %>"><%- body %></div> <button type="submit" id="edit-comment-submit" class="btn btn-primary post-update"><%- gettext("Update comment") %></button> <button class="btn btn-outline-primary post-cancel"><%- gettext("Cancel") %></button> </div> @@ -565,7 +561,7 @@ </script> <script aria-hidden="true" type="text/template" id="inline-discussion-template"> <section class="discussion inline-discussion" data-discussion-id="<%- discussionId %>"> - <div class="add_post_btn_container <%if (read_only) {%>is-hidden<%} %>"> + <div class="add_post_btn_container <% if (read_only) { %> is-hidden <% } %>"> <button class="btn-link new-post-btn"><%- gettext("Add a Post") %></button> </div> diff --git a/common/static/data/geoip/GeoLite2-Country.mmdb b/common/static/data/geoip/GeoLite2-Country.mmdb index c068fc5f01e7f141ef8003e8be4dba19ff782994..8e413da8d63d9731c6165cd23e998ff6dcf4d29b 100644 Binary files a/common/static/data/geoip/GeoLite2-Country.mmdb and b/common/static/data/geoip/GeoLite2-Country.mmdb differ diff --git a/common/static/js/capa/spec/formula_equation_preview_spec.js b/common/static/js/capa/spec/formula_equation_preview_spec.js index ad0a903e0352b1b7be818f2e41739151e19eca6c..17c147a8d0cf7af68c029bb9010099b3163ce237 100644 --- a/common/static/js/capa/spec/formula_equation_preview_spec.js +++ b/common/static/js/capa/spec/formula_equation_preview_spec.js @@ -1,3 +1,32 @@ +describe('escapeSelector', function() { + 'use strict'; + var escapeSelector = window.escapeSelector; + + it('correctly escapes css', function() { + // tests borrowed from + // https://github.com/jquery/jquery/blob/3edfa1bcdc50bca41ac58b2642b12f3feee03a3b/test/unit/selector.js#L2030 + expect(escapeSelector('-')).toEqual('\\-'); + expect(escapeSelector('-a')).toEqual('-a'); + expect(escapeSelector('--')).toEqual('--'); + expect(escapeSelector('--a')).toEqual('--a'); + expect(escapeSelector('\uFFFD')).toEqual('\uFFFD'); + expect(escapeSelector('\uFFFDb')).toEqual('\uFFFDb'); + expect(escapeSelector('a\uFFFDb')).toEqual('a\uFFFDb'); + expect(escapeSelector('1a')).toEqual('\\31 a'); + expect(escapeSelector('a\0b')).toEqual('a\uFFFDb'); + expect(escapeSelector('a3b')).toEqual('a3b'); + expect(escapeSelector('-4a')).toEqual('-\\34 a'); + expect(escapeSelector('\x01\x02\x1E\x1F')).toEqual('\\1 \\2 \\1e \\1f '); + + // This is the important one; xblocks and course ids often contain invalid characters, so if these aren't + // escaped when embedding/searching xblock IDs using css selectors, bad things happen. + expect(escapeSelector('course-v1:edX+DemoX+Demo_Course')).toEqual('course-v1\\:edX\\+DemoX\\+Demo_Course'); + expect(escapeSelector('block-v1:edX+DemoX+Demo_Course+type@sequential+block')).toEqual( + 'block-v1\\:edX\\+DemoX\\+Demo_Course\\+type\\@sequential\\+block' + ); + }); +}); + describe('Formula Equation Preview', function() { 'use strict'; var formulaEquationPreview = window.formulaEquationPreview; diff --git a/common/static/js/capa/src/formula_equation_preview.js b/common/static/js/capa/src/formula_equation_preview.js index 646ba0809c021da12426bc9339b329640b185746..8456171972620a9bb186d0acf7d2ef335b31420f 100644 --- a/common/static/js/capa/src/formula_equation_preview.js +++ b/common/static/js/capa/src/formula_equation_preview.js @@ -1,3 +1,38 @@ +function escapeSelector(id) { + 'use strict'; + // Wrapper around window.CSS.escape that uses a fallback method if CSS.escape is not available. This is designed to + // serialize a string to be used as a valid css selector. See + // https://drafts.csswg.org/cssom/#the-css.escape()-method For example, this can be used with xblock and course ids, + // which often contain invalid characters that must be escaped to function properly in css selectors. + // TODO: if this escaping is also required elsewhere, it may be useful to add a global CSS.escape polyfill and + // use that directly. + + // CSS string/identifier serialization https://drafts.csswg.org/cssom/#common-serializing-idioms + // This code borrowed from https://api.jquery.com/jQuery.escapeSelector/ (source: + // https://github.com/jquery/jquery/blob/3edfa1bc/src/selector/escapeSelector.js). When we upgrade to jQuery 3.0, we + // can use $.escapeSelector() instead of this shim escapeSelector function. + var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g; // eslint-disable-line no-control-regex + function fcssescape(ch, asCodePoint) { + if (asCodePoint) { + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if (ch === '\0') { + return '\uFFFD'; + } + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice(0, -1) + '\\' + ch.charCodeAt(ch.length - 1).toString(16) + ' '; + } + // Other potentially-special ASCII characters get backslash-escaped + return '\\' + ch; + } + + if (window.CSS && window.CSS.escape) { + return window.CSS.escape(id); + } else { + // ensure string and then run the replacements + return (id + '').replace(rcssescape, fcssescape); + } +} + var formulaEquationPreview = { minDelay: 300, // Minimum time between requests sent out. errorDelay: 1500 // Wait time before showing error (prevent frustration). @@ -13,7 +48,7 @@ formulaEquationPreview.enable = function() { function setupInput() { var $this = $(this); // cache the jQuery object - var $preview = $('#' + this.id + '_preview'); + var $preview = $('#' + escapeSelector(this.id) + '_preview'); var inputData = { // These are the mutable values diff --git a/common/static/sass/_mixins-inherited.scss b/common/static/sass/_mixins-inherited.scss index f2055eb61fc1e721ec59f5261e7887b973085676..e02e2510849a39faf1d0ef4a4520f913ab141b2d 100644 --- a/common/static/sass/_mixins-inherited.scss +++ b/common/static/sass/_mixins-inherited.scss @@ -173,12 +173,14 @@ background-color: $uxpl-green-base; color: $white; - &:hover, &:focus { + &:hover, + &:focus { background-color: $uxpl-green-hover-active; color: $white; } - &.disabled, &.is-disabled { + &.disabled, + &.is-disabled { border: 1px solid $green-l3 !important; background: $green-l3 !important; color: $white !important; @@ -195,12 +197,15 @@ background-color: theme-color("primary"); color: $white; - &:hover, &:focus, &:active { + &:hover, + &:focus, + &:active { background-color: $uxpl-blue-hover-active; color: $white; } - &.disabled, &.is-disabled { + &.disabled, + &.is-disabled { box-shadow: none; border: 1px solid $blue-l3 !important; background: $blue-l3 !important; @@ -217,12 +222,15 @@ background-color: $red; color: $white; - &:hover, &:focus, &:active { + &:hover, + &:focus, + &:active { background-color: $red-s1; color: $white; } - &.disabled, &.is-disabled { + &.disabled, + &.is-disabled { box-shadow: none; border: 1px solid $red-l3 !important; background: $red-l3 !important; @@ -239,12 +247,15 @@ background-color: $pink; color: $white; - &:hover, &:focus, &:active { + &:hover, + &:focus, + &:active { background-color: $pink-s1; color: $white; } - &.disabled, &.is-disabled { + &.disabled, + &.is-disabled { box-shadow: none; border: 1px solid $pink-l3 !important; background: $pink-l3 !important; @@ -262,12 +273,14 @@ background-color: $orange; color: $gray-d2; - &:hover, &:focus { + &:hover, + &:focus { background-color: $orange-s2; color: $gray-d2; } - &.disabled, &.is-disabled { + &.disabled, + &.is-disabled { border: 1px solid $orange-l3 !important; background: $orange-l2 !important; color: $gray-l1 !important; @@ -286,7 +299,8 @@ color: rgb(92, 103, 122); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - &:hover, &:focus { + &:hover, + &:focus { background-color: rgb(222, 236, 247); color: rgb(92, 103, 122); } @@ -318,7 +332,8 @@ background-color: $gray-d2; color: $gray-l3; - &:hover, &:focus { + &:hover, + &:focus { background-color: $gray-d3; color: $white; } diff --git a/common/static/sass/_mixins.scss b/common/static/sass/_mixins.scss index c530acb4d54f06a25e49c921ea41bfc8a89966d8..7b105b9305acb70e6bc1cecbca3a9628690b1b99 100644 --- a/common/static/sass/_mixins.scss +++ b/common/static/sass/_mixins.scss @@ -114,8 +114,8 @@ // used for page/view-level wrappers (for centering/grids) %ui-wrapper { @include clearfix(); - @include box-sizing(border-box); + box-sizing: border-box; width: 100%; } @@ -198,7 +198,8 @@ // +UI - Buttons - Extends // ==================== %ui-btn { - @include box-sizing(border-box); + box-sizing: border-box; + @include transition(color $tmg-f2 ease-in-out 0s, border-color $tmg-f2 ease-in-out 0s, background $tmg-f2 ease-in-out 0s, box-shadow $tmg-f2 ease-in-out 0s); display: inline-block; @@ -440,8 +441,7 @@ // +Content - Text Truncate - Extend // ==================== %cont-truncated { - @include box-sizing(border-box); - + box-sizing: border-box; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; diff --git a/common/static/sass/assets/_anims.scss b/common/static/sass/assets/_anims.scss index 10ae9f0a738f4ef29a31ab97f01901bb3f3b3361..d6c84b536a03180a69c2038a284b1fa99307a519 100644 --- a/common/static/sass/assets/_anims.scss +++ b/common/static/sass/assets/_anims.scss @@ -137,7 +137,8 @@ // flash @include keyframes(flash) { - 0%, 100% { + 0%, + 100% { opacity: 1; } @@ -148,11 +149,14 @@ // flash - double @include keyframes(flashDouble) { - 0%, 50%, 100% { + 0%, + 50%, + 100% { opacity: 1; } - 25%, 75% { + 25%, + 75% { opacity: 0; } } diff --git a/common/static/sass/edx-pattern-library-shims/_form.scss b/common/static/sass/edx-pattern-library-shims/_form.scss index cdfc9dd4acae80b75269ab955e21696012e088b5..51281142ca8d6de137482842b2349f6994a97e1e 100644 --- a/common/static/sass/edx-pattern-library-shims/_form.scss +++ b/common/static/sass/edx-pattern-library-shims/_form.scss @@ -19,9 +19,9 @@ .field-input:checked + .field-input-label { color: theme-color("primary"); } - } -.input-radio, .input-checkbox { +.input-radio, +.input-checkbox { @include margin-right($baseline / 2); } diff --git a/common/static/sass/neat/functions/_private.scss b/common/static/sass/neat/functions/_private.scss index 077bf7e2f9886700658cfa0cdf7b41b9c331dfbc..9c79c9bbbb633781342448f8ec52c1be7d1b5015 100644 --- a/common/static/sass/neat/functions/_private.scss +++ b/common/static/sass/neat/functions/_private.scss @@ -1,6 +1,6 @@ // Checks if a number is even @function is-even($int) { - @if $int%2 == 0 { + @if $int%2 == 0 { @return true; } @@ -96,7 +96,7 @@ // Layout direction @function get-direction($layout, $default) { $direction: nil; - + @if $layout == LTR or $layout == RTL { $direction: direction-from-layout($layout); } diff --git a/common/static/sass/neat/grid/_fill-parent.scss b/common/static/sass/neat/grid/_fill-parent.scss index 859c97790bff6cb657b29ff0bf8fe1c49e59da96..da336ea2d380fa3fd153e7684aecef697e8cc8b5 100644 --- a/common/static/sass/neat/grid/_fill-parent.scss +++ b/common/static/sass/neat/grid/_fill-parent.scss @@ -2,6 +2,6 @@ width: 100%; @if $border-box-sizing == false { - @include box-sizing(border-box); + box-sizing: border-box; } } diff --git a/common/static/sass/neat/grid/_grid.scss b/common/static/sass/neat/grid/_grid.scss index e074b6c536c8059a282e2a1f89ab31202188394e..a5b5e504f2ae7027d8f55f380b7c9a5c4bb54410 100644 --- a/common/static/sass/neat/grid/_grid.scss +++ b/common/static/sass/neat/grid/_grid.scss @@ -1,5 +1,5 @@ @if $border-box-sizing == true { * { - @include box-sizing(border-box); + box-sizing: border-box; } } diff --git a/common/static/sass/neat/grid/_omega.scss b/common/static/sass/neat/grid/_omega.scss index 0c6296419057c8bbd3518c04b5b5ae6e41fd51e0..f8d990ada028128b4cb69f0dc450ce52632c1598 100644 --- a/common/static/sass/neat/grid/_omega.scss +++ b/common/static/sass/neat/grid/_omega.scss @@ -4,7 +4,7 @@ $auto: if(belongs-to(auto, $query), true, false); @if $direction != default { - @warn "The omega mixin will no longer take a $direction argument. To change the layout direction, use row($direction) or set $default-layout-direction instead." + @warn "The omega mixin will no longer take a $direction argument. To change the layout direction, use row($direction) or set $default-layout-direction instead."; } @else { @@ -12,7 +12,7 @@ } @if $table { - @warn "The omega mixin no longer removes padding in table layouts." + @warn "The omega mixin no longer removes padding in table layouts."; } @if length($query) == 1 { @@ -44,7 +44,7 @@ } @else { - @warn "Too many arguments passed to the omega() mixin." + @warn "Too many arguments passed to the omega() mixin."; } } diff --git a/common/static/sass/neat/grid/_span-columns.scss b/common/static/sass/neat/grid/_span-columns.scss index 625294d863c989970c41c8dd4f9929df9a294f44..2345c5a9558bb2900340fd55918194339978ad02 100644 --- a/common/static/sass/neat/grid/_span-columns.scss +++ b/common/static/sass/neat/grid/_span-columns.scss @@ -10,7 +10,7 @@ $display-table: is-display-table($container-display-table, $display); - @if $display-table { + @if $display-table { display: table-cell; width: percentage($columns / $container-columns); } @@ -23,7 +23,7 @@ } @if $display == collapse { - @warn "The 'collapse' argument will be deprecated. Use 'block-collapse' instead." + @warn "The 'collapse' argument will be deprecated. Use 'block-collapse' instead."; } @if $display == collapse or $display == block-collapse { @@ -32,7 +32,6 @@ &:last-child { width: flex-grid($columns, $container-columns); } - } @else { diff --git a/common/static/sass/neat/grid/_visual-grid.scss b/common/static/sass/neat/grid/_visual-grid.scss index 340439c37fecc3887154164073521c5b15893d39..167bef9ecaec52b73b623abdeb008d3c0b920963 100644 --- a/common/static/sass/neat/grid/_visual-grid.scss +++ b/common/static/sass/neat/grid/_visual-grid.scss @@ -1,14 +1,14 @@ @mixin grid-column-gradient($values...) { background-image: deprecated-webkit-gradient(linear, left top, left bottom, $values); - background-image: -webkit-linear-gradient(left, $values); - background-image: -moz-linear-gradient(left, $values); - background-image: -ms-linear-gradient(left, $values); - background-image: -o-linear-gradient(left, $values); + background-image: -webkit-linear-gradient(left, $values); + background-image: -moz-linear-gradient(left, $values); + background-image: -ms-linear-gradient(left, $values); + background-image: -o-linear-gradient(left, $values); background-image: unquote("linear-gradient(left, #{$values})"); } @if $visual-grid == true or $visual-grid == yes { - body:before { + body:before { /* stylelint-disable-line */ content: ''; display: inline-block; @@ -29,7 +29,7 @@ } @else if $visual-grid-index == front { - z-index: 9999; + z-index: 9999; } @each $breakpoint in $visual-grid-breakpoints { diff --git a/common/templates/student/edx_ace/accountactivation/email/body.html b/common/templates/student/edx_ace/accountactivation/email/body.html index d6970cbba9a46e13927338b8c5c6f0c6a3d61e5d..6a217b7b77a8b27b8c965195da88f851e5392981 100644 --- a/common/templates/student/edx_ace/accountactivation/email/body.html +++ b/common/templates/student/edx_ace/accountactivation/email/body.html @@ -29,7 +29,9 @@ <br /> </p> - {% trans "Activate Your Account" as course_cta_text %}{{ course_cta_text | force_escape }} + {% filter force_escape %} + {% blocktrans asvar course_cta_text %}Activate Your Account{% endblocktrans %} + {% endfilter %} {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text course_cta_url=confirm_activation_link %} </td> </tr> diff --git a/common/templates/student/edx_ace/accountrecovery/email/body.html b/common/templates/student/edx_ace/accountrecovery/email/body.html index 5896ed446d6934b2a3db34ee291792b0106f581e..448d84a4383ee22a87335b086afab258196a97d6 100644 --- a/common/templates/student/edx_ace/accountrecovery/email/body.html +++ b/common/templates/student/edx_ace/accountrecovery/email/body.html @@ -34,9 +34,10 @@ {% trans "If you didn't request this change, you can disregard this email - we have not yet reset your password." as tmsg %}{{ tmsg | force_escape }} <br /> </p> - {# xss-lint: disable=django-trans-missing-escape #} - {% trans "Create Password" as course_cta_text %} + {% filter force_escape %} + {% blocktrans asvar course_cta_text %}Create Password{% endblocktrans %} + {% endfilter %} {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text course_cta_url=reset_link %} </td> </tr> diff --git a/common/templates/student/edx_ace/calendarsync/email/body.html b/common/templates/student/edx_ace/calendarsync/email/body.html deleted file mode 100644 index 9ee009defc107185895375c54516da8276f7d3c8..0000000000000000000000000000000000000000 --- a/common/templates/student/edx_ace/calendarsync/email/body.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends 'ace_common/edx_ace/common/base_body.html' %} - -{% load django_markup %} -{% load i18n %} -{% load static %} -{% block content %} -<table width="100%" align="left" border="0" cellpadding="0" cellspacing="0" role="presentation"> - <tr> - <td> - <h1> - {% filter force_escape %}{{ calendar_sync_headline }}{% endfilter %} - </h1> - <p style="color: rgba(0,0,0,.75);"> - {% filter force_escape %} - {{ calendar_sync_body }} - {% endfilter %} - <br /> - </p> - </td> - </tr> -</table> -{% endblock %} diff --git a/common/templates/student/edx_ace/calendarsync/email/body.txt b/common/templates/student/edx_ace/calendarsync/email/body.txt deleted file mode 100644 index d2e6f46bb1006c684b6c473f67e36ee1aa820888..0000000000000000000000000000000000000000 --- a/common/templates/student/edx_ace/calendarsync/email/body.txt +++ /dev/null @@ -1,2 +0,0 @@ -{% load i18n %}{% autoescape off %} -{{ calendar_sync_body }} diff --git a/common/templates/student/edx_ace/calendarsync/email/from_name.txt b/common/templates/student/edx_ace/calendarsync/email/from_name.txt deleted file mode 100644 index dcbc23c00480bfe0b4ae3fa9439d49f885130ae1..0000000000000000000000000000000000000000 --- a/common/templates/student/edx_ace/calendarsync/email/from_name.txt +++ /dev/null @@ -1 +0,0 @@ -{{ platform_name }} diff --git a/common/templates/student/edx_ace/calendarsync/email/head.html b/common/templates/student/edx_ace/calendarsync/email/head.html deleted file mode 100644 index 366ada7ad92e41ef3842688d49b34f2b2525a7a7..0000000000000000000000000000000000000000 --- a/common/templates/student/edx_ace/calendarsync/email/head.html +++ /dev/null @@ -1 +0,0 @@ -{% extends 'ace_common/edx_ace/common/base_head.html' %} diff --git a/common/templates/student/edx_ace/calendarsync/email/subject.txt b/common/templates/student/edx_ace/calendarsync/email/subject.txt deleted file mode 100644 index 7ef3d19b84483ecce246d878294953add489d2ef..0000000000000000000000000000000000000000 --- a/common/templates/student/edx_ace/calendarsync/email/subject.txt +++ /dev/null @@ -1,4 +0,0 @@ -{% load i18n %} -{% autoescape off %} -{{ calendar_sync_subject }} -{% endautoescape %} diff --git a/common/templates/student/edx_ace/emailchange/email/body.html b/common/templates/student/edx_ace/emailchange/email/body.html index 68ac4237b953a2ce726a60a7d2a7f218ce0329c1..b5c2c5edf21ea5b2d6b5621c207f6f4306598302 100644 --- a/common/templates/student/edx_ace/emailchange/email/body.html +++ b/common/templates/student/edx_ace/emailchange/email/body.html @@ -15,8 +15,10 @@ {% endfilter %} <br /> </p> - {# xss-lint: disable=django-trans-missing-escape #} - {% trans "Confirm Email Change" as course_cta_text %} + + {% filter force_escape %} + {% blocktrans asvar course_cta_text %}Confirm Email Change{% endblocktrans %} + {% endfilter %} {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text course_cta_url=confirm_link %} <p style="color: rgba(0,0,0,.75);"> diff --git a/common/templates/student/edx_ace/recoveryemailcreate/email/body.html b/common/templates/student/edx_ace/recoveryemailcreate/email/body.html index 4f4d06b3835fcff6373cfe3134b5840dc5078625..dff24fc4f43fd8a50fac0469a8c406a292d4aaea 100644 --- a/common/templates/student/edx_ace/recoveryemailcreate/email/body.html +++ b/common/templates/student/edx_ace/recoveryemailcreate/email/body.html @@ -7,16 +7,22 @@ <tr> <td> <h1> - {% trans "Create Recovery Email" %} + {% trans "Create Recovery Email" as create_recovery_text %}{{ create_recovery_text | force_escape }} </h1> <p style="color: rgba(0,0,0,.75);"> + {% filter force_escape %} {% blocktrans %}You've registered this recovery email address for {{ platform_name }}.{% endblocktrans %} + {% endfilter %} <br/> + {% filter force_escape %} {% blocktrans %}If you set this email address, click "confirm email." If you didn't request this change, you can disregard this email.{% endblocktrans %} + {% endfilter %} <br /> </p> - {% trans "Confirm Email" as course_cta_text %} + {% filter force_escape %} + {% blocktrans asvar course_cta_text %}Confirm Email{% endblocktrans %} + {% endfilter %} {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text course_cta_url=confirm_link %} </td> diff --git a/common/test/acceptance/fixtures/config.py b/common/test/acceptance/fixtures/config.py index 0e359bdbc15581d09283d30d3ee3935833610d08..ad6152be12c4a1e74b3811d2e82b1f3746027e84 100644 --- a/common/test/acceptance/fixtures/config.py +++ b/common/test/acceptance/fixtures/config.py @@ -90,7 +90,7 @@ class ConfigModelFixture(object): # auto_auth returns information about the newly created user # capture this so it can be used by by the testcases. user_pattern = re.compile( - six.text_type(r'Logged in user {0} \({1}\) with password {2} and user_id {3}').format( # pylint: disable=unicode-format-string + six.text_type(r'Logged in user {0} \({1}\) with password {2} and user_id {3}').format( r'(?P<username>\S+)', r'(?P<email>[^\)]+)', r'(?P<password>\S+)', r'(?P<user_id>\d+)')) user_matches = re.match(user_pattern, response.text) if user_matches: diff --git a/common/test/acceptance/pages/common/utils.py b/common/test/acceptance/pages/common/utils.py index aa93e751103a26ab79e76af7d9564f39ff4ccb30..6fcd0a6b297774f99a8a92dd148bec3de21e7432 100644 --- a/common/test/acceptance/pages/common/utils.py +++ b/common/test/acceptance/pages/common/utils.py @@ -8,7 +8,6 @@ from bok_choy.promise import BrokenPromise from selenium.webdriver.common.action_chains import ActionChains from common.test.acceptance.pages.lms.create_mode import ModeCreationPage -from common.test.acceptance.pages.lms.pay_and_verify import FakePaymentPage, PaymentAndVerificationFlow from common.test.acceptance.pages.lms.track_selection import TrackSelectionPage from common.test.acceptance.tests.helpers import disable_animations @@ -115,16 +114,11 @@ def enroll_user_track(browser, course_id, track): necessary pages. Selects the track and handles payment for verified. Supported tracks are 'verified' or 'audit'. """ - payment_and_verification_flow = PaymentAndVerificationFlow(browser, course_id) - fake_payment_page = FakePaymentPage(browser, course_id) track_selection = TrackSelectionPage(browser, course_id) - # Select track and process payment + # Select track track_selection.visit() track_selection.enroll(track) - if track == 'verified': - payment_and_verification_flow.proceed_to_payment() - fake_payment_page.submit_payment() def add_enrollment_course_modes(browser, course_id, tracks): diff --git a/common/test/acceptance/pages/lms/create_mode.py b/common/test/acceptance/pages/lms/create_mode.py index c2f3f5807fdb1a2ce976988b061b7efb447d367b..8c4f2cfe2970b38f19b8d9a5abb0c3ee6d8bd555 100644 --- a/common/test/acceptance/pages/lms/create_mode.py +++ b/common/test/acceptance/pages/lms/create_mode.py @@ -3,7 +3,7 @@ import re -import six.moves.urllib.parse # pylint: disable=import-error +import six.moves.urllib.parse from bok_choy.page_object import PageObject from common.test.acceptance.pages.lms import BASE_URL diff --git a/common/test/acceptance/pages/lms/dashboard.py b/common/test/acceptance/pages/lms/dashboard.py index ecb3c1e733c05fe0add291a276ce0006e1dffaef..7384234395b54979f9ea1c55e589447f487ee62b 100644 --- a/common/test/acceptance/pages/lms/dashboard.py +++ b/common/test/acceptance/pages/lms/dashboard.py @@ -82,32 +82,6 @@ class DashboardPage(PageObject): return enrollment_mode - def upgrade_enrollment(self, course_name, upgrade_page): - """Interact with the upgrade button for the course with the provided name. - - Arguments: - course_name (str): The name of the course whose mode should be checked. - upgrade_page (PageObject): The page to wait on after clicking the upgrade button. Importing - the definition of PaymentAndVerificationFlow results in a circular dependency. - - Raises: - Exception, if no enrollment corresponding to the provided course name appears - on the dashboard. - """ - # Filter elements by course name, only returning the relevant course item - course_listing = self.q(css=".course").filter(lambda el: course_name in el.text).results - - if course_listing: - # There should only be one course listing corresponding to the provided course name. - el = course_listing[0] - - # Click the upgrade button - el.find_element_by_css_selector('#upgrade-to-verified').click() - - upgrade_page.wait_for_page() - else: - raise Exception(u"No enrollment for {} is visible on the dashboard.".format(course_name)) - def view_course(self, course_id): """ Go to the course with `course_id` (e.g. edx/Open_DemoX/edx_demo_course) diff --git a/common/test/acceptance/pages/lms/fields.py b/common/test/acceptance/pages/lms/fields.py index 1237251d6dc1a26f24b7d60838407d33d7c8f867..28dc5414675587054554bf88fe179523cbdf106e 100644 --- a/common/test/acceptance/pages/lms/fields.py +++ b/common/test/acceptance/pages/lms/fields.py @@ -70,7 +70,6 @@ class FieldsMixin(object): Return the title of a field. """ self.wait_for_field(field_id) - # pylint: disable=unicode-format-string query = self.q(css=six.u('.u-field-{} .u-field-title').format(field_id)) return query.text[0] if query.present else None @@ -79,7 +78,6 @@ class FieldsMixin(object): Return the current message in a field. """ self.wait_for_field(field_id) - # pylint: disable=unicode-format-string query = self.q(css=six.u('.u-field-{} .u-field-message'.format(field_id))) return query.text[0] if query.present else None @@ -159,7 +157,6 @@ class FieldsMixin(object): Get or set the value of a text field. """ self.wait_for_field(field_id) - # pylint: disable=unicode-format-string query = self.q(css=six.u('.u-field-{} input'.format(field_id))) if not query.present: return None diff --git a/common/test/acceptance/pages/lms/login_and_register.py b/common/test/acceptance/pages/lms/login_and_register.py index d4298507a24528d135b0571c297d138c061e11d6..de97aefd1f7baf2098c4b87ada3c9f4d6486df20 100644 --- a/common/test/acceptance/pages/lms/login_and_register.py +++ b/common/test/acceptance/pages/lms/login_and_register.py @@ -3,7 +3,7 @@ from bok_choy.page_object import PageObject, unguarded from bok_choy.promise import EmptyPromise, Promise -from six.moves.urllib.parse import urlencode # pylint: disable=import-error +from six.moves.urllib.parse import urlencode from common.test.acceptance.pages.lms import BASE_URL from common.test.acceptance.pages.lms.dashboard import DashboardPage diff --git a/common/test/acceptance/pages/lms/pay_and_verify.py b/common/test/acceptance/pages/lms/pay_and_verify.py index 3bb15138df5e9ea7c9fbb61d6c43bee874d67f02..4e5109c3be73eafe8ab78ec2d005c7d8e222850a 100644 --- a/common/test/acceptance/pages/lms/pay_and_verify.py +++ b/common/test/acceptance/pages/lms/pay_and_verify.py @@ -1,8 +1,6 @@ """Payment and verification pages""" -import re - from bok_choy.page_object import PageObject from bok_choy.promise import Promise @@ -75,12 +73,6 @@ class PaymentAndVerificationFlow(PageObject): """Interact with the radio buttons appearing on the first page of the upgrade flow.""" self.q(css=".contribution-option > input").first.click() - def proceed_to_payment(self): - """Interact with the payment button.""" - self.q(css=".payment-button").click() - - FakePaymentPage(self.browser, self._course_id).wait_for_page() - def immediate_verification(self): """Interact with the immediate verification button.""" self.q(css="#verify_now_button").click() @@ -119,50 +111,3 @@ class PaymentAndVerificationFlow(PageObject): raise Exception("The dashboard can only be accessed from the enrollment confirmation.") DashboardPage(self.browser).wait_for_page() - - -class FakePaymentPage(PageObject): - """Interact with the fake payment endpoint. - - This page is hidden behind the feature flag `ENABLE_PAYMENT_FAKE`, - which is enabled in the Bok Choy env settings. - - Configuring this payment endpoint also requires configuring the Bok Choy - auth settings with the following: - - "CC_PROCESSOR_NAME": "CyberSource2", - "CC_PROCESSOR": { - "CyberSource2": { - "SECRET_KEY": <string>, - "ACCESS_KEY": <string>, - "PROFILE_ID": "edx", - "PURCHASE_ENDPOINT": "/shoppingcart/payment_fake" - } - } - """ - def __init__(self, browser, course_id): - """Initialize the page. - - Arguments: - browser (Browser): The browser instance. - course_id (unicode): The course in which the user is enrolling. - """ - super(FakePaymentPage, self).__init__(browser) - self._course_id = course_id - - url = BASE_URL + "/shoppingcart/payment_fake/" - - def is_browser_on_page(self): - """Check if a step in the payment and verification flow has loaded.""" - message = self.q(css='BODY').text - if not message: - return False - - match = re.search('Payment page', message[0]) - return True if match else False - - def submit_payment(self): - """Interact with the payment submission button.""" - self.q(css="input[value='Submit']").click() - - return PaymentAndVerificationFlow(self.browser, self._course_id, entry_point='payment-confirmation').wait_for_page() diff --git a/common/test/acceptance/pages/studio/asset_index.py b/common/test/acceptance/pages/studio/asset_index.py index a757ca4b9601fc5aa7773caff4a57b65fdae896d..d8f465aaa0e6ad746a768179c865e0ecbbbc2c9a 100644 --- a/common/test/acceptance/pages/studio/asset_index.py +++ b/common/test/acceptance/pages/studio/asset_index.py @@ -18,7 +18,6 @@ from common.test.acceptance.pages.studio.course_page import CoursePage # file path found from CourseFixture logic UPLOAD_SUFFIX = '/data/uploads/studio-uploads/' -# pylint: disable=no-value-for-parameter UPLOAD_FILE_DIR = Path(__file__).abspath().dirname().dirname().dirname().dirname() + UPLOAD_SUFFIX diff --git a/common/test/acceptance/pages/studio/import_export.py b/common/test/acceptance/pages/studio/import_export.py index a152b331612e88ab88b541b51c8abc554482d0a0..6b2f5f005972a24e9463580609ac28d096768523 100644 --- a/common/test/acceptance/pages/studio/import_export.py +++ b/common/test/acceptance/pages/studio/import_export.py @@ -68,7 +68,7 @@ class ImportExportMixin(object): """ string = self.q(css='.item-progresspoint-success-date').text[0] - return re.match(six.text_type(r'\(([^ ]+).+?(\d{2}:\d{2})'), string).groups() # pylint: disable=unicode-format-string + return re.match(six.text_type(r'\(([^ ]+).+?(\d{2}:\d{2})'), string).groups() def wait_for_tasks(self, completed=False, fail_on=None): """ diff --git a/common/test/acceptance/pages/studio/textbook_upload.py b/common/test/acceptance/pages/studio/textbook_upload.py index 56c29464d10ddab18ce8f7abe4ff832291108b13..c730e8b3b8d9737abd4056e758232509e37a4a1b 100644 --- a/common/test/acceptance/pages/studio/textbook_upload.py +++ b/common/test/acceptance/pages/studio/textbook_upload.py @@ -43,7 +43,7 @@ class TextbookUploadPage(CoursePage): Uploads a pdf textbook. """ # If the pdf upload section has not yet been toggled on, click on the upload pdf button - test_dir = path(__file__).abspath().dirname().dirname().dirname().dirname() # pylint:disable=no-value-for-parameter + test_dir = path(__file__).abspath().dirname().dirname().dirname().dirname() file_path = test_dir + '/data/uploads/' + file_name click_css(self, ".edit-textbook .action-upload", require_notification=False) diff --git a/common/test/acceptance/tests/discussion/test_discussion.py b/common/test/acceptance/tests/discussion/test_discussion.py index 0be1f78ff40cdcb58f2c8fd41f944223d829f919..d3923fa980578e4c581a258d6604f7f2c3e97b82 100644 --- a/common/test/acceptance/tests/discussion/test_discussion.py +++ b/common/test/acceptance/tests/discussion/test_discussion.py @@ -1032,7 +1032,7 @@ class DiscussionEditorPreviewTest(UniqueCourseTest): self.page.set_new_post_editor_value( six.text_type( r'\begin{equation}' - r'\tau_g(\omega) = - \frac{d}{d\omega}\phi(\omega) \hspace{2em} (1) ' # pylint: disable=unicode-format-string + r'\tau_g(\omega) = - \frac{d}{d\omega}\phi(\omega) \hspace{2em} (1) ' r'\end{equation}' ) ) diff --git a/common/test/acceptance/tests/helpers.py b/common/test/acceptance/tests/helpers.py index 9323b9b3d0a0ccc1eceb85ea81e93152cb6673f8..6ccb438a3634a30548616236b825a23b9e762925 100644 --- a/common/test/acceptance/tests/helpers.py +++ b/common/test/acceptance/tests/helpers.py @@ -112,7 +112,7 @@ def load_data_str(rel_path): Load a file from the "data" directory as a string. `rel_path` is the path relative to the data directory. """ - full_path = path(__file__).abspath().dirname() / "data" / rel_path # pylint: disable=no-value-for-parameter + full_path = path(__file__).abspath().dirname() / "data" / rel_path with open(full_path) as data_file: return data_file.read() diff --git a/common/test/acceptance/tests/lms/test_lms.py b/common/test/acceptance/tests/lms/test_lms.py index e4a8f2cbd7a3b8c1061a972728fe3a7d17196a2e..8c258be4856e47d972e8689116bf1a19cb951adb 100644 --- a/common/test/acceptance/tests/lms/test_lms.py +++ b/common/test/acceptance/tests/lms/test_lms.py @@ -13,7 +13,6 @@ import pytz from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.pages.common.auto_auth import AutoAuthPage from common.test.acceptance.pages.common.logout import LogoutPage -from common.test.acceptance.pages.common.utils import enroll_user_track from common.test.acceptance.pages.lms import BASE_URL from common.test.acceptance.pages.lms.account_settings import AccountSettingsPage from common.test.acceptance.pages.lms.course_about import CourseAboutPage @@ -29,15 +28,12 @@ from common.test.acceptance.pages.lms.create_mode import ModeCreationPage from common.test.acceptance.pages.lms.dashboard import DashboardPage from common.test.acceptance.pages.lms.discovery import CourseDiscoveryPage from common.test.acceptance.pages.lms.login_and_register import CombinedLoginAndRegisterPage, ResetPasswordPage -from common.test.acceptance.pages.lms.pay_and_verify import FakePaymentPage, PaymentAndVerificationFlow from common.test.acceptance.pages.lms.problem import ProblemPage from common.test.acceptance.pages.lms.tab_nav import TabNavPage from common.test.acceptance.tests.helpers import ( EventsTestMixin, UniqueCourseTest, - get_selected_option_text, remove_file, - select_option_by_text ) from openedx.core.lib.tests import attr @@ -396,96 +392,6 @@ class RegisterFromCombinedPageTest(UniqueCourseTest): account_settings.wait_for_message(field_id, "Successfully unlinked") -@attr(shard=19) -class PayAndVerifyTest(EventsTestMixin, UniqueCourseTest): - """Test that we can proceed through the payment and verification flow.""" - def setUp(self): - """Initialize the test. - - Create the necessary page objects, create a test course and configure its modes, - create a user and log them in. - """ - super(PayAndVerifyTest, self).setUp() - - self.payment_and_verification_flow = PaymentAndVerificationFlow(self.browser, self.course_id) - self.immediate_verification_page = PaymentAndVerificationFlow(self.browser, self.course_id, entry_point='verify-now') - self.upgrade_page = PaymentAndVerificationFlow(self.browser, self.course_id, entry_point='upgrade') - self.fake_payment_page = FakePaymentPage(self.browser, self.course_id) - self.dashboard_page = DashboardPage(self.browser) - - # Create a course - CourseFixture( - self.course_info['org'], - self.course_info['number'], - self.course_info['run'], - self.course_info['display_name'] - ).install() - - # Add an honor mode to the course - ModeCreationPage(self.browser, self.course_id).visit() - - # Add a verified mode to the course - ModeCreationPage(self.browser, self.course_id, mode_slug=u'verified', mode_display_name=u'Verified Certificate', min_price=10, suggested_prices='10,20').visit() - - def test_deferred_verification_enrollment(self): - # Create a user and log them in - student_id = AutoAuthPage(self.browser).visit().get_user_id() - - enroll_user_track(self.browser, self.course_id, 'verified') - - # Navigate to the dashboard - self.dashboard_page.visit() - - # Expect that we're enrolled as verified in the course - enrollment_mode = self.dashboard_page.get_enrollment_mode(self.course_info["display_name"]) - self.assertEqual(enrollment_mode, 'verified') - - def test_enrollment_upgrade(self): - # Create a user, log them in, and enroll them in the honor mode - student_id = AutoAuthPage(self.browser, course_id=self.course_id).visit().get_user_id() - - # Navigate to the dashboard - self.dashboard_page.visit() - - # Expect that we're enrolled as honor in the course - enrollment_mode = self.dashboard_page.get_enrollment_mode(self.course_info["display_name"]) - self.assertEqual(enrollment_mode, 'honor') - - # Click the upsell button on the dashboard - self.dashboard_page.upgrade_enrollment(self.course_info["display_name"], self.upgrade_page) - - # Select the first contribution option appearing on the page - self.upgrade_page.indicate_contribution() - - # Proceed to the fake payment page - self.upgrade_page.proceed_to_payment() - - def only_enrollment_events(event): - """Filter out all non-enrollment events.""" - return event['event_type'].startswith('edx.course.enrollment.') - - expected_events = [ - { - 'event_type': 'edx.course.enrollment.mode_changed', - 'event': { - 'user_id': int(student_id), - 'mode': 'verified', - } - } - ] - - with self.assert_events_match_during(event_filter=only_enrollment_events, expected_events=expected_events): - # Submit payment - self.fake_payment_page.submit_payment() - - # Navigate to the dashboard - self.dashboard_page.visit() - - # Expect that we're enrolled as verified in the course - enrollment_mode = self.dashboard_page.get_enrollment_mode(self.course_info["display_name"]) - self.assertEqual(enrollment_mode, 'verified') - - @attr('a11y') class CourseWikiA11yTest(UniqueCourseTest): """ diff --git a/common/test/acceptance/tests/lms/test_lms_courseware.py b/common/test/acceptance/tests/lms/test_lms_courseware.py index 54781b15128ca7051d4d4fdead5896ec9ade09a4..7afb955c412290ab5dbe65ad1b759cddbb157608 100644 --- a/common/test/acceptance/tests/lms/test_lms_courseware.py +++ b/common/test/acceptance/tests/lms/test_lms_courseware.py @@ -7,7 +7,6 @@ End-to-end tests for the LMS. import json from datetime import datetime, timedelta -import ddt from six.moves import range from openedx.core.lib.tests import attr @@ -17,12 +16,8 @@ from ...pages.common.auto_auth import AutoAuthPage from ...pages.common.logout import LogoutPage from ...pages.lms.course_home import CourseHomePage from ...pages.lms.courseware import CoursewarePage, CoursewareSequentialTabPage -from ...pages.lms.create_mode import ModeCreationPage -from ...pages.lms.dashboard import DashboardPage -from ...pages.lms.pay_and_verify import FakePaymentPage, PaymentAndVerificationFlow from ...pages.lms.problem import ProblemPage from ...pages.lms.progress import ProgressPage -from ...pages.lms.track_selection import TrackSelectionPage from ...pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage from ..helpers import EventsTestMixin, UniqueCourseTest, auto_auth, create_multiple_choice_problem @@ -126,223 +121,6 @@ class CoursewareTest(UniqueCourseTest): self.assertEqual(course_nav.breadcrumb_unit_title, test_unit_title) -@attr(shard=9) -@ddt.ddt -class ProctoredExamTest(UniqueCourseTest): - """ - Tests for proctored exams. - """ - USERNAME = "STUDENT_TESTER" - EMAIL = "student101@example.com" - - def setUp(self): - super(ProctoredExamTest, self).setUp() - - self.courseware_page = CoursewarePage(self.browser, self.course_id) - - self.studio_course_outline = StudioCourseOutlinePage( - self.browser, - self.course_info['org'], - self.course_info['number'], - self.course_info['run'] - ) - - # Install a course with sections/problems, tabs, updates, and handouts - course_fix = CourseFixture( - self.course_info['org'], self.course_info['number'], - self.course_info['run'], self.course_info['display_name'] - ) - course_fix.add_advanced_settings({ - "enable_proctored_exams": {"value": "true"} - }) - course_fix.add_advanced_settings({ - "show_review_rules": {"value": "true"} - }) - - course_fix.add_children( - XBlockFixtureDesc('chapter', 'Test Section 1').add_children( - XBlockFixtureDesc('sequential', 'Test Subsection 1').add_children( - XBlockFixtureDesc('problem', 'Test Problem 1') - ) - ) - ).install() - - self.track_selection_page = TrackSelectionPage(self.browser, self.course_id) - self.payment_and_verification_flow = PaymentAndVerificationFlow(self.browser, self.course_id) - self.immediate_verification_page = PaymentAndVerificationFlow( - self.browser, self.course_id, entry_point='verify-now' - ) - self.upgrade_page = PaymentAndVerificationFlow(self.browser, self.course_id, entry_point='upgrade') - self.fake_payment_page = FakePaymentPage(self.browser, self.course_id) - self.dashboard_page = DashboardPage(self.browser) - self.problem_page = ProblemPage(self.browser) - - # Add a verified mode to the course - ModeCreationPage( - self.browser, self.course_id, mode_slug=u'verified', mode_display_name=u'Verified Certificate', - min_price=10, suggested_prices='10,20' - ).visit() - - # Auto-auth register for the course. - auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id) - - def _login_as_a_verified_user(self): - """ - login as a verififed user - """ - - auto_auth( - self.browser, - self.USERNAME, - self.EMAIL, - False, - self.course_id, - should_manually_verify=True - ) - - # the track selection page cannot be visited. see the other tests to see if any prereq is there. - # Navigate to the track selection page - self.track_selection_page.visit() - - # Enter the payment and verification flow by choosing to enroll as verified - self.track_selection_page.enroll('verified') - - # Proceed to the fake payment page - self.payment_and_verification_flow.proceed_to_payment() - - # Submit payment - self.fake_payment_page.submit_payment() - - def test_can_create_proctored_exam_in_studio(self): - """ - Given that I am a staff member - When I visit the course outline page in studio. - And open the subsection edit dialog - Then I can view all settings related to Proctored and timed exams - """ - LogoutPage(self.browser).visit() - auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id) - self.studio_course_outline.visit() - - self.studio_course_outline.open_subsection_settings_dialog() - self.assertTrue(self.studio_course_outline.proctoring_items_are_displayed()) - - def test_proctored_exam_flow(self): - """ - Given that I am a staff member on the exam settings section - select advanced settings tab - When I Make the exam proctored. - And I login as a verified student. - And I verify the user's ID. - And visit the courseware as a verified student. - Then I can see an option to take the exam as a proctored exam. - """ - LogoutPage(self.browser).visit() - auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id) - self.studio_course_outline.visit() - self.studio_course_outline.open_subsection_settings_dialog() - - self.studio_course_outline.select_advanced_tab() - self.studio_course_outline.make_exam_proctored() - - LogoutPage(self.browser).visit() - self._login_as_a_verified_user() - - self.courseware_page.visit() - self.assertTrue(self.courseware_page.can_start_proctored_exam) - - def _setup_and_take_timed_exam(self, hide_after_due=False): - """ - Helper to perform the common action "set up a timed exam as staff, - then take it as student" - """ - LogoutPage(self.browser).visit() - auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id) - self.studio_course_outline.visit() - self.studio_course_outline.open_subsection_settings_dialog() - - self.studio_course_outline.select_advanced_tab() - self.studio_course_outline.make_exam_timed(hide_after_due=hide_after_due) - - LogoutPage(self.browser).visit() - self._login_as_a_verified_user() - self.courseware_page.visit() - - self.courseware_page.start_timed_exam() - self.assertTrue(self.courseware_page.is_timer_bar_present) - - self.courseware_page.stop_timed_exam() - self.courseware_page.wait_for_page() - self.assertTrue(self.courseware_page.has_submitted_exam_message()) - - LogoutPage(self.browser).visit() - - @ddt.data(True, False) - def test_timed_exam_flow(self, hide_after_due): - """ - Given that I am a staff member on the exam settings section - select advanced settings tab - When I Make the exam timed. - And I login as a verified student. - And visit the courseware as a verified student. - And I start the timed exam - Then I am taken to the exam with a timer bar showing - When I finish the exam - Then I see the exam submitted dialog in place of the exam - When I log back into studio as a staff member - And change the problem's due date to be in the past - And log back in as the original verified student - Then I see the exam or message in accordance with the hide_after_due setting - """ - self._setup_and_take_timed_exam(hide_after_due) - - LogoutPage(self.browser).visit() - auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id) - self.studio_course_outline.visit() - last_week = (datetime.today() - timedelta(days=7)).strftime("%m/%d/%Y") - self.studio_course_outline.change_problem_due_date(last_week) - - LogoutPage(self.browser).visit() - auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id) - self.courseware_page.visit() - self.assertEqual(self.courseware_page.has_submitted_exam_message(), hide_after_due) - - def test_field_visiblity_with_all_exam_types(self): - """ - Given that I am a staff member - And I have visited the course outline page in studio. - And the subsection edit dialog is open - select advanced settings tab - For each of None, Timed, Proctored, and Practice exam types - The time allotted and review rules fields have proper visibility - None: False, False - Timed: True, False - Proctored: True, True - Practice: True, False - """ - LogoutPage(self.browser).visit() - auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id) - self.studio_course_outline.visit() - - self.studio_course_outline.open_subsection_settings_dialog() - self.studio_course_outline.select_advanced_tab() - - self.studio_course_outline.select_none_exam() - self.assertFalse(self.studio_course_outline.time_allotted_field_visible()) - self.assertFalse(self.studio_course_outline.exam_review_rules_field_visible()) - - self.studio_course_outline.select_timed_exam() - self.assertTrue(self.studio_course_outline.time_allotted_field_visible()) - self.assertFalse(self.studio_course_outline.exam_review_rules_field_visible()) - - self.studio_course_outline.select_proctored_exam() - self.assertTrue(self.studio_course_outline.time_allotted_field_visible()) - - self.studio_course_outline.select_practice_exam() - self.assertTrue(self.studio_course_outline.time_allotted_field_visible()) - self.assertFalse(self.studio_course_outline.exam_review_rules_field_visible()) - - class CoursewareMultipleVerticalsTestBase(UniqueCourseTest, EventsTestMixin): """ Base class with setup for testing courseware with multiple verticals diff --git a/common/test/acceptance/tests/lms/test_lms_dashboard.py b/common/test/acceptance/tests/lms/test_lms_dashboard.py index 8b0790dc4ea464bd6aebe1370517ca533c961f69..5982148a65973d0447713d4a6260dc87eed0be95 100644 --- a/common/test/acceptance/tests/lms/test_lms_dashboard.py +++ b/common/test/acceptance/tests/lms/test_lms_dashboard.py @@ -7,7 +7,7 @@ End-to-end tests for the main LMS Dashboard (aka, Student Dashboard). import datetime import re import six -from six.moves.urllib.parse import unquote # pylint: disable=import-error +from six.moves.urllib.parse import unquote from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.pages.common.auto_auth import AutoAuthPage from common.test.acceptance.pages.lms.course_home import CourseHomePage diff --git a/common/test/acceptance/tests/lms/test_progress_page.py b/common/test/acceptance/tests/lms/test_progress_page.py index eef12c4fd83223eb2f7806a2e640351e24f67e09..5744800cfffaed923c653dbfdda6b3cd6aeac612 100644 --- a/common/test/acceptance/tests/lms/test_progress_page.py +++ b/common/test/acceptance/tests/lms/test_progress_page.py @@ -346,7 +346,7 @@ class SubsectionGradingPolicyA11yTest(SubsectionGradingPolicyBase): # Verify that y-Axis labels are aria-hidden self.assertEqual(['100%', 'true'], self.progress_page.y_tick_label(0)) self.assertEqual(['0%', 'true'], self.progress_page.y_tick_label(1)) - self.assertEqual(['Pass 50%', 'true'], self.progress_page.y_tick_label(2)) # pylint: disable=unicode-format-string + self.assertEqual(['Pass 50%', 'true'], self.progress_page.y_tick_label(2)) # Verify x-Axis labels and sr-text self._check_tick_text(0, [u'Homework 1 - Test Subsection 1 - 50% (1/2)'], u'HW 01') @@ -407,7 +407,7 @@ class SubsectionGradingPolicyA11yTest(SubsectionGradingPolicyBase): # Verify the overall score. The first element in the array is the sr-only text, and the # second is the total text (including the sr-only text). - self.assertEqual(['Overall Score', 'Overall Score\n2%'], self.progress_page.graph_overall_score()) # pylint: disable=unicode-format-string + self.assertEqual(['Overall Score', 'Overall Score\n2%'], self.progress_page.graph_overall_score()) class ProgressPageA11yTest(ProgressPageBaseTest): diff --git a/common/test/db_cache/bok_choy_data_default.json b/common/test/db_cache/bok_choy_data_default.json index 169f9624a3b2806aa702d9c778fca8afce062120..b5cb52b5a4a6682e4475d4bd429fba842837a5f1 100644 --- a/common/test/db_cache/bok_choy_data_default.json +++ b/common/test/db_cache/bok_choy_data_default.json @@ -1 +1 @@ -[{"model": "contenttypes.contenttype", "pk": 1, "fields": {"app_label": "api_admin", "model": "apiaccessrequest"}}, {"model": "contenttypes.contenttype", "pk": 2, "fields": {"app_label": "auth", "model": "permission"}}, {"model": "contenttypes.contenttype", "pk": 3, "fields": {"app_label": "auth", "model": "group"}}, {"model": "contenttypes.contenttype", "pk": 4, "fields": {"app_label": "auth", "model": "user"}}, {"model": "contenttypes.contenttype", "pk": 5, "fields": {"app_label": "contenttypes", "model": "contenttype"}}, {"model": "contenttypes.contenttype", "pk": 6, "fields": {"app_label": "redirects", "model": "redirect"}}, {"model": "contenttypes.contenttype", "pk": 7, "fields": {"app_label": "sessions", "model": "session"}}, {"model": "contenttypes.contenttype", "pk": 8, "fields": {"app_label": "sites", "model": "site"}}, {"model": "contenttypes.contenttype", "pk": 9, "fields": {"app_label": "djcelery", "model": "taskmeta"}}, {"model": "contenttypes.contenttype", "pk": 10, "fields": {"app_label": "djcelery", "model": "tasksetmeta"}}, {"model": "contenttypes.contenttype", "pk": 11, "fields": {"app_label": "djcelery", "model": "intervalschedule"}}, {"model": "contenttypes.contenttype", "pk": 12, "fields": {"app_label": "djcelery", "model": "crontabschedule"}}, {"model": "contenttypes.contenttype", "pk": 13, "fields": {"app_label": "djcelery", "model": "periodictasks"}}, {"model": "contenttypes.contenttype", "pk": 14, "fields": {"app_label": "djcelery", "model": "periodictask"}}, {"model": "contenttypes.contenttype", "pk": 15, "fields": {"app_label": "djcelery", "model": "workerstate"}}, {"model": "contenttypes.contenttype", "pk": 16, "fields": {"app_label": "djcelery", "model": "taskstate"}}, {"model": "contenttypes.contenttype", "pk": 17, "fields": {"app_label": "waffle", "model": "flag"}}, {"model": "contenttypes.contenttype", "pk": 18, "fields": {"app_label": "waffle", "model": "switch"}}, {"model": "contenttypes.contenttype", "pk": 19, "fields": {"app_label": "waffle", "model": "sample"}}, {"model": "contenttypes.contenttype", "pk": 20, "fields": {"app_label": "status", "model": "globalstatusmessage"}}, {"model": "contenttypes.contenttype", "pk": 21, "fields": {"app_label": "status", "model": "coursemessage"}}, {"model": "contenttypes.contenttype", "pk": 22, "fields": {"app_label": "static_replace", "model": "assetbaseurlconfig"}}, {"model": "contenttypes.contenttype", "pk": 23, "fields": {"app_label": "static_replace", "model": "assetexcludedextensionsconfig"}}, {"model": "contenttypes.contenttype", "pk": 24, "fields": {"app_label": "contentserver", "model": "courseassetcachettlconfig"}}, {"model": "contenttypes.contenttype", "pk": 25, "fields": {"app_label": "contentserver", "model": "cdnuseragentsconfig"}}, {"model": "contenttypes.contenttype", "pk": 26, "fields": {"app_label": "theming", "model": "sitetheme"}}, {"model": "contenttypes.contenttype", "pk": 27, "fields": {"app_label": "site_configuration", "model": "siteconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 28, "fields": {"app_label": "site_configuration", "model": "siteconfigurationhistory"}}, {"model": "contenttypes.contenttype", "pk": 29, "fields": {"app_label": "video_config", "model": "hlsplaybackenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 30, "fields": {"app_label": "video_config", "model": "coursehlsplaybackenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 31, "fields": {"app_label": "video_config", "model": "videotranscriptenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 32, "fields": {"app_label": "video_config", "model": "coursevideotranscriptenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 33, "fields": {"app_label": "video_pipeline", "model": "videopipelineintegration"}}, {"model": "contenttypes.contenttype", "pk": 34, "fields": {"app_label": "video_pipeline", "model": "videouploadsenabledbydefault"}}, {"model": "contenttypes.contenttype", "pk": 35, "fields": {"app_label": "video_pipeline", "model": "coursevideouploadsenabledbydefault"}}, {"model": "contenttypes.contenttype", "pk": 36, "fields": {"app_label": "bookmarks", "model": "bookmark"}}, {"model": "contenttypes.contenttype", "pk": 37, "fields": {"app_label": "bookmarks", "model": "xblockcache"}}, {"model": "contenttypes.contenttype", "pk": 38, "fields": {"app_label": "courseware", "model": "studentmodule"}}, {"model": "contenttypes.contenttype", "pk": 39, "fields": {"app_label": "courseware", "model": "studentmodulehistory"}}, {"model": "contenttypes.contenttype", "pk": 40, "fields": {"app_label": "courseware", "model": "xmoduleuserstatesummaryfield"}}, {"model": "contenttypes.contenttype", "pk": 41, "fields": {"app_label": "courseware", "model": "xmodulestudentprefsfield"}}, {"model": "contenttypes.contenttype", "pk": 42, "fields": {"app_label": "courseware", "model": "xmodulestudentinfofield"}}, {"model": "contenttypes.contenttype", "pk": 43, "fields": {"app_label": "courseware", "model": "offlinecomputedgrade"}}, {"model": "contenttypes.contenttype", "pk": 44, "fields": {"app_label": "courseware", "model": "offlinecomputedgradelog"}}, {"model": "contenttypes.contenttype", "pk": 45, "fields": {"app_label": "courseware", "model": "studentfieldoverride"}}, {"model": "contenttypes.contenttype", "pk": 46, "fields": {"app_label": "courseware", "model": "dynamicupgradedeadlineconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 47, "fields": {"app_label": "courseware", "model": "coursedynamicupgradedeadlineconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 48, "fields": {"app_label": "courseware", "model": "orgdynamicupgradedeadlineconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 49, "fields": {"app_label": "student", "model": "anonymoususerid"}}, {"model": "contenttypes.contenttype", "pk": 50, "fields": {"app_label": "student", "model": "userstanding"}}, {"model": "contenttypes.contenttype", "pk": 51, "fields": {"app_label": "student", "model": "userprofile"}}, {"model": "contenttypes.contenttype", "pk": 52, "fields": {"app_label": "student", "model": "usersignupsource"}}, {"model": "contenttypes.contenttype", "pk": 53, "fields": {"app_label": "student", "model": "usertestgroup"}}, {"model": "contenttypes.contenttype", "pk": 54, "fields": {"app_label": "student", "model": "registration"}}, {"model": "contenttypes.contenttype", "pk": 55, "fields": {"app_label": "student", "model": "pendingnamechange"}}, {"model": "contenttypes.contenttype", "pk": 56, "fields": {"app_label": "student", "model": "pendingemailchange"}}, {"model": "contenttypes.contenttype", "pk": 57, "fields": {"app_label": "student", "model": "passwordhistory"}}, {"model": "contenttypes.contenttype", "pk": 58, "fields": {"app_label": "student", "model": "loginfailures"}}, {"model": "contenttypes.contenttype", "pk": 59, "fields": {"app_label": "student", "model": "courseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 60, "fields": {"app_label": "student", "model": "manualenrollmentaudit"}}, {"model": "contenttypes.contenttype", "pk": 61, "fields": {"app_label": "student", "model": "courseenrollmentallowed"}}, {"model": "contenttypes.contenttype", "pk": 62, "fields": {"app_label": "student", "model": "courseaccessrole"}}, {"model": "contenttypes.contenttype", "pk": 63, "fields": {"app_label": "student", "model": "dashboardconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 64, "fields": {"app_label": "student", "model": "linkedinaddtoprofileconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 65, "fields": {"app_label": "student", "model": "entranceexamconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 66, "fields": {"app_label": "student", "model": "languageproficiency"}}, {"model": "contenttypes.contenttype", "pk": 67, "fields": {"app_label": "student", "model": "sociallink"}}, {"model": "contenttypes.contenttype", "pk": 68, "fields": {"app_label": "student", "model": "courseenrollmentattribute"}}, {"model": "contenttypes.contenttype", "pk": 69, "fields": {"app_label": "student", "model": "enrollmentrefundconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 70, "fields": {"app_label": "student", "model": "registrationcookieconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 71, "fields": {"app_label": "student", "model": "userattribute"}}, {"model": "contenttypes.contenttype", "pk": 72, "fields": {"app_label": "student", "model": "logoutviewconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 73, "fields": {"app_label": "track", "model": "trackinglog"}}, {"model": "contenttypes.contenttype", "pk": 74, "fields": {"app_label": "util", "model": "ratelimitconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 75, "fields": {"app_label": "certificates", "model": "certificatewhitelist"}}, {"model": "contenttypes.contenttype", "pk": 76, "fields": {"app_label": "certificates", "model": "generatedcertificate"}}, {"model": "contenttypes.contenttype", "pk": 77, "fields": {"app_label": "certificates", "model": "certificategenerationhistory"}}, {"model": "contenttypes.contenttype", "pk": 78, "fields": {"app_label": "certificates", "model": "certificateinvalidation"}}, {"model": "contenttypes.contenttype", "pk": 79, "fields": {"app_label": "certificates", "model": "examplecertificateset"}}, {"model": "contenttypes.contenttype", "pk": 80, "fields": {"app_label": "certificates", "model": "examplecertificate"}}, {"model": "contenttypes.contenttype", "pk": 81, "fields": {"app_label": "certificates", "model": "certificategenerationcoursesetting"}}, {"model": "contenttypes.contenttype", "pk": 82, "fields": {"app_label": "certificates", "model": "certificategenerationconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 83, "fields": {"app_label": "certificates", "model": "certificatehtmlviewconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 84, "fields": {"app_label": "certificates", "model": "certificatetemplate"}}, {"model": "contenttypes.contenttype", "pk": 85, "fields": {"app_label": "certificates", "model": "certificatetemplateasset"}}, {"model": "contenttypes.contenttype", "pk": 86, "fields": {"app_label": "instructor_task", "model": "instructortask"}}, {"model": "contenttypes.contenttype", "pk": 87, "fields": {"app_label": "instructor_task", "model": "gradereportsetting"}}, {"model": "contenttypes.contenttype", "pk": 88, "fields": {"app_label": "course_groups", "model": "courseusergroup"}}, {"model": "contenttypes.contenttype", "pk": 89, "fields": {"app_label": "course_groups", "model": "cohortmembership"}}, {"model": "contenttypes.contenttype", "pk": 90, "fields": {"app_label": "course_groups", "model": "courseusergrouppartitiongroup"}}, {"model": "contenttypes.contenttype", "pk": 91, "fields": {"app_label": "course_groups", "model": "coursecohortssettings"}}, {"model": "contenttypes.contenttype", "pk": 92, "fields": {"app_label": "course_groups", "model": "coursecohort"}}, {"model": "contenttypes.contenttype", "pk": 93, "fields": {"app_label": "course_groups", "model": "unregisteredlearnercohortassignments"}}, {"model": "contenttypes.contenttype", "pk": 94, "fields": {"app_label": "bulk_email", "model": "target"}}, {"model": "contenttypes.contenttype", "pk": 95, "fields": {"app_label": "bulk_email", "model": "cohorttarget"}}, {"model": "contenttypes.contenttype", "pk": 96, "fields": {"app_label": "bulk_email", "model": "coursemodetarget"}}, {"model": "contenttypes.contenttype", "pk": 97, "fields": {"app_label": "bulk_email", "model": "courseemail"}}, {"model": "contenttypes.contenttype", "pk": 98, "fields": {"app_label": "bulk_email", "model": "optout"}}, {"model": "contenttypes.contenttype", "pk": 99, "fields": {"app_label": "bulk_email", "model": "courseemailtemplate"}}, {"model": "contenttypes.contenttype", "pk": 100, "fields": {"app_label": "bulk_email", "model": "courseauthorization"}}, {"model": "contenttypes.contenttype", "pk": 101, "fields": {"app_label": "bulk_email", "model": "bulkemailflag"}}, {"model": "contenttypes.contenttype", "pk": 102, "fields": {"app_label": "branding", "model": "brandinginfoconfig"}}, {"model": "contenttypes.contenttype", "pk": 103, "fields": {"app_label": "branding", "model": "brandingapiconfig"}}, {"model": "contenttypes.contenttype", "pk": 104, "fields": {"app_label": "grades", "model": "visibleblocks"}}, {"model": "contenttypes.contenttype", "pk": 105, "fields": {"app_label": "grades", "model": "persistentsubsectiongrade"}}, {"model": "contenttypes.contenttype", "pk": 106, "fields": {"app_label": "grades", "model": "persistentcoursegrade"}}, {"model": "contenttypes.contenttype", "pk": 107, "fields": {"app_label": "grades", "model": "persistentsubsectiongradeoverride"}}, {"model": "contenttypes.contenttype", "pk": 108, "fields": {"app_label": "grades", "model": "persistentgradesenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 109, "fields": {"app_label": "grades", "model": "coursepersistentgradesflag"}}, {"model": "contenttypes.contenttype", "pk": 110, "fields": {"app_label": "grades", "model": "computegradessetting"}}, {"model": "contenttypes.contenttype", "pk": 111, "fields": {"app_label": "external_auth", "model": "externalauthmap"}}, {"model": "contenttypes.contenttype", "pk": 112, "fields": {"app_label": "django_openid_auth", "model": "nonce"}}, {"model": "contenttypes.contenttype", "pk": 113, "fields": {"app_label": "django_openid_auth", "model": "association"}}, {"model": "contenttypes.contenttype", "pk": 114, "fields": {"app_label": "django_openid_auth", "model": "useropenid"}}, {"model": "contenttypes.contenttype", "pk": 115, "fields": {"app_label": "oauth2", "model": "client"}}, {"model": "contenttypes.contenttype", "pk": 116, "fields": {"app_label": "oauth2", "model": "grant"}}, {"model": "contenttypes.contenttype", "pk": 117, "fields": {"app_label": "oauth2", "model": "accesstoken"}}, {"model": "contenttypes.contenttype", "pk": 118, "fields": {"app_label": "oauth2", "model": "refreshtoken"}}, {"model": "contenttypes.contenttype", "pk": 119, "fields": {"app_label": "edx_oauth2_provider", "model": "trustedclient"}}, {"model": "contenttypes.contenttype", "pk": 120, "fields": {"app_label": "oauth2_provider", "model": "application"}}, {"model": "contenttypes.contenttype", "pk": 121, "fields": {"app_label": "oauth2_provider", "model": "grant"}}, {"model": "contenttypes.contenttype", "pk": 122, "fields": {"app_label": "oauth2_provider", "model": "accesstoken"}}, {"model": "contenttypes.contenttype", "pk": 123, "fields": {"app_label": "oauth2_provider", "model": "refreshtoken"}}, {"model": "contenttypes.contenttype", "pk": 124, "fields": {"app_label": "oauth_dispatch", "model": "restrictedapplication"}}, {"model": "contenttypes.contenttype", "pk": 125, "fields": {"app_label": "third_party_auth", "model": "oauth2providerconfig"}}, {"model": "contenttypes.contenttype", "pk": 126, "fields": {"app_label": "third_party_auth", "model": "samlproviderconfig"}}, {"model": "contenttypes.contenttype", "pk": 127, "fields": {"app_label": "third_party_auth", "model": "samlconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 128, "fields": {"app_label": "third_party_auth", "model": "samlproviderdata"}}, {"model": "contenttypes.contenttype", "pk": 129, "fields": {"app_label": "third_party_auth", "model": "ltiproviderconfig"}}, {"model": "contenttypes.contenttype", "pk": 130, "fields": {"app_label": "third_party_auth", "model": "providerapipermissions"}}, {"model": "contenttypes.contenttype", "pk": 131, "fields": {"app_label": "oauth_provider", "model": "nonce"}}, {"model": "contenttypes.contenttype", "pk": 132, "fields": {"app_label": "oauth_provider", "model": "scope"}}, {"model": "contenttypes.contenttype", "pk": 133, "fields": {"app_label": "oauth_provider", "model": "consumer"}}, {"model": "contenttypes.contenttype", "pk": 134, "fields": {"app_label": "oauth_provider", "model": "token"}}, {"model": "contenttypes.contenttype", "pk": 135, "fields": {"app_label": "oauth_provider", "model": "resource"}}, {"model": "contenttypes.contenttype", "pk": 136, "fields": {"app_label": "wiki", "model": "article"}}, {"model": "contenttypes.contenttype", "pk": 137, "fields": {"app_label": "wiki", "model": "articleforobject"}}, {"model": "contenttypes.contenttype", "pk": 138, "fields": {"app_label": "wiki", "model": "articlerevision"}}, {"model": "contenttypes.contenttype", "pk": 139, "fields": {"app_label": "wiki", "model": "articleplugin"}}, {"model": "contenttypes.contenttype", "pk": 140, "fields": {"app_label": "wiki", "model": "reusableplugin"}}, {"model": "contenttypes.contenttype", "pk": 141, "fields": {"app_label": "wiki", "model": "simpleplugin"}}, {"model": "contenttypes.contenttype", "pk": 142, "fields": {"app_label": "wiki", "model": "revisionplugin"}}, {"model": "contenttypes.contenttype", "pk": 143, "fields": {"app_label": "wiki", "model": "revisionpluginrevision"}}, {"model": "contenttypes.contenttype", "pk": 144, "fields": {"app_label": "wiki", "model": "urlpath"}}, {"model": "contenttypes.contenttype", "pk": 145, "fields": {"app_label": "django_notify", "model": "notificationtype"}}, {"model": "contenttypes.contenttype", "pk": 146, "fields": {"app_label": "django_notify", "model": "settings"}}, {"model": "contenttypes.contenttype", "pk": 147, "fields": {"app_label": "django_notify", "model": "subscription"}}, {"model": "contenttypes.contenttype", "pk": 148, "fields": {"app_label": "django_notify", "model": "notification"}}, {"model": "contenttypes.contenttype", "pk": 149, "fields": {"app_label": "admin", "model": "logentry"}}, {"model": "contenttypes.contenttype", "pk": 150, "fields": {"app_label": "django_comment_common", "model": "role"}}, {"model": "contenttypes.contenttype", "pk": 151, "fields": {"app_label": "django_comment_common", "model": "permission"}}, {"model": "contenttypes.contenttype", "pk": 152, "fields": {"app_label": "django_comment_common", "model": "forumsconfig"}}, {"model": "contenttypes.contenttype", "pk": 153, "fields": {"app_label": "django_comment_common", "model": "coursediscussionsettings"}}, {"model": "contenttypes.contenttype", "pk": 154, "fields": {"app_label": "notes", "model": "note"}}, {"model": "contenttypes.contenttype", "pk": 155, "fields": {"app_label": "splash", "model": "splashconfig"}}, {"model": "contenttypes.contenttype", "pk": 156, "fields": {"app_label": "user_api", "model": "userpreference"}}, {"model": "contenttypes.contenttype", "pk": 157, "fields": {"app_label": "user_api", "model": "usercoursetag"}}, {"model": "contenttypes.contenttype", "pk": 158, "fields": {"app_label": "user_api", "model": "userorgtag"}}, {"model": "contenttypes.contenttype", "pk": 159, "fields": {"app_label": "shoppingcart", "model": "order"}}, {"model": "contenttypes.contenttype", "pk": 160, "fields": {"app_label": "shoppingcart", "model": "orderitem"}}, {"model": "contenttypes.contenttype", "pk": 161, "fields": {"app_label": "shoppingcart", "model": "invoice"}}, {"model": "contenttypes.contenttype", "pk": 162, "fields": {"app_label": "shoppingcart", "model": "invoicetransaction"}}, {"model": "contenttypes.contenttype", "pk": 163, "fields": {"app_label": "shoppingcart", "model": "invoiceitem"}}, {"model": "contenttypes.contenttype", "pk": 164, "fields": {"app_label": "shoppingcart", "model": "courseregistrationcodeinvoiceitem"}}, {"model": "contenttypes.contenttype", "pk": 165, "fields": {"app_label": "shoppingcart", "model": "invoicehistory"}}, {"model": "contenttypes.contenttype", "pk": 166, "fields": {"app_label": "shoppingcart", "model": "courseregistrationcode"}}, {"model": "contenttypes.contenttype", "pk": 167, "fields": {"app_label": "shoppingcart", "model": "registrationcoderedemption"}}, {"model": "contenttypes.contenttype", "pk": 168, "fields": {"app_label": "shoppingcart", "model": "coupon"}}, {"model": "contenttypes.contenttype", "pk": 169, "fields": {"app_label": "shoppingcart", "model": "couponredemption"}}, {"model": "contenttypes.contenttype", "pk": 170, "fields": {"app_label": "shoppingcart", "model": "paidcourseregistration"}}, {"model": "contenttypes.contenttype", "pk": 171, "fields": {"app_label": "shoppingcart", "model": "courseregcodeitem"}}, {"model": "contenttypes.contenttype", "pk": 172, "fields": {"app_label": "shoppingcart", "model": "courseregcodeitemannotation"}}, {"model": "contenttypes.contenttype", "pk": 173, "fields": {"app_label": "shoppingcart", "model": "paidcourseregistrationannotation"}}, {"model": "contenttypes.contenttype", "pk": 174, "fields": {"app_label": "shoppingcart", "model": "certificateitem"}}, {"model": "contenttypes.contenttype", "pk": 175, "fields": {"app_label": "shoppingcart", "model": "donationconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 176, "fields": {"app_label": "shoppingcart", "model": "donation"}}, {"model": "contenttypes.contenttype", "pk": 177, "fields": {"app_label": "course_modes", "model": "coursemode"}}, {"model": "contenttypes.contenttype", "pk": 178, "fields": {"app_label": "course_modes", "model": "coursemodesarchive"}}, {"model": "contenttypes.contenttype", "pk": 179, "fields": {"app_label": "course_modes", "model": "coursemodeexpirationconfig"}}, {"model": "contenttypes.contenttype", "pk": 180, "fields": {"app_label": "entitlements", "model": "courseentitlement"}}, {"model": "contenttypes.contenttype", "pk": 181, "fields": {"app_label": "verify_student", "model": "softwaresecurephotoverification"}}, {"model": "contenttypes.contenttype", "pk": 182, "fields": {"app_label": "verify_student", "model": "verificationdeadline"}}, {"model": "contenttypes.contenttype", "pk": 183, "fields": {"app_label": "verify_student", "model": "verificationcheckpoint"}}, {"model": "contenttypes.contenttype", "pk": 184, "fields": {"app_label": "verify_student", "model": "verificationstatus"}}, {"model": "contenttypes.contenttype", "pk": 185, "fields": {"app_label": "verify_student", "model": "incoursereverificationconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 186, "fields": {"app_label": "verify_student", "model": "icrvstatusemailsconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 187, "fields": {"app_label": "verify_student", "model": "skippedreverification"}}, {"model": "contenttypes.contenttype", "pk": 188, "fields": {"app_label": "dark_lang", "model": "darklangconfig"}}, {"model": "contenttypes.contenttype", "pk": 189, "fields": {"app_label": "microsite_configuration", "model": "microsite"}}, {"model": "contenttypes.contenttype", "pk": 190, "fields": {"app_label": "microsite_configuration", "model": "micrositehistory"}}, {"model": "contenttypes.contenttype", "pk": 191, "fields": {"app_label": "microsite_configuration", "model": "micrositeorganizationmapping"}}, {"model": "contenttypes.contenttype", "pk": 192, "fields": {"app_label": "microsite_configuration", "model": "micrositetemplate"}}, {"model": "contenttypes.contenttype", "pk": 193, "fields": {"app_label": "rss_proxy", "model": "whitelistedrssurl"}}, {"model": "contenttypes.contenttype", "pk": 194, "fields": {"app_label": "embargo", "model": "embargoedcourse"}}, {"model": "contenttypes.contenttype", "pk": 195, "fields": {"app_label": "embargo", "model": "embargoedstate"}}, {"model": "contenttypes.contenttype", "pk": 196, "fields": {"app_label": "embargo", "model": "restrictedcourse"}}, {"model": "contenttypes.contenttype", "pk": 197, "fields": {"app_label": "embargo", "model": "country"}}, {"model": "contenttypes.contenttype", "pk": 198, "fields": {"app_label": "embargo", "model": "countryaccessrule"}}, {"model": "contenttypes.contenttype", "pk": 199, "fields": {"app_label": "embargo", "model": "courseaccessrulehistory"}}, {"model": "contenttypes.contenttype", "pk": 200, "fields": {"app_label": "embargo", "model": "ipfilter"}}, {"model": "contenttypes.contenttype", "pk": 201, "fields": {"app_label": "course_action_state", "model": "coursererunstate"}}, {"model": "contenttypes.contenttype", "pk": 202, "fields": {"app_label": "mobile_api", "model": "mobileapiconfig"}}, {"model": "contenttypes.contenttype", "pk": 203, "fields": {"app_label": "mobile_api", "model": "appversionconfig"}}, {"model": "contenttypes.contenttype", "pk": 204, "fields": {"app_label": "mobile_api", "model": "ignoremobileavailableflagconfig"}}, {"model": "contenttypes.contenttype", "pk": 205, "fields": {"app_label": "social_django", "model": "usersocialauth"}}, {"model": "contenttypes.contenttype", "pk": 206, "fields": {"app_label": "social_django", "model": "nonce"}}, {"model": "contenttypes.contenttype", "pk": 207, "fields": {"app_label": "social_django", "model": "association"}}, {"model": "contenttypes.contenttype", "pk": 208, "fields": {"app_label": "social_django", "model": "code"}}, {"model": "contenttypes.contenttype", "pk": 209, "fields": {"app_label": "social_django", "model": "partial"}}, {"model": "contenttypes.contenttype", "pk": 210, "fields": {"app_label": "survey", "model": "surveyform"}}, {"model": "contenttypes.contenttype", "pk": 211, "fields": {"app_label": "survey", "model": "surveyanswer"}}, {"model": "contenttypes.contenttype", "pk": 212, "fields": {"app_label": "lms_xblock", "model": "xblockasidesconfig"}}, {"model": "contenttypes.contenttype", "pk": 213, "fields": {"app_label": "problem_builder", "model": "answer"}}, {"model": "contenttypes.contenttype", "pk": 214, "fields": {"app_label": "problem_builder", "model": "share"}}, {"model": "contenttypes.contenttype", "pk": 215, "fields": {"app_label": "submissions", "model": "studentitem"}}, {"model": "contenttypes.contenttype", "pk": 216, "fields": {"app_label": "submissions", "model": "submission"}}, {"model": "contenttypes.contenttype", "pk": 217, "fields": {"app_label": "submissions", "model": "score"}}, {"model": "contenttypes.contenttype", "pk": 218, "fields": {"app_label": "submissions", "model": "scoresummary"}}, {"model": "contenttypes.contenttype", "pk": 219, "fields": {"app_label": "submissions", "model": "scoreannotation"}}, {"model": "contenttypes.contenttype", "pk": 220, "fields": {"app_label": "assessment", "model": "rubric"}}, {"model": "contenttypes.contenttype", "pk": 221, "fields": {"app_label": "assessment", "model": "criterion"}}, {"model": "contenttypes.contenttype", "pk": 222, "fields": {"app_label": "assessment", "model": "criterionoption"}}, {"model": "contenttypes.contenttype", "pk": 223, "fields": {"app_label": "assessment", "model": "assessment"}}, {"model": "contenttypes.contenttype", "pk": 224, "fields": {"app_label": "assessment", "model": "assessmentpart"}}, {"model": "contenttypes.contenttype", "pk": 225, "fields": {"app_label": "assessment", "model": "assessmentfeedbackoption"}}, {"model": "contenttypes.contenttype", "pk": 226, "fields": {"app_label": "assessment", "model": "assessmentfeedback"}}, {"model": "contenttypes.contenttype", "pk": 227, "fields": {"app_label": "assessment", "model": "peerworkflow"}}, {"model": "contenttypes.contenttype", "pk": 228, "fields": {"app_label": "assessment", "model": "peerworkflowitem"}}, {"model": "contenttypes.contenttype", "pk": 229, "fields": {"app_label": "assessment", "model": "trainingexample"}}, {"model": "contenttypes.contenttype", "pk": 230, "fields": {"app_label": "assessment", "model": "studenttrainingworkflow"}}, {"model": "contenttypes.contenttype", "pk": 231, "fields": {"app_label": "assessment", "model": "studenttrainingworkflowitem"}}, {"model": "contenttypes.contenttype", "pk": 232, "fields": {"app_label": "assessment", "model": "staffworkflow"}}, {"model": "contenttypes.contenttype", "pk": 233, "fields": {"app_label": "workflow", "model": "assessmentworkflow"}}, {"model": "contenttypes.contenttype", "pk": 234, "fields": {"app_label": "workflow", "model": "assessmentworkflowstep"}}, {"model": "contenttypes.contenttype", "pk": 235, "fields": {"app_label": "workflow", "model": "assessmentworkflowcancellation"}}, {"model": "contenttypes.contenttype", "pk": 236, "fields": {"app_label": "edxval", "model": "profile"}}, {"model": "contenttypes.contenttype", "pk": 237, "fields": {"app_label": "edxval", "model": "video"}}, {"model": "contenttypes.contenttype", "pk": 238, "fields": {"app_label": "edxval", "model": "coursevideo"}}, {"model": "contenttypes.contenttype", "pk": 239, "fields": {"app_label": "edxval", "model": "encodedvideo"}}, {"model": "contenttypes.contenttype", "pk": 240, "fields": {"app_label": "edxval", "model": "videoimage"}}, {"model": "contenttypes.contenttype", "pk": 241, "fields": {"app_label": "edxval", "model": "videotranscript"}}, {"model": "contenttypes.contenttype", "pk": 242, "fields": {"app_label": "edxval", "model": "transcriptpreference"}}, {"model": "contenttypes.contenttype", "pk": 243, "fields": {"app_label": "edxval", "model": "thirdpartytranscriptcredentialsstate"}}, {"model": "contenttypes.contenttype", "pk": 244, "fields": {"app_label": "course_overviews", "model": "courseoverview"}}, {"model": "contenttypes.contenttype", "pk": 245, "fields": {"app_label": "course_overviews", "model": "courseoverviewtab"}}, {"model": "contenttypes.contenttype", "pk": 246, "fields": {"app_label": "course_overviews", "model": "courseoverviewimageset"}}, {"model": "contenttypes.contenttype", "pk": 247, "fields": {"app_label": "course_overviews", "model": "courseoverviewimageconfig"}}, {"model": "contenttypes.contenttype", "pk": 248, "fields": {"app_label": "course_structures", "model": "coursestructure"}}, {"model": "contenttypes.contenttype", "pk": 249, "fields": {"app_label": "block_structure", "model": "blockstructureconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 250, "fields": {"app_label": "block_structure", "model": "blockstructuremodel"}}, {"model": "contenttypes.contenttype", "pk": 251, "fields": {"app_label": "cors_csrf", "model": "xdomainproxyconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 252, "fields": {"app_label": "commerce", "model": "commerceconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 253, "fields": {"app_label": "credit", "model": "creditprovider"}}, {"model": "contenttypes.contenttype", "pk": 254, "fields": {"app_label": "credit", "model": "creditcourse"}}, {"model": "contenttypes.contenttype", "pk": 255, "fields": {"app_label": "credit", "model": "creditrequirement"}}, {"model": "contenttypes.contenttype", "pk": 256, "fields": {"app_label": "credit", "model": "creditrequirementstatus"}}, {"model": "contenttypes.contenttype", "pk": 257, "fields": {"app_label": "credit", "model": "crediteligibility"}}, {"model": "contenttypes.contenttype", "pk": 258, "fields": {"app_label": "credit", "model": "creditrequest"}}, {"model": "contenttypes.contenttype", "pk": 259, "fields": {"app_label": "credit", "model": "creditconfig"}}, {"model": "contenttypes.contenttype", "pk": 260, "fields": {"app_label": "teams", "model": "courseteam"}}, {"model": "contenttypes.contenttype", "pk": 261, "fields": {"app_label": "teams", "model": "courseteammembership"}}, {"model": "contenttypes.contenttype", "pk": 262, "fields": {"app_label": "xblock_django", "model": "xblockconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 263, "fields": {"app_label": "xblock_django", "model": "xblockstudioconfigurationflag"}}, {"model": "contenttypes.contenttype", "pk": 264, "fields": {"app_label": "xblock_django", "model": "xblockstudioconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 265, "fields": {"app_label": "programs", "model": "programsapiconfig"}}, {"model": "contenttypes.contenttype", "pk": 266, "fields": {"app_label": "catalog", "model": "catalogintegration"}}, {"model": "contenttypes.contenttype", "pk": 267, "fields": {"app_label": "self_paced", "model": "selfpacedconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 268, "fields": {"app_label": "thumbnail", "model": "kvstore"}}, {"model": "contenttypes.contenttype", "pk": 269, "fields": {"app_label": "credentials", "model": "credentialsapiconfig"}}, {"model": "contenttypes.contenttype", "pk": 270, "fields": {"app_label": "milestones", "model": "milestone"}}, {"model": "contenttypes.contenttype", "pk": 271, "fields": {"app_label": "milestones", "model": "milestonerelationshiptype"}}, {"model": "contenttypes.contenttype", "pk": 272, "fields": {"app_label": "milestones", "model": "coursemilestone"}}, {"model": "contenttypes.contenttype", "pk": 273, "fields": {"app_label": "milestones", "model": "coursecontentmilestone"}}, {"model": "contenttypes.contenttype", "pk": 274, "fields": {"app_label": "milestones", "model": "usermilestone"}}, {"model": "contenttypes.contenttype", "pk": 275, "fields": {"app_label": "api_admin", "model": "apiaccessconfig"}}, {"model": "contenttypes.contenttype", "pk": 276, "fields": {"app_label": "api_admin", "model": "catalog"}}, {"model": "contenttypes.contenttype", "pk": 277, "fields": {"app_label": "verified_track_content", "model": "verifiedtrackcohortedcourse"}}, {"model": "contenttypes.contenttype", "pk": 278, "fields": {"app_label": "verified_track_content", "model": "migrateverifiedtrackcohortssetting"}}, {"model": "contenttypes.contenttype", "pk": 279, "fields": {"app_label": "badges", "model": "badgeclass"}}, {"model": "contenttypes.contenttype", "pk": 280, "fields": {"app_label": "badges", "model": "badgeassertion"}}, {"model": "contenttypes.contenttype", "pk": 281, "fields": {"app_label": "badges", "model": "coursecompleteimageconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 282, "fields": {"app_label": "badges", "model": "courseeventbadgesconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 283, "fields": {"app_label": "email_marketing", "model": "emailmarketingconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 284, "fields": {"app_label": "celery_utils", "model": "failedtask"}}, {"model": "contenttypes.contenttype", "pk": 285, "fields": {"app_label": "celery_utils", "model": "chorddata"}}, {"model": "contenttypes.contenttype", "pk": 286, "fields": {"app_label": "crawlers", "model": "crawlersconfig"}}, {"model": "contenttypes.contenttype", "pk": 287, "fields": {"app_label": "waffle_utils", "model": "waffleflagcourseoverridemodel"}}, {"model": "contenttypes.contenttype", "pk": 288, "fields": {"app_label": "schedules", "model": "schedule"}}, {"model": "contenttypes.contenttype", "pk": 289, "fields": {"app_label": "schedules", "model": "scheduleconfig"}}, {"model": "contenttypes.contenttype", "pk": 290, "fields": {"app_label": "schedules", "model": "scheduleexperience"}}, {"model": "contenttypes.contenttype", "pk": 291, "fields": {"app_label": "course_goals", "model": "coursegoal"}}, {"model": "contenttypes.contenttype", "pk": 292, "fields": {"app_label": "completion", "model": "blockcompletion"}}, {"model": "contenttypes.contenttype", "pk": 293, "fields": {"app_label": "experiments", "model": "experimentdata"}}, {"model": "contenttypes.contenttype", "pk": 294, "fields": {"app_label": "experiments", "model": "experimentkeyvalue"}}, {"model": "contenttypes.contenttype", "pk": 295, "fields": {"app_label": "edx_proctoring", "model": "proctoredexam"}}, {"model": "contenttypes.contenttype", "pk": 296, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamreviewpolicy"}}, {"model": "contenttypes.contenttype", "pk": 297, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamreviewpolicyhistory"}}, {"model": "contenttypes.contenttype", "pk": 298, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamstudentattempt"}}, {"model": "contenttypes.contenttype", "pk": 299, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamstudentattempthistory"}}, {"model": "contenttypes.contenttype", "pk": 300, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamstudentallowance"}}, {"model": "contenttypes.contenttype", "pk": 301, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamstudentallowancehistory"}}, {"model": "contenttypes.contenttype", "pk": 302, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamsoftwaresecurereview"}}, {"model": "contenttypes.contenttype", "pk": 303, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamsoftwaresecurereviewhistory"}}, {"model": "contenttypes.contenttype", "pk": 304, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamsoftwaresecurecomment"}}, {"model": "contenttypes.contenttype", "pk": 305, "fields": {"app_label": "organizations", "model": "organization"}}, {"model": "contenttypes.contenttype", "pk": 306, "fields": {"app_label": "organizations", "model": "organizationcourse"}}, {"model": "contenttypes.contenttype", "pk": 307, "fields": {"app_label": "enterprise", "model": "historicalenterprisecustomer"}}, {"model": "contenttypes.contenttype", "pk": 308, "fields": {"app_label": "enterprise", "model": "enterprisecustomer"}}, {"model": "contenttypes.contenttype", "pk": 309, "fields": {"app_label": "enterprise", "model": "enterprisecustomeruser"}}, {"model": "contenttypes.contenttype", "pk": 310, "fields": {"app_label": "enterprise", "model": "pendingenterprisecustomeruser"}}, {"model": "contenttypes.contenttype", "pk": 311, "fields": {"app_label": "enterprise", "model": "pendingenrollment"}}, {"model": "contenttypes.contenttype", "pk": 312, "fields": {"app_label": "enterprise", "model": "enterprisecustomerbrandingconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 313, "fields": {"app_label": "enterprise", "model": "enterprisecustomeridentityprovider"}}, {"model": "contenttypes.contenttype", "pk": 314, "fields": {"app_label": "enterprise", "model": "historicalenterprisecustomerentitlement"}}, {"model": "contenttypes.contenttype", "pk": 315, "fields": {"app_label": "enterprise", "model": "enterprisecustomerentitlement"}}, {"model": "contenttypes.contenttype", "pk": 316, "fields": {"app_label": "enterprise", "model": "historicalenterprisecourseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 317, "fields": {"app_label": "enterprise", "model": "enterprisecourseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 318, "fields": {"app_label": "enterprise", "model": "historicalenterprisecustomercatalog"}}, {"model": "contenttypes.contenttype", "pk": 319, "fields": {"app_label": "enterprise", "model": "enterprisecustomercatalog"}}, {"model": "contenttypes.contenttype", "pk": 320, "fields": {"app_label": "enterprise", "model": "historicalenrollmentnotificationemailtemplate"}}, {"model": "contenttypes.contenttype", "pk": 321, "fields": {"app_label": "enterprise", "model": "enrollmentnotificationemailtemplate"}}, {"model": "contenttypes.contenttype", "pk": 322, "fields": {"app_label": "enterprise", "model": "enterprisecustomerreportingconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 323, "fields": {"app_label": "consent", "model": "historicaldatasharingconsent"}}, {"model": "contenttypes.contenttype", "pk": 324, "fields": {"app_label": "consent", "model": "datasharingconsent"}}, {"model": "contenttypes.contenttype", "pk": 325, "fields": {"app_label": "integrated_channel", "model": "learnerdatatransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 326, "fields": {"app_label": "integrated_channel", "model": "catalogtransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 327, "fields": {"app_label": "degreed", "model": "degreedglobalconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 328, "fields": {"app_label": "degreed", "model": "historicaldegreedenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 329, "fields": {"app_label": "degreed", "model": "degreedenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 330, "fields": {"app_label": "degreed", "model": "degreedlearnerdatatransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 331, "fields": {"app_label": "sap_success_factors", "model": "sapsuccessfactorsglobalconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 332, "fields": {"app_label": "sap_success_factors", "model": "historicalsapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 333, "fields": {"app_label": "sap_success_factors", "model": "sapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 334, "fields": {"app_label": "sap_success_factors", "model": "sapsuccessfactorslearnerdatatransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 335, "fields": {"app_label": "ccx", "model": "customcourseforedx"}}, {"model": "contenttypes.contenttype", "pk": 336, "fields": {"app_label": "ccx", "model": "ccxfieldoverride"}}, {"model": "contenttypes.contenttype", "pk": 337, "fields": {"app_label": "ccxcon", "model": "ccxcon"}}, {"model": "contenttypes.contenttype", "pk": 338, "fields": {"app_label": "coursewarehistoryextended", "model": "studentmodulehistoryextended"}}, {"model": "contenttypes.contenttype", "pk": 339, "fields": {"app_label": "contentstore", "model": "videouploadconfig"}}, {"model": "contenttypes.contenttype", "pk": 340, "fields": {"app_label": "contentstore", "model": "pushnotificationconfig"}}, {"model": "contenttypes.contenttype", "pk": 341, "fields": {"app_label": "contentstore", "model": "newassetspageflag"}}, {"model": "contenttypes.contenttype", "pk": 342, "fields": {"app_label": "contentstore", "model": "coursenewassetspageflag"}}, {"model": "contenttypes.contenttype", "pk": 343, "fields": {"app_label": "course_creators", "model": "coursecreator"}}, {"model": "contenttypes.contenttype", "pk": 344, "fields": {"app_label": "xblock_config", "model": "studioconfig"}}, {"model": "contenttypes.contenttype", "pk": 345, "fields": {"app_label": "xblock_config", "model": "courseeditltifieldsenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 346, "fields": {"app_label": "tagging", "model": "tagcategories"}}, {"model": "contenttypes.contenttype", "pk": 347, "fields": {"app_label": "tagging", "model": "tagavailablevalues"}}, {"model": "contenttypes.contenttype", "pk": 348, "fields": {"app_label": "user_tasks", "model": "usertaskstatus"}}, {"model": "contenttypes.contenttype", "pk": 349, "fields": {"app_label": "user_tasks", "model": "usertaskartifact"}}, {"model": "contenttypes.contenttype", "pk": 350, "fields": {"app_label": "entitlements", "model": "courseentitlementpolicy"}}, {"model": "contenttypes.contenttype", "pk": 351, "fields": {"app_label": "entitlements", "model": "courseentitlementsupportdetail"}}, {"model": "contenttypes.contenttype", "pk": 352, "fields": {"app_label": "integrated_channel", "model": "contentmetadataitemtransmission"}}, {"model": "contenttypes.contenttype", "pk": 353, "fields": {"app_label": "video_config", "model": "transcriptmigrationsetting"}}, {"model": "contenttypes.contenttype", "pk": 354, "fields": {"app_label": "verify_student", "model": "ssoverification"}}, {"model": "contenttypes.contenttype", "pk": 355, "fields": {"app_label": "user_api", "model": "userretirementstatus"}}, {"model": "contenttypes.contenttype", "pk": 356, "fields": {"app_label": "user_api", "model": "retirementstate"}}, {"model": "contenttypes.contenttype", "pk": 357, "fields": {"app_label": "consent", "model": "datasharingconsenttextoverrides"}}, {"model": "contenttypes.contenttype", "pk": 358, "fields": {"app_label": "user_api", "model": "userretirementrequest"}}, {"model": "contenttypes.contenttype", "pk": 359, "fields": {"app_label": "django_comment_common", "model": "discussionsidmapping"}}, {"model": "contenttypes.contenttype", "pk": 360, "fields": {"app_label": "oauth_dispatch", "model": "scopedapplication"}}, {"model": "contenttypes.contenttype", "pk": 361, "fields": {"app_label": "oauth_dispatch", "model": "scopedapplicationorganization"}}, {"model": "contenttypes.contenttype", "pk": 362, "fields": {"app_label": "user_api", "model": "userretirementpartnerreportingstatus"}}, {"model": "contenttypes.contenttype", "pk": 363, "fields": {"app_label": "verify_student", "model": "manualverification"}}, {"model": "contenttypes.contenttype", "pk": 364, "fields": {"app_label": "oauth_dispatch", "model": "applicationorganization"}}, {"model": "contenttypes.contenttype", "pk": 365, "fields": {"app_label": "oauth_dispatch", "model": "applicationaccess"}}, {"model": "contenttypes.contenttype", "pk": 366, "fields": {"app_label": "video_config", "model": "migrationenqueuedcourse"}}, {"model": "contenttypes.contenttype", "pk": 367, "fields": {"app_label": "xapi", "model": "xapilrsconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 368, "fields": {"app_label": "credentials", "model": "notifycredentialsconfig"}}, {"model": "contenttypes.contenttype", "pk": 369, "fields": {"app_label": "video_config", "model": "updatedcoursevideos"}}, {"model": "contenttypes.contenttype", "pk": 370, "fields": {"app_label": "video_config", "model": "videothumbnailsetting"}}, {"model": "contenttypes.contenttype", "pk": 371, "fields": {"app_label": "course_duration_limits", "model": "coursedurationlimitconfig"}}, {"model": "contenttypes.contenttype", "pk": 372, "fields": {"app_label": "content_type_gating", "model": "contenttypegatingconfig"}}, {"model": "contenttypes.contenttype", "pk": 373, "fields": {"app_label": "grades", "model": "persistentsubsectiongradeoverridehistory"}}, {"model": "contenttypes.contenttype", "pk": 374, "fields": {"app_label": "student", "model": "accountrecovery"}}, {"model": "contenttypes.contenttype", "pk": 375, "fields": {"app_label": "enterprise", "model": "enterprisecustomertype"}}, {"model": "contenttypes.contenttype", "pk": 376, "fields": {"app_label": "student", "model": "pendingsecondaryemailchange"}}, {"model": "contenttypes.contenttype", "pk": 377, "fields": {"app_label": "lti_provider", "model": "lticonsumer"}}, {"model": "contenttypes.contenttype", "pk": 378, "fields": {"app_label": "lti_provider", "model": "gradedassignment"}}, {"model": "contenttypes.contenttype", "pk": 379, "fields": {"app_label": "lti_provider", "model": "ltiuser"}}, {"model": "contenttypes.contenttype", "pk": 380, "fields": {"app_label": "lti_provider", "model": "outcomeservice"}}, {"model": "contenttypes.contenttype", "pk": 381, "fields": {"app_label": "enterprise", "model": "systemwideenterpriserole"}}, {"model": "contenttypes.contenttype", "pk": 382, "fields": {"app_label": "enterprise", "model": "systemwideenterpriseuserroleassignment"}}, {"model": "contenttypes.contenttype", "pk": 383, "fields": {"app_label": "announcements", "model": "announcement"}}, {"model": "contenttypes.contenttype", "pk": 753, "fields": {"app_label": "enterprise", "model": "enterprisefeatureuserroleassignment"}}, {"model": "contenttypes.contenttype", "pk": 754, "fields": {"app_label": "enterprise", "model": "enterprisefeaturerole"}}, {"model": "contenttypes.contenttype", "pk": 755, "fields": {"app_label": "program_enrollments", "model": "programenrollment"}}, {"model": "contenttypes.contenttype", "pk": 756, "fields": {"app_label": "program_enrollments", "model": "historicalprogramenrollment"}}, {"model": "contenttypes.contenttype", "pk": 757, "fields": {"app_label": "program_enrollments", "model": "programcourseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 758, "fields": {"app_label": "program_enrollments", "model": "historicalprogramcourseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 759, "fields": {"app_label": "edx_when", "model": "contentdate"}}, {"model": "contenttypes.contenttype", "pk": 760, "fields": {"app_label": "edx_when", "model": "userdate"}}, {"model": "contenttypes.contenttype", "pk": 761, "fields": {"app_label": "edx_when", "model": "datepolicy"}}, {"model": "contenttypes.contenttype", "pk": 762, "fields": {"app_label": "student", "model": "historicalcourseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 763, "fields": {"app_label": "cornerstone", "model": "cornerstoneglobalconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 764, "fields": {"app_label": "cornerstone", "model": "historicalcornerstoneenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 765, "fields": {"app_label": "cornerstone", "model": "cornerstonelearnerdatatransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 766, "fields": {"app_label": "cornerstone", "model": "cornerstoneenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 767, "fields": {"app_label": "discounts", "model": "discountrestrictionconfig"}}, {"model": "contenttypes.contenttype", "pk": 768, "fields": {"app_label": "entitlements", "model": "historicalcourseentitlement"}}, {"model": "contenttypes.contenttype", "pk": 769, "fields": {"app_label": "organizations", "model": "historicalorganization"}}, {"model": "contenttypes.contenttype", "pk": 770, "fields": {"app_label": "grades", "model": "historicalpersistentsubsectiongradeoverride"}}, {"model": "contenttypes.contenttype", "pk": 771, "fields": {"app_label": "super_csv", "model": "csvoperation"}}, {"model": "contenttypes.contenttype", "pk": 772, "fields": {"app_label": "bulk_grades", "model": "scoreoverrider"}}, {"model": "contenttypes.contenttype", "pk": 773, "fields": {"app_label": "course_modes", "model": "historicalcoursemode"}}, {"model": "contenttypes.contenttype", "pk": 774, "fields": {"app_label": "course_overviews", "model": "historicalcourseoverview"}}, {"model": "contenttypes.contenttype", "pk": 775, "fields": {"app_label": "system_wide_roles", "model": "systemwiderole"}}, {"model": "contenttypes.contenttype", "pk": 776, "fields": {"app_label": "system_wide_roles", "model": "systemwideroleassignment"}}, {"model": "contenttypes.contenttype", "pk": 777, "fields": {"app_label": "enterprise", "model": "enterprisecatalogquery"}}, {"model": "contenttypes.contenttype", "pk": 778, "fields": {"app_label": "enterprise", "model": "historicalpendingenrollment"}}, {"model": "contenttypes.contenttype", "pk": 779, "fields": {"app_label": "enterprise", "model": "historicalpendingenterprisecustomeruser"}}, {"model": "contenttypes.contenttype", "pk": 780, "fields": {"app_label": "xapi", "model": "xapilearnerdatatransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 781, "fields": {"app_label": "video_config", "model": "courseyoutubeblockedflag"}}, {"model": "contenttypes.contenttype", "pk": 782, "fields": {"app_label": "content_libraries", "model": "contentlibrary"}}, {"model": "contenttypes.contenttype", "pk": 783, "fields": {"app_label": "content_libraries", "model": "contentlibrarypermission"}}, {"model": "contenttypes.contenttype", "pk": 784, "fields": {"app_label": "course_overviews", "model": "simulatecoursepublishconfig"}}, {"model": "contenttypes.contenttype", "pk": 785, "fields": {"app_label": "student", "model": "bulkunenrollconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 786, "fields": {"app_label": "discounts", "model": "discountpercentageconfig"}}, {"model": "contenttypes.contenttype", "pk": 787, "fields": {"app_label": "student", "model": "fbeenrollmentexclusion"}}, {"model": "contenttypes.contenttype", "pk": 788, "fields": {"app_label": "student", "model": "allowedauthuser"}}, {"model": "contenttypes.contenttype", "pk": 789, "fields": {"app_label": "enterprise", "model": "enterpriseenrollmentsource"}}, {"model": "contenttypes.contenttype", "pk": 790, "fields": {"app_label": "verify_student", "model": "sspverificationretryconfig"}}, {"model": "contenttypes.contenttype", "pk": 791, "fields": {"app_label": "programs", "model": "customprogramsconfig"}}, {"model": "contenttypes.contenttype", "pk": 792, "fields": {"app_label": "assessment", "model": "historicalsharedfileupload"}}, {"model": "contenttypes.contenttype", "pk": 793, "fields": {"app_label": "assessment", "model": "sharedfileupload"}}, {"model": "contenttypes.contenttype", "pk": 794, "fields": {"app_label": "certificates", "model": "historicalgeneratedcertificate"}}, {"model": "contenttypes.contenttype", "pk": 795, "fields": {"app_label": "entitlements", "model": "historicalcourseentitlementsupportdetail"}}, {"model": "contenttypes.contenttype", "pk": 796, "fields": {"app_label": "student", "model": "historicalmanualenrollmentaudit"}}, {"model": "contenttypes.contenttype", "pk": 797, "fields": {"app_label": "external_user_ids", "model": "historicalexternalid"}}, {"model": "contenttypes.contenttype", "pk": 798, "fields": {"app_label": "external_user_ids", "model": "historicalexternalidtype"}}, {"model": "contenttypes.contenttype", "pk": 799, "fields": {"app_label": "external_user_ids", "model": "externalid"}}, {"model": "contenttypes.contenttype", "pk": 800, "fields": {"app_label": "external_user_ids", "model": "externalidtype"}}, {"model": "contenttypes.contenttype", "pk": 801, "fields": {"app_label": "course_date_signals", "model": "selfpacedrelativedatesconfig"}}, {"model": "contenttypes.contenttype", "pk": 802, "fields": {"app_label": "calendar_sync", "model": "historicalusercalendarsyncconfig"}}, {"model": "contenttypes.contenttype", "pk": 803, "fields": {"app_label": "calendar_sync", "model": "usercalendarsyncconfig"}}, {"model": "contenttypes.contenttype", "pk": 804, "fields": {"app_label": "experiments", "model": "historicalexperimentkeyvalue"}}, {"model": "contenttypes.contenttype", "pk": 805, "fields": {"app_label": "schedules", "model": "historicalschedule"}}, {"model": "contenttypes.contenttype", "pk": 806, "fields": {"app_label": "student", "model": "accountrecoveryconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 807, "fields": {"app_label": "edxval", "model": "transcriptcredentials"}}, {"model": "contenttypes.contenttype", "pk": 808, "fields": {"app_label": "assessment", "model": "teamstaffworkflow"}}, {"model": "contenttypes.contenttype", "pk": 809, "fields": {"app_label": "workflow", "model": "teamassessmentworkflow"}}, {"model": "contenttypes.contenttype", "pk": 810, "fields": {"app_label": "program_enrollments", "model": "courseaccessroleassignment"}}, {"model": "contenttypes.contenttype", "pk": 811, "fields": {"app_label": "submissions", "model": "teamsubmission"}}, {"model": "sites.site", "pk": 1, "fields": {"domain": "example.com", "name": "example.com"}}, {"model": "waffle.sample", "pk": 1, "fields": {"name": "use_enterprise_catalog", "percent": "0.0", "note": "", "created": "2020-04-10T22:07:16.651Z", "modified": "2020-04-10T22:07:16.651Z"}}, {"model": "bulk_email.courseemailtemplate", "pk": 1, "fields": {"html_template": "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html xmlns:fb='http://www.facebook.com/2008/fbml' xmlns:og='http://opengraph.org/schema/'> <head><meta property='og:title' content='Update from {course_title}'/><meta property='fb:page_id' content='43929265776' /> <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'> <title>Update from {course_title}</title> </head> <body leftmargin='0' marginwidth='0' topmargin='0' marginheight='0' offset='0' style='margin: 0;padding: 0;background-color: #ffffff;'> <center> <table align='center' border='0' cellpadding='0' cellspacing='0' height='100%' width='100%' id='bodyTable' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;margin: 0;padding: 0;background-color: #ffffff;height: 100% !important;width: 100% !important;'> <tr> <td align='center' valign='top' id='bodyCell' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;margin: 0;padding: 0;border-top: 0;height: 100% !important;width: 100% !important;'> <!-- BEGIN TEMPLATE // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN PREHEADER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templatePreheader' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='preheaderContainer' style='padding-top: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='366' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-left: 18px;padding-bottom: 9px;padding-right: 0;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 11px;line-height: 125%;text-align: left;'> <br> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END PREHEADER --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN HEADER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateHeader' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='headerContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnImageBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnImageBlockOuter'> <tr> <td valign='top' style='padding: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;' class='mcnImageBlockInner'> <table align='left' width='100%' border='0' cellpadding='0' cellspacing='0' class='mcnImageContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td class='mcnImageContent' valign='top' style='padding-right: 9px;padding-left: 9px;padding-top: 0;padding-bottom: 0;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <a href='http://edx.org' title='' class='' target='_self' style='word-wrap: break-word !important;'> <img align='left' alt='edX' src='http://courses.edx.org/static/images/bulk_email/edXHeaderImage.jpg' width='564.0000152587891' style='max-width: 600px;padding-bottom: 0;display: inline !important;vertical-align: bottom;border: 0;line-height: 100%;outline: none;text-decoration: none;height: auto !important;' class='mcnImage'> </a> </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='599' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 15px;line-height: 150%;text-align: left;'> <div style='text-align: right;'><span style='font-size:11px;'><span style='color:#00a0e3;'>Connect with edX:</span></span> <a href='http://facebook.com/edxonline' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/FacebookIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://twitter.com/edxonline' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/TwitterIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='https://plus.google.com/108235383044095082735' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/GooglePlusIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://www.meetup.com/edX-Communities/' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/MeetupIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a></div> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END HEADER --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN BODY // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateBody' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='bodyContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnCaptionBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnCaptionBlockOuter'> <tr> <td class='mcnCaptionBlockInner' valign='top' style='padding: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' class='mcnCaptionLeftContentOuter' width='100%' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnCaptionLeftContentInner' style='padding: 0 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='right' border='0' cellpadding='0' cellspacing='0' class='mcnCaptionLeftImageContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td class='mcnCaptionLeftImageContent' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <img alt='' src='{course_image_url}' width='176' style='max-width: 180px;border: 0;line-height: 100%;outline: none;text-decoration: none;vertical-align: bottom;height: auto !important;' class='mcnImage'> </td> </tr> </tbody></table> <table class='mcnCaptionLeftTextContentContainer' align='left' border='0' cellpadding='0' cellspacing='0' width='352' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> <h3 class='null' style='display: block;font-family: Helvetica;font-size: 18px;font-style: normal;font-weight: bold;line-height: 125%;letter-spacing: -.5px;margin: 0;text-align: left;color: #606060 !important;'><strong style='font-size: 22px;'>{course_title}</strong><br></h3><br> </td> </tr> </tbody></table> </td> </tr></tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> {{message_body}} </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnDividerBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnDividerBlockOuter'> <tr> <td class='mcnDividerBlockInner' style='padding: 18px 18px 3px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table class='mcnDividerContent' border='0' cellpadding='0' cellspacing='0' width='100%' style='border-top-width: 1px;border-top-style: solid;border-top-color: #666666;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <span></span> </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> <div style='text-align: right;'><a href='http://facebook.com/edxonline' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/FacebookIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://twitter.com/edxonline' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/TwitterIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='https://plus.google.com/108235383044095082735' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/GooglePlusIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://www.meetup.com/edX-Communities/' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/MeetupIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a></div> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END BODY --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN FOOTER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateFooter' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #9FCFE8;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='footerContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #f2f2f2;font-family: Helvetica;font-size: 11px;line-height: 125%;text-align: left;'> <em>Copyright \u00a9 2013 edX, All rights reserved.</em><br><br><br> <b>Our mailing address is:</b><br> edX<br> 11 Cambridge Center, Suite 101<br> Cambridge, MA, USA 02142<br><br><br>This email was automatically sent from {platform_name}. <br>You are receiving this email at address {email} because you are enrolled in <a href='{course_url}'>{course_title}</a>.<br>To stop receiving email like this, update your course email settings <a href='{email_settings_url}'>here</a>. <br> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END FOOTER --> </td> </tr> </table> <!-- // END TEMPLATE --> </td> </tr> </table> </center> </body> </body> </html>", "plain_template": "{course_title}\n\n{{message_body}}\r\n----\r\nCopyright 2013 edX, All rights reserved.\r\n----\r\nConnect with edX:\r\nFacebook (http://facebook.com/edxonline)\r\nTwitter (http://twitter.com/edxonline)\r\nGoogle+ (https://plus.google.com/108235383044095082735)\r\nMeetup (http://www.meetup.com/edX-Communities/)\r\n----\r\nThis email was automatically sent from {platform_name}.\r\nYou are receiving this email at address {email} because you are enrolled in {course_title}\r\n(URL: {course_url} ).\r\nTo stop receiving email like this, update your course email settings at {email_settings_url}.\r\n", "name": null}}, {"model": "bulk_email.courseemailtemplate", "pk": 2, "fields": {"html_template": "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html xmlns:fb='http://www.facebook.com/2008/fbml' xmlns:og='http://opengraph.org/schema/'> <head><meta property='og:title' content='Update from {course_title}'/><meta property='fb:page_id' content='43929265776' /> <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'> THIS IS A BRANDED HTML TEMPLATE <title>Update from {course_title}</title> </head> <body leftmargin='0' marginwidth='0' topmargin='0' marginheight='0' offset='0' style='margin: 0;padding: 0;background-color: #ffffff;'> <center> <table align='center' border='0' cellpadding='0' cellspacing='0' height='100%' width='100%' id='bodyTable' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;margin: 0;padding: 0;background-color: #ffffff;height: 100% !important;width: 100% !important;'> <tr> <td align='center' valign='top' id='bodyCell' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;margin: 0;padding: 0;border-top: 0;height: 100% !important;width: 100% !important;'> <!-- BEGIN TEMPLATE // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN PREHEADER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templatePreheader' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='preheaderContainer' style='padding-top: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='366' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-left: 18px;padding-bottom: 9px;padding-right: 0;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 11px;line-height: 125%;text-align: left;'> <br> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END PREHEADER --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN HEADER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateHeader' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='headerContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnImageBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnImageBlockOuter'> <tr> <td valign='top' style='padding: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;' class='mcnImageBlockInner'> <table align='left' width='100%' border='0' cellpadding='0' cellspacing='0' class='mcnImageContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td class='mcnImageContent' valign='top' style='padding-right: 9px;padding-left: 9px;padding-top: 0;padding-bottom: 0;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <a href='http://edx.org' title='' class='' target='_self' style='word-wrap: break-word !important;'> <img align='left' alt='edX' src='http://courses.edx.org/static/images/bulk_email/edXHeaderImage.jpg' width='564.0000152587891' style='max-width: 600px;padding-bottom: 0;display: inline !important;vertical-align: bottom;border: 0;line-height: 100%;outline: none;text-decoration: none;height: auto !important;' class='mcnImage'> </a> </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='599' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 15px;line-height: 150%;text-align: left;'> <div style='text-align: right;'><span style='font-size:11px;'><span style='color:#00a0e3;'>Connect with edX:</span></span> <a href='http://facebook.com/edxonline' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/FacebookIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://twitter.com/edxonline' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/TwitterIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='https://plus.google.com/108235383044095082735' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/GooglePlusIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://www.meetup.com/edX-Communities/' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/MeetupIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a></div> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END HEADER --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN BODY // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateBody' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='bodyContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnCaptionBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnCaptionBlockOuter'> <tr> <td class='mcnCaptionBlockInner' valign='top' style='padding: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' class='mcnCaptionLeftContentOuter' width='100%' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnCaptionLeftContentInner' style='padding: 0 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='right' border='0' cellpadding='0' cellspacing='0' class='mcnCaptionLeftImageContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td class='mcnCaptionLeftImageContent' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <img alt='' src='{course_image_url}' width='176' style='max-width: 180px;border: 0;line-height: 100%;outline: none;text-decoration: none;vertical-align: bottom;height: auto !important;' class='mcnImage'> </td> </tr> </tbody></table> <table class='mcnCaptionLeftTextContentContainer' align='left' border='0' cellpadding='0' cellspacing='0' width='352' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> <h3 class='null' style='display: block;font-family: Helvetica;font-size: 18px;font-style: normal;font-weight: bold;line-height: 125%;letter-spacing: -.5px;margin: 0;text-align: left;color: #606060 !important;'><strong style='font-size: 22px;'>{course_title}</strong><br></h3><br> </td> </tr> </tbody></table> </td> </tr></tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> {{message_body}} </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnDividerBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnDividerBlockOuter'> <tr> <td class='mcnDividerBlockInner' style='padding: 18px 18px 3px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table class='mcnDividerContent' border='0' cellpadding='0' cellspacing='0' width='100%' style='border-top-width: 1px;border-top-style: solid;border-top-color: #666666;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <span></span> </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> <div style='text-align: right;'><a href='http://facebook.com/edxonline' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/FacebookIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://twitter.com/edxonline' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/TwitterIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='https://plus.google.com/108235383044095082735' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/GooglePlusIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://www.meetup.com/edX-Communities/' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/MeetupIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a></div> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END BODY --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN FOOTER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateFooter' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #9FCFE8;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='footerContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #f2f2f2;font-family: Helvetica;font-size: 11px;line-height: 125%;text-align: left;'> <em>Copyright \u00a9 2013 edX, All rights reserved.</em><br><br><br> <b>Our mailing address is:</b><br> edX<br> 11 Cambridge Center, Suite 101<br> Cambridge, MA, USA 02142<br><br><br>This email was automatically sent from {platform_name}. <br>You are receiving this email at address {email} because you are enrolled in <a href='{course_url}'>{course_title}</a>.<br>To stop receiving email like this, update your course email settings <a href='{email_settings_url}'>here</a>. <br> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END FOOTER --> </td> </tr> </table> <!-- // END TEMPLATE --> </td> </tr> </table> </center> </body> </body> </html>", "plain_template": "THIS IS A BRANDED TEXT TEMPLATE. {course_title}\n\n{{message_body}}\r\n----\r\nCopyright 2013 edX, All rights reserved.\r\n----\r\nConnect with edX:\r\nFacebook (http://facebook.com/edxonline)\r\nTwitter (http://twitter.com/edxonline)\r\nGoogle+ (https://plus.google.com/108235383044095082735)\r\nMeetup (http://www.meetup.com/edX-Communities/)\r\n----\r\nThis email was automatically sent from {platform_name}.\r\nYou are receiving this email at address {email} because you are enrolled in {course_title}\r\n(URL: {course_url} ).\r\nTo stop receiving email like this, update your course email settings at {email_settings_url}.\r\n", "name": "branded.template"}}, {"model": "system_wide_roles.systemwiderole", "pk": 1, "fields": {"created": "2019-08-16T20:33:10.090Z", "modified": "2019-08-16T20:33:10.090Z", "name": "student_support_admin", "description": null}}, {"model": "embargo.country", "pk": 1, "fields": {"country": "AF"}}, {"model": "embargo.country", "pk": 2, "fields": {"country": "AX"}}, {"model": "embargo.country", "pk": 3, "fields": {"country": "AL"}}, {"model": "embargo.country", "pk": 4, "fields": {"country": "DZ"}}, {"model": "embargo.country", "pk": 5, "fields": {"country": "AS"}}, {"model": "embargo.country", "pk": 6, "fields": {"country": "AD"}}, {"model": "embargo.country", "pk": 7, "fields": {"country": "AO"}}, {"model": "embargo.country", "pk": 8, "fields": {"country": "AI"}}, {"model": "embargo.country", "pk": 9, "fields": {"country": "AQ"}}, {"model": "embargo.country", "pk": 10, "fields": {"country": "AG"}}, {"model": "embargo.country", "pk": 11, "fields": {"country": "AR"}}, {"model": "embargo.country", "pk": 12, "fields": {"country": "AM"}}, {"model": "embargo.country", "pk": 13, "fields": {"country": "AW"}}, {"model": "embargo.country", "pk": 14, "fields": {"country": "AU"}}, {"model": "embargo.country", "pk": 15, "fields": {"country": "AT"}}, {"model": "embargo.country", "pk": 16, "fields": {"country": "AZ"}}, {"model": "embargo.country", "pk": 17, "fields": {"country": "BS"}}, {"model": "embargo.country", "pk": 18, "fields": {"country": "BH"}}, {"model": "embargo.country", "pk": 19, "fields": {"country": "BD"}}, {"model": "embargo.country", "pk": 20, "fields": {"country": "BB"}}, {"model": "embargo.country", "pk": 21, "fields": {"country": "BY"}}, {"model": "embargo.country", "pk": 22, "fields": {"country": "BE"}}, {"model": "embargo.country", "pk": 23, "fields": {"country": "BZ"}}, {"model": "embargo.country", "pk": 24, "fields": {"country": "BJ"}}, {"model": "embargo.country", "pk": 25, "fields": {"country": "BM"}}, {"model": "embargo.country", "pk": 26, "fields": {"country": "BT"}}, {"model": "embargo.country", "pk": 27, "fields": {"country": "BO"}}, {"model": "embargo.country", "pk": 28, "fields": {"country": "BQ"}}, {"model": "embargo.country", "pk": 29, "fields": {"country": "BA"}}, {"model": "embargo.country", "pk": 30, "fields": {"country": "BW"}}, {"model": "embargo.country", "pk": 31, "fields": {"country": "BV"}}, {"model": "embargo.country", "pk": 32, "fields": {"country": "BR"}}, {"model": "embargo.country", "pk": 33, "fields": {"country": "IO"}}, {"model": "embargo.country", "pk": 34, "fields": {"country": "BN"}}, {"model": "embargo.country", "pk": 35, "fields": {"country": "BG"}}, {"model": "embargo.country", "pk": 36, "fields": {"country": "BF"}}, {"model": "embargo.country", "pk": 37, "fields": {"country": "BI"}}, {"model": "embargo.country", "pk": 38, "fields": {"country": "CV"}}, {"model": "embargo.country", "pk": 39, "fields": {"country": "KH"}}, {"model": "embargo.country", "pk": 40, "fields": {"country": "CM"}}, {"model": "embargo.country", "pk": 41, "fields": {"country": "CA"}}, {"model": "embargo.country", "pk": 42, "fields": {"country": "KY"}}, {"model": "embargo.country", "pk": 43, "fields": {"country": "CF"}}, {"model": "embargo.country", "pk": 44, "fields": {"country": "TD"}}, {"model": "embargo.country", "pk": 45, "fields": {"country": "CL"}}, {"model": "embargo.country", "pk": 46, "fields": {"country": "CN"}}, {"model": "embargo.country", "pk": 47, "fields": {"country": "CX"}}, {"model": "embargo.country", "pk": 48, "fields": {"country": "CC"}}, {"model": "embargo.country", "pk": 49, "fields": {"country": "CO"}}, {"model": "embargo.country", "pk": 50, "fields": {"country": "KM"}}, {"model": "embargo.country", "pk": 51, "fields": {"country": "CG"}}, {"model": "embargo.country", "pk": 52, "fields": {"country": "CD"}}, {"model": "embargo.country", "pk": 53, "fields": {"country": "CK"}}, {"model": "embargo.country", "pk": 54, "fields": {"country": "CR"}}, {"model": "embargo.country", "pk": 55, "fields": {"country": "CI"}}, {"model": "embargo.country", "pk": 56, "fields": {"country": "HR"}}, {"model": "embargo.country", "pk": 57, "fields": {"country": "CU"}}, {"model": "embargo.country", "pk": 58, "fields": {"country": "CW"}}, {"model": "embargo.country", "pk": 59, "fields": {"country": "CY"}}, {"model": "embargo.country", "pk": 60, "fields": {"country": "CZ"}}, {"model": "embargo.country", "pk": 61, "fields": {"country": "DK"}}, {"model": "embargo.country", "pk": 62, "fields": {"country": "DJ"}}, {"model": "embargo.country", "pk": 63, "fields": {"country": "DM"}}, {"model": "embargo.country", "pk": 64, "fields": {"country": "DO"}}, {"model": "embargo.country", "pk": 65, "fields": {"country": "EC"}}, {"model": "embargo.country", "pk": 66, "fields": {"country": "EG"}}, {"model": "embargo.country", "pk": 67, "fields": {"country": "SV"}}, {"model": "embargo.country", "pk": 68, "fields": {"country": "GQ"}}, {"model": "embargo.country", "pk": 69, "fields": {"country": "ER"}}, {"model": "embargo.country", "pk": 70, "fields": {"country": "EE"}}, {"model": "embargo.country", "pk": 71, "fields": {"country": "ET"}}, {"model": "embargo.country", "pk": 72, "fields": {"country": "FK"}}, {"model": "embargo.country", "pk": 73, "fields": {"country": "FO"}}, {"model": "embargo.country", "pk": 74, "fields": {"country": "FJ"}}, {"model": "embargo.country", "pk": 75, "fields": {"country": "FI"}}, {"model": "embargo.country", "pk": 76, "fields": {"country": "FR"}}, {"model": "embargo.country", "pk": 77, "fields": {"country": "GF"}}, {"model": "embargo.country", "pk": 78, "fields": {"country": "PF"}}, {"model": "embargo.country", "pk": 79, "fields": {"country": "TF"}}, {"model": "embargo.country", "pk": 80, "fields": {"country": "GA"}}, {"model": "embargo.country", "pk": 81, "fields": {"country": "GM"}}, {"model": "embargo.country", "pk": 82, "fields": {"country": "GE"}}, {"model": "embargo.country", "pk": 83, "fields": {"country": "DE"}}, {"model": "embargo.country", "pk": 84, "fields": {"country": "GH"}}, {"model": "embargo.country", "pk": 85, "fields": {"country": "GI"}}, {"model": "embargo.country", "pk": 86, "fields": {"country": "GR"}}, {"model": "embargo.country", "pk": 87, "fields": {"country": "GL"}}, {"model": "embargo.country", "pk": 88, "fields": {"country": "GD"}}, {"model": "embargo.country", "pk": 89, "fields": {"country": "GP"}}, {"model": "embargo.country", "pk": 90, "fields": {"country": "GU"}}, {"model": "embargo.country", "pk": 91, "fields": {"country": "GT"}}, {"model": "embargo.country", "pk": 92, "fields": {"country": "GG"}}, {"model": "embargo.country", "pk": 93, "fields": {"country": "GN"}}, {"model": "embargo.country", "pk": 94, "fields": {"country": "GW"}}, {"model": "embargo.country", "pk": 95, "fields": {"country": "GY"}}, {"model": "embargo.country", "pk": 96, "fields": {"country": "HT"}}, {"model": "embargo.country", "pk": 97, "fields": {"country": "HM"}}, {"model": "embargo.country", "pk": 98, "fields": {"country": "VA"}}, {"model": "embargo.country", "pk": 99, "fields": {"country": "HN"}}, {"model": "embargo.country", "pk": 100, "fields": {"country": "HK"}}, {"model": "embargo.country", "pk": 101, "fields": {"country": "HU"}}, {"model": "embargo.country", "pk": 102, "fields": {"country": "IS"}}, {"model": "embargo.country", "pk": 103, "fields": {"country": "IN"}}, {"model": "embargo.country", "pk": 104, "fields": {"country": "ID"}}, {"model": "embargo.country", "pk": 105, "fields": {"country": "IR"}}, {"model": "embargo.country", "pk": 106, "fields": {"country": "IQ"}}, {"model": "embargo.country", "pk": 107, "fields": {"country": "IE"}}, {"model": "embargo.country", "pk": 108, "fields": {"country": "IM"}}, {"model": "embargo.country", "pk": 109, "fields": {"country": "IL"}}, {"model": "embargo.country", "pk": 110, "fields": {"country": "IT"}}, {"model": "embargo.country", "pk": 111, "fields": {"country": "JM"}}, {"model": "embargo.country", "pk": 112, "fields": {"country": "JP"}}, {"model": "embargo.country", "pk": 113, "fields": {"country": "JE"}}, {"model": "embargo.country", "pk": 114, "fields": {"country": "JO"}}, {"model": "embargo.country", "pk": 115, "fields": {"country": "KZ"}}, {"model": "embargo.country", "pk": 116, "fields": {"country": "KE"}}, {"model": "embargo.country", "pk": 117, "fields": {"country": "KI"}}, {"model": "embargo.country", "pk": 118, "fields": {"country": "XK"}}, {"model": "embargo.country", "pk": 119, "fields": {"country": "KW"}}, {"model": "embargo.country", "pk": 120, "fields": {"country": "KG"}}, {"model": "embargo.country", "pk": 121, "fields": {"country": "LA"}}, {"model": "embargo.country", "pk": 122, "fields": {"country": "LV"}}, {"model": "embargo.country", "pk": 123, "fields": {"country": "LB"}}, {"model": "embargo.country", "pk": 124, "fields": {"country": "LS"}}, {"model": "embargo.country", "pk": 125, "fields": {"country": "LR"}}, {"model": "embargo.country", "pk": 126, "fields": {"country": "LY"}}, {"model": "embargo.country", "pk": 127, "fields": {"country": "LI"}}, {"model": "embargo.country", "pk": 128, "fields": {"country": "LT"}}, {"model": "embargo.country", "pk": 129, "fields": {"country": "LU"}}, {"model": "embargo.country", "pk": 130, "fields": {"country": "MO"}}, {"model": "embargo.country", "pk": 131, "fields": {"country": "MK"}}, {"model": "embargo.country", "pk": 132, "fields": {"country": "MG"}}, {"model": "embargo.country", "pk": 133, "fields": {"country": "MW"}}, {"model": "embargo.country", "pk": 134, "fields": {"country": "MY"}}, {"model": "embargo.country", "pk": 135, "fields": {"country": "MV"}}, {"model": "embargo.country", "pk": 136, "fields": {"country": "ML"}}, {"model": "embargo.country", "pk": 137, "fields": {"country": "MT"}}, {"model": "embargo.country", "pk": 138, "fields": {"country": "MH"}}, {"model": "embargo.country", "pk": 139, "fields": {"country": "MQ"}}, {"model": "embargo.country", "pk": 140, "fields": {"country": "MR"}}, {"model": "embargo.country", "pk": 141, "fields": {"country": "MU"}}, {"model": "embargo.country", "pk": 142, "fields": {"country": "YT"}}, {"model": "embargo.country", "pk": 143, "fields": {"country": "MX"}}, {"model": "embargo.country", "pk": 144, "fields": {"country": "FM"}}, {"model": "embargo.country", "pk": 145, "fields": {"country": "MD"}}, {"model": "embargo.country", "pk": 146, "fields": {"country": "MC"}}, {"model": "embargo.country", "pk": 147, "fields": {"country": "MN"}}, {"model": "embargo.country", "pk": 148, "fields": {"country": "ME"}}, {"model": "embargo.country", "pk": 149, "fields": {"country": "MS"}}, {"model": "embargo.country", "pk": 150, "fields": {"country": "MA"}}, {"model": "embargo.country", "pk": 151, "fields": {"country": "MZ"}}, {"model": "embargo.country", "pk": 152, "fields": {"country": "MM"}}, {"model": "embargo.country", "pk": 153, "fields": {"country": "NA"}}, {"model": "embargo.country", "pk": 154, "fields": {"country": "NR"}}, {"model": "embargo.country", "pk": 155, "fields": {"country": "NP"}}, {"model": "embargo.country", "pk": 156, "fields": {"country": "NL"}}, {"model": "embargo.country", "pk": 157, "fields": {"country": "NC"}}, {"model": "embargo.country", "pk": 158, "fields": {"country": "NZ"}}, {"model": "embargo.country", "pk": 159, "fields": {"country": "NI"}}, {"model": "embargo.country", "pk": 160, "fields": {"country": "NE"}}, {"model": "embargo.country", "pk": 161, "fields": {"country": "NG"}}, {"model": "embargo.country", "pk": 162, "fields": {"country": "NU"}}, {"model": "embargo.country", "pk": 163, "fields": {"country": "NF"}}, {"model": "embargo.country", "pk": 164, "fields": {"country": "KP"}}, {"model": "embargo.country", "pk": 165, "fields": {"country": "MP"}}, {"model": "embargo.country", "pk": 166, "fields": {"country": "NO"}}, {"model": "embargo.country", "pk": 167, "fields": {"country": "OM"}}, {"model": "embargo.country", "pk": 168, "fields": {"country": "PK"}}, {"model": "embargo.country", "pk": 169, "fields": {"country": "PW"}}, {"model": "embargo.country", "pk": 170, "fields": {"country": "PS"}}, {"model": "embargo.country", "pk": 171, "fields": {"country": "PA"}}, {"model": "embargo.country", "pk": 172, "fields": {"country": "PG"}}, {"model": "embargo.country", "pk": 173, "fields": {"country": "PY"}}, {"model": "embargo.country", "pk": 174, "fields": {"country": "PE"}}, {"model": "embargo.country", "pk": 175, "fields": {"country": "PH"}}, {"model": "embargo.country", "pk": 176, "fields": {"country": "PN"}}, {"model": "embargo.country", "pk": 177, "fields": {"country": "PL"}}, {"model": "embargo.country", "pk": 178, "fields": {"country": "PT"}}, {"model": "embargo.country", "pk": 179, "fields": {"country": "PR"}}, {"model": "embargo.country", "pk": 180, "fields": {"country": "QA"}}, {"model": "embargo.country", "pk": 181, "fields": {"country": "RE"}}, {"model": "embargo.country", "pk": 182, "fields": {"country": "RO"}}, {"model": "embargo.country", "pk": 183, "fields": {"country": "RU"}}, {"model": "embargo.country", "pk": 184, "fields": {"country": "RW"}}, {"model": "embargo.country", "pk": 185, "fields": {"country": "BL"}}, {"model": "embargo.country", "pk": 186, "fields": {"country": "SH"}}, {"model": "embargo.country", "pk": 187, "fields": {"country": "KN"}}, {"model": "embargo.country", "pk": 188, "fields": {"country": "LC"}}, {"model": "embargo.country", "pk": 189, "fields": {"country": "MF"}}, {"model": "embargo.country", "pk": 190, "fields": {"country": "PM"}}, {"model": "embargo.country", "pk": 191, "fields": {"country": "VC"}}, {"model": "embargo.country", "pk": 192, "fields": {"country": "WS"}}, {"model": "embargo.country", "pk": 193, "fields": {"country": "SM"}}, {"model": "embargo.country", "pk": 194, "fields": {"country": "ST"}}, {"model": "embargo.country", "pk": 195, "fields": {"country": "SA"}}, {"model": "embargo.country", "pk": 196, "fields": {"country": "SN"}}, {"model": "embargo.country", "pk": 197, "fields": {"country": "RS"}}, {"model": "embargo.country", "pk": 198, "fields": {"country": "SC"}}, {"model": "embargo.country", "pk": 199, "fields": {"country": "SL"}}, {"model": "embargo.country", "pk": 200, "fields": {"country": "SG"}}, {"model": "embargo.country", "pk": 201, "fields": {"country": "SX"}}, {"model": "embargo.country", "pk": 202, "fields": {"country": "SK"}}, {"model": "embargo.country", "pk": 203, "fields": {"country": "SI"}}, {"model": "embargo.country", "pk": 204, "fields": {"country": "SB"}}, {"model": "embargo.country", "pk": 205, "fields": {"country": "SO"}}, {"model": "embargo.country", "pk": 206, "fields": {"country": "ZA"}}, {"model": "embargo.country", "pk": 207, "fields": {"country": "GS"}}, {"model": "embargo.country", "pk": 208, "fields": {"country": "KR"}}, {"model": "embargo.country", "pk": 209, "fields": {"country": "SS"}}, {"model": "embargo.country", "pk": 210, "fields": {"country": "ES"}}, {"model": "embargo.country", "pk": 211, "fields": {"country": "LK"}}, {"model": "embargo.country", "pk": 212, "fields": {"country": "SD"}}, {"model": "embargo.country", "pk": 213, "fields": {"country": "SR"}}, {"model": "embargo.country", "pk": 214, "fields": {"country": "SJ"}}, {"model": "embargo.country", "pk": 215, "fields": {"country": "SZ"}}, {"model": "embargo.country", "pk": 216, "fields": {"country": "SE"}}, {"model": "embargo.country", "pk": 217, "fields": {"country": "CH"}}, {"model": "embargo.country", "pk": 218, "fields": {"country": "SY"}}, {"model": "embargo.country", "pk": 219, "fields": {"country": "TW"}}, {"model": "embargo.country", "pk": 220, "fields": {"country": "TJ"}}, {"model": "embargo.country", "pk": 221, "fields": {"country": "TZ"}}, {"model": "embargo.country", "pk": 222, "fields": {"country": "TH"}}, {"model": "embargo.country", "pk": 223, "fields": {"country": "TL"}}, {"model": "embargo.country", "pk": 224, "fields": {"country": "TG"}}, {"model": "embargo.country", "pk": 225, "fields": {"country": "TK"}}, {"model": "embargo.country", "pk": 226, "fields": {"country": "TO"}}, {"model": "embargo.country", "pk": 227, "fields": {"country": "TT"}}, {"model": "embargo.country", "pk": 228, "fields": {"country": "TN"}}, {"model": "embargo.country", "pk": 229, "fields": {"country": "TR"}}, {"model": "embargo.country", "pk": 230, "fields": {"country": "TM"}}, {"model": "embargo.country", "pk": 231, "fields": {"country": "TC"}}, {"model": "embargo.country", "pk": 232, "fields": {"country": "TV"}}, {"model": "embargo.country", "pk": 233, "fields": {"country": "UG"}}, {"model": "embargo.country", "pk": 234, "fields": {"country": "UA"}}, {"model": "embargo.country", "pk": 235, "fields": {"country": "AE"}}, {"model": "embargo.country", "pk": 236, "fields": {"country": "GB"}}, {"model": "embargo.country", "pk": 237, "fields": {"country": "UM"}}, {"model": "embargo.country", "pk": 238, "fields": {"country": "US"}}, {"model": "embargo.country", "pk": 239, "fields": {"country": "UY"}}, {"model": "embargo.country", "pk": 240, "fields": {"country": "UZ"}}, {"model": "embargo.country", "pk": 241, "fields": {"country": "VU"}}, {"model": "embargo.country", "pk": 242, "fields": {"country": "VE"}}, {"model": "embargo.country", "pk": 243, "fields": {"country": "VN"}}, {"model": "embargo.country", "pk": 244, "fields": {"country": "VG"}}, {"model": "embargo.country", "pk": 245, "fields": {"country": "VI"}}, {"model": "embargo.country", "pk": 246, "fields": {"country": "WF"}}, {"model": "embargo.country", "pk": 247, "fields": {"country": "EH"}}, {"model": "embargo.country", "pk": 248, "fields": {"country": "YE"}}, {"model": "embargo.country", "pk": 249, "fields": {"country": "ZM"}}, {"model": "embargo.country", "pk": 250, "fields": {"country": "ZW"}}, {"model": "edxval.profile", "pk": 1, "fields": {"profile_name": "desktop_mp4"}}, {"model": "edxval.profile", "pk": 2, "fields": {"profile_name": "desktop_webm"}}, {"model": "edxval.profile", "pk": 3, "fields": {"profile_name": "mobile_high"}}, {"model": "edxval.profile", "pk": 4, "fields": {"profile_name": "mobile_low"}}, {"model": "edxval.profile", "pk": 5, "fields": {"profile_name": "youtube"}}, {"model": "edxval.profile", "pk": 6, "fields": {"profile_name": "hls"}}, {"model": "edxval.profile", "pk": 7, "fields": {"profile_name": "audio_mp3"}}, {"model": "milestones.milestonerelationshiptype", "pk": 1, "fields": {"created": "2017-12-06T02:29:37.764Z", "modified": "2017-12-06T02:29:37.764Z", "name": "fulfills", "description": "Autogenerated milestone relationship type \"fulfills\"", "active": true}}, {"model": "milestones.milestonerelationshiptype", "pk": 2, "fields": {"created": "2017-12-06T02:29:37.767Z", "modified": "2017-12-06T02:29:37.767Z", "name": "requires", "description": "Autogenerated milestone relationship type \"requires\"", "active": true}}, {"model": "badges.coursecompleteimageconfiguration", "pk": 1, "fields": {"mode": "honor", "icon": "badges/honor_MYTwjzI.png", "default": false}}, {"model": "badges.coursecompleteimageconfiguration", "pk": 2, "fields": {"mode": "verified", "icon": "badges/verified_VzaI0PC.png", "default": false}}, {"model": "badges.coursecompleteimageconfiguration", "pk": 3, "fields": {"mode": "professional", "icon": "badges/professional_g7d5Aru.png", "default": false}}, {"model": "external_user_ids.externalidtype", "pk": 1, "fields": {"created": "2020-02-11T13:55:31.885Z", "modified": "2020-02-11T13:55:31.885Z", "name": "mb_coaching", "description": "MicroBachelors Coaching"}}, {"model": "enterprise.enterprisecustomertype", "pk": 1, "fields": {"created": "2018-12-19T16:43:27.202Z", "modified": "2018-12-19T16:43:27.202Z", "name": "Enterprise"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 1, "fields": {"created": "2019-11-15T09:41:34.937Z", "modified": "2019-11-15T09:41:34.938Z", "name": "Enterprise Enrollment URL", "slug": "enrollment_url"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 2, "fields": {"created": "2019-11-15T09:41:34.939Z", "modified": "2019-11-25T17:51:47.271Z", "name": "Enterprise User Enrollment Background Task", "slug": "enrollment_task"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 3, "fields": {"created": "2019-11-15T09:41:34.941Z", "modified": "2019-11-15T09:41:34.941Z", "name": "Manual Enterprise Enrollment", "slug": "manual"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 4, "fields": {"created": "2019-11-15T09:41:34.942Z", "modified": "2019-11-15T09:41:34.942Z", "name": "Enterprise API Enrollment", "slug": "enterprise_api"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 5, "fields": {"created": "2019-11-15T09:41:34.943Z", "modified": "2019-11-15T09:41:34.944Z", "name": "Enterprise Offer Redemption", "slug": "offer_redemption"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 6, "fields": {"created": "2019-12-03T20:57:24.395Z", "modified": "2019-12-03T20:57:24.396Z", "name": "Enterprise management command enrollment", "slug": "management_command"}}, {"model": "enterprise.systemwideenterpriserole", "pk": 1, "fields": {"created": "2019-03-08T15:47:17.791Z", "modified": "2019-03-08T15:47:17.792Z", "name": "enterprise_admin", "description": null}}, {"model": "enterprise.systemwideenterpriserole", "pk": 2, "fields": {"created": "2019-03-08T15:47:17.794Z", "modified": "2019-03-08T15:47:17.794Z", "name": "enterprise_learner", "description": null}}, {"model": "enterprise.systemwideenterpriserole", "pk": 3, "fields": {"created": "2019-03-28T19:29:40.175Z", "modified": "2019-03-28T19:29:40.175Z", "name": "enterprise_openedx_operator", "description": null}}, {"model": "enterprise.enterprisefeaturerole", "pk": 1, "fields": {"created": "2019-03-28T19:29:40.102Z", "modified": "2019-03-28T19:29:40.103Z", "name": "catalog_admin", "description": null}}, {"model": "enterprise.enterprisefeaturerole", "pk": 2, "fields": {"created": "2019-03-28T19:29:40.105Z", "modified": "2019-03-28T19:29:40.105Z", "name": "dashboard_admin", "description": null}}, {"model": "enterprise.enterprisefeaturerole", "pk": 3, "fields": {"created": "2019-03-28T19:29:40.108Z", "modified": "2019-03-28T19:29:40.108Z", "name": "enrollment_api_admin", "description": null}}, {"model": "enterprise.enterprisefeaturerole", "pk": 4, "fields": {"created": "2019-08-30T19:28:00.560Z", "modified": "2019-08-30T19:28:00.560Z", "name": "reporting_config_admin", "description": null}}, {"model": "auth.permission", "pk": 1, "fields": {"name": "Can add permission", "content_type": 2, "codename": "add_permission"}}, {"model": "auth.permission", "pk": 2, "fields": {"name": "Can change permission", "content_type": 2, "codename": "change_permission"}}, {"model": "auth.permission", "pk": 3, "fields": {"name": "Can delete permission", "content_type": 2, "codename": "delete_permission"}}, {"model": "auth.permission", "pk": 4, "fields": {"name": "Can add group", "content_type": 3, "codename": "add_group"}}, {"model": "auth.permission", "pk": 5, "fields": {"name": "Can change group", "content_type": 3, "codename": "change_group"}}, {"model": "auth.permission", "pk": 6, "fields": {"name": "Can delete group", "content_type": 3, "codename": "delete_group"}}, {"model": "auth.permission", "pk": 7, "fields": {"name": "Can add user", "content_type": 4, "codename": "add_user"}}, {"model": "auth.permission", "pk": 8, "fields": {"name": "Can change user", "content_type": 4, "codename": "change_user"}}, {"model": "auth.permission", "pk": 9, "fields": {"name": "Can delete user", "content_type": 4, "codename": "delete_user"}}, {"model": "auth.permission", "pk": 10, "fields": {"name": "Can add content type", "content_type": 5, "codename": "add_contenttype"}}, {"model": "auth.permission", "pk": 11, "fields": {"name": "Can change content type", "content_type": 5, "codename": "change_contenttype"}}, {"model": "auth.permission", "pk": 12, "fields": {"name": "Can delete content type", "content_type": 5, "codename": "delete_contenttype"}}, {"model": "auth.permission", "pk": 13, "fields": {"name": "Can add redirect", "content_type": 6, "codename": "add_redirect"}}, {"model": "auth.permission", "pk": 14, "fields": {"name": "Can change redirect", "content_type": 6, "codename": "change_redirect"}}, {"model": "auth.permission", "pk": 15, "fields": {"name": "Can delete redirect", "content_type": 6, "codename": "delete_redirect"}}, {"model": "auth.permission", "pk": 16, "fields": {"name": "Can add session", "content_type": 7, "codename": "add_session"}}, {"model": "auth.permission", "pk": 17, "fields": {"name": "Can change session", "content_type": 7, "codename": "change_session"}}, {"model": "auth.permission", "pk": 18, "fields": {"name": "Can delete session", "content_type": 7, "codename": "delete_session"}}, {"model": "auth.permission", "pk": 19, "fields": {"name": "Can add site", "content_type": 8, "codename": "add_site"}}, {"model": "auth.permission", "pk": 20, "fields": {"name": "Can change site", "content_type": 8, "codename": "change_site"}}, {"model": "auth.permission", "pk": 21, "fields": {"name": "Can delete site", "content_type": 8, "codename": "delete_site"}}, {"model": "auth.permission", "pk": 22, "fields": {"name": "Can add task state", "content_type": 9, "codename": "add_taskmeta"}}, {"model": "auth.permission", "pk": 23, "fields": {"name": "Can change task state", "content_type": 9, "codename": "change_taskmeta"}}, {"model": "auth.permission", "pk": 24, "fields": {"name": "Can delete task state", "content_type": 9, "codename": "delete_taskmeta"}}, {"model": "auth.permission", "pk": 25, "fields": {"name": "Can add saved group result", "content_type": 10, "codename": "add_tasksetmeta"}}, {"model": "auth.permission", "pk": 26, "fields": {"name": "Can change saved group result", "content_type": 10, "codename": "change_tasksetmeta"}}, {"model": "auth.permission", "pk": 27, "fields": {"name": "Can delete saved group result", "content_type": 10, "codename": "delete_tasksetmeta"}}, {"model": "auth.permission", "pk": 28, "fields": {"name": "Can add interval", "content_type": 11, "codename": "add_intervalschedule"}}, {"model": "auth.permission", "pk": 29, "fields": {"name": "Can change interval", "content_type": 11, "codename": "change_intervalschedule"}}, {"model": "auth.permission", "pk": 30, "fields": {"name": "Can delete interval", "content_type": 11, "codename": "delete_intervalschedule"}}, {"model": "auth.permission", "pk": 31, "fields": {"name": "Can add crontab", "content_type": 12, "codename": "add_crontabschedule"}}, {"model": "auth.permission", "pk": 32, "fields": {"name": "Can change crontab", "content_type": 12, "codename": "change_crontabschedule"}}, {"model": "auth.permission", "pk": 33, "fields": {"name": "Can delete crontab", "content_type": 12, "codename": "delete_crontabschedule"}}, {"model": "auth.permission", "pk": 34, "fields": {"name": "Can add periodic tasks", "content_type": 13, "codename": "add_periodictasks"}}, {"model": "auth.permission", "pk": 35, "fields": {"name": "Can change periodic tasks", "content_type": 13, "codename": "change_periodictasks"}}, {"model": "auth.permission", "pk": 36, "fields": {"name": "Can delete periodic tasks", "content_type": 13, "codename": "delete_periodictasks"}}, {"model": "auth.permission", "pk": 37, "fields": {"name": "Can add periodic task", "content_type": 14, "codename": "add_periodictask"}}, {"model": "auth.permission", "pk": 38, "fields": {"name": "Can change periodic task", "content_type": 14, "codename": "change_periodictask"}}, {"model": "auth.permission", "pk": 39, "fields": {"name": "Can delete periodic task", "content_type": 14, "codename": "delete_periodictask"}}, {"model": "auth.permission", "pk": 40, "fields": {"name": "Can add worker", "content_type": 15, "codename": "add_workerstate"}}, {"model": "auth.permission", "pk": 41, "fields": {"name": "Can change worker", "content_type": 15, "codename": "change_workerstate"}}, {"model": "auth.permission", "pk": 42, "fields": {"name": "Can delete worker", "content_type": 15, "codename": "delete_workerstate"}}, {"model": "auth.permission", "pk": 43, "fields": {"name": "Can add task", "content_type": 16, "codename": "add_taskstate"}}, {"model": "auth.permission", "pk": 44, "fields": {"name": "Can change task", "content_type": 16, "codename": "change_taskstate"}}, {"model": "auth.permission", "pk": 45, "fields": {"name": "Can delete task", "content_type": 16, "codename": "delete_taskstate"}}, {"model": "auth.permission", "pk": 46, "fields": {"name": "Can add flag", "content_type": 17, "codename": "add_flag"}}, {"model": "auth.permission", "pk": 47, "fields": {"name": "Can change flag", "content_type": 17, "codename": "change_flag"}}, {"model": "auth.permission", "pk": 48, "fields": {"name": "Can delete flag", "content_type": 17, "codename": "delete_flag"}}, {"model": "auth.permission", "pk": 49, "fields": {"name": "Can add switch", "content_type": 18, "codename": "add_switch"}}, {"model": "auth.permission", "pk": 50, "fields": {"name": "Can change switch", "content_type": 18, "codename": "change_switch"}}, {"model": "auth.permission", "pk": 51, "fields": {"name": "Can delete switch", "content_type": 18, "codename": "delete_switch"}}, {"model": "auth.permission", "pk": 52, "fields": {"name": "Can add sample", "content_type": 19, "codename": "add_sample"}}, {"model": "auth.permission", "pk": 53, "fields": {"name": "Can change sample", "content_type": 19, "codename": "change_sample"}}, {"model": "auth.permission", "pk": 54, "fields": {"name": "Can delete sample", "content_type": 19, "codename": "delete_sample"}}, {"model": "auth.permission", "pk": 55, "fields": {"name": "Can add global status message", "content_type": 20, "codename": "add_globalstatusmessage"}}, {"model": "auth.permission", "pk": 56, "fields": {"name": "Can change global status message", "content_type": 20, "codename": "change_globalstatusmessage"}}, {"model": "auth.permission", "pk": 57, "fields": {"name": "Can delete global status message", "content_type": 20, "codename": "delete_globalstatusmessage"}}, {"model": "auth.permission", "pk": 58, "fields": {"name": "Can add course message", "content_type": 21, "codename": "add_coursemessage"}}, {"model": "auth.permission", "pk": 59, "fields": {"name": "Can change course message", "content_type": 21, "codename": "change_coursemessage"}}, {"model": "auth.permission", "pk": 60, "fields": {"name": "Can delete course message", "content_type": 21, "codename": "delete_coursemessage"}}, {"model": "auth.permission", "pk": 61, "fields": {"name": "Can add asset base url config", "content_type": 22, "codename": "add_assetbaseurlconfig"}}, {"model": "auth.permission", "pk": 62, "fields": {"name": "Can change asset base url config", "content_type": 22, "codename": "change_assetbaseurlconfig"}}, {"model": "auth.permission", "pk": 63, "fields": {"name": "Can delete asset base url config", "content_type": 22, "codename": "delete_assetbaseurlconfig"}}, {"model": "auth.permission", "pk": 64, "fields": {"name": "Can add asset excluded extensions config", "content_type": 23, "codename": "add_assetexcludedextensionsconfig"}}, {"model": "auth.permission", "pk": 65, "fields": {"name": "Can change asset excluded extensions config", "content_type": 23, "codename": "change_assetexcludedextensionsconfig"}}, {"model": "auth.permission", "pk": 66, "fields": {"name": "Can delete asset excluded extensions config", "content_type": 23, "codename": "delete_assetexcludedextensionsconfig"}}, {"model": "auth.permission", "pk": 67, "fields": {"name": "Can add course asset cache ttl config", "content_type": 24, "codename": "add_courseassetcachettlconfig"}}, {"model": "auth.permission", "pk": 68, "fields": {"name": "Can change course asset cache ttl config", "content_type": 24, "codename": "change_courseassetcachettlconfig"}}, {"model": "auth.permission", "pk": 69, "fields": {"name": "Can delete course asset cache ttl config", "content_type": 24, "codename": "delete_courseassetcachettlconfig"}}, {"model": "auth.permission", "pk": 70, "fields": {"name": "Can add cdn user agents config", "content_type": 25, "codename": "add_cdnuseragentsconfig"}}, {"model": "auth.permission", "pk": 71, "fields": {"name": "Can change cdn user agents config", "content_type": 25, "codename": "change_cdnuseragentsconfig"}}, {"model": "auth.permission", "pk": 72, "fields": {"name": "Can delete cdn user agents config", "content_type": 25, "codename": "delete_cdnuseragentsconfig"}}, {"model": "auth.permission", "pk": 73, "fields": {"name": "Can add site theme", "content_type": 26, "codename": "add_sitetheme"}}, {"model": "auth.permission", "pk": 74, "fields": {"name": "Can change site theme", "content_type": 26, "codename": "change_sitetheme"}}, {"model": "auth.permission", "pk": 75, "fields": {"name": "Can delete site theme", "content_type": 26, "codename": "delete_sitetheme"}}, {"model": "auth.permission", "pk": 76, "fields": {"name": "Can add site configuration", "content_type": 27, "codename": "add_siteconfiguration"}}, {"model": "auth.permission", "pk": 77, "fields": {"name": "Can change site configuration", "content_type": 27, "codename": "change_siteconfiguration"}}, {"model": "auth.permission", "pk": 78, "fields": {"name": "Can delete site configuration", "content_type": 27, "codename": "delete_siteconfiguration"}}, {"model": "auth.permission", "pk": 79, "fields": {"name": "Can add site configuration history", "content_type": 28, "codename": "add_siteconfigurationhistory"}}, {"model": "auth.permission", "pk": 80, "fields": {"name": "Can change site configuration history", "content_type": 28, "codename": "change_siteconfigurationhistory"}}, {"model": "auth.permission", "pk": 81, "fields": {"name": "Can delete site configuration history", "content_type": 28, "codename": "delete_siteconfigurationhistory"}}, {"model": "auth.permission", "pk": 82, "fields": {"name": "Can add hls playback enabled flag", "content_type": 29, "codename": "add_hlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 83, "fields": {"name": "Can change hls playback enabled flag", "content_type": 29, "codename": "change_hlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 84, "fields": {"name": "Can delete hls playback enabled flag", "content_type": 29, "codename": "delete_hlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 85, "fields": {"name": "Can add course hls playback enabled flag", "content_type": 30, "codename": "add_coursehlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 86, "fields": {"name": "Can change course hls playback enabled flag", "content_type": 30, "codename": "change_coursehlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 87, "fields": {"name": "Can delete course hls playback enabled flag", "content_type": 30, "codename": "delete_coursehlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 88, "fields": {"name": "Can add video transcript enabled flag", "content_type": 31, "codename": "add_videotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 89, "fields": {"name": "Can change video transcript enabled flag", "content_type": 31, "codename": "change_videotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 90, "fields": {"name": "Can delete video transcript enabled flag", "content_type": 31, "codename": "delete_videotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 91, "fields": {"name": "Can add course video transcript enabled flag", "content_type": 32, "codename": "add_coursevideotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 92, "fields": {"name": "Can change course video transcript enabled flag", "content_type": 32, "codename": "change_coursevideotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 93, "fields": {"name": "Can delete course video transcript enabled flag", "content_type": 32, "codename": "delete_coursevideotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 94, "fields": {"name": "Can add video pipeline integration", "content_type": 33, "codename": "add_videopipelineintegration"}}, {"model": "auth.permission", "pk": 95, "fields": {"name": "Can change video pipeline integration", "content_type": 33, "codename": "change_videopipelineintegration"}}, {"model": "auth.permission", "pk": 96, "fields": {"name": "Can delete video pipeline integration", "content_type": 33, "codename": "delete_videopipelineintegration"}}, {"model": "auth.permission", "pk": 97, "fields": {"name": "Can add video uploads enabled by default", "content_type": 34, "codename": "add_videouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 98, "fields": {"name": "Can change video uploads enabled by default", "content_type": 34, "codename": "change_videouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 99, "fields": {"name": "Can delete video uploads enabled by default", "content_type": 34, "codename": "delete_videouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 100, "fields": {"name": "Can add course video uploads enabled by default", "content_type": 35, "codename": "add_coursevideouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 101, "fields": {"name": "Can change course video uploads enabled by default", "content_type": 35, "codename": "change_coursevideouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 102, "fields": {"name": "Can delete course video uploads enabled by default", "content_type": 35, "codename": "delete_coursevideouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 103, "fields": {"name": "Can add bookmark", "content_type": 36, "codename": "add_bookmark"}}, {"model": "auth.permission", "pk": 104, "fields": {"name": "Can change bookmark", "content_type": 36, "codename": "change_bookmark"}}, {"model": "auth.permission", "pk": 105, "fields": {"name": "Can delete bookmark", "content_type": 36, "codename": "delete_bookmark"}}, {"model": "auth.permission", "pk": 106, "fields": {"name": "Can add x block cache", "content_type": 37, "codename": "add_xblockcache"}}, {"model": "auth.permission", "pk": 107, "fields": {"name": "Can change x block cache", "content_type": 37, "codename": "change_xblockcache"}}, {"model": "auth.permission", "pk": 108, "fields": {"name": "Can delete x block cache", "content_type": 37, "codename": "delete_xblockcache"}}, {"model": "auth.permission", "pk": 109, "fields": {"name": "Can add student module", "content_type": 38, "codename": "add_studentmodule"}}, {"model": "auth.permission", "pk": 110, "fields": {"name": "Can change student module", "content_type": 38, "codename": "change_studentmodule"}}, {"model": "auth.permission", "pk": 111, "fields": {"name": "Can delete student module", "content_type": 38, "codename": "delete_studentmodule"}}, {"model": "auth.permission", "pk": 112, "fields": {"name": "Can add student module history", "content_type": 39, "codename": "add_studentmodulehistory"}}, {"model": "auth.permission", "pk": 113, "fields": {"name": "Can change student module history", "content_type": 39, "codename": "change_studentmodulehistory"}}, {"model": "auth.permission", "pk": 114, "fields": {"name": "Can delete student module history", "content_type": 39, "codename": "delete_studentmodulehistory"}}, {"model": "auth.permission", "pk": 115, "fields": {"name": "Can add x module user state summary field", "content_type": 40, "codename": "add_xmoduleuserstatesummaryfield"}}, {"model": "auth.permission", "pk": 116, "fields": {"name": "Can change x module user state summary field", "content_type": 40, "codename": "change_xmoduleuserstatesummaryfield"}}, {"model": "auth.permission", "pk": 117, "fields": {"name": "Can delete x module user state summary field", "content_type": 40, "codename": "delete_xmoduleuserstatesummaryfield"}}, {"model": "auth.permission", "pk": 118, "fields": {"name": "Can add x module student prefs field", "content_type": 41, "codename": "add_xmodulestudentprefsfield"}}, {"model": "auth.permission", "pk": 119, "fields": {"name": "Can change x module student prefs field", "content_type": 41, "codename": "change_xmodulestudentprefsfield"}}, {"model": "auth.permission", "pk": 120, "fields": {"name": "Can delete x module student prefs field", "content_type": 41, "codename": "delete_xmodulestudentprefsfield"}}, {"model": "auth.permission", "pk": 121, "fields": {"name": "Can add x module student info field", "content_type": 42, "codename": "add_xmodulestudentinfofield"}}, {"model": "auth.permission", "pk": 122, "fields": {"name": "Can change x module student info field", "content_type": 42, "codename": "change_xmodulestudentinfofield"}}, {"model": "auth.permission", "pk": 123, "fields": {"name": "Can delete x module student info field", "content_type": 42, "codename": "delete_xmodulestudentinfofield"}}, {"model": "auth.permission", "pk": 124, "fields": {"name": "Can add offline computed grade", "content_type": 43, "codename": "add_offlinecomputedgrade"}}, {"model": "auth.permission", "pk": 125, "fields": {"name": "Can change offline computed grade", "content_type": 43, "codename": "change_offlinecomputedgrade"}}, {"model": "auth.permission", "pk": 126, "fields": {"name": "Can delete offline computed grade", "content_type": 43, "codename": "delete_offlinecomputedgrade"}}, {"model": "auth.permission", "pk": 127, "fields": {"name": "Can add offline computed grade log", "content_type": 44, "codename": "add_offlinecomputedgradelog"}}, {"model": "auth.permission", "pk": 128, "fields": {"name": "Can change offline computed grade log", "content_type": 44, "codename": "change_offlinecomputedgradelog"}}, {"model": "auth.permission", "pk": 129, "fields": {"name": "Can delete offline computed grade log", "content_type": 44, "codename": "delete_offlinecomputedgradelog"}}, {"model": "auth.permission", "pk": 130, "fields": {"name": "Can add student field override", "content_type": 45, "codename": "add_studentfieldoverride"}}, {"model": "auth.permission", "pk": 131, "fields": {"name": "Can change student field override", "content_type": 45, "codename": "change_studentfieldoverride"}}, {"model": "auth.permission", "pk": 132, "fields": {"name": "Can delete student field override", "content_type": 45, "codename": "delete_studentfieldoverride"}}, {"model": "auth.permission", "pk": 133, "fields": {"name": "Can add dynamic upgrade deadline configuration", "content_type": 46, "codename": "add_dynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 134, "fields": {"name": "Can change dynamic upgrade deadline configuration", "content_type": 46, "codename": "change_dynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 135, "fields": {"name": "Can delete dynamic upgrade deadline configuration", "content_type": 46, "codename": "delete_dynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 136, "fields": {"name": "Can add course dynamic upgrade deadline configuration", "content_type": 47, "codename": "add_coursedynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 137, "fields": {"name": "Can change course dynamic upgrade deadline configuration", "content_type": 47, "codename": "change_coursedynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 138, "fields": {"name": "Can delete course dynamic upgrade deadline configuration", "content_type": 47, "codename": "delete_coursedynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 139, "fields": {"name": "Can add org dynamic upgrade deadline configuration", "content_type": 48, "codename": "add_orgdynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 140, "fields": {"name": "Can change org dynamic upgrade deadline configuration", "content_type": 48, "codename": "change_orgdynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 141, "fields": {"name": "Can delete org dynamic upgrade deadline configuration", "content_type": 48, "codename": "delete_orgdynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 142, "fields": {"name": "Can add anonymous user id", "content_type": 49, "codename": "add_anonymoususerid"}}, {"model": "auth.permission", "pk": 143, "fields": {"name": "Can change anonymous user id", "content_type": 49, "codename": "change_anonymoususerid"}}, {"model": "auth.permission", "pk": 144, "fields": {"name": "Can delete anonymous user id", "content_type": 49, "codename": "delete_anonymoususerid"}}, {"model": "auth.permission", "pk": 145, "fields": {"name": "Can add user standing", "content_type": 50, "codename": "add_userstanding"}}, {"model": "auth.permission", "pk": 146, "fields": {"name": "Can change user standing", "content_type": 50, "codename": "change_userstanding"}}, {"model": "auth.permission", "pk": 147, "fields": {"name": "Can delete user standing", "content_type": 50, "codename": "delete_userstanding"}}, {"model": "auth.permission", "pk": 148, "fields": {"name": "Can add user profile", "content_type": 51, "codename": "add_userprofile"}}, {"model": "auth.permission", "pk": 149, "fields": {"name": "Can change user profile", "content_type": 51, "codename": "change_userprofile"}}, {"model": "auth.permission", "pk": 150, "fields": {"name": "Can delete user profile", "content_type": 51, "codename": "delete_userprofile"}}, {"model": "auth.permission", "pk": 151, "fields": {"name": "Can deactivate, but NOT delete users", "content_type": 51, "codename": "can_deactivate_users"}}, {"model": "auth.permission", "pk": 152, "fields": {"name": "Can add user signup source", "content_type": 52, "codename": "add_usersignupsource"}}, {"model": "auth.permission", "pk": 153, "fields": {"name": "Can change user signup source", "content_type": 52, "codename": "change_usersignupsource"}}, {"model": "auth.permission", "pk": 154, "fields": {"name": "Can delete user signup source", "content_type": 52, "codename": "delete_usersignupsource"}}, {"model": "auth.permission", "pk": 155, "fields": {"name": "Can add user test group", "content_type": 53, "codename": "add_usertestgroup"}}, {"model": "auth.permission", "pk": 156, "fields": {"name": "Can change user test group", "content_type": 53, "codename": "change_usertestgroup"}}, {"model": "auth.permission", "pk": 157, "fields": {"name": "Can delete user test group", "content_type": 53, "codename": "delete_usertestgroup"}}, {"model": "auth.permission", "pk": 158, "fields": {"name": "Can add registration", "content_type": 54, "codename": "add_registration"}}, {"model": "auth.permission", "pk": 159, "fields": {"name": "Can change registration", "content_type": 54, "codename": "change_registration"}}, {"model": "auth.permission", "pk": 160, "fields": {"name": "Can delete registration", "content_type": 54, "codename": "delete_registration"}}, {"model": "auth.permission", "pk": 161, "fields": {"name": "Can add pending name change", "content_type": 55, "codename": "add_pendingnamechange"}}, {"model": "auth.permission", "pk": 162, "fields": {"name": "Can change pending name change", "content_type": 55, "codename": "change_pendingnamechange"}}, {"model": "auth.permission", "pk": 163, "fields": {"name": "Can delete pending name change", "content_type": 55, "codename": "delete_pendingnamechange"}}, {"model": "auth.permission", "pk": 164, "fields": {"name": "Can add pending email change", "content_type": 56, "codename": "add_pendingemailchange"}}, {"model": "auth.permission", "pk": 165, "fields": {"name": "Can change pending email change", "content_type": 56, "codename": "change_pendingemailchange"}}, {"model": "auth.permission", "pk": 166, "fields": {"name": "Can delete pending email change", "content_type": 56, "codename": "delete_pendingemailchange"}}, {"model": "auth.permission", "pk": 167, "fields": {"name": "Can add password history", "content_type": 57, "codename": "add_passwordhistory"}}, {"model": "auth.permission", "pk": 168, "fields": {"name": "Can change password history", "content_type": 57, "codename": "change_passwordhistory"}}, {"model": "auth.permission", "pk": 169, "fields": {"name": "Can delete password history", "content_type": 57, "codename": "delete_passwordhistory"}}, {"model": "auth.permission", "pk": 170, "fields": {"name": "Can add login failures", "content_type": 58, "codename": "add_loginfailures"}}, {"model": "auth.permission", "pk": 171, "fields": {"name": "Can change login failures", "content_type": 58, "codename": "change_loginfailures"}}, {"model": "auth.permission", "pk": 172, "fields": {"name": "Can delete login failures", "content_type": 58, "codename": "delete_loginfailures"}}, {"model": "auth.permission", "pk": 173, "fields": {"name": "Can add course enrollment", "content_type": 59, "codename": "add_courseenrollment"}}, {"model": "auth.permission", "pk": 174, "fields": {"name": "Can change course enrollment", "content_type": 59, "codename": "change_courseenrollment"}}, {"model": "auth.permission", "pk": 175, "fields": {"name": "Can delete course enrollment", "content_type": 59, "codename": "delete_courseenrollment"}}, {"model": "auth.permission", "pk": 176, "fields": {"name": "Can add manual enrollment audit", "content_type": 60, "codename": "add_manualenrollmentaudit"}}, {"model": "auth.permission", "pk": 177, "fields": {"name": "Can change manual enrollment audit", "content_type": 60, "codename": "change_manualenrollmentaudit"}}, {"model": "auth.permission", "pk": 178, "fields": {"name": "Can delete manual enrollment audit", "content_type": 60, "codename": "delete_manualenrollmentaudit"}}, {"model": "auth.permission", "pk": 179, "fields": {"name": "Can add course enrollment allowed", "content_type": 61, "codename": "add_courseenrollmentallowed"}}, {"model": "auth.permission", "pk": 180, "fields": {"name": "Can change course enrollment allowed", "content_type": 61, "codename": "change_courseenrollmentallowed"}}, {"model": "auth.permission", "pk": 181, "fields": {"name": "Can delete course enrollment allowed", "content_type": 61, "codename": "delete_courseenrollmentallowed"}}, {"model": "auth.permission", "pk": 182, "fields": {"name": "Can add course access role", "content_type": 62, "codename": "add_courseaccessrole"}}, {"model": "auth.permission", "pk": 183, "fields": {"name": "Can change course access role", "content_type": 62, "codename": "change_courseaccessrole"}}, {"model": "auth.permission", "pk": 184, "fields": {"name": "Can delete course access role", "content_type": 62, "codename": "delete_courseaccessrole"}}, {"model": "auth.permission", "pk": 185, "fields": {"name": "Can add dashboard configuration", "content_type": 63, "codename": "add_dashboardconfiguration"}}, {"model": "auth.permission", "pk": 186, "fields": {"name": "Can change dashboard configuration", "content_type": 63, "codename": "change_dashboardconfiguration"}}, {"model": "auth.permission", "pk": 187, "fields": {"name": "Can delete dashboard configuration", "content_type": 63, "codename": "delete_dashboardconfiguration"}}, {"model": "auth.permission", "pk": 188, "fields": {"name": "Can add linked in add to profile configuration", "content_type": 64, "codename": "add_linkedinaddtoprofileconfiguration"}}, {"model": "auth.permission", "pk": 189, "fields": {"name": "Can change linked in add to profile configuration", "content_type": 64, "codename": "change_linkedinaddtoprofileconfiguration"}}, {"model": "auth.permission", "pk": 190, "fields": {"name": "Can delete linked in add to profile configuration", "content_type": 64, "codename": "delete_linkedinaddtoprofileconfiguration"}}, {"model": "auth.permission", "pk": 191, "fields": {"name": "Can add entrance exam configuration", "content_type": 65, "codename": "add_entranceexamconfiguration"}}, {"model": "auth.permission", "pk": 192, "fields": {"name": "Can change entrance exam configuration", "content_type": 65, "codename": "change_entranceexamconfiguration"}}, {"model": "auth.permission", "pk": 193, "fields": {"name": "Can delete entrance exam configuration", "content_type": 65, "codename": "delete_entranceexamconfiguration"}}, {"model": "auth.permission", "pk": 194, "fields": {"name": "Can add language proficiency", "content_type": 66, "codename": "add_languageproficiency"}}, {"model": "auth.permission", "pk": 195, "fields": {"name": "Can change language proficiency", "content_type": 66, "codename": "change_languageproficiency"}}, {"model": "auth.permission", "pk": 196, "fields": {"name": "Can delete language proficiency", "content_type": 66, "codename": "delete_languageproficiency"}}, {"model": "auth.permission", "pk": 197, "fields": {"name": "Can add social link", "content_type": 67, "codename": "add_sociallink"}}, {"model": "auth.permission", "pk": 198, "fields": {"name": "Can change social link", "content_type": 67, "codename": "change_sociallink"}}, {"model": "auth.permission", "pk": 199, "fields": {"name": "Can delete social link", "content_type": 67, "codename": "delete_sociallink"}}, {"model": "auth.permission", "pk": 200, "fields": {"name": "Can add course enrollment attribute", "content_type": 68, "codename": "add_courseenrollmentattribute"}}, {"model": "auth.permission", "pk": 201, "fields": {"name": "Can change course enrollment attribute", "content_type": 68, "codename": "change_courseenrollmentattribute"}}, {"model": "auth.permission", "pk": 202, "fields": {"name": "Can delete course enrollment attribute", "content_type": 68, "codename": "delete_courseenrollmentattribute"}}, {"model": "auth.permission", "pk": 203, "fields": {"name": "Can add enrollment refund configuration", "content_type": 69, "codename": "add_enrollmentrefundconfiguration"}}, {"model": "auth.permission", "pk": 204, "fields": {"name": "Can change enrollment refund configuration", "content_type": 69, "codename": "change_enrollmentrefundconfiguration"}}, {"model": "auth.permission", "pk": 205, "fields": {"name": "Can delete enrollment refund configuration", "content_type": 69, "codename": "delete_enrollmentrefundconfiguration"}}, {"model": "auth.permission", "pk": 206, "fields": {"name": "Can add registration cookie configuration", "content_type": 70, "codename": "add_registrationcookieconfiguration"}}, {"model": "auth.permission", "pk": 207, "fields": {"name": "Can change registration cookie configuration", "content_type": 70, "codename": "change_registrationcookieconfiguration"}}, {"model": "auth.permission", "pk": 208, "fields": {"name": "Can delete registration cookie configuration", "content_type": 70, "codename": "delete_registrationcookieconfiguration"}}, {"model": "auth.permission", "pk": 209, "fields": {"name": "Can add user attribute", "content_type": 71, "codename": "add_userattribute"}}, {"model": "auth.permission", "pk": 210, "fields": {"name": "Can change user attribute", "content_type": 71, "codename": "change_userattribute"}}, {"model": "auth.permission", "pk": 211, "fields": {"name": "Can delete user attribute", "content_type": 71, "codename": "delete_userattribute"}}, {"model": "auth.permission", "pk": 212, "fields": {"name": "Can add logout view configuration", "content_type": 72, "codename": "add_logoutviewconfiguration"}}, {"model": "auth.permission", "pk": 213, "fields": {"name": "Can change logout view configuration", "content_type": 72, "codename": "change_logoutviewconfiguration"}}, {"model": "auth.permission", "pk": 214, "fields": {"name": "Can delete logout view configuration", "content_type": 72, "codename": "delete_logoutviewconfiguration"}}, {"model": "auth.permission", "pk": 215, "fields": {"name": "Can add tracking log", "content_type": 73, "codename": "add_trackinglog"}}, {"model": "auth.permission", "pk": 216, "fields": {"name": "Can change tracking log", "content_type": 73, "codename": "change_trackinglog"}}, {"model": "auth.permission", "pk": 217, "fields": {"name": "Can delete tracking log", "content_type": 73, "codename": "delete_trackinglog"}}, {"model": "auth.permission", "pk": 218, "fields": {"name": "Can add rate limit configuration", "content_type": 74, "codename": "add_ratelimitconfiguration"}}, {"model": "auth.permission", "pk": 219, "fields": {"name": "Can change rate limit configuration", "content_type": 74, "codename": "change_ratelimitconfiguration"}}, {"model": "auth.permission", "pk": 220, "fields": {"name": "Can delete rate limit configuration", "content_type": 74, "codename": "delete_ratelimitconfiguration"}}, {"model": "auth.permission", "pk": 221, "fields": {"name": "Can add certificate whitelist", "content_type": 75, "codename": "add_certificatewhitelist"}}, {"model": "auth.permission", "pk": 222, "fields": {"name": "Can change certificate whitelist", "content_type": 75, "codename": "change_certificatewhitelist"}}, {"model": "auth.permission", "pk": 223, "fields": {"name": "Can delete certificate whitelist", "content_type": 75, "codename": "delete_certificatewhitelist"}}, {"model": "auth.permission", "pk": 224, "fields": {"name": "Can add generated certificate", "content_type": 76, "codename": "add_generatedcertificate"}}, {"model": "auth.permission", "pk": 225, "fields": {"name": "Can change generated certificate", "content_type": 76, "codename": "change_generatedcertificate"}}, {"model": "auth.permission", "pk": 226, "fields": {"name": "Can delete generated certificate", "content_type": 76, "codename": "delete_generatedcertificate"}}, {"model": "auth.permission", "pk": 227, "fields": {"name": "Can add certificate generation history", "content_type": 77, "codename": "add_certificategenerationhistory"}}, {"model": "auth.permission", "pk": 228, "fields": {"name": "Can change certificate generation history", "content_type": 77, "codename": "change_certificategenerationhistory"}}, {"model": "auth.permission", "pk": 229, "fields": {"name": "Can delete certificate generation history", "content_type": 77, "codename": "delete_certificategenerationhistory"}}, {"model": "auth.permission", "pk": 230, "fields": {"name": "Can add certificate invalidation", "content_type": 78, "codename": "add_certificateinvalidation"}}, {"model": "auth.permission", "pk": 231, "fields": {"name": "Can change certificate invalidation", "content_type": 78, "codename": "change_certificateinvalidation"}}, {"model": "auth.permission", "pk": 232, "fields": {"name": "Can delete certificate invalidation", "content_type": 78, "codename": "delete_certificateinvalidation"}}, {"model": "auth.permission", "pk": 233, "fields": {"name": "Can add example certificate set", "content_type": 79, "codename": "add_examplecertificateset"}}, {"model": "auth.permission", "pk": 234, "fields": {"name": "Can change example certificate set", "content_type": 79, "codename": "change_examplecertificateset"}}, {"model": "auth.permission", "pk": 235, "fields": {"name": "Can delete example certificate set", "content_type": 79, "codename": "delete_examplecertificateset"}}, {"model": "auth.permission", "pk": 236, "fields": {"name": "Can add example certificate", "content_type": 80, "codename": "add_examplecertificate"}}, {"model": "auth.permission", "pk": 237, "fields": {"name": "Can change example certificate", "content_type": 80, "codename": "change_examplecertificate"}}, {"model": "auth.permission", "pk": 238, "fields": {"name": "Can delete example certificate", "content_type": 80, "codename": "delete_examplecertificate"}}, {"model": "auth.permission", "pk": 239, "fields": {"name": "Can add certificate generation course setting", "content_type": 81, "codename": "add_certificategenerationcoursesetting"}}, {"model": "auth.permission", "pk": 240, "fields": {"name": "Can change certificate generation course setting", "content_type": 81, "codename": "change_certificategenerationcoursesetting"}}, {"model": "auth.permission", "pk": 241, "fields": {"name": "Can delete certificate generation course setting", "content_type": 81, "codename": "delete_certificategenerationcoursesetting"}}, {"model": "auth.permission", "pk": 242, "fields": {"name": "Can add certificate generation configuration", "content_type": 82, "codename": "add_certificategenerationconfiguration"}}, {"model": "auth.permission", "pk": 243, "fields": {"name": "Can change certificate generation configuration", "content_type": 82, "codename": "change_certificategenerationconfiguration"}}, {"model": "auth.permission", "pk": 244, "fields": {"name": "Can delete certificate generation configuration", "content_type": 82, "codename": "delete_certificategenerationconfiguration"}}, {"model": "auth.permission", "pk": 245, "fields": {"name": "Can add certificate html view configuration", "content_type": 83, "codename": "add_certificatehtmlviewconfiguration"}}, {"model": "auth.permission", "pk": 246, "fields": {"name": "Can change certificate html view configuration", "content_type": 83, "codename": "change_certificatehtmlviewconfiguration"}}, {"model": "auth.permission", "pk": 247, "fields": {"name": "Can delete certificate html view configuration", "content_type": 83, "codename": "delete_certificatehtmlviewconfiguration"}}, {"model": "auth.permission", "pk": 248, "fields": {"name": "Can add certificate template", "content_type": 84, "codename": "add_certificatetemplate"}}, {"model": "auth.permission", "pk": 249, "fields": {"name": "Can change certificate template", "content_type": 84, "codename": "change_certificatetemplate"}}, {"model": "auth.permission", "pk": 250, "fields": {"name": "Can delete certificate template", "content_type": 84, "codename": "delete_certificatetemplate"}}, {"model": "auth.permission", "pk": 251, "fields": {"name": "Can add certificate template asset", "content_type": 85, "codename": "add_certificatetemplateasset"}}, {"model": "auth.permission", "pk": 252, "fields": {"name": "Can change certificate template asset", "content_type": 85, "codename": "change_certificatetemplateasset"}}, {"model": "auth.permission", "pk": 253, "fields": {"name": "Can delete certificate template asset", "content_type": 85, "codename": "delete_certificatetemplateasset"}}, {"model": "auth.permission", "pk": 254, "fields": {"name": "Can add instructor task", "content_type": 86, "codename": "add_instructortask"}}, {"model": "auth.permission", "pk": 255, "fields": {"name": "Can change instructor task", "content_type": 86, "codename": "change_instructortask"}}, {"model": "auth.permission", "pk": 256, "fields": {"name": "Can delete instructor task", "content_type": 86, "codename": "delete_instructortask"}}, {"model": "auth.permission", "pk": 257, "fields": {"name": "Can add grade report setting", "content_type": 87, "codename": "add_gradereportsetting"}}, {"model": "auth.permission", "pk": 258, "fields": {"name": "Can change grade report setting", "content_type": 87, "codename": "change_gradereportsetting"}}, {"model": "auth.permission", "pk": 259, "fields": {"name": "Can delete grade report setting", "content_type": 87, "codename": "delete_gradereportsetting"}}, {"model": "auth.permission", "pk": 260, "fields": {"name": "Can add course user group", "content_type": 88, "codename": "add_courseusergroup"}}, {"model": "auth.permission", "pk": 261, "fields": {"name": "Can change course user group", "content_type": 88, "codename": "change_courseusergroup"}}, {"model": "auth.permission", "pk": 262, "fields": {"name": "Can delete course user group", "content_type": 88, "codename": "delete_courseusergroup"}}, {"model": "auth.permission", "pk": 263, "fields": {"name": "Can add cohort membership", "content_type": 89, "codename": "add_cohortmembership"}}, {"model": "auth.permission", "pk": 264, "fields": {"name": "Can change cohort membership", "content_type": 89, "codename": "change_cohortmembership"}}, {"model": "auth.permission", "pk": 265, "fields": {"name": "Can delete cohort membership", "content_type": 89, "codename": "delete_cohortmembership"}}, {"model": "auth.permission", "pk": 266, "fields": {"name": "Can add course user group partition group", "content_type": 90, "codename": "add_courseusergrouppartitiongroup"}}, {"model": "auth.permission", "pk": 267, "fields": {"name": "Can change course user group partition group", "content_type": 90, "codename": "change_courseusergrouppartitiongroup"}}, {"model": "auth.permission", "pk": 268, "fields": {"name": "Can delete course user group partition group", "content_type": 90, "codename": "delete_courseusergrouppartitiongroup"}}, {"model": "auth.permission", "pk": 269, "fields": {"name": "Can add course cohorts settings", "content_type": 91, "codename": "add_coursecohortssettings"}}, {"model": "auth.permission", "pk": 270, "fields": {"name": "Can change course cohorts settings", "content_type": 91, "codename": "change_coursecohortssettings"}}, {"model": "auth.permission", "pk": 271, "fields": {"name": "Can delete course cohorts settings", "content_type": 91, "codename": "delete_coursecohortssettings"}}, {"model": "auth.permission", "pk": 272, "fields": {"name": "Can add course cohort", "content_type": 92, "codename": "add_coursecohort"}}, {"model": "auth.permission", "pk": 273, "fields": {"name": "Can change course cohort", "content_type": 92, "codename": "change_coursecohort"}}, {"model": "auth.permission", "pk": 274, "fields": {"name": "Can delete course cohort", "content_type": 92, "codename": "delete_coursecohort"}}, {"model": "auth.permission", "pk": 275, "fields": {"name": "Can add unregistered learner cohort assignments", "content_type": 93, "codename": "add_unregisteredlearnercohortassignments"}}, {"model": "auth.permission", "pk": 276, "fields": {"name": "Can change unregistered learner cohort assignments", "content_type": 93, "codename": "change_unregisteredlearnercohortassignments"}}, {"model": "auth.permission", "pk": 277, "fields": {"name": "Can delete unregistered learner cohort assignments", "content_type": 93, "codename": "delete_unregisteredlearnercohortassignments"}}, {"model": "auth.permission", "pk": 278, "fields": {"name": "Can add target", "content_type": 94, "codename": "add_target"}}, {"model": "auth.permission", "pk": 279, "fields": {"name": "Can change target", "content_type": 94, "codename": "change_target"}}, {"model": "auth.permission", "pk": 280, "fields": {"name": "Can delete target", "content_type": 94, "codename": "delete_target"}}, {"model": "auth.permission", "pk": 281, "fields": {"name": "Can add cohort target", "content_type": 95, "codename": "add_cohorttarget"}}, {"model": "auth.permission", "pk": 282, "fields": {"name": "Can change cohort target", "content_type": 95, "codename": "change_cohorttarget"}}, {"model": "auth.permission", "pk": 283, "fields": {"name": "Can delete cohort target", "content_type": 95, "codename": "delete_cohorttarget"}}, {"model": "auth.permission", "pk": 284, "fields": {"name": "Can add course mode target", "content_type": 96, "codename": "add_coursemodetarget"}}, {"model": "auth.permission", "pk": 285, "fields": {"name": "Can change course mode target", "content_type": 96, "codename": "change_coursemodetarget"}}, {"model": "auth.permission", "pk": 286, "fields": {"name": "Can delete course mode target", "content_type": 96, "codename": "delete_coursemodetarget"}}, {"model": "auth.permission", "pk": 287, "fields": {"name": "Can add course email", "content_type": 97, "codename": "add_courseemail"}}, {"model": "auth.permission", "pk": 288, "fields": {"name": "Can change course email", "content_type": 97, "codename": "change_courseemail"}}, {"model": "auth.permission", "pk": 289, "fields": {"name": "Can delete course email", "content_type": 97, "codename": "delete_courseemail"}}, {"model": "auth.permission", "pk": 290, "fields": {"name": "Can add optout", "content_type": 98, "codename": "add_optout"}}, {"model": "auth.permission", "pk": 291, "fields": {"name": "Can change optout", "content_type": 98, "codename": "change_optout"}}, {"model": "auth.permission", "pk": 292, "fields": {"name": "Can delete optout", "content_type": 98, "codename": "delete_optout"}}, {"model": "auth.permission", "pk": 293, "fields": {"name": "Can add course email template", "content_type": 99, "codename": "add_courseemailtemplate"}}, {"model": "auth.permission", "pk": 294, "fields": {"name": "Can change course email template", "content_type": 99, "codename": "change_courseemailtemplate"}}, {"model": "auth.permission", "pk": 295, "fields": {"name": "Can delete course email template", "content_type": 99, "codename": "delete_courseemailtemplate"}}, {"model": "auth.permission", "pk": 296, "fields": {"name": "Can add course authorization", "content_type": 100, "codename": "add_courseauthorization"}}, {"model": "auth.permission", "pk": 297, "fields": {"name": "Can change course authorization", "content_type": 100, "codename": "change_courseauthorization"}}, {"model": "auth.permission", "pk": 298, "fields": {"name": "Can delete course authorization", "content_type": 100, "codename": "delete_courseauthorization"}}, {"model": "auth.permission", "pk": 299, "fields": {"name": "Can add bulk email flag", "content_type": 101, "codename": "add_bulkemailflag"}}, {"model": "auth.permission", "pk": 300, "fields": {"name": "Can change bulk email flag", "content_type": 101, "codename": "change_bulkemailflag"}}, {"model": "auth.permission", "pk": 301, "fields": {"name": "Can delete bulk email flag", "content_type": 101, "codename": "delete_bulkemailflag"}}, {"model": "auth.permission", "pk": 302, "fields": {"name": "Can add branding info config", "content_type": 102, "codename": "add_brandinginfoconfig"}}, {"model": "auth.permission", "pk": 303, "fields": {"name": "Can change branding info config", "content_type": 102, "codename": "change_brandinginfoconfig"}}, {"model": "auth.permission", "pk": 304, "fields": {"name": "Can delete branding info config", "content_type": 102, "codename": "delete_brandinginfoconfig"}}, {"model": "auth.permission", "pk": 305, "fields": {"name": "Can add branding api config", "content_type": 103, "codename": "add_brandingapiconfig"}}, {"model": "auth.permission", "pk": 306, "fields": {"name": "Can change branding api config", "content_type": 103, "codename": "change_brandingapiconfig"}}, {"model": "auth.permission", "pk": 307, "fields": {"name": "Can delete branding api config", "content_type": 103, "codename": "delete_brandingapiconfig"}}, {"model": "auth.permission", "pk": 308, "fields": {"name": "Can add visible blocks", "content_type": 104, "codename": "add_visibleblocks"}}, {"model": "auth.permission", "pk": 309, "fields": {"name": "Can change visible blocks", "content_type": 104, "codename": "change_visibleblocks"}}, {"model": "auth.permission", "pk": 310, "fields": {"name": "Can delete visible blocks", "content_type": 104, "codename": "delete_visibleblocks"}}, {"model": "auth.permission", "pk": 311, "fields": {"name": "Can add persistent subsection grade", "content_type": 105, "codename": "add_persistentsubsectiongrade"}}, {"model": "auth.permission", "pk": 312, "fields": {"name": "Can change persistent subsection grade", "content_type": 105, "codename": "change_persistentsubsectiongrade"}}, {"model": "auth.permission", "pk": 313, "fields": {"name": "Can delete persistent subsection grade", "content_type": 105, "codename": "delete_persistentsubsectiongrade"}}, {"model": "auth.permission", "pk": 314, "fields": {"name": "Can add persistent course grade", "content_type": 106, "codename": "add_persistentcoursegrade"}}, {"model": "auth.permission", "pk": 315, "fields": {"name": "Can change persistent course grade", "content_type": 106, "codename": "change_persistentcoursegrade"}}, {"model": "auth.permission", "pk": 316, "fields": {"name": "Can delete persistent course grade", "content_type": 106, "codename": "delete_persistentcoursegrade"}}, {"model": "auth.permission", "pk": 317, "fields": {"name": "Can add persistent subsection grade override", "content_type": 107, "codename": "add_persistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 318, "fields": {"name": "Can change persistent subsection grade override", "content_type": 107, "codename": "change_persistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 319, "fields": {"name": "Can delete persistent subsection grade override", "content_type": 107, "codename": "delete_persistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 320, "fields": {"name": "Can add persistent grades enabled flag", "content_type": 108, "codename": "add_persistentgradesenabledflag"}}, {"model": "auth.permission", "pk": 321, "fields": {"name": "Can change persistent grades enabled flag", "content_type": 108, "codename": "change_persistentgradesenabledflag"}}, {"model": "auth.permission", "pk": 322, "fields": {"name": "Can delete persistent grades enabled flag", "content_type": 108, "codename": "delete_persistentgradesenabledflag"}}, {"model": "auth.permission", "pk": 323, "fields": {"name": "Can add course persistent grades flag", "content_type": 109, "codename": "add_coursepersistentgradesflag"}}, {"model": "auth.permission", "pk": 324, "fields": {"name": "Can change course persistent grades flag", "content_type": 109, "codename": "change_coursepersistentgradesflag"}}, {"model": "auth.permission", "pk": 325, "fields": {"name": "Can delete course persistent grades flag", "content_type": 109, "codename": "delete_coursepersistentgradesflag"}}, {"model": "auth.permission", "pk": 326, "fields": {"name": "Can add compute grades setting", "content_type": 110, "codename": "add_computegradessetting"}}, {"model": "auth.permission", "pk": 327, "fields": {"name": "Can change compute grades setting", "content_type": 110, "codename": "change_computegradessetting"}}, {"model": "auth.permission", "pk": 328, "fields": {"name": "Can delete compute grades setting", "content_type": 110, "codename": "delete_computegradessetting"}}, {"model": "auth.permission", "pk": 329, "fields": {"name": "Can add external auth map", "content_type": 111, "codename": "add_externalauthmap"}}, {"model": "auth.permission", "pk": 330, "fields": {"name": "Can change external auth map", "content_type": 111, "codename": "change_externalauthmap"}}, {"model": "auth.permission", "pk": 331, "fields": {"name": "Can delete external auth map", "content_type": 111, "codename": "delete_externalauthmap"}}, {"model": "auth.permission", "pk": 332, "fields": {"name": "Can add nonce", "content_type": 112, "codename": "add_nonce"}}, {"model": "auth.permission", "pk": 333, "fields": {"name": "Can change nonce", "content_type": 112, "codename": "change_nonce"}}, {"model": "auth.permission", "pk": 334, "fields": {"name": "Can delete nonce", "content_type": 112, "codename": "delete_nonce"}}, {"model": "auth.permission", "pk": 335, "fields": {"name": "Can add association", "content_type": 113, "codename": "add_association"}}, {"model": "auth.permission", "pk": 336, "fields": {"name": "Can change association", "content_type": 113, "codename": "change_association"}}, {"model": "auth.permission", "pk": 337, "fields": {"name": "Can delete association", "content_type": 113, "codename": "delete_association"}}, {"model": "auth.permission", "pk": 338, "fields": {"name": "Can add user open id", "content_type": 114, "codename": "add_useropenid"}}, {"model": "auth.permission", "pk": 339, "fields": {"name": "Can change user open id", "content_type": 114, "codename": "change_useropenid"}}, {"model": "auth.permission", "pk": 340, "fields": {"name": "Can delete user open id", "content_type": 114, "codename": "delete_useropenid"}}, {"model": "auth.permission", "pk": 341, "fields": {"name": "The OpenID has been verified", "content_type": 114, "codename": "account_verified"}}, {"model": "auth.permission", "pk": 342, "fields": {"name": "Can add client", "content_type": 115, "codename": "add_client"}}, {"model": "auth.permission", "pk": 343, "fields": {"name": "Can change client", "content_type": 115, "codename": "change_client"}}, {"model": "auth.permission", "pk": 344, "fields": {"name": "Can delete client", "content_type": 115, "codename": "delete_client"}}, {"model": "auth.permission", "pk": 345, "fields": {"name": "Can add grant", "content_type": 116, "codename": "add_grant"}}, {"model": "auth.permission", "pk": 346, "fields": {"name": "Can change grant", "content_type": 116, "codename": "change_grant"}}, {"model": "auth.permission", "pk": 347, "fields": {"name": "Can delete grant", "content_type": 116, "codename": "delete_grant"}}, {"model": "auth.permission", "pk": 348, "fields": {"name": "Can add access token", "content_type": 117, "codename": "add_accesstoken"}}, {"model": "auth.permission", "pk": 349, "fields": {"name": "Can change access token", "content_type": 117, "codename": "change_accesstoken"}}, {"model": "auth.permission", "pk": 350, "fields": {"name": "Can delete access token", "content_type": 117, "codename": "delete_accesstoken"}}, {"model": "auth.permission", "pk": 351, "fields": {"name": "Can add refresh token", "content_type": 118, "codename": "add_refreshtoken"}}, {"model": "auth.permission", "pk": 352, "fields": {"name": "Can change refresh token", "content_type": 118, "codename": "change_refreshtoken"}}, {"model": "auth.permission", "pk": 353, "fields": {"name": "Can delete refresh token", "content_type": 118, "codename": "delete_refreshtoken"}}, {"model": "auth.permission", "pk": 354, "fields": {"name": "Can add trusted client", "content_type": 119, "codename": "add_trustedclient"}}, {"model": "auth.permission", "pk": 355, "fields": {"name": "Can change trusted client", "content_type": 119, "codename": "change_trustedclient"}}, {"model": "auth.permission", "pk": 356, "fields": {"name": "Can delete trusted client", "content_type": 119, "codename": "delete_trustedclient"}}, {"model": "auth.permission", "pk": 357, "fields": {"name": "Can add application", "content_type": 120, "codename": "add_application"}}, {"model": "auth.permission", "pk": 358, "fields": {"name": "Can change application", "content_type": 120, "codename": "change_application"}}, {"model": "auth.permission", "pk": 359, "fields": {"name": "Can delete application", "content_type": 120, "codename": "delete_application"}}, {"model": "auth.permission", "pk": 360, "fields": {"name": "Can add grant", "content_type": 121, "codename": "add_grant"}}, {"model": "auth.permission", "pk": 361, "fields": {"name": "Can change grant", "content_type": 121, "codename": "change_grant"}}, {"model": "auth.permission", "pk": 362, "fields": {"name": "Can delete grant", "content_type": 121, "codename": "delete_grant"}}, {"model": "auth.permission", "pk": 363, "fields": {"name": "Can add access token", "content_type": 122, "codename": "add_accesstoken"}}, {"model": "auth.permission", "pk": 364, "fields": {"name": "Can change access token", "content_type": 122, "codename": "change_accesstoken"}}, {"model": "auth.permission", "pk": 365, "fields": {"name": "Can delete access token", "content_type": 122, "codename": "delete_accesstoken"}}, {"model": "auth.permission", "pk": 366, "fields": {"name": "Can add refresh token", "content_type": 123, "codename": "add_refreshtoken"}}, {"model": "auth.permission", "pk": 367, "fields": {"name": "Can change refresh token", "content_type": 123, "codename": "change_refreshtoken"}}, {"model": "auth.permission", "pk": 368, "fields": {"name": "Can delete refresh token", "content_type": 123, "codename": "delete_refreshtoken"}}, {"model": "auth.permission", "pk": 369, "fields": {"name": "Can add restricted application", "content_type": 124, "codename": "add_restrictedapplication"}}, {"model": "auth.permission", "pk": 370, "fields": {"name": "Can change restricted application", "content_type": 124, "codename": "change_restrictedapplication"}}, {"model": "auth.permission", "pk": 371, "fields": {"name": "Can delete restricted application", "content_type": 124, "codename": "delete_restrictedapplication"}}, {"model": "auth.permission", "pk": 372, "fields": {"name": "Can add Provider Configuration (OAuth)", "content_type": 125, "codename": "add_oauth2providerconfig"}}, {"model": "auth.permission", "pk": 373, "fields": {"name": "Can change Provider Configuration (OAuth)", "content_type": 125, "codename": "change_oauth2providerconfig"}}, {"model": "auth.permission", "pk": 374, "fields": {"name": "Can delete Provider Configuration (OAuth)", "content_type": 125, "codename": "delete_oauth2providerconfig"}}, {"model": "auth.permission", "pk": 375, "fields": {"name": "Can add Provider Configuration (SAML IdP)", "content_type": 126, "codename": "add_samlproviderconfig"}}, {"model": "auth.permission", "pk": 376, "fields": {"name": "Can change Provider Configuration (SAML IdP)", "content_type": 126, "codename": "change_samlproviderconfig"}}, {"model": "auth.permission", "pk": 377, "fields": {"name": "Can delete Provider Configuration (SAML IdP)", "content_type": 126, "codename": "delete_samlproviderconfig"}}, {"model": "auth.permission", "pk": 378, "fields": {"name": "Can add SAML Configuration", "content_type": 127, "codename": "add_samlconfiguration"}}, {"model": "auth.permission", "pk": 379, "fields": {"name": "Can change SAML Configuration", "content_type": 127, "codename": "change_samlconfiguration"}}, {"model": "auth.permission", "pk": 380, "fields": {"name": "Can delete SAML Configuration", "content_type": 127, "codename": "delete_samlconfiguration"}}, {"model": "auth.permission", "pk": 381, "fields": {"name": "Can add SAML Provider Data", "content_type": 128, "codename": "add_samlproviderdata"}}, {"model": "auth.permission", "pk": 382, "fields": {"name": "Can change SAML Provider Data", "content_type": 128, "codename": "change_samlproviderdata"}}, {"model": "auth.permission", "pk": 383, "fields": {"name": "Can delete SAML Provider Data", "content_type": 128, "codename": "delete_samlproviderdata"}}, {"model": "auth.permission", "pk": 384, "fields": {"name": "Can add Provider Configuration (LTI)", "content_type": 129, "codename": "add_ltiproviderconfig"}}, {"model": "auth.permission", "pk": 385, "fields": {"name": "Can change Provider Configuration (LTI)", "content_type": 129, "codename": "change_ltiproviderconfig"}}, {"model": "auth.permission", "pk": 386, "fields": {"name": "Can delete Provider Configuration (LTI)", "content_type": 129, "codename": "delete_ltiproviderconfig"}}, {"model": "auth.permission", "pk": 387, "fields": {"name": "Can add Provider API Permission", "content_type": 130, "codename": "add_providerapipermissions"}}, {"model": "auth.permission", "pk": 388, "fields": {"name": "Can change Provider API Permission", "content_type": 130, "codename": "change_providerapipermissions"}}, {"model": "auth.permission", "pk": 389, "fields": {"name": "Can delete Provider API Permission", "content_type": 130, "codename": "delete_providerapipermissions"}}, {"model": "auth.permission", "pk": 390, "fields": {"name": "Can add nonce", "content_type": 131, "codename": "add_nonce"}}, {"model": "auth.permission", "pk": 391, "fields": {"name": "Can change nonce", "content_type": 131, "codename": "change_nonce"}}, {"model": "auth.permission", "pk": 392, "fields": {"name": "Can delete nonce", "content_type": 131, "codename": "delete_nonce"}}, {"model": "auth.permission", "pk": 393, "fields": {"name": "Can add scope", "content_type": 132, "codename": "add_scope"}}, {"model": "auth.permission", "pk": 394, "fields": {"name": "Can change scope", "content_type": 132, "codename": "change_scope"}}, {"model": "auth.permission", "pk": 395, "fields": {"name": "Can delete scope", "content_type": 132, "codename": "delete_scope"}}, {"model": "auth.permission", "pk": 396, "fields": {"name": "Can add resource", "content_type": 132, "codename": "add_resource"}}, {"model": "auth.permission", "pk": 397, "fields": {"name": "Can change resource", "content_type": 132, "codename": "change_resource"}}, {"model": "auth.permission", "pk": 398, "fields": {"name": "Can delete resource", "content_type": 132, "codename": "delete_resource"}}, {"model": "auth.permission", "pk": 399, "fields": {"name": "Can add consumer", "content_type": 133, "codename": "add_consumer"}}, {"model": "auth.permission", "pk": 400, "fields": {"name": "Can change consumer", "content_type": 133, "codename": "change_consumer"}}, {"model": "auth.permission", "pk": 401, "fields": {"name": "Can delete consumer", "content_type": 133, "codename": "delete_consumer"}}, {"model": "auth.permission", "pk": 402, "fields": {"name": "Can add token", "content_type": 134, "codename": "add_token"}}, {"model": "auth.permission", "pk": 403, "fields": {"name": "Can change token", "content_type": 134, "codename": "change_token"}}, {"model": "auth.permission", "pk": 404, "fields": {"name": "Can delete token", "content_type": 134, "codename": "delete_token"}}, {"model": "auth.permission", "pk": 405, "fields": {"name": "Can add article", "content_type": 136, "codename": "add_article"}}, {"model": "auth.permission", "pk": 406, "fields": {"name": "Can change article", "content_type": 136, "codename": "change_article"}}, {"model": "auth.permission", "pk": 407, "fields": {"name": "Can delete article", "content_type": 136, "codename": "delete_article"}}, {"model": "auth.permission", "pk": 408, "fields": {"name": "Can edit all articles and lock/unlock/restore", "content_type": 136, "codename": "moderate"}}, {"model": "auth.permission", "pk": 409, "fields": {"name": "Can change ownership of any article", "content_type": 136, "codename": "assign"}}, {"model": "auth.permission", "pk": 410, "fields": {"name": "Can assign permissions to other users", "content_type": 136, "codename": "grant"}}, {"model": "auth.permission", "pk": 411, "fields": {"name": "Can add Article for object", "content_type": 137, "codename": "add_articleforobject"}}, {"model": "auth.permission", "pk": 412, "fields": {"name": "Can change Article for object", "content_type": 137, "codename": "change_articleforobject"}}, {"model": "auth.permission", "pk": 413, "fields": {"name": "Can delete Article for object", "content_type": 137, "codename": "delete_articleforobject"}}, {"model": "auth.permission", "pk": 414, "fields": {"name": "Can add article revision", "content_type": 138, "codename": "add_articlerevision"}}, {"model": "auth.permission", "pk": 415, "fields": {"name": "Can change article revision", "content_type": 138, "codename": "change_articlerevision"}}, {"model": "auth.permission", "pk": 416, "fields": {"name": "Can delete article revision", "content_type": 138, "codename": "delete_articlerevision"}}, {"model": "auth.permission", "pk": 417, "fields": {"name": "Can add article plugin", "content_type": 139, "codename": "add_articleplugin"}}, {"model": "auth.permission", "pk": 418, "fields": {"name": "Can change article plugin", "content_type": 139, "codename": "change_articleplugin"}}, {"model": "auth.permission", "pk": 419, "fields": {"name": "Can delete article plugin", "content_type": 139, "codename": "delete_articleplugin"}}, {"model": "auth.permission", "pk": 420, "fields": {"name": "Can add reusable plugin", "content_type": 140, "codename": "add_reusableplugin"}}, {"model": "auth.permission", "pk": 421, "fields": {"name": "Can change reusable plugin", "content_type": 140, "codename": "change_reusableplugin"}}, {"model": "auth.permission", "pk": 422, "fields": {"name": "Can delete reusable plugin", "content_type": 140, "codename": "delete_reusableplugin"}}, {"model": "auth.permission", "pk": 423, "fields": {"name": "Can add simple plugin", "content_type": 141, "codename": "add_simpleplugin"}}, {"model": "auth.permission", "pk": 424, "fields": {"name": "Can change simple plugin", "content_type": 141, "codename": "change_simpleplugin"}}, {"model": "auth.permission", "pk": 425, "fields": {"name": "Can delete simple plugin", "content_type": 141, "codename": "delete_simpleplugin"}}, {"model": "auth.permission", "pk": 426, "fields": {"name": "Can add revision plugin", "content_type": 142, "codename": "add_revisionplugin"}}, {"model": "auth.permission", "pk": 427, "fields": {"name": "Can change revision plugin", "content_type": 142, "codename": "change_revisionplugin"}}, {"model": "auth.permission", "pk": 428, "fields": {"name": "Can delete revision plugin", "content_type": 142, "codename": "delete_revisionplugin"}}, {"model": "auth.permission", "pk": 429, "fields": {"name": "Can add revision plugin revision", "content_type": 143, "codename": "add_revisionpluginrevision"}}, {"model": "auth.permission", "pk": 430, "fields": {"name": "Can change revision plugin revision", "content_type": 143, "codename": "change_revisionpluginrevision"}}, {"model": "auth.permission", "pk": 431, "fields": {"name": "Can delete revision plugin revision", "content_type": 143, "codename": "delete_revisionpluginrevision"}}, {"model": "auth.permission", "pk": 432, "fields": {"name": "Can add URL path", "content_type": 144, "codename": "add_urlpath"}}, {"model": "auth.permission", "pk": 433, "fields": {"name": "Can change URL path", "content_type": 144, "codename": "change_urlpath"}}, {"model": "auth.permission", "pk": 434, "fields": {"name": "Can delete URL path", "content_type": 144, "codename": "delete_urlpath"}}, {"model": "auth.permission", "pk": 435, "fields": {"name": "Can add type", "content_type": 145, "codename": "add_notificationtype"}}, {"model": "auth.permission", "pk": 436, "fields": {"name": "Can change type", "content_type": 145, "codename": "change_notificationtype"}}, {"model": "auth.permission", "pk": 437, "fields": {"name": "Can delete type", "content_type": 145, "codename": "delete_notificationtype"}}, {"model": "auth.permission", "pk": 438, "fields": {"name": "Can add settings", "content_type": 146, "codename": "add_settings"}}, {"model": "auth.permission", "pk": 439, "fields": {"name": "Can change settings", "content_type": 146, "codename": "change_settings"}}, {"model": "auth.permission", "pk": 440, "fields": {"name": "Can delete settings", "content_type": 146, "codename": "delete_settings"}}, {"model": "auth.permission", "pk": 441, "fields": {"name": "Can add subscription", "content_type": 147, "codename": "add_subscription"}}, {"model": "auth.permission", "pk": 442, "fields": {"name": "Can change subscription", "content_type": 147, "codename": "change_subscription"}}, {"model": "auth.permission", "pk": 443, "fields": {"name": "Can delete subscription", "content_type": 147, "codename": "delete_subscription"}}, {"model": "auth.permission", "pk": 444, "fields": {"name": "Can add notification", "content_type": 148, "codename": "add_notification"}}, {"model": "auth.permission", "pk": 445, "fields": {"name": "Can change notification", "content_type": 148, "codename": "change_notification"}}, {"model": "auth.permission", "pk": 446, "fields": {"name": "Can delete notification", "content_type": 148, "codename": "delete_notification"}}, {"model": "auth.permission", "pk": 447, "fields": {"name": "Can add log entry", "content_type": 149, "codename": "add_logentry"}}, {"model": "auth.permission", "pk": 448, "fields": {"name": "Can change log entry", "content_type": 149, "codename": "change_logentry"}}, {"model": "auth.permission", "pk": 449, "fields": {"name": "Can delete log entry", "content_type": 149, "codename": "delete_logentry"}}, {"model": "auth.permission", "pk": 450, "fields": {"name": "Can add role", "content_type": 150, "codename": "add_role"}}, {"model": "auth.permission", "pk": 451, "fields": {"name": "Can change role", "content_type": 150, "codename": "change_role"}}, {"model": "auth.permission", "pk": 452, "fields": {"name": "Can delete role", "content_type": 150, "codename": "delete_role"}}, {"model": "auth.permission", "pk": 453, "fields": {"name": "Can add permission", "content_type": 151, "codename": "add_permission"}}, {"model": "auth.permission", "pk": 454, "fields": {"name": "Can change permission", "content_type": 151, "codename": "change_permission"}}, {"model": "auth.permission", "pk": 455, "fields": {"name": "Can delete permission", "content_type": 151, "codename": "delete_permission"}}, {"model": "auth.permission", "pk": 456, "fields": {"name": "Can add forums config", "content_type": 152, "codename": "add_forumsconfig"}}, {"model": "auth.permission", "pk": 457, "fields": {"name": "Can change forums config", "content_type": 152, "codename": "change_forumsconfig"}}, {"model": "auth.permission", "pk": 458, "fields": {"name": "Can delete forums config", "content_type": 152, "codename": "delete_forumsconfig"}}, {"model": "auth.permission", "pk": 459, "fields": {"name": "Can add course discussion settings", "content_type": 153, "codename": "add_coursediscussionsettings"}}, {"model": "auth.permission", "pk": 460, "fields": {"name": "Can change course discussion settings", "content_type": 153, "codename": "change_coursediscussionsettings"}}, {"model": "auth.permission", "pk": 461, "fields": {"name": "Can delete course discussion settings", "content_type": 153, "codename": "delete_coursediscussionsettings"}}, {"model": "auth.permission", "pk": 462, "fields": {"name": "Can add note", "content_type": 154, "codename": "add_note"}}, {"model": "auth.permission", "pk": 463, "fields": {"name": "Can change note", "content_type": 154, "codename": "change_note"}}, {"model": "auth.permission", "pk": 464, "fields": {"name": "Can delete note", "content_type": 154, "codename": "delete_note"}}, {"model": "auth.permission", "pk": 465, "fields": {"name": "Can add splash config", "content_type": 155, "codename": "add_splashconfig"}}, {"model": "auth.permission", "pk": 466, "fields": {"name": "Can change splash config", "content_type": 155, "codename": "change_splashconfig"}}, {"model": "auth.permission", "pk": 467, "fields": {"name": "Can delete splash config", "content_type": 155, "codename": "delete_splashconfig"}}, {"model": "auth.permission", "pk": 468, "fields": {"name": "Can add user preference", "content_type": 156, "codename": "add_userpreference"}}, {"model": "auth.permission", "pk": 469, "fields": {"name": "Can change user preference", "content_type": 156, "codename": "change_userpreference"}}, {"model": "auth.permission", "pk": 470, "fields": {"name": "Can delete user preference", "content_type": 156, "codename": "delete_userpreference"}}, {"model": "auth.permission", "pk": 471, "fields": {"name": "Can add user course tag", "content_type": 157, "codename": "add_usercoursetag"}}, {"model": "auth.permission", "pk": 472, "fields": {"name": "Can change user course tag", "content_type": 157, "codename": "change_usercoursetag"}}, {"model": "auth.permission", "pk": 473, "fields": {"name": "Can delete user course tag", "content_type": 157, "codename": "delete_usercoursetag"}}, {"model": "auth.permission", "pk": 474, "fields": {"name": "Can add user org tag", "content_type": 158, "codename": "add_userorgtag"}}, {"model": "auth.permission", "pk": 475, "fields": {"name": "Can change user org tag", "content_type": 158, "codename": "change_userorgtag"}}, {"model": "auth.permission", "pk": 476, "fields": {"name": "Can delete user org tag", "content_type": 158, "codename": "delete_userorgtag"}}, {"model": "auth.permission", "pk": 477, "fields": {"name": "Can add order", "content_type": 159, "codename": "add_order"}}, {"model": "auth.permission", "pk": 478, "fields": {"name": "Can change order", "content_type": 159, "codename": "change_order"}}, {"model": "auth.permission", "pk": 479, "fields": {"name": "Can delete order", "content_type": 159, "codename": "delete_order"}}, {"model": "auth.permission", "pk": 480, "fields": {"name": "Can add order item", "content_type": 160, "codename": "add_orderitem"}}, {"model": "auth.permission", "pk": 481, "fields": {"name": "Can change order item", "content_type": 160, "codename": "change_orderitem"}}, {"model": "auth.permission", "pk": 482, "fields": {"name": "Can delete order item", "content_type": 160, "codename": "delete_orderitem"}}, {"model": "auth.permission", "pk": 483, "fields": {"name": "Can add invoice", "content_type": 161, "codename": "add_invoice"}}, {"model": "auth.permission", "pk": 484, "fields": {"name": "Can change invoice", "content_type": 161, "codename": "change_invoice"}}, {"model": "auth.permission", "pk": 485, "fields": {"name": "Can delete invoice", "content_type": 161, "codename": "delete_invoice"}}, {"model": "auth.permission", "pk": 486, "fields": {"name": "Can add invoice transaction", "content_type": 162, "codename": "add_invoicetransaction"}}, {"model": "auth.permission", "pk": 487, "fields": {"name": "Can change invoice transaction", "content_type": 162, "codename": "change_invoicetransaction"}}, {"model": "auth.permission", "pk": 488, "fields": {"name": "Can delete invoice transaction", "content_type": 162, "codename": "delete_invoicetransaction"}}, {"model": "auth.permission", "pk": 489, "fields": {"name": "Can add invoice item", "content_type": 163, "codename": "add_invoiceitem"}}, {"model": "auth.permission", "pk": 490, "fields": {"name": "Can change invoice item", "content_type": 163, "codename": "change_invoiceitem"}}, {"model": "auth.permission", "pk": 491, "fields": {"name": "Can delete invoice item", "content_type": 163, "codename": "delete_invoiceitem"}}, {"model": "auth.permission", "pk": 492, "fields": {"name": "Can add course registration code invoice item", "content_type": 164, "codename": "add_courseregistrationcodeinvoiceitem"}}, {"model": "auth.permission", "pk": 493, "fields": {"name": "Can change course registration code invoice item", "content_type": 164, "codename": "change_courseregistrationcodeinvoiceitem"}}, {"model": "auth.permission", "pk": 494, "fields": {"name": "Can delete course registration code invoice item", "content_type": 164, "codename": "delete_courseregistrationcodeinvoiceitem"}}, {"model": "auth.permission", "pk": 495, "fields": {"name": "Can add invoice history", "content_type": 165, "codename": "add_invoicehistory"}}, {"model": "auth.permission", "pk": 496, "fields": {"name": "Can change invoice history", "content_type": 165, "codename": "change_invoicehistory"}}, {"model": "auth.permission", "pk": 497, "fields": {"name": "Can delete invoice history", "content_type": 165, "codename": "delete_invoicehistory"}}, {"model": "auth.permission", "pk": 498, "fields": {"name": "Can add course registration code", "content_type": 166, "codename": "add_courseregistrationcode"}}, {"model": "auth.permission", "pk": 499, "fields": {"name": "Can change course registration code", "content_type": 166, "codename": "change_courseregistrationcode"}}, {"model": "auth.permission", "pk": 500, "fields": {"name": "Can delete course registration code", "content_type": 166, "codename": "delete_courseregistrationcode"}}, {"model": "auth.permission", "pk": 501, "fields": {"name": "Can add registration code redemption", "content_type": 167, "codename": "add_registrationcoderedemption"}}, {"model": "auth.permission", "pk": 502, "fields": {"name": "Can change registration code redemption", "content_type": 167, "codename": "change_registrationcoderedemption"}}, {"model": "auth.permission", "pk": 503, "fields": {"name": "Can delete registration code redemption", "content_type": 167, "codename": "delete_registrationcoderedemption"}}, {"model": "auth.permission", "pk": 504, "fields": {"name": "Can add coupon", "content_type": 168, "codename": "add_coupon"}}, {"model": "auth.permission", "pk": 505, "fields": {"name": "Can change coupon", "content_type": 168, "codename": "change_coupon"}}, {"model": "auth.permission", "pk": 506, "fields": {"name": "Can delete coupon", "content_type": 168, "codename": "delete_coupon"}}, {"model": "auth.permission", "pk": 507, "fields": {"name": "Can add coupon redemption", "content_type": 169, "codename": "add_couponredemption"}}, {"model": "auth.permission", "pk": 508, "fields": {"name": "Can change coupon redemption", "content_type": 169, "codename": "change_couponredemption"}}, {"model": "auth.permission", "pk": 509, "fields": {"name": "Can delete coupon redemption", "content_type": 169, "codename": "delete_couponredemption"}}, {"model": "auth.permission", "pk": 510, "fields": {"name": "Can add paid course registration", "content_type": 170, "codename": "add_paidcourseregistration"}}, {"model": "auth.permission", "pk": 511, "fields": {"name": "Can change paid course registration", "content_type": 170, "codename": "change_paidcourseregistration"}}, {"model": "auth.permission", "pk": 512, "fields": {"name": "Can delete paid course registration", "content_type": 170, "codename": "delete_paidcourseregistration"}}, {"model": "auth.permission", "pk": 513, "fields": {"name": "Can add course reg code item", "content_type": 171, "codename": "add_courseregcodeitem"}}, {"model": "auth.permission", "pk": 514, "fields": {"name": "Can change course reg code item", "content_type": 171, "codename": "change_courseregcodeitem"}}, {"model": "auth.permission", "pk": 515, "fields": {"name": "Can delete course reg code item", "content_type": 171, "codename": "delete_courseregcodeitem"}}, {"model": "auth.permission", "pk": 516, "fields": {"name": "Can add course reg code item annotation", "content_type": 172, "codename": "add_courseregcodeitemannotation"}}, {"model": "auth.permission", "pk": 517, "fields": {"name": "Can change course reg code item annotation", "content_type": 172, "codename": "change_courseregcodeitemannotation"}}, {"model": "auth.permission", "pk": 518, "fields": {"name": "Can delete course reg code item annotation", "content_type": 172, "codename": "delete_courseregcodeitemannotation"}}, {"model": "auth.permission", "pk": 519, "fields": {"name": "Can add paid course registration annotation", "content_type": 173, "codename": "add_paidcourseregistrationannotation"}}, {"model": "auth.permission", "pk": 520, "fields": {"name": "Can change paid course registration annotation", "content_type": 173, "codename": "change_paidcourseregistrationannotation"}}, {"model": "auth.permission", "pk": 521, "fields": {"name": "Can delete paid course registration annotation", "content_type": 173, "codename": "delete_paidcourseregistrationannotation"}}, {"model": "auth.permission", "pk": 522, "fields": {"name": "Can add certificate item", "content_type": 174, "codename": "add_certificateitem"}}, {"model": "auth.permission", "pk": 523, "fields": {"name": "Can change certificate item", "content_type": 174, "codename": "change_certificateitem"}}, {"model": "auth.permission", "pk": 524, "fields": {"name": "Can delete certificate item", "content_type": 174, "codename": "delete_certificateitem"}}, {"model": "auth.permission", "pk": 525, "fields": {"name": "Can add donation configuration", "content_type": 175, "codename": "add_donationconfiguration"}}, {"model": "auth.permission", "pk": 526, "fields": {"name": "Can change donation configuration", "content_type": 175, "codename": "change_donationconfiguration"}}, {"model": "auth.permission", "pk": 527, "fields": {"name": "Can delete donation configuration", "content_type": 175, "codename": "delete_donationconfiguration"}}, {"model": "auth.permission", "pk": 528, "fields": {"name": "Can add donation", "content_type": 176, "codename": "add_donation"}}, {"model": "auth.permission", "pk": 529, "fields": {"name": "Can change donation", "content_type": 176, "codename": "change_donation"}}, {"model": "auth.permission", "pk": 530, "fields": {"name": "Can delete donation", "content_type": 176, "codename": "delete_donation"}}, {"model": "auth.permission", "pk": 531, "fields": {"name": "Can add course mode", "content_type": 177, "codename": "add_coursemode"}}, {"model": "auth.permission", "pk": 532, "fields": {"name": "Can change course mode", "content_type": 177, "codename": "change_coursemode"}}, {"model": "auth.permission", "pk": 533, "fields": {"name": "Can delete course mode", "content_type": 177, "codename": "delete_coursemode"}}, {"model": "auth.permission", "pk": 534, "fields": {"name": "Can add course modes archive", "content_type": 178, "codename": "add_coursemodesarchive"}}, {"model": "auth.permission", "pk": 535, "fields": {"name": "Can change course modes archive", "content_type": 178, "codename": "change_coursemodesarchive"}}, {"model": "auth.permission", "pk": 536, "fields": {"name": "Can delete course modes archive", "content_type": 178, "codename": "delete_coursemodesarchive"}}, {"model": "auth.permission", "pk": 537, "fields": {"name": "Can add course mode expiration config", "content_type": 179, "codename": "add_coursemodeexpirationconfig"}}, {"model": "auth.permission", "pk": 538, "fields": {"name": "Can change course mode expiration config", "content_type": 179, "codename": "change_coursemodeexpirationconfig"}}, {"model": "auth.permission", "pk": 539, "fields": {"name": "Can delete course mode expiration config", "content_type": 179, "codename": "delete_coursemodeexpirationconfig"}}, {"model": "auth.permission", "pk": 540, "fields": {"name": "Can add course entitlement", "content_type": 180, "codename": "add_courseentitlement"}}, {"model": "auth.permission", "pk": 541, "fields": {"name": "Can change course entitlement", "content_type": 180, "codename": "change_courseentitlement"}}, {"model": "auth.permission", "pk": 542, "fields": {"name": "Can delete course entitlement", "content_type": 180, "codename": "delete_courseentitlement"}}, {"model": "auth.permission", "pk": 543, "fields": {"name": "Can add software secure photo verification", "content_type": 181, "codename": "add_softwaresecurephotoverification"}}, {"model": "auth.permission", "pk": 544, "fields": {"name": "Can change software secure photo verification", "content_type": 181, "codename": "change_softwaresecurephotoverification"}}, {"model": "auth.permission", "pk": 545, "fields": {"name": "Can delete software secure photo verification", "content_type": 181, "codename": "delete_softwaresecurephotoverification"}}, {"model": "auth.permission", "pk": 546, "fields": {"name": "Can add verification deadline", "content_type": 182, "codename": "add_verificationdeadline"}}, {"model": "auth.permission", "pk": 547, "fields": {"name": "Can change verification deadline", "content_type": 182, "codename": "change_verificationdeadline"}}, {"model": "auth.permission", "pk": 548, "fields": {"name": "Can delete verification deadline", "content_type": 182, "codename": "delete_verificationdeadline"}}, {"model": "auth.permission", "pk": 549, "fields": {"name": "Can add verification checkpoint", "content_type": 183, "codename": "add_verificationcheckpoint"}}, {"model": "auth.permission", "pk": 550, "fields": {"name": "Can change verification checkpoint", "content_type": 183, "codename": "change_verificationcheckpoint"}}, {"model": "auth.permission", "pk": 551, "fields": {"name": "Can delete verification checkpoint", "content_type": 183, "codename": "delete_verificationcheckpoint"}}, {"model": "auth.permission", "pk": 552, "fields": {"name": "Can add Verification Status", "content_type": 184, "codename": "add_verificationstatus"}}, {"model": "auth.permission", "pk": 553, "fields": {"name": "Can change Verification Status", "content_type": 184, "codename": "change_verificationstatus"}}, {"model": "auth.permission", "pk": 554, "fields": {"name": "Can delete Verification Status", "content_type": 184, "codename": "delete_verificationstatus"}}, {"model": "auth.permission", "pk": 555, "fields": {"name": "Can add in course reverification configuration", "content_type": 185, "codename": "add_incoursereverificationconfiguration"}}, {"model": "auth.permission", "pk": 556, "fields": {"name": "Can change in course reverification configuration", "content_type": 185, "codename": "change_incoursereverificationconfiguration"}}, {"model": "auth.permission", "pk": 557, "fields": {"name": "Can delete in course reverification configuration", "content_type": 185, "codename": "delete_incoursereverificationconfiguration"}}, {"model": "auth.permission", "pk": 558, "fields": {"name": "Can add icrv status emails configuration", "content_type": 186, "codename": "add_icrvstatusemailsconfiguration"}}, {"model": "auth.permission", "pk": 559, "fields": {"name": "Can change icrv status emails configuration", "content_type": 186, "codename": "change_icrvstatusemailsconfiguration"}}, {"model": "auth.permission", "pk": 560, "fields": {"name": "Can delete icrv status emails configuration", "content_type": 186, "codename": "delete_icrvstatusemailsconfiguration"}}, {"model": "auth.permission", "pk": 561, "fields": {"name": "Can add skipped reverification", "content_type": 187, "codename": "add_skippedreverification"}}, {"model": "auth.permission", "pk": 562, "fields": {"name": "Can change skipped reverification", "content_type": 187, "codename": "change_skippedreverification"}}, {"model": "auth.permission", "pk": 563, "fields": {"name": "Can delete skipped reverification", "content_type": 187, "codename": "delete_skippedreverification"}}, {"model": "auth.permission", "pk": 564, "fields": {"name": "Can add dark lang config", "content_type": 188, "codename": "add_darklangconfig"}}, {"model": "auth.permission", "pk": 565, "fields": {"name": "Can change dark lang config", "content_type": 188, "codename": "change_darklangconfig"}}, {"model": "auth.permission", "pk": 566, "fields": {"name": "Can delete dark lang config", "content_type": 188, "codename": "delete_darklangconfig"}}, {"model": "auth.permission", "pk": 567, "fields": {"name": "Can add microsite", "content_type": 189, "codename": "add_microsite"}}, {"model": "auth.permission", "pk": 568, "fields": {"name": "Can change microsite", "content_type": 189, "codename": "change_microsite"}}, {"model": "auth.permission", "pk": 569, "fields": {"name": "Can delete microsite", "content_type": 189, "codename": "delete_microsite"}}, {"model": "auth.permission", "pk": 570, "fields": {"name": "Can add microsite history", "content_type": 190, "codename": "add_micrositehistory"}}, {"model": "auth.permission", "pk": 571, "fields": {"name": "Can change microsite history", "content_type": 190, "codename": "change_micrositehistory"}}, {"model": "auth.permission", "pk": 572, "fields": {"name": "Can delete microsite history", "content_type": 190, "codename": "delete_micrositehistory"}}, {"model": "auth.permission", "pk": 573, "fields": {"name": "Can add microsite organization mapping", "content_type": 191, "codename": "add_micrositeorganizationmapping"}}, {"model": "auth.permission", "pk": 574, "fields": {"name": "Can change microsite organization mapping", "content_type": 191, "codename": "change_micrositeorganizationmapping"}}, {"model": "auth.permission", "pk": 575, "fields": {"name": "Can delete microsite organization mapping", "content_type": 191, "codename": "delete_micrositeorganizationmapping"}}, {"model": "auth.permission", "pk": 576, "fields": {"name": "Can add microsite template", "content_type": 192, "codename": "add_micrositetemplate"}}, {"model": "auth.permission", "pk": 577, "fields": {"name": "Can change microsite template", "content_type": 192, "codename": "change_micrositetemplate"}}, {"model": "auth.permission", "pk": 578, "fields": {"name": "Can delete microsite template", "content_type": 192, "codename": "delete_micrositetemplate"}}, {"model": "auth.permission", "pk": 579, "fields": {"name": "Can add whitelisted rss url", "content_type": 193, "codename": "add_whitelistedrssurl"}}, {"model": "auth.permission", "pk": 580, "fields": {"name": "Can change whitelisted rss url", "content_type": 193, "codename": "change_whitelistedrssurl"}}, {"model": "auth.permission", "pk": 581, "fields": {"name": "Can delete whitelisted rss url", "content_type": 193, "codename": "delete_whitelistedrssurl"}}, {"model": "auth.permission", "pk": 582, "fields": {"name": "Can add embargoed course", "content_type": 194, "codename": "add_embargoedcourse"}}, {"model": "auth.permission", "pk": 583, "fields": {"name": "Can change embargoed course", "content_type": 194, "codename": "change_embargoedcourse"}}, {"model": "auth.permission", "pk": 584, "fields": {"name": "Can delete embargoed course", "content_type": 194, "codename": "delete_embargoedcourse"}}, {"model": "auth.permission", "pk": 585, "fields": {"name": "Can add embargoed state", "content_type": 195, "codename": "add_embargoedstate"}}, {"model": "auth.permission", "pk": 586, "fields": {"name": "Can change embargoed state", "content_type": 195, "codename": "change_embargoedstate"}}, {"model": "auth.permission", "pk": 587, "fields": {"name": "Can delete embargoed state", "content_type": 195, "codename": "delete_embargoedstate"}}, {"model": "auth.permission", "pk": 588, "fields": {"name": "Can add restricted course", "content_type": 196, "codename": "add_restrictedcourse"}}, {"model": "auth.permission", "pk": 589, "fields": {"name": "Can change restricted course", "content_type": 196, "codename": "change_restrictedcourse"}}, {"model": "auth.permission", "pk": 590, "fields": {"name": "Can delete restricted course", "content_type": 196, "codename": "delete_restrictedcourse"}}, {"model": "auth.permission", "pk": 591, "fields": {"name": "Can add country", "content_type": 197, "codename": "add_country"}}, {"model": "auth.permission", "pk": 592, "fields": {"name": "Can change country", "content_type": 197, "codename": "change_country"}}, {"model": "auth.permission", "pk": 593, "fields": {"name": "Can delete country", "content_type": 197, "codename": "delete_country"}}, {"model": "auth.permission", "pk": 594, "fields": {"name": "Can add country access rule", "content_type": 198, "codename": "add_countryaccessrule"}}, {"model": "auth.permission", "pk": 595, "fields": {"name": "Can change country access rule", "content_type": 198, "codename": "change_countryaccessrule"}}, {"model": "auth.permission", "pk": 596, "fields": {"name": "Can delete country access rule", "content_type": 198, "codename": "delete_countryaccessrule"}}, {"model": "auth.permission", "pk": 597, "fields": {"name": "Can add course access rule history", "content_type": 199, "codename": "add_courseaccessrulehistory"}}, {"model": "auth.permission", "pk": 598, "fields": {"name": "Can change course access rule history", "content_type": 199, "codename": "change_courseaccessrulehistory"}}, {"model": "auth.permission", "pk": 599, "fields": {"name": "Can delete course access rule history", "content_type": 199, "codename": "delete_courseaccessrulehistory"}}, {"model": "auth.permission", "pk": 600, "fields": {"name": "Can add ip filter", "content_type": 200, "codename": "add_ipfilter"}}, {"model": "auth.permission", "pk": 601, "fields": {"name": "Can change ip filter", "content_type": 200, "codename": "change_ipfilter"}}, {"model": "auth.permission", "pk": 602, "fields": {"name": "Can delete ip filter", "content_type": 200, "codename": "delete_ipfilter"}}, {"model": "auth.permission", "pk": 603, "fields": {"name": "Can add course rerun state", "content_type": 201, "codename": "add_coursererunstate"}}, {"model": "auth.permission", "pk": 604, "fields": {"name": "Can change course rerun state", "content_type": 201, "codename": "change_coursererunstate"}}, {"model": "auth.permission", "pk": 605, "fields": {"name": "Can delete course rerun state", "content_type": 201, "codename": "delete_coursererunstate"}}, {"model": "auth.permission", "pk": 606, "fields": {"name": "Can add mobile api config", "content_type": 202, "codename": "add_mobileapiconfig"}}, {"model": "auth.permission", "pk": 607, "fields": {"name": "Can change mobile api config", "content_type": 202, "codename": "change_mobileapiconfig"}}, {"model": "auth.permission", "pk": 608, "fields": {"name": "Can delete mobile api config", "content_type": 202, "codename": "delete_mobileapiconfig"}}, {"model": "auth.permission", "pk": 609, "fields": {"name": "Can add app version config", "content_type": 203, "codename": "add_appversionconfig"}}, {"model": "auth.permission", "pk": 610, "fields": {"name": "Can change app version config", "content_type": 203, "codename": "change_appversionconfig"}}, {"model": "auth.permission", "pk": 611, "fields": {"name": "Can delete app version config", "content_type": 203, "codename": "delete_appversionconfig"}}, {"model": "auth.permission", "pk": 612, "fields": {"name": "Can add ignore mobile available flag config", "content_type": 204, "codename": "add_ignoremobileavailableflagconfig"}}, {"model": "auth.permission", "pk": 613, "fields": {"name": "Can change ignore mobile available flag config", "content_type": 204, "codename": "change_ignoremobileavailableflagconfig"}}, {"model": "auth.permission", "pk": 614, "fields": {"name": "Can delete ignore mobile available flag config", "content_type": 204, "codename": "delete_ignoremobileavailableflagconfig"}}, {"model": "auth.permission", "pk": 615, "fields": {"name": "Can add user social auth", "content_type": 205, "codename": "add_usersocialauth"}}, {"model": "auth.permission", "pk": 616, "fields": {"name": "Can change user social auth", "content_type": 205, "codename": "change_usersocialauth"}}, {"model": "auth.permission", "pk": 617, "fields": {"name": "Can delete user social auth", "content_type": 205, "codename": "delete_usersocialauth"}}, {"model": "auth.permission", "pk": 618, "fields": {"name": "Can add nonce", "content_type": 206, "codename": "add_nonce"}}, {"model": "auth.permission", "pk": 619, "fields": {"name": "Can change nonce", "content_type": 206, "codename": "change_nonce"}}, {"model": "auth.permission", "pk": 620, "fields": {"name": "Can delete nonce", "content_type": 206, "codename": "delete_nonce"}}, {"model": "auth.permission", "pk": 621, "fields": {"name": "Can add association", "content_type": 207, "codename": "add_association"}}, {"model": "auth.permission", "pk": 622, "fields": {"name": "Can change association", "content_type": 207, "codename": "change_association"}}, {"model": "auth.permission", "pk": 623, "fields": {"name": "Can delete association", "content_type": 207, "codename": "delete_association"}}, {"model": "auth.permission", "pk": 624, "fields": {"name": "Can add code", "content_type": 208, "codename": "add_code"}}, {"model": "auth.permission", "pk": 625, "fields": {"name": "Can change code", "content_type": 208, "codename": "change_code"}}, {"model": "auth.permission", "pk": 626, "fields": {"name": "Can delete code", "content_type": 208, "codename": "delete_code"}}, {"model": "auth.permission", "pk": 627, "fields": {"name": "Can add partial", "content_type": 209, "codename": "add_partial"}}, {"model": "auth.permission", "pk": 628, "fields": {"name": "Can change partial", "content_type": 209, "codename": "change_partial"}}, {"model": "auth.permission", "pk": 629, "fields": {"name": "Can delete partial", "content_type": 209, "codename": "delete_partial"}}, {"model": "auth.permission", "pk": 630, "fields": {"name": "Can add survey form", "content_type": 210, "codename": "add_surveyform"}}, {"model": "auth.permission", "pk": 631, "fields": {"name": "Can change survey form", "content_type": 210, "codename": "change_surveyform"}}, {"model": "auth.permission", "pk": 632, "fields": {"name": "Can delete survey form", "content_type": 210, "codename": "delete_surveyform"}}, {"model": "auth.permission", "pk": 633, "fields": {"name": "Can add survey answer", "content_type": 211, "codename": "add_surveyanswer"}}, {"model": "auth.permission", "pk": 634, "fields": {"name": "Can change survey answer", "content_type": 211, "codename": "change_surveyanswer"}}, {"model": "auth.permission", "pk": 635, "fields": {"name": "Can delete survey answer", "content_type": 211, "codename": "delete_surveyanswer"}}, {"model": "auth.permission", "pk": 636, "fields": {"name": "Can add x block asides config", "content_type": 212, "codename": "add_xblockasidesconfig"}}, {"model": "auth.permission", "pk": 637, "fields": {"name": "Can change x block asides config", "content_type": 212, "codename": "change_xblockasidesconfig"}}, {"model": "auth.permission", "pk": 638, "fields": {"name": "Can delete x block asides config", "content_type": 212, "codename": "delete_xblockasidesconfig"}}, {"model": "auth.permission", "pk": 639, "fields": {"name": "Can add answer", "content_type": 213, "codename": "add_answer"}}, {"model": "auth.permission", "pk": 640, "fields": {"name": "Can change answer", "content_type": 213, "codename": "change_answer"}}, {"model": "auth.permission", "pk": 641, "fields": {"name": "Can delete answer", "content_type": 213, "codename": "delete_answer"}}, {"model": "auth.permission", "pk": 642, "fields": {"name": "Can add share", "content_type": 214, "codename": "add_share"}}, {"model": "auth.permission", "pk": 643, "fields": {"name": "Can change share", "content_type": 214, "codename": "change_share"}}, {"model": "auth.permission", "pk": 644, "fields": {"name": "Can delete share", "content_type": 214, "codename": "delete_share"}}, {"model": "auth.permission", "pk": 645, "fields": {"name": "Can add student item", "content_type": 215, "codename": "add_studentitem"}}, {"model": "auth.permission", "pk": 646, "fields": {"name": "Can change student item", "content_type": 215, "codename": "change_studentitem"}}, {"model": "auth.permission", "pk": 647, "fields": {"name": "Can delete student item", "content_type": 215, "codename": "delete_studentitem"}}, {"model": "auth.permission", "pk": 648, "fields": {"name": "Can add submission", "content_type": 216, "codename": "add_submission"}}, {"model": "auth.permission", "pk": 649, "fields": {"name": "Can change submission", "content_type": 216, "codename": "change_submission"}}, {"model": "auth.permission", "pk": 650, "fields": {"name": "Can delete submission", "content_type": 216, "codename": "delete_submission"}}, {"model": "auth.permission", "pk": 651, "fields": {"name": "Can add score", "content_type": 217, "codename": "add_score"}}, {"model": "auth.permission", "pk": 652, "fields": {"name": "Can change score", "content_type": 217, "codename": "change_score"}}, {"model": "auth.permission", "pk": 653, "fields": {"name": "Can delete score", "content_type": 217, "codename": "delete_score"}}, {"model": "auth.permission", "pk": 654, "fields": {"name": "Can add score summary", "content_type": 218, "codename": "add_scoresummary"}}, {"model": "auth.permission", "pk": 655, "fields": {"name": "Can change score summary", "content_type": 218, "codename": "change_scoresummary"}}, {"model": "auth.permission", "pk": 656, "fields": {"name": "Can delete score summary", "content_type": 218, "codename": "delete_scoresummary"}}, {"model": "auth.permission", "pk": 657, "fields": {"name": "Can add score annotation", "content_type": 219, "codename": "add_scoreannotation"}}, {"model": "auth.permission", "pk": 658, "fields": {"name": "Can change score annotation", "content_type": 219, "codename": "change_scoreannotation"}}, {"model": "auth.permission", "pk": 659, "fields": {"name": "Can delete score annotation", "content_type": 219, "codename": "delete_scoreannotation"}}, {"model": "auth.permission", "pk": 660, "fields": {"name": "Can add rubric", "content_type": 220, "codename": "add_rubric"}}, {"model": "auth.permission", "pk": 661, "fields": {"name": "Can change rubric", "content_type": 220, "codename": "change_rubric"}}, {"model": "auth.permission", "pk": 662, "fields": {"name": "Can delete rubric", "content_type": 220, "codename": "delete_rubric"}}, {"model": "auth.permission", "pk": 663, "fields": {"name": "Can add criterion", "content_type": 221, "codename": "add_criterion"}}, {"model": "auth.permission", "pk": 664, "fields": {"name": "Can change criterion", "content_type": 221, "codename": "change_criterion"}}, {"model": "auth.permission", "pk": 665, "fields": {"name": "Can delete criterion", "content_type": 221, "codename": "delete_criterion"}}, {"model": "auth.permission", "pk": 666, "fields": {"name": "Can add criterion option", "content_type": 222, "codename": "add_criterionoption"}}, {"model": "auth.permission", "pk": 667, "fields": {"name": "Can change criterion option", "content_type": 222, "codename": "change_criterionoption"}}, {"model": "auth.permission", "pk": 668, "fields": {"name": "Can delete criterion option", "content_type": 222, "codename": "delete_criterionoption"}}, {"model": "auth.permission", "pk": 669, "fields": {"name": "Can add assessment", "content_type": 223, "codename": "add_assessment"}}, {"model": "auth.permission", "pk": 670, "fields": {"name": "Can change assessment", "content_type": 223, "codename": "change_assessment"}}, {"model": "auth.permission", "pk": 671, "fields": {"name": "Can delete assessment", "content_type": 223, "codename": "delete_assessment"}}, {"model": "auth.permission", "pk": 672, "fields": {"name": "Can add assessment part", "content_type": 224, "codename": "add_assessmentpart"}}, {"model": "auth.permission", "pk": 673, "fields": {"name": "Can change assessment part", "content_type": 224, "codename": "change_assessmentpart"}}, {"model": "auth.permission", "pk": 674, "fields": {"name": "Can delete assessment part", "content_type": 224, "codename": "delete_assessmentpart"}}, {"model": "auth.permission", "pk": 675, "fields": {"name": "Can add assessment feedback option", "content_type": 225, "codename": "add_assessmentfeedbackoption"}}, {"model": "auth.permission", "pk": 676, "fields": {"name": "Can change assessment feedback option", "content_type": 225, "codename": "change_assessmentfeedbackoption"}}, {"model": "auth.permission", "pk": 677, "fields": {"name": "Can delete assessment feedback option", "content_type": 225, "codename": "delete_assessmentfeedbackoption"}}, {"model": "auth.permission", "pk": 678, "fields": {"name": "Can add assessment feedback", "content_type": 226, "codename": "add_assessmentfeedback"}}, {"model": "auth.permission", "pk": 679, "fields": {"name": "Can change assessment feedback", "content_type": 226, "codename": "change_assessmentfeedback"}}, {"model": "auth.permission", "pk": 680, "fields": {"name": "Can delete assessment feedback", "content_type": 226, "codename": "delete_assessmentfeedback"}}, {"model": "auth.permission", "pk": 681, "fields": {"name": "Can add peer workflow", "content_type": 227, "codename": "add_peerworkflow"}}, {"model": "auth.permission", "pk": 682, "fields": {"name": "Can change peer workflow", "content_type": 227, "codename": "change_peerworkflow"}}, {"model": "auth.permission", "pk": 683, "fields": {"name": "Can delete peer workflow", "content_type": 227, "codename": "delete_peerworkflow"}}, {"model": "auth.permission", "pk": 684, "fields": {"name": "Can add peer workflow item", "content_type": 228, "codename": "add_peerworkflowitem"}}, {"model": "auth.permission", "pk": 685, "fields": {"name": "Can change peer workflow item", "content_type": 228, "codename": "change_peerworkflowitem"}}, {"model": "auth.permission", "pk": 686, "fields": {"name": "Can delete peer workflow item", "content_type": 228, "codename": "delete_peerworkflowitem"}}, {"model": "auth.permission", "pk": 687, "fields": {"name": "Can add training example", "content_type": 229, "codename": "add_trainingexample"}}, {"model": "auth.permission", "pk": 688, "fields": {"name": "Can change training example", "content_type": 229, "codename": "change_trainingexample"}}, {"model": "auth.permission", "pk": 689, "fields": {"name": "Can delete training example", "content_type": 229, "codename": "delete_trainingexample"}}, {"model": "auth.permission", "pk": 690, "fields": {"name": "Can add student training workflow", "content_type": 230, "codename": "add_studenttrainingworkflow"}}, {"model": "auth.permission", "pk": 691, "fields": {"name": "Can change student training workflow", "content_type": 230, "codename": "change_studenttrainingworkflow"}}, {"model": "auth.permission", "pk": 692, "fields": {"name": "Can delete student training workflow", "content_type": 230, "codename": "delete_studenttrainingworkflow"}}, {"model": "auth.permission", "pk": 693, "fields": {"name": "Can add student training workflow item", "content_type": 231, "codename": "add_studenttrainingworkflowitem"}}, {"model": "auth.permission", "pk": 694, "fields": {"name": "Can change student training workflow item", "content_type": 231, "codename": "change_studenttrainingworkflowitem"}}, {"model": "auth.permission", "pk": 695, "fields": {"name": "Can delete student training workflow item", "content_type": 231, "codename": "delete_studenttrainingworkflowitem"}}, {"model": "auth.permission", "pk": 696, "fields": {"name": "Can add staff workflow", "content_type": 232, "codename": "add_staffworkflow"}}, {"model": "auth.permission", "pk": 697, "fields": {"name": "Can change staff workflow", "content_type": 232, "codename": "change_staffworkflow"}}, {"model": "auth.permission", "pk": 698, "fields": {"name": "Can delete staff workflow", "content_type": 232, "codename": "delete_staffworkflow"}}, {"model": "auth.permission", "pk": 699, "fields": {"name": "Can add assessment workflow", "content_type": 233, "codename": "add_assessmentworkflow"}}, {"model": "auth.permission", "pk": 700, "fields": {"name": "Can change assessment workflow", "content_type": 233, "codename": "change_assessmentworkflow"}}, {"model": "auth.permission", "pk": 701, "fields": {"name": "Can delete assessment workflow", "content_type": 233, "codename": "delete_assessmentworkflow"}}, {"model": "auth.permission", "pk": 702, "fields": {"name": "Can add assessment workflow step", "content_type": 234, "codename": "add_assessmentworkflowstep"}}, {"model": "auth.permission", "pk": 703, "fields": {"name": "Can change assessment workflow step", "content_type": 234, "codename": "change_assessmentworkflowstep"}}, {"model": "auth.permission", "pk": 704, "fields": {"name": "Can delete assessment workflow step", "content_type": 234, "codename": "delete_assessmentworkflowstep"}}, {"model": "auth.permission", "pk": 705, "fields": {"name": "Can add assessment workflow cancellation", "content_type": 235, "codename": "add_assessmentworkflowcancellation"}}, {"model": "auth.permission", "pk": 706, "fields": {"name": "Can change assessment workflow cancellation", "content_type": 235, "codename": "change_assessmentworkflowcancellation"}}, {"model": "auth.permission", "pk": 707, "fields": {"name": "Can delete assessment workflow cancellation", "content_type": 235, "codename": "delete_assessmentworkflowcancellation"}}, {"model": "auth.permission", "pk": 708, "fields": {"name": "Can add profile", "content_type": 236, "codename": "add_profile"}}, {"model": "auth.permission", "pk": 709, "fields": {"name": "Can change profile", "content_type": 236, "codename": "change_profile"}}, {"model": "auth.permission", "pk": 710, "fields": {"name": "Can delete profile", "content_type": 236, "codename": "delete_profile"}}, {"model": "auth.permission", "pk": 711, "fields": {"name": "Can add video", "content_type": 237, "codename": "add_video"}}, {"model": "auth.permission", "pk": 712, "fields": {"name": "Can change video", "content_type": 237, "codename": "change_video"}}, {"model": "auth.permission", "pk": 713, "fields": {"name": "Can delete video", "content_type": 237, "codename": "delete_video"}}, {"model": "auth.permission", "pk": 714, "fields": {"name": "Can add course video", "content_type": 238, "codename": "add_coursevideo"}}, {"model": "auth.permission", "pk": 715, "fields": {"name": "Can change course video", "content_type": 238, "codename": "change_coursevideo"}}, {"model": "auth.permission", "pk": 716, "fields": {"name": "Can delete course video", "content_type": 238, "codename": "delete_coursevideo"}}, {"model": "auth.permission", "pk": 717, "fields": {"name": "Can add encoded video", "content_type": 239, "codename": "add_encodedvideo"}}, {"model": "auth.permission", "pk": 718, "fields": {"name": "Can change encoded video", "content_type": 239, "codename": "change_encodedvideo"}}, {"model": "auth.permission", "pk": 719, "fields": {"name": "Can delete encoded video", "content_type": 239, "codename": "delete_encodedvideo"}}, {"model": "auth.permission", "pk": 720, "fields": {"name": "Can add video image", "content_type": 240, "codename": "add_videoimage"}}, {"model": "auth.permission", "pk": 721, "fields": {"name": "Can change video image", "content_type": 240, "codename": "change_videoimage"}}, {"model": "auth.permission", "pk": 722, "fields": {"name": "Can delete video image", "content_type": 240, "codename": "delete_videoimage"}}, {"model": "auth.permission", "pk": 723, "fields": {"name": "Can add video transcript", "content_type": 241, "codename": "add_videotranscript"}}, {"model": "auth.permission", "pk": 724, "fields": {"name": "Can change video transcript", "content_type": 241, "codename": "change_videotranscript"}}, {"model": "auth.permission", "pk": 725, "fields": {"name": "Can delete video transcript", "content_type": 241, "codename": "delete_videotranscript"}}, {"model": "auth.permission", "pk": 726, "fields": {"name": "Can add transcript preference", "content_type": 242, "codename": "add_transcriptpreference"}}, {"model": "auth.permission", "pk": 727, "fields": {"name": "Can change transcript preference", "content_type": 242, "codename": "change_transcriptpreference"}}, {"model": "auth.permission", "pk": 728, "fields": {"name": "Can delete transcript preference", "content_type": 242, "codename": "delete_transcriptpreference"}}, {"model": "auth.permission", "pk": 729, "fields": {"name": "Can add third party transcript credentials state", "content_type": 243, "codename": "add_thirdpartytranscriptcredentialsstate"}}, {"model": "auth.permission", "pk": 730, "fields": {"name": "Can change third party transcript credentials state", "content_type": 243, "codename": "change_thirdpartytranscriptcredentialsstate"}}, {"model": "auth.permission", "pk": 731, "fields": {"name": "Can delete third party transcript credentials state", "content_type": 243, "codename": "delete_thirdpartytranscriptcredentialsstate"}}, {"model": "auth.permission", "pk": 732, "fields": {"name": "Can add course overview", "content_type": 244, "codename": "add_courseoverview"}}, {"model": "auth.permission", "pk": 733, "fields": {"name": "Can change course overview", "content_type": 244, "codename": "change_courseoverview"}}, {"model": "auth.permission", "pk": 734, "fields": {"name": "Can delete course overview", "content_type": 244, "codename": "delete_courseoverview"}}, {"model": "auth.permission", "pk": 735, "fields": {"name": "Can add course overview tab", "content_type": 245, "codename": "add_courseoverviewtab"}}, {"model": "auth.permission", "pk": 736, "fields": {"name": "Can change course overview tab", "content_type": 245, "codename": "change_courseoverviewtab"}}, {"model": "auth.permission", "pk": 737, "fields": {"name": "Can delete course overview tab", "content_type": 245, "codename": "delete_courseoverviewtab"}}, {"model": "auth.permission", "pk": 738, "fields": {"name": "Can add course overview image set", "content_type": 246, "codename": "add_courseoverviewimageset"}}, {"model": "auth.permission", "pk": 739, "fields": {"name": "Can change course overview image set", "content_type": 246, "codename": "change_courseoverviewimageset"}}, {"model": "auth.permission", "pk": 740, "fields": {"name": "Can delete course overview image set", "content_type": 246, "codename": "delete_courseoverviewimageset"}}, {"model": "auth.permission", "pk": 741, "fields": {"name": "Can add course overview image config", "content_type": 247, "codename": "add_courseoverviewimageconfig"}}, {"model": "auth.permission", "pk": 742, "fields": {"name": "Can change course overview image config", "content_type": 247, "codename": "change_courseoverviewimageconfig"}}, {"model": "auth.permission", "pk": 743, "fields": {"name": "Can delete course overview image config", "content_type": 247, "codename": "delete_courseoverviewimageconfig"}}, {"model": "auth.permission", "pk": 744, "fields": {"name": "Can add course structure", "content_type": 248, "codename": "add_coursestructure"}}, {"model": "auth.permission", "pk": 745, "fields": {"name": "Can change course structure", "content_type": 248, "codename": "change_coursestructure"}}, {"model": "auth.permission", "pk": 746, "fields": {"name": "Can delete course structure", "content_type": 248, "codename": "delete_coursestructure"}}, {"model": "auth.permission", "pk": 747, "fields": {"name": "Can add block structure configuration", "content_type": 249, "codename": "add_blockstructureconfiguration"}}, {"model": "auth.permission", "pk": 748, "fields": {"name": "Can change block structure configuration", "content_type": 249, "codename": "change_blockstructureconfiguration"}}, {"model": "auth.permission", "pk": 749, "fields": {"name": "Can delete block structure configuration", "content_type": 249, "codename": "delete_blockstructureconfiguration"}}, {"model": "auth.permission", "pk": 750, "fields": {"name": "Can add block structure model", "content_type": 250, "codename": "add_blockstructuremodel"}}, {"model": "auth.permission", "pk": 751, "fields": {"name": "Can change block structure model", "content_type": 250, "codename": "change_blockstructuremodel"}}, {"model": "auth.permission", "pk": 752, "fields": {"name": "Can delete block structure model", "content_type": 250, "codename": "delete_blockstructuremodel"}}, {"model": "auth.permission", "pk": 753, "fields": {"name": "Can add x domain proxy configuration", "content_type": 251, "codename": "add_xdomainproxyconfiguration"}}, {"model": "auth.permission", "pk": 754, "fields": {"name": "Can change x domain proxy configuration", "content_type": 251, "codename": "change_xdomainproxyconfiguration"}}, {"model": "auth.permission", "pk": 755, "fields": {"name": "Can delete x domain proxy configuration", "content_type": 251, "codename": "delete_xdomainproxyconfiguration"}}, {"model": "auth.permission", "pk": 756, "fields": {"name": "Can add commerce configuration", "content_type": 252, "codename": "add_commerceconfiguration"}}, {"model": "auth.permission", "pk": 757, "fields": {"name": "Can change commerce configuration", "content_type": 252, "codename": "change_commerceconfiguration"}}, {"model": "auth.permission", "pk": 758, "fields": {"name": "Can delete commerce configuration", "content_type": 252, "codename": "delete_commerceconfiguration"}}, {"model": "auth.permission", "pk": 759, "fields": {"name": "Can add credit provider", "content_type": 253, "codename": "add_creditprovider"}}, {"model": "auth.permission", "pk": 760, "fields": {"name": "Can change credit provider", "content_type": 253, "codename": "change_creditprovider"}}, {"model": "auth.permission", "pk": 761, "fields": {"name": "Can delete credit provider", "content_type": 253, "codename": "delete_creditprovider"}}, {"model": "auth.permission", "pk": 762, "fields": {"name": "Can add credit course", "content_type": 254, "codename": "add_creditcourse"}}, {"model": "auth.permission", "pk": 763, "fields": {"name": "Can change credit course", "content_type": 254, "codename": "change_creditcourse"}}, {"model": "auth.permission", "pk": 764, "fields": {"name": "Can delete credit course", "content_type": 254, "codename": "delete_creditcourse"}}, {"model": "auth.permission", "pk": 765, "fields": {"name": "Can add credit requirement", "content_type": 255, "codename": "add_creditrequirement"}}, {"model": "auth.permission", "pk": 766, "fields": {"name": "Can change credit requirement", "content_type": 255, "codename": "change_creditrequirement"}}, {"model": "auth.permission", "pk": 767, "fields": {"name": "Can delete credit requirement", "content_type": 255, "codename": "delete_creditrequirement"}}, {"model": "auth.permission", "pk": 768, "fields": {"name": "Can add credit requirement status", "content_type": 256, "codename": "add_creditrequirementstatus"}}, {"model": "auth.permission", "pk": 769, "fields": {"name": "Can change credit requirement status", "content_type": 256, "codename": "change_creditrequirementstatus"}}, {"model": "auth.permission", "pk": 770, "fields": {"name": "Can delete credit requirement status", "content_type": 256, "codename": "delete_creditrequirementstatus"}}, {"model": "auth.permission", "pk": 771, "fields": {"name": "Can add credit eligibility", "content_type": 257, "codename": "add_crediteligibility"}}, {"model": "auth.permission", "pk": 772, "fields": {"name": "Can change credit eligibility", "content_type": 257, "codename": "change_crediteligibility"}}, {"model": "auth.permission", "pk": 773, "fields": {"name": "Can delete credit eligibility", "content_type": 257, "codename": "delete_crediteligibility"}}, {"model": "auth.permission", "pk": 774, "fields": {"name": "Can add credit request", "content_type": 258, "codename": "add_creditrequest"}}, {"model": "auth.permission", "pk": 775, "fields": {"name": "Can change credit request", "content_type": 258, "codename": "change_creditrequest"}}, {"model": "auth.permission", "pk": 776, "fields": {"name": "Can delete credit request", "content_type": 258, "codename": "delete_creditrequest"}}, {"model": "auth.permission", "pk": 777, "fields": {"name": "Can add credit config", "content_type": 259, "codename": "add_creditconfig"}}, {"model": "auth.permission", "pk": 778, "fields": {"name": "Can change credit config", "content_type": 259, "codename": "change_creditconfig"}}, {"model": "auth.permission", "pk": 779, "fields": {"name": "Can delete credit config", "content_type": 259, "codename": "delete_creditconfig"}}, {"model": "auth.permission", "pk": 780, "fields": {"name": "Can add course team", "content_type": 260, "codename": "add_courseteam"}}, {"model": "auth.permission", "pk": 781, "fields": {"name": "Can change course team", "content_type": 260, "codename": "change_courseteam"}}, {"model": "auth.permission", "pk": 782, "fields": {"name": "Can delete course team", "content_type": 260, "codename": "delete_courseteam"}}, {"model": "auth.permission", "pk": 783, "fields": {"name": "Can add course team membership", "content_type": 261, "codename": "add_courseteammembership"}}, {"model": "auth.permission", "pk": 784, "fields": {"name": "Can change course team membership", "content_type": 261, "codename": "change_courseteammembership"}}, {"model": "auth.permission", "pk": 785, "fields": {"name": "Can delete course team membership", "content_type": 261, "codename": "delete_courseteammembership"}}, {"model": "auth.permission", "pk": 786, "fields": {"name": "Can add x block configuration", "content_type": 262, "codename": "add_xblockconfiguration"}}, {"model": "auth.permission", "pk": 787, "fields": {"name": "Can change x block configuration", "content_type": 262, "codename": "change_xblockconfiguration"}}, {"model": "auth.permission", "pk": 788, "fields": {"name": "Can delete x block configuration", "content_type": 262, "codename": "delete_xblockconfiguration"}}, {"model": "auth.permission", "pk": 789, "fields": {"name": "Can add x block studio configuration flag", "content_type": 263, "codename": "add_xblockstudioconfigurationflag"}}, {"model": "auth.permission", "pk": 790, "fields": {"name": "Can change x block studio configuration flag", "content_type": 263, "codename": "change_xblockstudioconfigurationflag"}}, {"model": "auth.permission", "pk": 791, "fields": {"name": "Can delete x block studio configuration flag", "content_type": 263, "codename": "delete_xblockstudioconfigurationflag"}}, {"model": "auth.permission", "pk": 792, "fields": {"name": "Can add x block studio configuration", "content_type": 264, "codename": "add_xblockstudioconfiguration"}}, {"model": "auth.permission", "pk": 793, "fields": {"name": "Can change x block studio configuration", "content_type": 264, "codename": "change_xblockstudioconfiguration"}}, {"model": "auth.permission", "pk": 794, "fields": {"name": "Can delete x block studio configuration", "content_type": 264, "codename": "delete_xblockstudioconfiguration"}}, {"model": "auth.permission", "pk": 795, "fields": {"name": "Can add programs api config", "content_type": 265, "codename": "add_programsapiconfig"}}, {"model": "auth.permission", "pk": 796, "fields": {"name": "Can change programs api config", "content_type": 265, "codename": "change_programsapiconfig"}}, {"model": "auth.permission", "pk": 797, "fields": {"name": "Can delete programs api config", "content_type": 265, "codename": "delete_programsapiconfig"}}, {"model": "auth.permission", "pk": 798, "fields": {"name": "Can add catalog integration", "content_type": 266, "codename": "add_catalogintegration"}}, {"model": "auth.permission", "pk": 799, "fields": {"name": "Can change catalog integration", "content_type": 266, "codename": "change_catalogintegration"}}, {"model": "auth.permission", "pk": 800, "fields": {"name": "Can delete catalog integration", "content_type": 266, "codename": "delete_catalogintegration"}}, {"model": "auth.permission", "pk": 801, "fields": {"name": "Can add self paced configuration", "content_type": 267, "codename": "add_selfpacedconfiguration"}}, {"model": "auth.permission", "pk": 802, "fields": {"name": "Can change self paced configuration", "content_type": 267, "codename": "change_selfpacedconfiguration"}}, {"model": "auth.permission", "pk": 803, "fields": {"name": "Can delete self paced configuration", "content_type": 267, "codename": "delete_selfpacedconfiguration"}}, {"model": "auth.permission", "pk": 804, "fields": {"name": "Can add kv store", "content_type": 268, "codename": "add_kvstore"}}, {"model": "auth.permission", "pk": 805, "fields": {"name": "Can change kv store", "content_type": 268, "codename": "change_kvstore"}}, {"model": "auth.permission", "pk": 806, "fields": {"name": "Can delete kv store", "content_type": 268, "codename": "delete_kvstore"}}, {"model": "auth.permission", "pk": 807, "fields": {"name": "Can add credentials api config", "content_type": 269, "codename": "add_credentialsapiconfig"}}, {"model": "auth.permission", "pk": 808, "fields": {"name": "Can change credentials api config", "content_type": 269, "codename": "change_credentialsapiconfig"}}, {"model": "auth.permission", "pk": 809, "fields": {"name": "Can delete credentials api config", "content_type": 269, "codename": "delete_credentialsapiconfig"}}, {"model": "auth.permission", "pk": 810, "fields": {"name": "Can add milestone", "content_type": 270, "codename": "add_milestone"}}, {"model": "auth.permission", "pk": 811, "fields": {"name": "Can change milestone", "content_type": 270, "codename": "change_milestone"}}, {"model": "auth.permission", "pk": 812, "fields": {"name": "Can delete milestone", "content_type": 270, "codename": "delete_milestone"}}, {"model": "auth.permission", "pk": 813, "fields": {"name": "Can add milestone relationship type", "content_type": 271, "codename": "add_milestonerelationshiptype"}}, {"model": "auth.permission", "pk": 814, "fields": {"name": "Can change milestone relationship type", "content_type": 271, "codename": "change_milestonerelationshiptype"}}, {"model": "auth.permission", "pk": 815, "fields": {"name": "Can delete milestone relationship type", "content_type": 271, "codename": "delete_milestonerelationshiptype"}}, {"model": "auth.permission", "pk": 816, "fields": {"name": "Can add course milestone", "content_type": 272, "codename": "add_coursemilestone"}}, {"model": "auth.permission", "pk": 817, "fields": {"name": "Can change course milestone", "content_type": 272, "codename": "change_coursemilestone"}}, {"model": "auth.permission", "pk": 818, "fields": {"name": "Can delete course milestone", "content_type": 272, "codename": "delete_coursemilestone"}}, {"model": "auth.permission", "pk": 819, "fields": {"name": "Can add course content milestone", "content_type": 273, "codename": "add_coursecontentmilestone"}}, {"model": "auth.permission", "pk": 820, "fields": {"name": "Can change course content milestone", "content_type": 273, "codename": "change_coursecontentmilestone"}}, {"model": "auth.permission", "pk": 821, "fields": {"name": "Can delete course content milestone", "content_type": 273, "codename": "delete_coursecontentmilestone"}}, {"model": "auth.permission", "pk": 822, "fields": {"name": "Can add user milestone", "content_type": 274, "codename": "add_usermilestone"}}, {"model": "auth.permission", "pk": 823, "fields": {"name": "Can change user milestone", "content_type": 274, "codename": "change_usermilestone"}}, {"model": "auth.permission", "pk": 824, "fields": {"name": "Can delete user milestone", "content_type": 274, "codename": "delete_usermilestone"}}, {"model": "auth.permission", "pk": 825, "fields": {"name": "Can add api access request", "content_type": 1, "codename": "add_apiaccessrequest"}}, {"model": "auth.permission", "pk": 826, "fields": {"name": "Can change api access request", "content_type": 1, "codename": "change_apiaccessrequest"}}, {"model": "auth.permission", "pk": 827, "fields": {"name": "Can delete api access request", "content_type": 1, "codename": "delete_apiaccessrequest"}}, {"model": "auth.permission", "pk": 828, "fields": {"name": "Can add api access config", "content_type": 275, "codename": "add_apiaccessconfig"}}, {"model": "auth.permission", "pk": 829, "fields": {"name": "Can change api access config", "content_type": 275, "codename": "change_apiaccessconfig"}}, {"model": "auth.permission", "pk": 830, "fields": {"name": "Can delete api access config", "content_type": 275, "codename": "delete_apiaccessconfig"}}, {"model": "auth.permission", "pk": 831, "fields": {"name": "Can add catalog", "content_type": 276, "codename": "add_catalog"}}, {"model": "auth.permission", "pk": 832, "fields": {"name": "Can change catalog", "content_type": 276, "codename": "change_catalog"}}, {"model": "auth.permission", "pk": 833, "fields": {"name": "Can delete catalog", "content_type": 276, "codename": "delete_catalog"}}, {"model": "auth.permission", "pk": 834, "fields": {"name": "Can add verified track cohorted course", "content_type": 277, "codename": "add_verifiedtrackcohortedcourse"}}, {"model": "auth.permission", "pk": 835, "fields": {"name": "Can change verified track cohorted course", "content_type": 277, "codename": "change_verifiedtrackcohortedcourse"}}, {"model": "auth.permission", "pk": 836, "fields": {"name": "Can delete verified track cohorted course", "content_type": 277, "codename": "delete_verifiedtrackcohortedcourse"}}, {"model": "auth.permission", "pk": 837, "fields": {"name": "Can add migrate verified track cohorts setting", "content_type": 278, "codename": "add_migrateverifiedtrackcohortssetting"}}, {"model": "auth.permission", "pk": 838, "fields": {"name": "Can change migrate verified track cohorts setting", "content_type": 278, "codename": "change_migrateverifiedtrackcohortssetting"}}, {"model": "auth.permission", "pk": 839, "fields": {"name": "Can delete migrate verified track cohorts setting", "content_type": 278, "codename": "delete_migrateverifiedtrackcohortssetting"}}, {"model": "auth.permission", "pk": 840, "fields": {"name": "Can add badge class", "content_type": 279, "codename": "add_badgeclass"}}, {"model": "auth.permission", "pk": 841, "fields": {"name": "Can change badge class", "content_type": 279, "codename": "change_badgeclass"}}, {"model": "auth.permission", "pk": 842, "fields": {"name": "Can delete badge class", "content_type": 279, "codename": "delete_badgeclass"}}, {"model": "auth.permission", "pk": 843, "fields": {"name": "Can add badge assertion", "content_type": 280, "codename": "add_badgeassertion"}}, {"model": "auth.permission", "pk": 844, "fields": {"name": "Can change badge assertion", "content_type": 280, "codename": "change_badgeassertion"}}, {"model": "auth.permission", "pk": 845, "fields": {"name": "Can delete badge assertion", "content_type": 280, "codename": "delete_badgeassertion"}}, {"model": "auth.permission", "pk": 846, "fields": {"name": "Can add course complete image configuration", "content_type": 281, "codename": "add_coursecompleteimageconfiguration"}}, {"model": "auth.permission", "pk": 847, "fields": {"name": "Can change course complete image configuration", "content_type": 281, "codename": "change_coursecompleteimageconfiguration"}}, {"model": "auth.permission", "pk": 848, "fields": {"name": "Can delete course complete image configuration", "content_type": 281, "codename": "delete_coursecompleteimageconfiguration"}}, {"model": "auth.permission", "pk": 849, "fields": {"name": "Can add course event badges configuration", "content_type": 282, "codename": "add_courseeventbadgesconfiguration"}}, {"model": "auth.permission", "pk": 850, "fields": {"name": "Can change course event badges configuration", "content_type": 282, "codename": "change_courseeventbadgesconfiguration"}}, {"model": "auth.permission", "pk": 851, "fields": {"name": "Can delete course event badges configuration", "content_type": 282, "codename": "delete_courseeventbadgesconfiguration"}}, {"model": "auth.permission", "pk": 852, "fields": {"name": "Can add email marketing configuration", "content_type": 283, "codename": "add_emailmarketingconfiguration"}}, {"model": "auth.permission", "pk": 853, "fields": {"name": "Can change email marketing configuration", "content_type": 283, "codename": "change_emailmarketingconfiguration"}}, {"model": "auth.permission", "pk": 854, "fields": {"name": "Can delete email marketing configuration", "content_type": 283, "codename": "delete_emailmarketingconfiguration"}}, {"model": "auth.permission", "pk": 855, "fields": {"name": "Can add failed task", "content_type": 284, "codename": "add_failedtask"}}, {"model": "auth.permission", "pk": 856, "fields": {"name": "Can change failed task", "content_type": 284, "codename": "change_failedtask"}}, {"model": "auth.permission", "pk": 857, "fields": {"name": "Can delete failed task", "content_type": 284, "codename": "delete_failedtask"}}, {"model": "auth.permission", "pk": 858, "fields": {"name": "Can add chord data", "content_type": 285, "codename": "add_chorddata"}}, {"model": "auth.permission", "pk": 859, "fields": {"name": "Can change chord data", "content_type": 285, "codename": "change_chorddata"}}, {"model": "auth.permission", "pk": 860, "fields": {"name": "Can delete chord data", "content_type": 285, "codename": "delete_chorddata"}}, {"model": "auth.permission", "pk": 861, "fields": {"name": "Can add crawlers config", "content_type": 286, "codename": "add_crawlersconfig"}}, {"model": "auth.permission", "pk": 862, "fields": {"name": "Can change crawlers config", "content_type": 286, "codename": "change_crawlersconfig"}}, {"model": "auth.permission", "pk": 863, "fields": {"name": "Can delete crawlers config", "content_type": 286, "codename": "delete_crawlersconfig"}}, {"model": "auth.permission", "pk": 864, "fields": {"name": "Can add Waffle flag course override", "content_type": 287, "codename": "add_waffleflagcourseoverridemodel"}}, {"model": "auth.permission", "pk": 865, "fields": {"name": "Can change Waffle flag course override", "content_type": 287, "codename": "change_waffleflagcourseoverridemodel"}}, {"model": "auth.permission", "pk": 866, "fields": {"name": "Can delete Waffle flag course override", "content_type": 287, "codename": "delete_waffleflagcourseoverridemodel"}}, {"model": "auth.permission", "pk": 867, "fields": {"name": "Can add Schedule", "content_type": 288, "codename": "add_schedule"}}, {"model": "auth.permission", "pk": 868, "fields": {"name": "Can change Schedule", "content_type": 288, "codename": "change_schedule"}}, {"model": "auth.permission", "pk": 869, "fields": {"name": "Can delete Schedule", "content_type": 288, "codename": "delete_schedule"}}, {"model": "auth.permission", "pk": 870, "fields": {"name": "Can add schedule config", "content_type": 289, "codename": "add_scheduleconfig"}}, {"model": "auth.permission", "pk": 871, "fields": {"name": "Can change schedule config", "content_type": 289, "codename": "change_scheduleconfig"}}, {"model": "auth.permission", "pk": 872, "fields": {"name": "Can delete schedule config", "content_type": 289, "codename": "delete_scheduleconfig"}}, {"model": "auth.permission", "pk": 873, "fields": {"name": "Can add schedule experience", "content_type": 290, "codename": "add_scheduleexperience"}}, {"model": "auth.permission", "pk": 874, "fields": {"name": "Can change schedule experience", "content_type": 290, "codename": "change_scheduleexperience"}}, {"model": "auth.permission", "pk": 875, "fields": {"name": "Can delete schedule experience", "content_type": 290, "codename": "delete_scheduleexperience"}}, {"model": "auth.permission", "pk": 876, "fields": {"name": "Can add course goal", "content_type": 291, "codename": "add_coursegoal"}}, {"model": "auth.permission", "pk": 877, "fields": {"name": "Can change course goal", "content_type": 291, "codename": "change_coursegoal"}}, {"model": "auth.permission", "pk": 878, "fields": {"name": "Can delete course goal", "content_type": 291, "codename": "delete_coursegoal"}}, {"model": "auth.permission", "pk": 879, "fields": {"name": "Can add block completion", "content_type": 292, "codename": "add_blockcompletion"}}, {"model": "auth.permission", "pk": 880, "fields": {"name": "Can change block completion", "content_type": 292, "codename": "change_blockcompletion"}}, {"model": "auth.permission", "pk": 881, "fields": {"name": "Can delete block completion", "content_type": 292, "codename": "delete_blockcompletion"}}, {"model": "auth.permission", "pk": 882, "fields": {"name": "Can add Experiment Data", "content_type": 293, "codename": "add_experimentdata"}}, {"model": "auth.permission", "pk": 883, "fields": {"name": "Can change Experiment Data", "content_type": 293, "codename": "change_experimentdata"}}, {"model": "auth.permission", "pk": 884, "fields": {"name": "Can delete Experiment Data", "content_type": 293, "codename": "delete_experimentdata"}}, {"model": "auth.permission", "pk": 885, "fields": {"name": "Can add Experiment Key-Value Pair", "content_type": 294, "codename": "add_experimentkeyvalue"}}, {"model": "auth.permission", "pk": 886, "fields": {"name": "Can change Experiment Key-Value Pair", "content_type": 294, "codename": "change_experimentkeyvalue"}}, {"model": "auth.permission", "pk": 887, "fields": {"name": "Can delete Experiment Key-Value Pair", "content_type": 294, "codename": "delete_experimentkeyvalue"}}, {"model": "auth.permission", "pk": 888, "fields": {"name": "Can add proctored exam", "content_type": 295, "codename": "add_proctoredexam"}}, {"model": "auth.permission", "pk": 889, "fields": {"name": "Can change proctored exam", "content_type": 295, "codename": "change_proctoredexam"}}, {"model": "auth.permission", "pk": 890, "fields": {"name": "Can delete proctored exam", "content_type": 295, "codename": "delete_proctoredexam"}}, {"model": "auth.permission", "pk": 891, "fields": {"name": "Can add Proctored exam review policy", "content_type": 296, "codename": "add_proctoredexamreviewpolicy"}}, {"model": "auth.permission", "pk": 892, "fields": {"name": "Can change Proctored exam review policy", "content_type": 296, "codename": "change_proctoredexamreviewpolicy"}}, {"model": "auth.permission", "pk": 893, "fields": {"name": "Can delete Proctored exam review policy", "content_type": 296, "codename": "delete_proctoredexamreviewpolicy"}}, {"model": "auth.permission", "pk": 894, "fields": {"name": "Can add proctored exam review policy history", "content_type": 297, "codename": "add_proctoredexamreviewpolicyhistory"}}, {"model": "auth.permission", "pk": 895, "fields": {"name": "Can change proctored exam review policy history", "content_type": 297, "codename": "change_proctoredexamreviewpolicyhistory"}}, {"model": "auth.permission", "pk": 896, "fields": {"name": "Can delete proctored exam review policy history", "content_type": 297, "codename": "delete_proctoredexamreviewpolicyhistory"}}, {"model": "auth.permission", "pk": 897, "fields": {"name": "Can add proctored exam attempt", "content_type": 298, "codename": "add_proctoredexamstudentattempt"}}, {"model": "auth.permission", "pk": 898, "fields": {"name": "Can change proctored exam attempt", "content_type": 298, "codename": "change_proctoredexamstudentattempt"}}, {"model": "auth.permission", "pk": 899, "fields": {"name": "Can delete proctored exam attempt", "content_type": 298, "codename": "delete_proctoredexamstudentattempt"}}, {"model": "auth.permission", "pk": 900, "fields": {"name": "Can add proctored exam attempt history", "content_type": 299, "codename": "add_proctoredexamstudentattempthistory"}}, {"model": "auth.permission", "pk": 901, "fields": {"name": "Can change proctored exam attempt history", "content_type": 299, "codename": "change_proctoredexamstudentattempthistory"}}, {"model": "auth.permission", "pk": 902, "fields": {"name": "Can delete proctored exam attempt history", "content_type": 299, "codename": "delete_proctoredexamstudentattempthistory"}}, {"model": "auth.permission", "pk": 903, "fields": {"name": "Can add proctored allowance", "content_type": 300, "codename": "add_proctoredexamstudentallowance"}}, {"model": "auth.permission", "pk": 904, "fields": {"name": "Can change proctored allowance", "content_type": 300, "codename": "change_proctoredexamstudentallowance"}}, {"model": "auth.permission", "pk": 905, "fields": {"name": "Can delete proctored allowance", "content_type": 300, "codename": "delete_proctoredexamstudentallowance"}}, {"model": "auth.permission", "pk": 906, "fields": {"name": "Can add proctored allowance history", "content_type": 301, "codename": "add_proctoredexamstudentallowancehistory"}}, {"model": "auth.permission", "pk": 907, "fields": {"name": "Can change proctored allowance history", "content_type": 301, "codename": "change_proctoredexamstudentallowancehistory"}}, {"model": "auth.permission", "pk": 908, "fields": {"name": "Can delete proctored allowance history", "content_type": 301, "codename": "delete_proctoredexamstudentallowancehistory"}}, {"model": "auth.permission", "pk": 909, "fields": {"name": "Can add Proctored exam software secure review", "content_type": 302, "codename": "add_proctoredexamsoftwaresecurereview"}}, {"model": "auth.permission", "pk": 910, "fields": {"name": "Can change Proctored exam software secure review", "content_type": 302, "codename": "change_proctoredexamsoftwaresecurereview"}}, {"model": "auth.permission", "pk": 911, "fields": {"name": "Can delete Proctored exam software secure review", "content_type": 302, "codename": "delete_proctoredexamsoftwaresecurereview"}}, {"model": "auth.permission", "pk": 912, "fields": {"name": "Can add Proctored exam review archive", "content_type": 303, "codename": "add_proctoredexamsoftwaresecurereviewhistory"}}, {"model": "auth.permission", "pk": 913, "fields": {"name": "Can change Proctored exam review archive", "content_type": 303, "codename": "change_proctoredexamsoftwaresecurereviewhistory"}}, {"model": "auth.permission", "pk": 914, "fields": {"name": "Can delete Proctored exam review archive", "content_type": 303, "codename": "delete_proctoredexamsoftwaresecurereviewhistory"}}, {"model": "auth.permission", "pk": 915, "fields": {"name": "Can add proctored exam software secure comment", "content_type": 304, "codename": "add_proctoredexamsoftwaresecurecomment"}}, {"model": "auth.permission", "pk": 916, "fields": {"name": "Can change proctored exam software secure comment", "content_type": 304, "codename": "change_proctoredexamsoftwaresecurecomment"}}, {"model": "auth.permission", "pk": 917, "fields": {"name": "Can delete proctored exam software secure comment", "content_type": 304, "codename": "delete_proctoredexamsoftwaresecurecomment"}}, {"model": "auth.permission", "pk": 918, "fields": {"name": "Can add organization", "content_type": 305, "codename": "add_organization"}}, {"model": "auth.permission", "pk": 919, "fields": {"name": "Can change organization", "content_type": 305, "codename": "change_organization"}}, {"model": "auth.permission", "pk": 920, "fields": {"name": "Can delete organization", "content_type": 305, "codename": "delete_organization"}}, {"model": "auth.permission", "pk": 921, "fields": {"name": "Can add Link Course", "content_type": 306, "codename": "add_organizationcourse"}}, {"model": "auth.permission", "pk": 922, "fields": {"name": "Can change Link Course", "content_type": 306, "codename": "change_organizationcourse"}}, {"model": "auth.permission", "pk": 923, "fields": {"name": "Can delete Link Course", "content_type": 306, "codename": "delete_organizationcourse"}}, {"model": "auth.permission", "pk": 924, "fields": {"name": "Can add historical Enterprise Customer", "content_type": 307, "codename": "add_historicalenterprisecustomer"}}, {"model": "auth.permission", "pk": 925, "fields": {"name": "Can change historical Enterprise Customer", "content_type": 307, "codename": "change_historicalenterprisecustomer"}}, {"model": "auth.permission", "pk": 926, "fields": {"name": "Can delete historical Enterprise Customer", "content_type": 307, "codename": "delete_historicalenterprisecustomer"}}, {"model": "auth.permission", "pk": 927, "fields": {"name": "Can add Enterprise Customer", "content_type": 308, "codename": "add_enterprisecustomer"}}, {"model": "auth.permission", "pk": 928, "fields": {"name": "Can change Enterprise Customer", "content_type": 308, "codename": "change_enterprisecustomer"}}, {"model": "auth.permission", "pk": 929, "fields": {"name": "Can delete Enterprise Customer", "content_type": 308, "codename": "delete_enterprisecustomer"}}, {"model": "auth.permission", "pk": 930, "fields": {"name": "Can add Enterprise Customer Learner", "content_type": 309, "codename": "add_enterprisecustomeruser"}}, {"model": "auth.permission", "pk": 931, "fields": {"name": "Can change Enterprise Customer Learner", "content_type": 309, "codename": "change_enterprisecustomeruser"}}, {"model": "auth.permission", "pk": 932, "fields": {"name": "Can delete Enterprise Customer Learner", "content_type": 309, "codename": "delete_enterprisecustomeruser"}}, {"model": "auth.permission", "pk": 933, "fields": {"name": "Can add pending enterprise customer user", "content_type": 310, "codename": "add_pendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 934, "fields": {"name": "Can change pending enterprise customer user", "content_type": 310, "codename": "change_pendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 935, "fields": {"name": "Can delete pending enterprise customer user", "content_type": 310, "codename": "delete_pendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 936, "fields": {"name": "Can add pending enrollment", "content_type": 311, "codename": "add_pendingenrollment"}}, {"model": "auth.permission", "pk": 937, "fields": {"name": "Can change pending enrollment", "content_type": 311, "codename": "change_pendingenrollment"}}, {"model": "auth.permission", "pk": 938, "fields": {"name": "Can delete pending enrollment", "content_type": 311, "codename": "delete_pendingenrollment"}}, {"model": "auth.permission", "pk": 939, "fields": {"name": "Can add Branding Configuration", "content_type": 312, "codename": "add_enterprisecustomerbrandingconfiguration"}}, {"model": "auth.permission", "pk": 940, "fields": {"name": "Can change Branding Configuration", "content_type": 312, "codename": "change_enterprisecustomerbrandingconfiguration"}}, {"model": "auth.permission", "pk": 941, "fields": {"name": "Can delete Branding Configuration", "content_type": 312, "codename": "delete_enterprisecustomerbrandingconfiguration"}}, {"model": "auth.permission", "pk": 942, "fields": {"name": "Can add enterprise customer identity provider", "content_type": 313, "codename": "add_enterprisecustomeridentityprovider"}}, {"model": "auth.permission", "pk": 943, "fields": {"name": "Can change enterprise customer identity provider", "content_type": 313, "codename": "change_enterprisecustomeridentityprovider"}}, {"model": "auth.permission", "pk": 944, "fields": {"name": "Can delete enterprise customer identity provider", "content_type": 313, "codename": "delete_enterprisecustomeridentityprovider"}}, {"model": "auth.permission", "pk": 945, "fields": {"name": "Can add historical Enterprise Customer Entitlement", "content_type": 314, "codename": "add_historicalenterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 946, "fields": {"name": "Can change historical Enterprise Customer Entitlement", "content_type": 314, "codename": "change_historicalenterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 947, "fields": {"name": "Can delete historical Enterprise Customer Entitlement", "content_type": 314, "codename": "delete_historicalenterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 948, "fields": {"name": "Can add Enterprise Customer Entitlement", "content_type": 315, "codename": "add_enterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 949, "fields": {"name": "Can change Enterprise Customer Entitlement", "content_type": 315, "codename": "change_enterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 950, "fields": {"name": "Can delete Enterprise Customer Entitlement", "content_type": 315, "codename": "delete_enterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 951, "fields": {"name": "Can add historical enterprise course enrollment", "content_type": 316, "codename": "add_historicalenterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 952, "fields": {"name": "Can change historical enterprise course enrollment", "content_type": 316, "codename": "change_historicalenterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 953, "fields": {"name": "Can delete historical enterprise course enrollment", "content_type": 316, "codename": "delete_historicalenterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 954, "fields": {"name": "Can add enterprise course enrollment", "content_type": 317, "codename": "add_enterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 955, "fields": {"name": "Can change enterprise course enrollment", "content_type": 317, "codename": "change_enterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 956, "fields": {"name": "Can delete enterprise course enrollment", "content_type": 317, "codename": "delete_enterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 957, "fields": {"name": "Can add historical Enterprise Customer Catalog", "content_type": 318, "codename": "add_historicalenterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 958, "fields": {"name": "Can change historical Enterprise Customer Catalog", "content_type": 318, "codename": "change_historicalenterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 959, "fields": {"name": "Can delete historical Enterprise Customer Catalog", "content_type": 318, "codename": "delete_historicalenterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 960, "fields": {"name": "Can add Enterprise Customer Catalog", "content_type": 319, "codename": "add_enterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 961, "fields": {"name": "Can change Enterprise Customer Catalog", "content_type": 319, "codename": "change_enterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 962, "fields": {"name": "Can delete Enterprise Customer Catalog", "content_type": 319, "codename": "delete_enterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 963, "fields": {"name": "Can add historical enrollment notification email template", "content_type": 320, "codename": "add_historicalenrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 964, "fields": {"name": "Can change historical enrollment notification email template", "content_type": 320, "codename": "change_historicalenrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 965, "fields": {"name": "Can delete historical enrollment notification email template", "content_type": 320, "codename": "delete_historicalenrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 966, "fields": {"name": "Can add enrollment notification email template", "content_type": 321, "codename": "add_enrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 967, "fields": {"name": "Can change enrollment notification email template", "content_type": 321, "codename": "change_enrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 968, "fields": {"name": "Can delete enrollment notification email template", "content_type": 321, "codename": "delete_enrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 969, "fields": {"name": "Can add enterprise customer reporting configuration", "content_type": 322, "codename": "add_enterprisecustomerreportingconfiguration"}}, {"model": "auth.permission", "pk": 970, "fields": {"name": "Can change enterprise customer reporting configuration", "content_type": 322, "codename": "change_enterprisecustomerreportingconfiguration"}}, {"model": "auth.permission", "pk": 971, "fields": {"name": "Can delete enterprise customer reporting configuration", "content_type": 322, "codename": "delete_enterprisecustomerreportingconfiguration"}}, {"model": "auth.permission", "pk": 972, "fields": {"name": "Can add historical Data Sharing Consent Record", "content_type": 323, "codename": "add_historicaldatasharingconsent"}}, {"model": "auth.permission", "pk": 973, "fields": {"name": "Can change historical Data Sharing Consent Record", "content_type": 323, "codename": "change_historicaldatasharingconsent"}}, {"model": "auth.permission", "pk": 974, "fields": {"name": "Can delete historical Data Sharing Consent Record", "content_type": 323, "codename": "delete_historicaldatasharingconsent"}}, {"model": "auth.permission", "pk": 975, "fields": {"name": "Can add Data Sharing Consent Record", "content_type": 324, "codename": "add_datasharingconsent"}}, {"model": "auth.permission", "pk": 976, "fields": {"name": "Can change Data Sharing Consent Record", "content_type": 324, "codename": "change_datasharingconsent"}}, {"model": "auth.permission", "pk": 977, "fields": {"name": "Can delete Data Sharing Consent Record", "content_type": 324, "codename": "delete_datasharingconsent"}}, {"model": "auth.permission", "pk": 978, "fields": {"name": "Can add learner data transmission audit", "content_type": 325, "codename": "add_learnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 979, "fields": {"name": "Can change learner data transmission audit", "content_type": 325, "codename": "change_learnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 980, "fields": {"name": "Can delete learner data transmission audit", "content_type": 325, "codename": "delete_learnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 981, "fields": {"name": "Can add catalog transmission audit", "content_type": 326, "codename": "add_catalogtransmissionaudit"}}, {"model": "auth.permission", "pk": 982, "fields": {"name": "Can change catalog transmission audit", "content_type": 326, "codename": "change_catalogtransmissionaudit"}}, {"model": "auth.permission", "pk": 983, "fields": {"name": "Can delete catalog transmission audit", "content_type": 326, "codename": "delete_catalogtransmissionaudit"}}, {"model": "auth.permission", "pk": 984, "fields": {"name": "Can add degreed global configuration", "content_type": 327, "codename": "add_degreedglobalconfiguration"}}, {"model": "auth.permission", "pk": 985, "fields": {"name": "Can change degreed global configuration", "content_type": 327, "codename": "change_degreedglobalconfiguration"}}, {"model": "auth.permission", "pk": 986, "fields": {"name": "Can delete degreed global configuration", "content_type": 327, "codename": "delete_degreedglobalconfiguration"}}, {"model": "auth.permission", "pk": 987, "fields": {"name": "Can add historical degreed enterprise customer configuration", "content_type": 328, "codename": "add_historicaldegreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 988, "fields": {"name": "Can change historical degreed enterprise customer configuration", "content_type": 328, "codename": "change_historicaldegreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 989, "fields": {"name": "Can delete historical degreed enterprise customer configuration", "content_type": 328, "codename": "delete_historicaldegreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 990, "fields": {"name": "Can add degreed enterprise customer configuration", "content_type": 329, "codename": "add_degreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 991, "fields": {"name": "Can change degreed enterprise customer configuration", "content_type": 329, "codename": "change_degreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 992, "fields": {"name": "Can delete degreed enterprise customer configuration", "content_type": 329, "codename": "delete_degreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 993, "fields": {"name": "Can add degreed learner data transmission audit", "content_type": 330, "codename": "add_degreedlearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 994, "fields": {"name": "Can change degreed learner data transmission audit", "content_type": 330, "codename": "change_degreedlearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 995, "fields": {"name": "Can delete degreed learner data transmission audit", "content_type": 330, "codename": "delete_degreedlearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 996, "fields": {"name": "Can add sap success factors global configuration", "content_type": 331, "codename": "add_sapsuccessfactorsglobalconfiguration"}}, {"model": "auth.permission", "pk": 997, "fields": {"name": "Can change sap success factors global configuration", "content_type": 331, "codename": "change_sapsuccessfactorsglobalconfiguration"}}, {"model": "auth.permission", "pk": 998, "fields": {"name": "Can delete sap success factors global configuration", "content_type": 331, "codename": "delete_sapsuccessfactorsglobalconfiguration"}}, {"model": "auth.permission", "pk": 999, "fields": {"name": "Can add historical sap success factors enterprise customer configuration", "content_type": 332, "codename": "add_historicalsapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1000, "fields": {"name": "Can change historical sap success factors enterprise customer configuration", "content_type": 332, "codename": "change_historicalsapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1001, "fields": {"name": "Can delete historical sap success factors enterprise customer configuration", "content_type": 332, "codename": "delete_historicalsapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1002, "fields": {"name": "Can add sap success factors enterprise customer configuration", "content_type": 333, "codename": "add_sapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1003, "fields": {"name": "Can change sap success factors enterprise customer configuration", "content_type": 333, "codename": "change_sapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1004, "fields": {"name": "Can delete sap success factors enterprise customer configuration", "content_type": 333, "codename": "delete_sapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1005, "fields": {"name": "Can add sap success factors learner data transmission audit", "content_type": 334, "codename": "add_sapsuccessfactorslearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 1006, "fields": {"name": "Can change sap success factors learner data transmission audit", "content_type": 334, "codename": "change_sapsuccessfactorslearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 1007, "fields": {"name": "Can delete sap success factors learner data transmission audit", "content_type": 334, "codename": "delete_sapsuccessfactorslearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 1008, "fields": {"name": "Can add custom course for ed x", "content_type": 335, "codename": "add_customcourseforedx"}}, {"model": "auth.permission", "pk": 1009, "fields": {"name": "Can change custom course for ed x", "content_type": 335, "codename": "change_customcourseforedx"}}, {"model": "auth.permission", "pk": 1010, "fields": {"name": "Can delete custom course for ed x", "content_type": 335, "codename": "delete_customcourseforedx"}}, {"model": "auth.permission", "pk": 1011, "fields": {"name": "Can add ccx field override", "content_type": 336, "codename": "add_ccxfieldoverride"}}, {"model": "auth.permission", "pk": 1012, "fields": {"name": "Can change ccx field override", "content_type": 336, "codename": "change_ccxfieldoverride"}}, {"model": "auth.permission", "pk": 1013, "fields": {"name": "Can delete ccx field override", "content_type": 336, "codename": "delete_ccxfieldoverride"}}, {"model": "auth.permission", "pk": 1014, "fields": {"name": "Can add CCX Connector", "content_type": 337, "codename": "add_ccxcon"}}, {"model": "auth.permission", "pk": 1015, "fields": {"name": "Can change CCX Connector", "content_type": 337, "codename": "change_ccxcon"}}, {"model": "auth.permission", "pk": 1016, "fields": {"name": "Can delete CCX Connector", "content_type": 337, "codename": "delete_ccxcon"}}, {"model": "auth.permission", "pk": 1017, "fields": {"name": "Can add student module history extended", "content_type": 338, "codename": "add_studentmodulehistoryextended"}}, {"model": "auth.permission", "pk": 1018, "fields": {"name": "Can change student module history extended", "content_type": 338, "codename": "change_studentmodulehistoryextended"}}, {"model": "auth.permission", "pk": 1019, "fields": {"name": "Can delete student module history extended", "content_type": 338, "codename": "delete_studentmodulehistoryextended"}}, {"model": "auth.permission", "pk": 1020, "fields": {"name": "Can add video upload config", "content_type": 339, "codename": "add_videouploadconfig"}}, {"model": "auth.permission", "pk": 1021, "fields": {"name": "Can change video upload config", "content_type": 339, "codename": "change_videouploadconfig"}}, {"model": "auth.permission", "pk": 1022, "fields": {"name": "Can delete video upload config", "content_type": 339, "codename": "delete_videouploadconfig"}}, {"model": "auth.permission", "pk": 1023, "fields": {"name": "Can add push notification config", "content_type": 340, "codename": "add_pushnotificationconfig"}}, {"model": "auth.permission", "pk": 1024, "fields": {"name": "Can change push notification config", "content_type": 340, "codename": "change_pushnotificationconfig"}}, {"model": "auth.permission", "pk": 1025, "fields": {"name": "Can delete push notification config", "content_type": 340, "codename": "delete_pushnotificationconfig"}}, {"model": "auth.permission", "pk": 1026, "fields": {"name": "Can add new assets page flag", "content_type": 341, "codename": "add_newassetspageflag"}}, {"model": "auth.permission", "pk": 1027, "fields": {"name": "Can change new assets page flag", "content_type": 341, "codename": "change_newassetspageflag"}}, {"model": "auth.permission", "pk": 1028, "fields": {"name": "Can delete new assets page flag", "content_type": 341, "codename": "delete_newassetspageflag"}}, {"model": "auth.permission", "pk": 1029, "fields": {"name": "Can add course new assets page flag", "content_type": 342, "codename": "add_coursenewassetspageflag"}}, {"model": "auth.permission", "pk": 1030, "fields": {"name": "Can change course new assets page flag", "content_type": 342, "codename": "change_coursenewassetspageflag"}}, {"model": "auth.permission", "pk": 1031, "fields": {"name": "Can delete course new assets page flag", "content_type": 342, "codename": "delete_coursenewassetspageflag"}}, {"model": "auth.permission", "pk": 1032, "fields": {"name": "Can add course creator", "content_type": 343, "codename": "add_coursecreator"}}, {"model": "auth.permission", "pk": 1033, "fields": {"name": "Can change course creator", "content_type": 343, "codename": "change_coursecreator"}}, {"model": "auth.permission", "pk": 1034, "fields": {"name": "Can delete course creator", "content_type": 343, "codename": "delete_coursecreator"}}, {"model": "auth.permission", "pk": 1035, "fields": {"name": "Can add studio config", "content_type": 344, "codename": "add_studioconfig"}}, {"model": "auth.permission", "pk": 1036, "fields": {"name": "Can change studio config", "content_type": 344, "codename": "change_studioconfig"}}, {"model": "auth.permission", "pk": 1037, "fields": {"name": "Can delete studio config", "content_type": 344, "codename": "delete_studioconfig"}}, {"model": "auth.permission", "pk": 1038, "fields": {"name": "Can add course edit lti fields enabled flag", "content_type": 345, "codename": "add_courseeditltifieldsenabledflag"}}, {"model": "auth.permission", "pk": 1039, "fields": {"name": "Can change course edit lti fields enabled flag", "content_type": 345, "codename": "change_courseeditltifieldsenabledflag"}}, {"model": "auth.permission", "pk": 1040, "fields": {"name": "Can delete course edit lti fields enabled flag", "content_type": 345, "codename": "delete_courseeditltifieldsenabledflag"}}, {"model": "auth.permission", "pk": 1041, "fields": {"name": "Can add tag category", "content_type": 346, "codename": "add_tagcategories"}}, {"model": "auth.permission", "pk": 1042, "fields": {"name": "Can change tag category", "content_type": 346, "codename": "change_tagcategories"}}, {"model": "auth.permission", "pk": 1043, "fields": {"name": "Can delete tag category", "content_type": 346, "codename": "delete_tagcategories"}}, {"model": "auth.permission", "pk": 1044, "fields": {"name": "Can add available tag value", "content_type": 347, "codename": "add_tagavailablevalues"}}, {"model": "auth.permission", "pk": 1045, "fields": {"name": "Can change available tag value", "content_type": 347, "codename": "change_tagavailablevalues"}}, {"model": "auth.permission", "pk": 1046, "fields": {"name": "Can delete available tag value", "content_type": 347, "codename": "delete_tagavailablevalues"}}, {"model": "auth.permission", "pk": 1047, "fields": {"name": "Can add user task status", "content_type": 348, "codename": "add_usertaskstatus"}}, {"model": "auth.permission", "pk": 1048, "fields": {"name": "Can change user task status", "content_type": 348, "codename": "change_usertaskstatus"}}, {"model": "auth.permission", "pk": 1049, "fields": {"name": "Can delete user task status", "content_type": 348, "codename": "delete_usertaskstatus"}}, {"model": "auth.permission", "pk": 1050, "fields": {"name": "Can add user task artifact", "content_type": 349, "codename": "add_usertaskartifact"}}, {"model": "auth.permission", "pk": 1051, "fields": {"name": "Can change user task artifact", "content_type": 349, "codename": "change_usertaskartifact"}}, {"model": "auth.permission", "pk": 1052, "fields": {"name": "Can delete user task artifact", "content_type": 349, "codename": "delete_usertaskartifact"}}, {"model": "auth.permission", "pk": 1053, "fields": {"name": "Can add course entitlement policy", "content_type": 350, "codename": "add_courseentitlementpolicy"}}, {"model": "auth.permission", "pk": 1054, "fields": {"name": "Can change course entitlement policy", "content_type": 350, "codename": "change_courseentitlementpolicy"}}, {"model": "auth.permission", "pk": 1055, "fields": {"name": "Can delete course entitlement policy", "content_type": 350, "codename": "delete_courseentitlementpolicy"}}, {"model": "auth.permission", "pk": 1056, "fields": {"name": "Can add course entitlement support detail", "content_type": 351, "codename": "add_courseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 1057, "fields": {"name": "Can change course entitlement support detail", "content_type": 351, "codename": "change_courseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 1058, "fields": {"name": "Can delete course entitlement support detail", "content_type": 351, "codename": "delete_courseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 1059, "fields": {"name": "Can add content metadata item transmission", "content_type": 352, "codename": "add_contentmetadataitemtransmission"}}, {"model": "auth.permission", "pk": 1060, "fields": {"name": "Can change content metadata item transmission", "content_type": 352, "codename": "change_contentmetadataitemtransmission"}}, {"model": "auth.permission", "pk": 1061, "fields": {"name": "Can delete content metadata item transmission", "content_type": 352, "codename": "delete_contentmetadataitemtransmission"}}, {"model": "auth.permission", "pk": 1062, "fields": {"name": "Can add transcript migration setting", "content_type": 353, "codename": "add_transcriptmigrationsetting"}}, {"model": "auth.permission", "pk": 1063, "fields": {"name": "Can change transcript migration setting", "content_type": 353, "codename": "change_transcriptmigrationsetting"}}, {"model": "auth.permission", "pk": 1064, "fields": {"name": "Can delete transcript migration setting", "content_type": 353, "codename": "delete_transcriptmigrationsetting"}}, {"model": "auth.permission", "pk": 1065, "fields": {"name": "Can add sso verification", "content_type": 354, "codename": "add_ssoverification"}}, {"model": "auth.permission", "pk": 1066, "fields": {"name": "Can change sso verification", "content_type": 354, "codename": "change_ssoverification"}}, {"model": "auth.permission", "pk": 1067, "fields": {"name": "Can delete sso verification", "content_type": 354, "codename": "delete_ssoverification"}}, {"model": "auth.permission", "pk": 1068, "fields": {"name": "Can add User Retirement Status", "content_type": 355, "codename": "add_userretirementstatus"}}, {"model": "auth.permission", "pk": 1069, "fields": {"name": "Can change User Retirement Status", "content_type": 355, "codename": "change_userretirementstatus"}}, {"model": "auth.permission", "pk": 1070, "fields": {"name": "Can delete User Retirement Status", "content_type": 355, "codename": "delete_userretirementstatus"}}, {"model": "auth.permission", "pk": 1071, "fields": {"name": "Can add retirement state", "content_type": 356, "codename": "add_retirementstate"}}, {"model": "auth.permission", "pk": 1072, "fields": {"name": "Can change retirement state", "content_type": 356, "codename": "change_retirementstate"}}, {"model": "auth.permission", "pk": 1073, "fields": {"name": "Can delete retirement state", "content_type": 356, "codename": "delete_retirementstate"}}, {"model": "auth.permission", "pk": 1074, "fields": {"name": "Can add data sharing consent text overrides", "content_type": 357, "codename": "add_datasharingconsenttextoverrides"}}, {"model": "auth.permission", "pk": 1075, "fields": {"name": "Can change data sharing consent text overrides", "content_type": 357, "codename": "change_datasharingconsenttextoverrides"}}, {"model": "auth.permission", "pk": 1076, "fields": {"name": "Can delete data sharing consent text overrides", "content_type": 357, "codename": "delete_datasharingconsenttextoverrides"}}, {"model": "auth.permission", "pk": 1077, "fields": {"name": "Can add User Retirement Request", "content_type": 358, "codename": "add_userretirementrequest"}}, {"model": "auth.permission", "pk": 1078, "fields": {"name": "Can change User Retirement Request", "content_type": 358, "codename": "change_userretirementrequest"}}, {"model": "auth.permission", "pk": 1079, "fields": {"name": "Can delete User Retirement Request", "content_type": 358, "codename": "delete_userretirementrequest"}}, {"model": "auth.permission", "pk": 1080, "fields": {"name": "Can add discussions id mapping", "content_type": 359, "codename": "add_discussionsidmapping"}}, {"model": "auth.permission", "pk": 1081, "fields": {"name": "Can change discussions id mapping", "content_type": 359, "codename": "change_discussionsidmapping"}}, {"model": "auth.permission", "pk": 1082, "fields": {"name": "Can delete discussions id mapping", "content_type": 359, "codename": "delete_discussionsidmapping"}}, {"model": "auth.permission", "pk": 1083, "fields": {"name": "Can add scoped application", "content_type": 360, "codename": "add_scopedapplication"}}, {"model": "auth.permission", "pk": 1084, "fields": {"name": "Can change scoped application", "content_type": 360, "codename": "change_scopedapplication"}}, {"model": "auth.permission", "pk": 1085, "fields": {"name": "Can delete scoped application", "content_type": 360, "codename": "delete_scopedapplication"}}, {"model": "auth.permission", "pk": 1086, "fields": {"name": "Can add scoped application organization", "content_type": 361, "codename": "add_scopedapplicationorganization"}}, {"model": "auth.permission", "pk": 1087, "fields": {"name": "Can change scoped application organization", "content_type": 361, "codename": "change_scopedapplicationorganization"}}, {"model": "auth.permission", "pk": 1088, "fields": {"name": "Can delete scoped application organization", "content_type": 361, "codename": "delete_scopedapplicationorganization"}}, {"model": "auth.permission", "pk": 1089, "fields": {"name": "Can add User Retirement Reporting Status", "content_type": 362, "codename": "add_userretirementpartnerreportingstatus"}}, {"model": "auth.permission", "pk": 1090, "fields": {"name": "Can change User Retirement Reporting Status", "content_type": 362, "codename": "change_userretirementpartnerreportingstatus"}}, {"model": "auth.permission", "pk": 1091, "fields": {"name": "Can delete User Retirement Reporting Status", "content_type": 362, "codename": "delete_userretirementpartnerreportingstatus"}}, {"model": "auth.permission", "pk": 1092, "fields": {"name": "Can add manual verification", "content_type": 363, "codename": "add_manualverification"}}, {"model": "auth.permission", "pk": 1093, "fields": {"name": "Can change manual verification", "content_type": 363, "codename": "change_manualverification"}}, {"model": "auth.permission", "pk": 1094, "fields": {"name": "Can delete manual verification", "content_type": 363, "codename": "delete_manualverification"}}, {"model": "auth.permission", "pk": 1095, "fields": {"name": "Can add application organization", "content_type": 364, "codename": "add_applicationorganization"}}, {"model": "auth.permission", "pk": 1096, "fields": {"name": "Can change application organization", "content_type": 364, "codename": "change_applicationorganization"}}, {"model": "auth.permission", "pk": 1097, "fields": {"name": "Can delete application organization", "content_type": 364, "codename": "delete_applicationorganization"}}, {"model": "auth.permission", "pk": 1098, "fields": {"name": "Can add application access", "content_type": 365, "codename": "add_applicationaccess"}}, {"model": "auth.permission", "pk": 1099, "fields": {"name": "Can change application access", "content_type": 365, "codename": "change_applicationaccess"}}, {"model": "auth.permission", "pk": 1100, "fields": {"name": "Can delete application access", "content_type": 365, "codename": "delete_applicationaccess"}}, {"model": "auth.permission", "pk": 1101, "fields": {"name": "Can add migration enqueued course", "content_type": 366, "codename": "add_migrationenqueuedcourse"}}, {"model": "auth.permission", "pk": 1102, "fields": {"name": "Can change migration enqueued course", "content_type": 366, "codename": "change_migrationenqueuedcourse"}}, {"model": "auth.permission", "pk": 1103, "fields": {"name": "Can delete migration enqueued course", "content_type": 366, "codename": "delete_migrationenqueuedcourse"}}, {"model": "auth.permission", "pk": 1104, "fields": {"name": "Can add xapilrs configuration", "content_type": 367, "codename": "add_xapilrsconfiguration"}}, {"model": "auth.permission", "pk": 1105, "fields": {"name": "Can change xapilrs configuration", "content_type": 367, "codename": "change_xapilrsconfiguration"}}, {"model": "auth.permission", "pk": 1106, "fields": {"name": "Can delete xapilrs configuration", "content_type": 367, "codename": "delete_xapilrsconfiguration"}}, {"model": "auth.permission", "pk": 1107, "fields": {"name": "Can add notify_credentials argument", "content_type": 368, "codename": "add_notifycredentialsconfig"}}, {"model": "auth.permission", "pk": 1108, "fields": {"name": "Can change notify_credentials argument", "content_type": 368, "codename": "change_notifycredentialsconfig"}}, {"model": "auth.permission", "pk": 1109, "fields": {"name": "Can delete notify_credentials argument", "content_type": 368, "codename": "delete_notifycredentialsconfig"}}, {"model": "auth.permission", "pk": 1110, "fields": {"name": "Can add updated course videos", "content_type": 369, "codename": "add_updatedcoursevideos"}}, {"model": "auth.permission", "pk": 1111, "fields": {"name": "Can change updated course videos", "content_type": 369, "codename": "change_updatedcoursevideos"}}, {"model": "auth.permission", "pk": 1112, "fields": {"name": "Can delete updated course videos", "content_type": 369, "codename": "delete_updatedcoursevideos"}}, {"model": "auth.permission", "pk": 1113, "fields": {"name": "Can add video thumbnail setting", "content_type": 370, "codename": "add_videothumbnailsetting"}}, {"model": "auth.permission", "pk": 1114, "fields": {"name": "Can change video thumbnail setting", "content_type": 370, "codename": "change_videothumbnailsetting"}}, {"model": "auth.permission", "pk": 1115, "fields": {"name": "Can delete video thumbnail setting", "content_type": 370, "codename": "delete_videothumbnailsetting"}}, {"model": "auth.permission", "pk": 1116, "fields": {"name": "Can add course duration limit config", "content_type": 371, "codename": "add_coursedurationlimitconfig"}}, {"model": "auth.permission", "pk": 1117, "fields": {"name": "Can change course duration limit config", "content_type": 371, "codename": "change_coursedurationlimitconfig"}}, {"model": "auth.permission", "pk": 1118, "fields": {"name": "Can delete course duration limit config", "content_type": 371, "codename": "delete_coursedurationlimitconfig"}}, {"model": "auth.permission", "pk": 1119, "fields": {"name": "Can add content type gating config", "content_type": 372, "codename": "add_contenttypegatingconfig"}}, {"model": "auth.permission", "pk": 1120, "fields": {"name": "Can change content type gating config", "content_type": 372, "codename": "change_contenttypegatingconfig"}}, {"model": "auth.permission", "pk": 1121, "fields": {"name": "Can delete content type gating config", "content_type": 372, "codename": "delete_contenttypegatingconfig"}}, {"model": "auth.permission", "pk": 1122, "fields": {"name": "Can add persistent subsection grade override history", "content_type": 373, "codename": "add_persistentsubsectiongradeoverridehistory"}}, {"model": "auth.permission", "pk": 1123, "fields": {"name": "Can change persistent subsection grade override history", "content_type": 373, "codename": "change_persistentsubsectiongradeoverridehistory"}}, {"model": "auth.permission", "pk": 1124, "fields": {"name": "Can delete persistent subsection grade override history", "content_type": 373, "codename": "delete_persistentsubsectiongradeoverridehistory"}}, {"model": "auth.permission", "pk": 1125, "fields": {"name": "Can add account recovery", "content_type": 374, "codename": "add_accountrecovery"}}, {"model": "auth.permission", "pk": 1126, "fields": {"name": "Can change account recovery", "content_type": 374, "codename": "change_accountrecovery"}}, {"model": "auth.permission", "pk": 1127, "fields": {"name": "Can delete account recovery", "content_type": 374, "codename": "delete_accountrecovery"}}, {"model": "auth.permission", "pk": 1128, "fields": {"name": "Can add Enterprise Customer Type", "content_type": 375, "codename": "add_enterprisecustomertype"}}, {"model": "auth.permission", "pk": 1129, "fields": {"name": "Can change Enterprise Customer Type", "content_type": 375, "codename": "change_enterprisecustomertype"}}, {"model": "auth.permission", "pk": 1130, "fields": {"name": "Can delete Enterprise Customer Type", "content_type": 375, "codename": "delete_enterprisecustomertype"}}, {"model": "auth.permission", "pk": 1131, "fields": {"name": "Can add pending secondary email change", "content_type": 376, "codename": "add_pendingsecondaryemailchange"}}, {"model": "auth.permission", "pk": 1132, "fields": {"name": "Can change pending secondary email change", "content_type": 376, "codename": "change_pendingsecondaryemailchange"}}, {"model": "auth.permission", "pk": 1133, "fields": {"name": "Can delete pending secondary email change", "content_type": 376, "codename": "delete_pendingsecondaryemailchange"}}, {"model": "auth.permission", "pk": 1134, "fields": {"name": "Can add lti consumer", "content_type": 377, "codename": "add_lticonsumer"}}, {"model": "auth.permission", "pk": 1135, "fields": {"name": "Can change lti consumer", "content_type": 377, "codename": "change_lticonsumer"}}, {"model": "auth.permission", "pk": 1136, "fields": {"name": "Can delete lti consumer", "content_type": 377, "codename": "delete_lticonsumer"}}, {"model": "auth.permission", "pk": 1137, "fields": {"name": "Can add graded assignment", "content_type": 378, "codename": "add_gradedassignment"}}, {"model": "auth.permission", "pk": 1138, "fields": {"name": "Can change graded assignment", "content_type": 378, "codename": "change_gradedassignment"}}, {"model": "auth.permission", "pk": 1139, "fields": {"name": "Can delete graded assignment", "content_type": 378, "codename": "delete_gradedassignment"}}, {"model": "auth.permission", "pk": 1140, "fields": {"name": "Can add lti user", "content_type": 379, "codename": "add_ltiuser"}}, {"model": "auth.permission", "pk": 1141, "fields": {"name": "Can change lti user", "content_type": 379, "codename": "change_ltiuser"}}, {"model": "auth.permission", "pk": 1142, "fields": {"name": "Can delete lti user", "content_type": 379, "codename": "delete_ltiuser"}}, {"model": "auth.permission", "pk": 1143, "fields": {"name": "Can add outcome service", "content_type": 380, "codename": "add_outcomeservice"}}, {"model": "auth.permission", "pk": 1144, "fields": {"name": "Can change outcome service", "content_type": 380, "codename": "change_outcomeservice"}}, {"model": "auth.permission", "pk": 1145, "fields": {"name": "Can delete outcome service", "content_type": 380, "codename": "delete_outcomeservice"}}, {"model": "auth.permission", "pk": 1146, "fields": {"name": "Can add system wide enterprise role", "content_type": 381, "codename": "add_systemwideenterpriserole"}}, {"model": "auth.permission", "pk": 1147, "fields": {"name": "Can change system wide enterprise role", "content_type": 381, "codename": "change_systemwideenterpriserole"}}, {"model": "auth.permission", "pk": 1148, "fields": {"name": "Can delete system wide enterprise role", "content_type": 381, "codename": "delete_systemwideenterpriserole"}}, {"model": "auth.permission", "pk": 1149, "fields": {"name": "Can add system wide enterprise user role assignment", "content_type": 382, "codename": "add_systemwideenterpriseuserroleassignment"}}, {"model": "auth.permission", "pk": 1150, "fields": {"name": "Can change system wide enterprise user role assignment", "content_type": 382, "codename": "change_systemwideenterpriseuserroleassignment"}}, {"model": "auth.permission", "pk": 1151, "fields": {"name": "Can delete system wide enterprise user role assignment", "content_type": 382, "codename": "delete_systemwideenterpriseuserroleassignment"}}, {"model": "auth.permission", "pk": 1152, "fields": {"name": "Can add announcement", "content_type": 383, "codename": "add_announcement"}}, {"model": "auth.permission", "pk": 1153, "fields": {"name": "Can change announcement", "content_type": 383, "codename": "change_announcement"}}, {"model": "auth.permission", "pk": 1154, "fields": {"name": "Can delete announcement", "content_type": 383, "codename": "delete_announcement"}}, {"model": "auth.permission", "pk": 2267, "fields": {"name": "Can add enterprise feature user role assignment", "content_type": 753, "codename": "add_enterprisefeatureuserroleassignment"}}, {"model": "auth.permission", "pk": 2268, "fields": {"name": "Can change enterprise feature user role assignment", "content_type": 753, "codename": "change_enterprisefeatureuserroleassignment"}}, {"model": "auth.permission", "pk": 2269, "fields": {"name": "Can delete enterprise feature user role assignment", "content_type": 753, "codename": "delete_enterprisefeatureuserroleassignment"}}, {"model": "auth.permission", "pk": 2270, "fields": {"name": "Can add enterprise feature role", "content_type": 754, "codename": "add_enterprisefeaturerole"}}, {"model": "auth.permission", "pk": 2271, "fields": {"name": "Can change enterprise feature role", "content_type": 754, "codename": "change_enterprisefeaturerole"}}, {"model": "auth.permission", "pk": 2272, "fields": {"name": "Can delete enterprise feature role", "content_type": 754, "codename": "delete_enterprisefeaturerole"}}, {"model": "auth.permission", "pk": 2273, "fields": {"name": "Can add program enrollment", "content_type": 755, "codename": "add_programenrollment"}}, {"model": "auth.permission", "pk": 2274, "fields": {"name": "Can change program enrollment", "content_type": 755, "codename": "change_programenrollment"}}, {"model": "auth.permission", "pk": 2275, "fields": {"name": "Can delete program enrollment", "content_type": 755, "codename": "delete_programenrollment"}}, {"model": "auth.permission", "pk": 2276, "fields": {"name": "Can add historical program enrollment", "content_type": 756, "codename": "add_historicalprogramenrollment"}}, {"model": "auth.permission", "pk": 2277, "fields": {"name": "Can change historical program enrollment", "content_type": 756, "codename": "change_historicalprogramenrollment"}}, {"model": "auth.permission", "pk": 2278, "fields": {"name": "Can delete historical program enrollment", "content_type": 756, "codename": "delete_historicalprogramenrollment"}}, {"model": "auth.permission", "pk": 2279, "fields": {"name": "Can add program course enrollment", "content_type": 757, "codename": "add_programcourseenrollment"}}, {"model": "auth.permission", "pk": 2280, "fields": {"name": "Can change program course enrollment", "content_type": 757, "codename": "change_programcourseenrollment"}}, {"model": "auth.permission", "pk": 2281, "fields": {"name": "Can delete program course enrollment", "content_type": 757, "codename": "delete_programcourseenrollment"}}, {"model": "auth.permission", "pk": 2282, "fields": {"name": "Can add historical program course enrollment", "content_type": 758, "codename": "add_historicalprogramcourseenrollment"}}, {"model": "auth.permission", "pk": 2283, "fields": {"name": "Can change historical program course enrollment", "content_type": 758, "codename": "change_historicalprogramcourseenrollment"}}, {"model": "auth.permission", "pk": 2284, "fields": {"name": "Can delete historical program course enrollment", "content_type": 758, "codename": "delete_historicalprogramcourseenrollment"}}, {"model": "auth.permission", "pk": 2285, "fields": {"name": "Can add content date", "content_type": 759, "codename": "add_contentdate"}}, {"model": "auth.permission", "pk": 2286, "fields": {"name": "Can change content date", "content_type": 759, "codename": "change_contentdate"}}, {"model": "auth.permission", "pk": 2287, "fields": {"name": "Can delete content date", "content_type": 759, "codename": "delete_contentdate"}}, {"model": "auth.permission", "pk": 2288, "fields": {"name": "Can add user date", "content_type": 760, "codename": "add_userdate"}}, {"model": "auth.permission", "pk": 2289, "fields": {"name": "Can change user date", "content_type": 760, "codename": "change_userdate"}}, {"model": "auth.permission", "pk": 2290, "fields": {"name": "Can delete user date", "content_type": 760, "codename": "delete_userdate"}}, {"model": "auth.permission", "pk": 2291, "fields": {"name": "Can add date policy", "content_type": 761, "codename": "add_datepolicy"}}, {"model": "auth.permission", "pk": 2292, "fields": {"name": "Can change date policy", "content_type": 761, "codename": "change_datepolicy"}}, {"model": "auth.permission", "pk": 2293, "fields": {"name": "Can delete date policy", "content_type": 761, "codename": "delete_datepolicy"}}, {"model": "auth.permission", "pk": 2294, "fields": {"name": "Can add historical course enrollment", "content_type": 762, "codename": "add_historicalcourseenrollment"}}, {"model": "auth.permission", "pk": 2295, "fields": {"name": "Can change historical course enrollment", "content_type": 762, "codename": "change_historicalcourseenrollment"}}, {"model": "auth.permission", "pk": 2296, "fields": {"name": "Can delete historical course enrollment", "content_type": 762, "codename": "delete_historicalcourseenrollment"}}, {"model": "auth.permission", "pk": 2297, "fields": {"name": "Can add cornerstone global configuration", "content_type": 763, "codename": "add_cornerstoneglobalconfiguration"}}, {"model": "auth.permission", "pk": 2298, "fields": {"name": "Can change cornerstone global configuration", "content_type": 763, "codename": "change_cornerstoneglobalconfiguration"}}, {"model": "auth.permission", "pk": 2299, "fields": {"name": "Can delete cornerstone global configuration", "content_type": 763, "codename": "delete_cornerstoneglobalconfiguration"}}, {"model": "auth.permission", "pk": 2300, "fields": {"name": "Can add historical cornerstone enterprise customer configuration", "content_type": 764, "codename": "add_historicalcornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2301, "fields": {"name": "Can change historical cornerstone enterprise customer configuration", "content_type": 764, "codename": "change_historicalcornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2302, "fields": {"name": "Can delete historical cornerstone enterprise customer configuration", "content_type": 764, "codename": "delete_historicalcornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2303, "fields": {"name": "Can add cornerstone learner data transmission audit", "content_type": 765, "codename": "add_cornerstonelearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2304, "fields": {"name": "Can change cornerstone learner data transmission audit", "content_type": 765, "codename": "change_cornerstonelearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2305, "fields": {"name": "Can delete cornerstone learner data transmission audit", "content_type": 765, "codename": "delete_cornerstonelearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2306, "fields": {"name": "Can add cornerstone enterprise customer configuration", "content_type": 766, "codename": "add_cornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2307, "fields": {"name": "Can change cornerstone enterprise customer configuration", "content_type": 766, "codename": "change_cornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2308, "fields": {"name": "Can delete cornerstone enterprise customer configuration", "content_type": 766, "codename": "delete_cornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2309, "fields": {"name": "Can add discount restriction config", "content_type": 767, "codename": "add_discountrestrictionconfig"}}, {"model": "auth.permission", "pk": 2310, "fields": {"name": "Can change discount restriction config", "content_type": 767, "codename": "change_discountrestrictionconfig"}}, {"model": "auth.permission", "pk": 2311, "fields": {"name": "Can delete discount restriction config", "content_type": 767, "codename": "delete_discountrestrictionconfig"}}, {"model": "auth.permission", "pk": 2312, "fields": {"name": "Can add historical course entitlement", "content_type": 768, "codename": "add_historicalcourseentitlement"}}, {"model": "auth.permission", "pk": 2313, "fields": {"name": "Can change historical course entitlement", "content_type": 768, "codename": "change_historicalcourseentitlement"}}, {"model": "auth.permission", "pk": 2314, "fields": {"name": "Can delete historical course entitlement", "content_type": 768, "codename": "delete_historicalcourseentitlement"}}, {"model": "auth.permission", "pk": 2315, "fields": {"name": "Can add historical organization", "content_type": 769, "codename": "add_historicalorganization"}}, {"model": "auth.permission", "pk": 2316, "fields": {"name": "Can change historical organization", "content_type": 769, "codename": "change_historicalorganization"}}, {"model": "auth.permission", "pk": 2317, "fields": {"name": "Can delete historical organization", "content_type": 769, "codename": "delete_historicalorganization"}}, {"model": "auth.permission", "pk": 2318, "fields": {"name": "Can add historical persistent subsection grade override", "content_type": 770, "codename": "add_historicalpersistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 2319, "fields": {"name": "Can change historical persistent subsection grade override", "content_type": 770, "codename": "change_historicalpersistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 2320, "fields": {"name": "Can delete historical persistent subsection grade override", "content_type": 770, "codename": "delete_historicalpersistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 2321, "fields": {"name": "Can add csv operation", "content_type": 771, "codename": "add_csvoperation"}}, {"model": "auth.permission", "pk": 2322, "fields": {"name": "Can change csv operation", "content_type": 771, "codename": "change_csvoperation"}}, {"model": "auth.permission", "pk": 2323, "fields": {"name": "Can delete csv operation", "content_type": 771, "codename": "delete_csvoperation"}}, {"model": "auth.permission", "pk": 2324, "fields": {"name": "Can add score overrider", "content_type": 772, "codename": "add_scoreoverrider"}}, {"model": "auth.permission", "pk": 2325, "fields": {"name": "Can change score overrider", "content_type": 772, "codename": "change_scoreoverrider"}}, {"model": "auth.permission", "pk": 2326, "fields": {"name": "Can delete score overrider", "content_type": 772, "codename": "delete_scoreoverrider"}}, {"model": "auth.permission", "pk": 2327, "fields": {"name": "Can add historical course mode", "content_type": 773, "codename": "add_historicalcoursemode"}}, {"model": "auth.permission", "pk": 2328, "fields": {"name": "Can change historical course mode", "content_type": 773, "codename": "change_historicalcoursemode"}}, {"model": "auth.permission", "pk": 2329, "fields": {"name": "Can delete historical course mode", "content_type": 773, "codename": "delete_historicalcoursemode"}}, {"model": "auth.permission", "pk": 2330, "fields": {"name": "Can add historical course overview", "content_type": 774, "codename": "add_historicalcourseoverview"}}, {"model": "auth.permission", "pk": 2331, "fields": {"name": "Can change historical course overview", "content_type": 774, "codename": "change_historicalcourseoverview"}}, {"model": "auth.permission", "pk": 2332, "fields": {"name": "Can delete historical course overview", "content_type": 774, "codename": "delete_historicalcourseoverview"}}, {"model": "auth.permission", "pk": 2333, "fields": {"name": "Can add system wide role", "content_type": 775, "codename": "add_systemwiderole"}}, {"model": "auth.permission", "pk": 2334, "fields": {"name": "Can change system wide role", "content_type": 775, "codename": "change_systemwiderole"}}, {"model": "auth.permission", "pk": 2335, "fields": {"name": "Can delete system wide role", "content_type": 775, "codename": "delete_systemwiderole"}}, {"model": "auth.permission", "pk": 2336, "fields": {"name": "Can add system wide role assignment", "content_type": 776, "codename": "add_systemwideroleassignment"}}, {"model": "auth.permission", "pk": 2337, "fields": {"name": "Can change system wide role assignment", "content_type": 776, "codename": "change_systemwideroleassignment"}}, {"model": "auth.permission", "pk": 2338, "fields": {"name": "Can delete system wide role assignment", "content_type": 776, "codename": "delete_systemwideroleassignment"}}, {"model": "auth.permission", "pk": 2339, "fields": {"name": "Can add Enterprise Catalog Query", "content_type": 777, "codename": "add_enterprisecatalogquery"}}, {"model": "auth.permission", "pk": 2340, "fields": {"name": "Can change Enterprise Catalog Query", "content_type": 777, "codename": "change_enterprisecatalogquery"}}, {"model": "auth.permission", "pk": 2341, "fields": {"name": "Can delete Enterprise Catalog Query", "content_type": 777, "codename": "delete_enterprisecatalogquery"}}, {"model": "auth.permission", "pk": 2342, "fields": {"name": "Can add historical pending enrollment", "content_type": 778, "codename": "add_historicalpendingenrollment"}}, {"model": "auth.permission", "pk": 2343, "fields": {"name": "Can change historical pending enrollment", "content_type": 778, "codename": "change_historicalpendingenrollment"}}, {"model": "auth.permission", "pk": 2344, "fields": {"name": "Can delete historical pending enrollment", "content_type": 778, "codename": "delete_historicalpendingenrollment"}}, {"model": "auth.permission", "pk": 2345, "fields": {"name": "Can add historical pending enterprise customer user", "content_type": 779, "codename": "add_historicalpendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 2346, "fields": {"name": "Can change historical pending enterprise customer user", "content_type": 779, "codename": "change_historicalpendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 2347, "fields": {"name": "Can delete historical pending enterprise customer user", "content_type": 779, "codename": "delete_historicalpendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 2348, "fields": {"name": "Can add xapi learner data transmission audit", "content_type": 780, "codename": "add_xapilearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2349, "fields": {"name": "Can change xapi learner data transmission audit", "content_type": 780, "codename": "change_xapilearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2350, "fields": {"name": "Can delete xapi learner data transmission audit", "content_type": 780, "codename": "delete_xapilearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2351, "fields": {"name": "Can add course youtube blocked flag", "content_type": 781, "codename": "add_courseyoutubeblockedflag"}}, {"model": "auth.permission", "pk": 2352, "fields": {"name": "Can change course youtube blocked flag", "content_type": 781, "codename": "change_courseyoutubeblockedflag"}}, {"model": "auth.permission", "pk": 2353, "fields": {"name": "Can delete course youtube blocked flag", "content_type": 781, "codename": "delete_courseyoutubeblockedflag"}}, {"model": "auth.permission", "pk": 2354, "fields": {"name": "Can add content library", "content_type": 782, "codename": "add_contentlibrary"}}, {"model": "auth.permission", "pk": 2355, "fields": {"name": "Can change content library", "content_type": 782, "codename": "change_contentlibrary"}}, {"model": "auth.permission", "pk": 2356, "fields": {"name": "Can delete content library", "content_type": 782, "codename": "delete_contentlibrary"}}, {"model": "auth.permission", "pk": 2357, "fields": {"name": "Can add content library permission", "content_type": 783, "codename": "add_contentlibrarypermission"}}, {"model": "auth.permission", "pk": 2358, "fields": {"name": "Can change content library permission", "content_type": 783, "codename": "change_contentlibrarypermission"}}, {"model": "auth.permission", "pk": 2359, "fields": {"name": "Can delete content library permission", "content_type": 783, "codename": "delete_contentlibrarypermission"}}, {"model": "auth.permission", "pk": 2360, "fields": {"name": "Can add simulate_publish argument", "content_type": 784, "codename": "add_simulatecoursepublishconfig"}}, {"model": "auth.permission", "pk": 2361, "fields": {"name": "Can change simulate_publish argument", "content_type": 784, "codename": "change_simulatecoursepublishconfig"}}, {"model": "auth.permission", "pk": 2362, "fields": {"name": "Can delete simulate_publish argument", "content_type": 784, "codename": "delete_simulatecoursepublishconfig"}}, {"model": "auth.permission", "pk": 2363, "fields": {"name": "Can add bulk unenroll configuration", "content_type": 785, "codename": "add_bulkunenrollconfiguration"}}, {"model": "auth.permission", "pk": 2364, "fields": {"name": "Can change bulk unenroll configuration", "content_type": 785, "codename": "change_bulkunenrollconfiguration"}}, {"model": "auth.permission", "pk": 2365, "fields": {"name": "Can delete bulk unenroll configuration", "content_type": 785, "codename": "delete_bulkunenrollconfiguration"}}, {"model": "auth.permission", "pk": 2366, "fields": {"name": "Can add discount percentage config", "content_type": 786, "codename": "add_discountpercentageconfig"}}, {"model": "auth.permission", "pk": 2367, "fields": {"name": "Can change discount percentage config", "content_type": 786, "codename": "change_discountpercentageconfig"}}, {"model": "auth.permission", "pk": 2368, "fields": {"name": "Can delete discount percentage config", "content_type": 786, "codename": "delete_discountpercentageconfig"}}, {"model": "auth.permission", "pk": 2369, "fields": {"name": "Can add fbe enrollment exclusion", "content_type": 787, "codename": "add_fbeenrollmentexclusion"}}, {"model": "auth.permission", "pk": 2370, "fields": {"name": "Can change fbe enrollment exclusion", "content_type": 787, "codename": "change_fbeenrollmentexclusion"}}, {"model": "auth.permission", "pk": 2371, "fields": {"name": "Can delete fbe enrollment exclusion", "content_type": 787, "codename": "delete_fbeenrollmentexclusion"}}, {"model": "auth.permission", "pk": 2372, "fields": {"name": "Can add allowed auth user", "content_type": 788, "codename": "add_allowedauthuser"}}, {"model": "auth.permission", "pk": 2373, "fields": {"name": "Can change allowed auth user", "content_type": 788, "codename": "change_allowedauthuser"}}, {"model": "auth.permission", "pk": 2374, "fields": {"name": "Can delete allowed auth user", "content_type": 788, "codename": "delete_allowedauthuser"}}, {"model": "auth.permission", "pk": 2375, "fields": {"name": "Can add enterprise enrollment source", "content_type": 789, "codename": "add_enterpriseenrollmentsource"}}, {"model": "auth.permission", "pk": 2376, "fields": {"name": "Can change enterprise enrollment source", "content_type": 789, "codename": "change_enterpriseenrollmentsource"}}, {"model": "auth.permission", "pk": 2377, "fields": {"name": "Can delete enterprise enrollment source", "content_type": 789, "codename": "delete_enterpriseenrollmentsource"}}, {"model": "auth.permission", "pk": 2378, "fields": {"name": "Can add sspv retry student argument", "content_type": 790, "codename": "add_sspverificationretryconfig"}}, {"model": "auth.permission", "pk": 2379, "fields": {"name": "Can change sspv retry student argument", "content_type": 790, "codename": "change_sspverificationretryconfig"}}, {"model": "auth.permission", "pk": 2380, "fields": {"name": "Can delete sspv retry student argument", "content_type": 790, "codename": "delete_sspverificationretryconfig"}}, {"model": "auth.permission", "pk": 2381, "fields": {"name": "Can add backpopulate_program_credentials argument", "content_type": 791, "codename": "add_customprogramsconfig"}}, {"model": "auth.permission", "pk": 2382, "fields": {"name": "Can change backpopulate_program_credentials argument", "content_type": 791, "codename": "change_customprogramsconfig"}}, {"model": "auth.permission", "pk": 2383, "fields": {"name": "Can delete backpopulate_program_credentials argument", "content_type": 791, "codename": "delete_customprogramsconfig"}}, {"model": "auth.permission", "pk": 2384, "fields": {"name": "Can add historical shared file upload", "content_type": 792, "codename": "add_historicalsharedfileupload"}}, {"model": "auth.permission", "pk": 2385, "fields": {"name": "Can change historical shared file upload", "content_type": 792, "codename": "change_historicalsharedfileupload"}}, {"model": "auth.permission", "pk": 2386, "fields": {"name": "Can delete historical shared file upload", "content_type": 792, "codename": "delete_historicalsharedfileupload"}}, {"model": "auth.permission", "pk": 2387, "fields": {"name": "Can add shared file upload", "content_type": 793, "codename": "add_sharedfileupload"}}, {"model": "auth.permission", "pk": 2388, "fields": {"name": "Can change shared file upload", "content_type": 793, "codename": "change_sharedfileupload"}}, {"model": "auth.permission", "pk": 2389, "fields": {"name": "Can delete shared file upload", "content_type": 793, "codename": "delete_sharedfileupload"}}, {"model": "auth.permission", "pk": 2390, "fields": {"name": "Can add historical generated certificate", "content_type": 794, "codename": "add_historicalgeneratedcertificate"}}, {"model": "auth.permission", "pk": 2391, "fields": {"name": "Can change historical generated certificate", "content_type": 794, "codename": "change_historicalgeneratedcertificate"}}, {"model": "auth.permission", "pk": 2392, "fields": {"name": "Can delete historical generated certificate", "content_type": 794, "codename": "delete_historicalgeneratedcertificate"}}, {"model": "auth.permission", "pk": 2393, "fields": {"name": "Can add historical course entitlement support detail", "content_type": 795, "codename": "add_historicalcourseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 2394, "fields": {"name": "Can change historical course entitlement support detail", "content_type": 795, "codename": "change_historicalcourseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 2395, "fields": {"name": "Can delete historical course entitlement support detail", "content_type": 795, "codename": "delete_historicalcourseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 2396, "fields": {"name": "Can add historical manual enrollment audit", "content_type": 796, "codename": "add_historicalmanualenrollmentaudit"}}, {"model": "auth.permission", "pk": 2397, "fields": {"name": "Can change historical manual enrollment audit", "content_type": 796, "codename": "change_historicalmanualenrollmentaudit"}}, {"model": "auth.permission", "pk": 2398, "fields": {"name": "Can delete historical manual enrollment audit", "content_type": 796, "codename": "delete_historicalmanualenrollmentaudit"}}, {"model": "auth.permission", "pk": 2399, "fields": {"name": "Can add historical external id", "content_type": 797, "codename": "add_historicalexternalid"}}, {"model": "auth.permission", "pk": 2400, "fields": {"name": "Can change historical external id", "content_type": 797, "codename": "change_historicalexternalid"}}, {"model": "auth.permission", "pk": 2401, "fields": {"name": "Can delete historical external id", "content_type": 797, "codename": "delete_historicalexternalid"}}, {"model": "auth.permission", "pk": 2402, "fields": {"name": "Can add historical external id type", "content_type": 798, "codename": "add_historicalexternalidtype"}}, {"model": "auth.permission", "pk": 2403, "fields": {"name": "Can change historical external id type", "content_type": 798, "codename": "change_historicalexternalidtype"}}, {"model": "auth.permission", "pk": 2404, "fields": {"name": "Can delete historical external id type", "content_type": 798, "codename": "delete_historicalexternalidtype"}}, {"model": "auth.permission", "pk": 2405, "fields": {"name": "Can add external id", "content_type": 799, "codename": "add_externalid"}}, {"model": "auth.permission", "pk": 2406, "fields": {"name": "Can change external id", "content_type": 799, "codename": "change_externalid"}}, {"model": "auth.permission", "pk": 2407, "fields": {"name": "Can delete external id", "content_type": 799, "codename": "delete_externalid"}}, {"model": "auth.permission", "pk": 2408, "fields": {"name": "Can add external id type", "content_type": 800, "codename": "add_externalidtype"}}, {"model": "auth.permission", "pk": 2409, "fields": {"name": "Can change external id type", "content_type": 800, "codename": "change_externalidtype"}}, {"model": "auth.permission", "pk": 2410, "fields": {"name": "Can delete external id type", "content_type": 800, "codename": "delete_externalidtype"}}, {"model": "auth.permission", "pk": 2411, "fields": {"name": "Can add self paced relative dates config", "content_type": 801, "codename": "add_selfpacedrelativedatesconfig"}}, {"model": "auth.permission", "pk": 2412, "fields": {"name": "Can change self paced relative dates config", "content_type": 801, "codename": "change_selfpacedrelativedatesconfig"}}, {"model": "auth.permission", "pk": 2413, "fields": {"name": "Can delete self paced relative dates config", "content_type": 801, "codename": "delete_selfpacedrelativedatesconfig"}}, {"model": "auth.permission", "pk": 2414, "fields": {"name": "Can add historical user calendar sync config", "content_type": 802, "codename": "add_historicalusercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2415, "fields": {"name": "Can change historical user calendar sync config", "content_type": 802, "codename": "change_historicalusercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2416, "fields": {"name": "Can delete historical user calendar sync config", "content_type": 802, "codename": "delete_historicalusercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2417, "fields": {"name": "Can add user calendar sync config", "content_type": 803, "codename": "add_usercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2418, "fields": {"name": "Can change user calendar sync config", "content_type": 803, "codename": "change_usercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2419, "fields": {"name": "Can delete user calendar sync config", "content_type": 803, "codename": "delete_usercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2420, "fields": {"name": "Can add historical Experiment Key-Value Pair", "content_type": 804, "codename": "add_historicalexperimentkeyvalue"}}, {"model": "auth.permission", "pk": 2421, "fields": {"name": "Can change historical Experiment Key-Value Pair", "content_type": 804, "codename": "change_historicalexperimentkeyvalue"}}, {"model": "auth.permission", "pk": 2422, "fields": {"name": "Can delete historical Experiment Key-Value Pair", "content_type": 804, "codename": "delete_historicalexperimentkeyvalue"}}, {"model": "auth.permission", "pk": 2423, "fields": {"name": "Can add historical Schedule", "content_type": 805, "codename": "add_historicalschedule"}}, {"model": "auth.permission", "pk": 2424, "fields": {"name": "Can change historical Schedule", "content_type": 805, "codename": "change_historicalschedule"}}, {"model": "auth.permission", "pk": 2425, "fields": {"name": "Can delete historical Schedule", "content_type": 805, "codename": "delete_historicalschedule"}}, {"model": "auth.permission", "pk": 2426, "fields": {"name": "Can add account recovery configuration", "content_type": 806, "codename": "add_accountrecoveryconfiguration"}}, {"model": "auth.permission", "pk": 2427, "fields": {"name": "Can change account recovery configuration", "content_type": 806, "codename": "change_accountrecoveryconfiguration"}}, {"model": "auth.permission", "pk": 2428, "fields": {"name": "Can delete account recovery configuration", "content_type": 806, "codename": "delete_accountrecoveryconfiguration"}}, {"model": "auth.permission", "pk": 2429, "fields": {"name": "Can add transcript credentials", "content_type": 807, "codename": "add_transcriptcredentials"}}, {"model": "auth.permission", "pk": 2430, "fields": {"name": "Can change transcript credentials", "content_type": 807, "codename": "change_transcriptcredentials"}}, {"model": "auth.permission", "pk": 2431, "fields": {"name": "Can delete transcript credentials", "content_type": 807, "codename": "delete_transcriptcredentials"}}, {"model": "auth.permission", "pk": 2432, "fields": {"name": "Can add team staff workflow", "content_type": 808, "codename": "add_teamstaffworkflow"}}, {"model": "auth.permission", "pk": 2433, "fields": {"name": "Can change team staff workflow", "content_type": 808, "codename": "change_teamstaffworkflow"}}, {"model": "auth.permission", "pk": 2434, "fields": {"name": "Can delete team staff workflow", "content_type": 808, "codename": "delete_teamstaffworkflow"}}, {"model": "auth.permission", "pk": 2435, "fields": {"name": "Can add team assessment workflow", "content_type": 809, "codename": "add_teamassessmentworkflow"}}, {"model": "auth.permission", "pk": 2436, "fields": {"name": "Can change team assessment workflow", "content_type": 809, "codename": "change_teamassessmentworkflow"}}, {"model": "auth.permission", "pk": 2437, "fields": {"name": "Can delete team assessment workflow", "content_type": 809, "codename": "delete_teamassessmentworkflow"}}, {"model": "auth.permission", "pk": 2438, "fields": {"name": "Can add course access role assignment", "content_type": 810, "codename": "add_courseaccessroleassignment"}}, {"model": "auth.permission", "pk": 2439, "fields": {"name": "Can change course access role assignment", "content_type": 810, "codename": "change_courseaccessroleassignment"}}, {"model": "auth.permission", "pk": 2440, "fields": {"name": "Can delete course access role assignment", "content_type": 810, "codename": "delete_courseaccessroleassignment"}}, {"model": "auth.permission", "pk": 2441, "fields": {"name": "Can add team submission", "content_type": 811, "codename": "add_teamsubmission"}}, {"model": "auth.permission", "pk": 2442, "fields": {"name": "Can change team submission", "content_type": 811, "codename": "change_teamsubmission"}}, {"model": "auth.permission", "pk": 2443, "fields": {"name": "Can delete team submission", "content_type": 811, "codename": "delete_teamsubmission"}}, {"model": "auth.group", "pk": 1, "fields": {"name": "API Access Request Approvers", "permissions": []}}, {"model": "auth.user", "pk": 1, "fields": {"password": "!FXJJHcjbqdW2yNqrkNvJXSnTXxNZVYIj3SsIt7BB", "last_login": null, "is_superuser": false, "username": "ecommerce_worker", "first_name": "", "last_name": "", "email": "ecommerce_worker@example.com", "is_staff": false, "is_active": true, "date_joined": "2017-12-06T02:20:20.329Z", "groups": [], "user_permissions": []}}, {"model": "auth.user", "pk": 2, "fields": {"password": "!rUv06Bh8BQoqyhkOEl2BtUKUwOX3NlpCVPBSwqBj", "last_login": null, "is_superuser": false, "username": "login_service_user", "first_name": "", "last_name": "", "email": "login_service_user@fake.email", "is_staff": false, "is_active": true, "date_joined": "2018-10-25T14:53:08.044Z", "groups": [], "user_permissions": []}}, {"model": "util.ratelimitconfiguration", "pk": 1, "fields": {"change_date": "2017-12-06T02:37:46.125Z", "changed_by": null, "enabled": true}}, {"model": "certificates.certificatehtmlviewconfiguration", "pk": 1, "fields": {"change_date": "2017-12-06T02:19:25.679Z", "changed_by": null, "enabled": false, "configuration": "{\"default\": {\"accomplishment_class_append\": \"accomplishment-certificate\", \"platform_name\": \"Your Platform Name Here\", \"logo_src\": \"/static/certificates/images/logo.png\", \"logo_url\": \"http://www.example.com\", \"company_verified_certificate_url\": \"http://www.example.com/verified-certificate\", \"company_privacy_url\": \"http://www.example.com/privacy-policy\", \"company_tos_url\": \"http://www.example.com/terms-service\", \"company_about_url\": \"http://www.example.com/about-us\"}, \"verified\": {\"certificate_type\": \"Verified\", \"certificate_title\": \"Verified Certificate of Achievement\"}, \"honor\": {\"certificate_type\": \"Honor Code\", \"certificate_title\": \"Certificate of Achievement\"}}"}}, {"model": "oauth2_provider.application", "pk": 2, "fields": {"client_id": "login-service-client-id", "user": 2, "redirect_uris": "", "client_type": "public", "authorization_grant_type": "password", "client_secret": "mpAwLT424Wm3HQfjVydNCceq7ZOERB72jVuzLSo0B7KldmPHqCmYQNyCMS2mklqzJN4XyT7VRcqHG7bHC0KDHIqcOAMpMisuCi7jIigmseHKKLjgjsx6DM9Rem2cOvO6", "name": "Login Service for JWT Cookies", "skip_authorization": false, "created": "2018-10-25T14:53:08.054Z", "updated": "2018-10-25T14:53:08.054Z"}}, {"model": "django_comment_common.forumsconfig", "pk": 1, "fields": {"change_date": "2017-12-06T02:23:41.040Z", "changed_by": null, "enabled": true, "connection_timeout": 5.0}}, {"model": "dark_lang.darklangconfig", "pk": 1, "fields": {"change_date": "2017-12-06T02:22:45.120Z", "changed_by": null, "enabled": true, "released_languages": "", "enable_beta_languages": false, "beta_languages": ""}}] \ No newline at end of file +[{"model": "contenttypes.contenttype", "pk": 1, "fields": {"app_label": "api_admin", "model": "apiaccessrequest"}}, {"model": "contenttypes.contenttype", "pk": 2, "fields": {"app_label": "auth", "model": "permission"}}, {"model": "contenttypes.contenttype", "pk": 3, "fields": {"app_label": "auth", "model": "group"}}, {"model": "contenttypes.contenttype", "pk": 4, "fields": {"app_label": "auth", "model": "user"}}, {"model": "contenttypes.contenttype", "pk": 5, "fields": {"app_label": "contenttypes", "model": "contenttype"}}, {"model": "contenttypes.contenttype", "pk": 6, "fields": {"app_label": "redirects", "model": "redirect"}}, {"model": "contenttypes.contenttype", "pk": 7, "fields": {"app_label": "sessions", "model": "session"}}, {"model": "contenttypes.contenttype", "pk": 8, "fields": {"app_label": "sites", "model": "site"}}, {"model": "contenttypes.contenttype", "pk": 9, "fields": {"app_label": "djcelery", "model": "taskmeta"}}, {"model": "contenttypes.contenttype", "pk": 10, "fields": {"app_label": "djcelery", "model": "tasksetmeta"}}, {"model": "contenttypes.contenttype", "pk": 11, "fields": {"app_label": "djcelery", "model": "intervalschedule"}}, {"model": "contenttypes.contenttype", "pk": 12, "fields": {"app_label": "djcelery", "model": "crontabschedule"}}, {"model": "contenttypes.contenttype", "pk": 13, "fields": {"app_label": "djcelery", "model": "periodictasks"}}, {"model": "contenttypes.contenttype", "pk": 14, "fields": {"app_label": "djcelery", "model": "periodictask"}}, {"model": "contenttypes.contenttype", "pk": 15, "fields": {"app_label": "djcelery", "model": "workerstate"}}, {"model": "contenttypes.contenttype", "pk": 16, "fields": {"app_label": "djcelery", "model": "taskstate"}}, {"model": "contenttypes.contenttype", "pk": 17, "fields": {"app_label": "waffle", "model": "flag"}}, {"model": "contenttypes.contenttype", "pk": 18, "fields": {"app_label": "waffle", "model": "switch"}}, {"model": "contenttypes.contenttype", "pk": 19, "fields": {"app_label": "waffle", "model": "sample"}}, {"model": "contenttypes.contenttype", "pk": 20, "fields": {"app_label": "status", "model": "globalstatusmessage"}}, {"model": "contenttypes.contenttype", "pk": 21, "fields": {"app_label": "status", "model": "coursemessage"}}, {"model": "contenttypes.contenttype", "pk": 22, "fields": {"app_label": "static_replace", "model": "assetbaseurlconfig"}}, {"model": "contenttypes.contenttype", "pk": 23, "fields": {"app_label": "static_replace", "model": "assetexcludedextensionsconfig"}}, {"model": "contenttypes.contenttype", "pk": 24, "fields": {"app_label": "contentserver", "model": "courseassetcachettlconfig"}}, {"model": "contenttypes.contenttype", "pk": 25, "fields": {"app_label": "contentserver", "model": "cdnuseragentsconfig"}}, {"model": "contenttypes.contenttype", "pk": 26, "fields": {"app_label": "theming", "model": "sitetheme"}}, {"model": "contenttypes.contenttype", "pk": 27, "fields": {"app_label": "site_configuration", "model": "siteconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 28, "fields": {"app_label": "site_configuration", "model": "siteconfigurationhistory"}}, {"model": "contenttypes.contenttype", "pk": 29, "fields": {"app_label": "video_config", "model": "hlsplaybackenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 30, "fields": {"app_label": "video_config", "model": "coursehlsplaybackenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 31, "fields": {"app_label": "video_config", "model": "videotranscriptenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 32, "fields": {"app_label": "video_config", "model": "coursevideotranscriptenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 33, "fields": {"app_label": "video_pipeline", "model": "videopipelineintegration"}}, {"model": "contenttypes.contenttype", "pk": 34, "fields": {"app_label": "video_pipeline", "model": "videouploadsenabledbydefault"}}, {"model": "contenttypes.contenttype", "pk": 35, "fields": {"app_label": "video_pipeline", "model": "coursevideouploadsenabledbydefault"}}, {"model": "contenttypes.contenttype", "pk": 36, "fields": {"app_label": "bookmarks", "model": "bookmark"}}, {"model": "contenttypes.contenttype", "pk": 37, "fields": {"app_label": "bookmarks", "model": "xblockcache"}}, {"model": "contenttypes.contenttype", "pk": 38, "fields": {"app_label": "courseware", "model": "studentmodule"}}, {"model": "contenttypes.contenttype", "pk": 39, "fields": {"app_label": "courseware", "model": "studentmodulehistory"}}, {"model": "contenttypes.contenttype", "pk": 40, "fields": {"app_label": "courseware", "model": "xmoduleuserstatesummaryfield"}}, {"model": "contenttypes.contenttype", "pk": 41, "fields": {"app_label": "courseware", "model": "xmodulestudentprefsfield"}}, {"model": "contenttypes.contenttype", "pk": 42, "fields": {"app_label": "courseware", "model": "xmodulestudentinfofield"}}, {"model": "contenttypes.contenttype", "pk": 43, "fields": {"app_label": "courseware", "model": "offlinecomputedgrade"}}, {"model": "contenttypes.contenttype", "pk": 44, "fields": {"app_label": "courseware", "model": "offlinecomputedgradelog"}}, {"model": "contenttypes.contenttype", "pk": 45, "fields": {"app_label": "courseware", "model": "studentfieldoverride"}}, {"model": "contenttypes.contenttype", "pk": 46, "fields": {"app_label": "courseware", "model": "dynamicupgradedeadlineconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 47, "fields": {"app_label": "courseware", "model": "coursedynamicupgradedeadlineconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 48, "fields": {"app_label": "courseware", "model": "orgdynamicupgradedeadlineconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 49, "fields": {"app_label": "student", "model": "anonymoususerid"}}, {"model": "contenttypes.contenttype", "pk": 50, "fields": {"app_label": "student", "model": "userstanding"}}, {"model": "contenttypes.contenttype", "pk": 51, "fields": {"app_label": "student", "model": "userprofile"}}, {"model": "contenttypes.contenttype", "pk": 52, "fields": {"app_label": "student", "model": "usersignupsource"}}, {"model": "contenttypes.contenttype", "pk": 53, "fields": {"app_label": "student", "model": "usertestgroup"}}, {"model": "contenttypes.contenttype", "pk": 54, "fields": {"app_label": "student", "model": "registration"}}, {"model": "contenttypes.contenttype", "pk": 55, "fields": {"app_label": "student", "model": "pendingnamechange"}}, {"model": "contenttypes.contenttype", "pk": 56, "fields": {"app_label": "student", "model": "pendingemailchange"}}, {"model": "contenttypes.contenttype", "pk": 57, "fields": {"app_label": "student", "model": "passwordhistory"}}, {"model": "contenttypes.contenttype", "pk": 58, "fields": {"app_label": "student", "model": "loginfailures"}}, {"model": "contenttypes.contenttype", "pk": 59, "fields": {"app_label": "student", "model": "courseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 60, "fields": {"app_label": "student", "model": "manualenrollmentaudit"}}, {"model": "contenttypes.contenttype", "pk": 61, "fields": {"app_label": "student", "model": "courseenrollmentallowed"}}, {"model": "contenttypes.contenttype", "pk": 62, "fields": {"app_label": "student", "model": "courseaccessrole"}}, {"model": "contenttypes.contenttype", "pk": 63, "fields": {"app_label": "student", "model": "dashboardconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 64, "fields": {"app_label": "student", "model": "linkedinaddtoprofileconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 65, "fields": {"app_label": "student", "model": "entranceexamconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 66, "fields": {"app_label": "student", "model": "languageproficiency"}}, {"model": "contenttypes.contenttype", "pk": 67, "fields": {"app_label": "student", "model": "sociallink"}}, {"model": "contenttypes.contenttype", "pk": 68, "fields": {"app_label": "student", "model": "courseenrollmentattribute"}}, {"model": "contenttypes.contenttype", "pk": 69, "fields": {"app_label": "student", "model": "enrollmentrefundconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 70, "fields": {"app_label": "student", "model": "registrationcookieconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 71, "fields": {"app_label": "student", "model": "userattribute"}}, {"model": "contenttypes.contenttype", "pk": 72, "fields": {"app_label": "student", "model": "logoutviewconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 73, "fields": {"app_label": "track", "model": "trackinglog"}}, {"model": "contenttypes.contenttype", "pk": 74, "fields": {"app_label": "util", "model": "ratelimitconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 75, "fields": {"app_label": "certificates", "model": "certificatewhitelist"}}, {"model": "contenttypes.contenttype", "pk": 76, "fields": {"app_label": "certificates", "model": "generatedcertificate"}}, {"model": "contenttypes.contenttype", "pk": 77, "fields": {"app_label": "certificates", "model": "certificategenerationhistory"}}, {"model": "contenttypes.contenttype", "pk": 78, "fields": {"app_label": "certificates", "model": "certificateinvalidation"}}, {"model": "contenttypes.contenttype", "pk": 79, "fields": {"app_label": "certificates", "model": "examplecertificateset"}}, {"model": "contenttypes.contenttype", "pk": 80, "fields": {"app_label": "certificates", "model": "examplecertificate"}}, {"model": "contenttypes.contenttype", "pk": 81, "fields": {"app_label": "certificates", "model": "certificategenerationcoursesetting"}}, {"model": "contenttypes.contenttype", "pk": 82, "fields": {"app_label": "certificates", "model": "certificategenerationconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 83, "fields": {"app_label": "certificates", "model": "certificatehtmlviewconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 84, "fields": {"app_label": "certificates", "model": "certificatetemplate"}}, {"model": "contenttypes.contenttype", "pk": 85, "fields": {"app_label": "certificates", "model": "certificatetemplateasset"}}, {"model": "contenttypes.contenttype", "pk": 86, "fields": {"app_label": "instructor_task", "model": "instructortask"}}, {"model": "contenttypes.contenttype", "pk": 87, "fields": {"app_label": "instructor_task", "model": "gradereportsetting"}}, {"model": "contenttypes.contenttype", "pk": 88, "fields": {"app_label": "course_groups", "model": "courseusergroup"}}, {"model": "contenttypes.contenttype", "pk": 89, "fields": {"app_label": "course_groups", "model": "cohortmembership"}}, {"model": "contenttypes.contenttype", "pk": 90, "fields": {"app_label": "course_groups", "model": "courseusergrouppartitiongroup"}}, {"model": "contenttypes.contenttype", "pk": 91, "fields": {"app_label": "course_groups", "model": "coursecohortssettings"}}, {"model": "contenttypes.contenttype", "pk": 92, "fields": {"app_label": "course_groups", "model": "coursecohort"}}, {"model": "contenttypes.contenttype", "pk": 93, "fields": {"app_label": "course_groups", "model": "unregisteredlearnercohortassignments"}}, {"model": "contenttypes.contenttype", "pk": 94, "fields": {"app_label": "bulk_email", "model": "target"}}, {"model": "contenttypes.contenttype", "pk": 95, "fields": {"app_label": "bulk_email", "model": "cohorttarget"}}, {"model": "contenttypes.contenttype", "pk": 96, "fields": {"app_label": "bulk_email", "model": "coursemodetarget"}}, {"model": "contenttypes.contenttype", "pk": 97, "fields": {"app_label": "bulk_email", "model": "courseemail"}}, {"model": "contenttypes.contenttype", "pk": 98, "fields": {"app_label": "bulk_email", "model": "optout"}}, {"model": "contenttypes.contenttype", "pk": 99, "fields": {"app_label": "bulk_email", "model": "courseemailtemplate"}}, {"model": "contenttypes.contenttype", "pk": 100, "fields": {"app_label": "bulk_email", "model": "courseauthorization"}}, {"model": "contenttypes.contenttype", "pk": 101, "fields": {"app_label": "bulk_email", "model": "bulkemailflag"}}, {"model": "contenttypes.contenttype", "pk": 102, "fields": {"app_label": "branding", "model": "brandinginfoconfig"}}, {"model": "contenttypes.contenttype", "pk": 103, "fields": {"app_label": "branding", "model": "brandingapiconfig"}}, {"model": "contenttypes.contenttype", "pk": 104, "fields": {"app_label": "grades", "model": "visibleblocks"}}, {"model": "contenttypes.contenttype", "pk": 105, "fields": {"app_label": "grades", "model": "persistentsubsectiongrade"}}, {"model": "contenttypes.contenttype", "pk": 106, "fields": {"app_label": "grades", "model": "persistentcoursegrade"}}, {"model": "contenttypes.contenttype", "pk": 107, "fields": {"app_label": "grades", "model": "persistentsubsectiongradeoverride"}}, {"model": "contenttypes.contenttype", "pk": 108, "fields": {"app_label": "grades", "model": "persistentgradesenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 109, "fields": {"app_label": "grades", "model": "coursepersistentgradesflag"}}, {"model": "contenttypes.contenttype", "pk": 110, "fields": {"app_label": "grades", "model": "computegradessetting"}}, {"model": "contenttypes.contenttype", "pk": 111, "fields": {"app_label": "external_auth", "model": "externalauthmap"}}, {"model": "contenttypes.contenttype", "pk": 112, "fields": {"app_label": "django_openid_auth", "model": "nonce"}}, {"model": "contenttypes.contenttype", "pk": 113, "fields": {"app_label": "django_openid_auth", "model": "association"}}, {"model": "contenttypes.contenttype", "pk": 114, "fields": {"app_label": "django_openid_auth", "model": "useropenid"}}, {"model": "contenttypes.contenttype", "pk": 115, "fields": {"app_label": "oauth2", "model": "client"}}, {"model": "contenttypes.contenttype", "pk": 116, "fields": {"app_label": "oauth2", "model": "grant"}}, {"model": "contenttypes.contenttype", "pk": 117, "fields": {"app_label": "oauth2", "model": "accesstoken"}}, {"model": "contenttypes.contenttype", "pk": 118, "fields": {"app_label": "oauth2", "model": "refreshtoken"}}, {"model": "contenttypes.contenttype", "pk": 119, "fields": {"app_label": "edx_oauth2_provider", "model": "trustedclient"}}, {"model": "contenttypes.contenttype", "pk": 120, "fields": {"app_label": "oauth2_provider", "model": "application"}}, {"model": "contenttypes.contenttype", "pk": 121, "fields": {"app_label": "oauth2_provider", "model": "grant"}}, {"model": "contenttypes.contenttype", "pk": 122, "fields": {"app_label": "oauth2_provider", "model": "accesstoken"}}, {"model": "contenttypes.contenttype", "pk": 123, "fields": {"app_label": "oauth2_provider", "model": "refreshtoken"}}, {"model": "contenttypes.contenttype", "pk": 124, "fields": {"app_label": "oauth_dispatch", "model": "restrictedapplication"}}, {"model": "contenttypes.contenttype", "pk": 125, "fields": {"app_label": "third_party_auth", "model": "oauth2providerconfig"}}, {"model": "contenttypes.contenttype", "pk": 126, "fields": {"app_label": "third_party_auth", "model": "samlproviderconfig"}}, {"model": "contenttypes.contenttype", "pk": 127, "fields": {"app_label": "third_party_auth", "model": "samlconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 128, "fields": {"app_label": "third_party_auth", "model": "samlproviderdata"}}, {"model": "contenttypes.contenttype", "pk": 129, "fields": {"app_label": "third_party_auth", "model": "ltiproviderconfig"}}, {"model": "contenttypes.contenttype", "pk": 130, "fields": {"app_label": "third_party_auth", "model": "providerapipermissions"}}, {"model": "contenttypes.contenttype", "pk": 131, "fields": {"app_label": "oauth_provider", "model": "nonce"}}, {"model": "contenttypes.contenttype", "pk": 132, "fields": {"app_label": "oauth_provider", "model": "scope"}}, {"model": "contenttypes.contenttype", "pk": 133, "fields": {"app_label": "oauth_provider", "model": "consumer"}}, {"model": "contenttypes.contenttype", "pk": 134, "fields": {"app_label": "oauth_provider", "model": "token"}}, {"model": "contenttypes.contenttype", "pk": 135, "fields": {"app_label": "oauth_provider", "model": "resource"}}, {"model": "contenttypes.contenttype", "pk": 136, "fields": {"app_label": "wiki", "model": "article"}}, {"model": "contenttypes.contenttype", "pk": 137, "fields": {"app_label": "wiki", "model": "articleforobject"}}, {"model": "contenttypes.contenttype", "pk": 138, "fields": {"app_label": "wiki", "model": "articlerevision"}}, {"model": "contenttypes.contenttype", "pk": 139, "fields": {"app_label": "wiki", "model": "articleplugin"}}, {"model": "contenttypes.contenttype", "pk": 140, "fields": {"app_label": "wiki", "model": "reusableplugin"}}, {"model": "contenttypes.contenttype", "pk": 141, "fields": {"app_label": "wiki", "model": "simpleplugin"}}, {"model": "contenttypes.contenttype", "pk": 142, "fields": {"app_label": "wiki", "model": "revisionplugin"}}, {"model": "contenttypes.contenttype", "pk": 143, "fields": {"app_label": "wiki", "model": "revisionpluginrevision"}}, {"model": "contenttypes.contenttype", "pk": 144, "fields": {"app_label": "wiki", "model": "urlpath"}}, {"model": "contenttypes.contenttype", "pk": 145, "fields": {"app_label": "django_notify", "model": "notificationtype"}}, {"model": "contenttypes.contenttype", "pk": 146, "fields": {"app_label": "django_notify", "model": "settings"}}, {"model": "contenttypes.contenttype", "pk": 147, "fields": {"app_label": "django_notify", "model": "subscription"}}, {"model": "contenttypes.contenttype", "pk": 148, "fields": {"app_label": "django_notify", "model": "notification"}}, {"model": "contenttypes.contenttype", "pk": 149, "fields": {"app_label": "admin", "model": "logentry"}}, {"model": "contenttypes.contenttype", "pk": 150, "fields": {"app_label": "django_comment_common", "model": "role"}}, {"model": "contenttypes.contenttype", "pk": 151, "fields": {"app_label": "django_comment_common", "model": "permission"}}, {"model": "contenttypes.contenttype", "pk": 152, "fields": {"app_label": "django_comment_common", "model": "forumsconfig"}}, {"model": "contenttypes.contenttype", "pk": 153, "fields": {"app_label": "django_comment_common", "model": "coursediscussionsettings"}}, {"model": "contenttypes.contenttype", "pk": 154, "fields": {"app_label": "notes", "model": "note"}}, {"model": "contenttypes.contenttype", "pk": 155, "fields": {"app_label": "splash", "model": "splashconfig"}}, {"model": "contenttypes.contenttype", "pk": 156, "fields": {"app_label": "user_api", "model": "userpreference"}}, {"model": "contenttypes.contenttype", "pk": 157, "fields": {"app_label": "user_api", "model": "usercoursetag"}}, {"model": "contenttypes.contenttype", "pk": 158, "fields": {"app_label": "user_api", "model": "userorgtag"}}, {"model": "contenttypes.contenttype", "pk": 159, "fields": {"app_label": "shoppingcart", "model": "order"}}, {"model": "contenttypes.contenttype", "pk": 160, "fields": {"app_label": "shoppingcart", "model": "orderitem"}}, {"model": "contenttypes.contenttype", "pk": 161, "fields": {"app_label": "shoppingcart", "model": "invoice"}}, {"model": "contenttypes.contenttype", "pk": 162, "fields": {"app_label": "shoppingcart", "model": "invoicetransaction"}}, {"model": "contenttypes.contenttype", "pk": 163, "fields": {"app_label": "shoppingcart", "model": "invoiceitem"}}, {"model": "contenttypes.contenttype", "pk": 164, "fields": {"app_label": "shoppingcart", "model": "courseregistrationcodeinvoiceitem"}}, {"model": "contenttypes.contenttype", "pk": 165, "fields": {"app_label": "shoppingcart", "model": "invoicehistory"}}, {"model": "contenttypes.contenttype", "pk": 166, "fields": {"app_label": "shoppingcart", "model": "courseregistrationcode"}}, {"model": "contenttypes.contenttype", "pk": 167, "fields": {"app_label": "shoppingcart", "model": "registrationcoderedemption"}}, {"model": "contenttypes.contenttype", "pk": 168, "fields": {"app_label": "shoppingcart", "model": "coupon"}}, {"model": "contenttypes.contenttype", "pk": 169, "fields": {"app_label": "shoppingcart", "model": "couponredemption"}}, {"model": "contenttypes.contenttype", "pk": 170, "fields": {"app_label": "shoppingcart", "model": "paidcourseregistration"}}, {"model": "contenttypes.contenttype", "pk": 171, "fields": {"app_label": "shoppingcart", "model": "courseregcodeitem"}}, {"model": "contenttypes.contenttype", "pk": 172, "fields": {"app_label": "shoppingcart", "model": "courseregcodeitemannotation"}}, {"model": "contenttypes.contenttype", "pk": 173, "fields": {"app_label": "shoppingcart", "model": "paidcourseregistrationannotation"}}, {"model": "contenttypes.contenttype", "pk": 174, "fields": {"app_label": "shoppingcart", "model": "certificateitem"}}, {"model": "contenttypes.contenttype", "pk": 175, "fields": {"app_label": "shoppingcart", "model": "donationconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 176, "fields": {"app_label": "shoppingcart", "model": "donation"}}, {"model": "contenttypes.contenttype", "pk": 177, "fields": {"app_label": "course_modes", "model": "coursemode"}}, {"model": "contenttypes.contenttype", "pk": 178, "fields": {"app_label": "course_modes", "model": "coursemodesarchive"}}, {"model": "contenttypes.contenttype", "pk": 179, "fields": {"app_label": "course_modes", "model": "coursemodeexpirationconfig"}}, {"model": "contenttypes.contenttype", "pk": 180, "fields": {"app_label": "entitlements", "model": "courseentitlement"}}, {"model": "contenttypes.contenttype", "pk": 181, "fields": {"app_label": "verify_student", "model": "softwaresecurephotoverification"}}, {"model": "contenttypes.contenttype", "pk": 182, "fields": {"app_label": "verify_student", "model": "verificationdeadline"}}, {"model": "contenttypes.contenttype", "pk": 183, "fields": {"app_label": "verify_student", "model": "verificationcheckpoint"}}, {"model": "contenttypes.contenttype", "pk": 184, "fields": {"app_label": "verify_student", "model": "verificationstatus"}}, {"model": "contenttypes.contenttype", "pk": 185, "fields": {"app_label": "verify_student", "model": "incoursereverificationconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 186, "fields": {"app_label": "verify_student", "model": "icrvstatusemailsconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 187, "fields": {"app_label": "verify_student", "model": "skippedreverification"}}, {"model": "contenttypes.contenttype", "pk": 188, "fields": {"app_label": "dark_lang", "model": "darklangconfig"}}, {"model": "contenttypes.contenttype", "pk": 189, "fields": {"app_label": "microsite_configuration", "model": "microsite"}}, {"model": "contenttypes.contenttype", "pk": 190, "fields": {"app_label": "microsite_configuration", "model": "micrositehistory"}}, {"model": "contenttypes.contenttype", "pk": 191, "fields": {"app_label": "microsite_configuration", "model": "micrositeorganizationmapping"}}, {"model": "contenttypes.contenttype", "pk": 192, "fields": {"app_label": "microsite_configuration", "model": "micrositetemplate"}}, {"model": "contenttypes.contenttype", "pk": 193, "fields": {"app_label": "rss_proxy", "model": "whitelistedrssurl"}}, {"model": "contenttypes.contenttype", "pk": 194, "fields": {"app_label": "embargo", "model": "embargoedcourse"}}, {"model": "contenttypes.contenttype", "pk": 195, "fields": {"app_label": "embargo", "model": "embargoedstate"}}, {"model": "contenttypes.contenttype", "pk": 196, "fields": {"app_label": "embargo", "model": "restrictedcourse"}}, {"model": "contenttypes.contenttype", "pk": 197, "fields": {"app_label": "embargo", "model": "country"}}, {"model": "contenttypes.contenttype", "pk": 198, "fields": {"app_label": "embargo", "model": "countryaccessrule"}}, {"model": "contenttypes.contenttype", "pk": 199, "fields": {"app_label": "embargo", "model": "courseaccessrulehistory"}}, {"model": "contenttypes.contenttype", "pk": 200, "fields": {"app_label": "embargo", "model": "ipfilter"}}, {"model": "contenttypes.contenttype", "pk": 201, "fields": {"app_label": "course_action_state", "model": "coursererunstate"}}, {"model": "contenttypes.contenttype", "pk": 202, "fields": {"app_label": "mobile_api", "model": "mobileapiconfig"}}, {"model": "contenttypes.contenttype", "pk": 203, "fields": {"app_label": "mobile_api", "model": "appversionconfig"}}, {"model": "contenttypes.contenttype", "pk": 204, "fields": {"app_label": "mobile_api", "model": "ignoremobileavailableflagconfig"}}, {"model": "contenttypes.contenttype", "pk": 205, "fields": {"app_label": "social_django", "model": "usersocialauth"}}, {"model": "contenttypes.contenttype", "pk": 206, "fields": {"app_label": "social_django", "model": "nonce"}}, {"model": "contenttypes.contenttype", "pk": 207, "fields": {"app_label": "social_django", "model": "association"}}, {"model": "contenttypes.contenttype", "pk": 208, "fields": {"app_label": "social_django", "model": "code"}}, {"model": "contenttypes.contenttype", "pk": 209, "fields": {"app_label": "social_django", "model": "partial"}}, {"model": "contenttypes.contenttype", "pk": 210, "fields": {"app_label": "survey", "model": "surveyform"}}, {"model": "contenttypes.contenttype", "pk": 211, "fields": {"app_label": "survey", "model": "surveyanswer"}}, {"model": "contenttypes.contenttype", "pk": 212, "fields": {"app_label": "lms_xblock", "model": "xblockasidesconfig"}}, {"model": "contenttypes.contenttype", "pk": 213, "fields": {"app_label": "problem_builder", "model": "answer"}}, {"model": "contenttypes.contenttype", "pk": 214, "fields": {"app_label": "problem_builder", "model": "share"}}, {"model": "contenttypes.contenttype", "pk": 215, "fields": {"app_label": "submissions", "model": "studentitem"}}, {"model": "contenttypes.contenttype", "pk": 216, "fields": {"app_label": "submissions", "model": "submission"}}, {"model": "contenttypes.contenttype", "pk": 217, "fields": {"app_label": "submissions", "model": "score"}}, {"model": "contenttypes.contenttype", "pk": 218, "fields": {"app_label": "submissions", "model": "scoresummary"}}, {"model": "contenttypes.contenttype", "pk": 219, "fields": {"app_label": "submissions", "model": "scoreannotation"}}, {"model": "contenttypes.contenttype", "pk": 220, "fields": {"app_label": "assessment", "model": "rubric"}}, {"model": "contenttypes.contenttype", "pk": 221, "fields": {"app_label": "assessment", "model": "criterion"}}, {"model": "contenttypes.contenttype", "pk": 222, "fields": {"app_label": "assessment", "model": "criterionoption"}}, {"model": "contenttypes.contenttype", "pk": 223, "fields": {"app_label": "assessment", "model": "assessment"}}, {"model": "contenttypes.contenttype", "pk": 224, "fields": {"app_label": "assessment", "model": "assessmentpart"}}, {"model": "contenttypes.contenttype", "pk": 225, "fields": {"app_label": "assessment", "model": "assessmentfeedbackoption"}}, {"model": "contenttypes.contenttype", "pk": 226, "fields": {"app_label": "assessment", "model": "assessmentfeedback"}}, {"model": "contenttypes.contenttype", "pk": 227, "fields": {"app_label": "assessment", "model": "peerworkflow"}}, {"model": "contenttypes.contenttype", "pk": 228, "fields": {"app_label": "assessment", "model": "peerworkflowitem"}}, {"model": "contenttypes.contenttype", "pk": 229, "fields": {"app_label": "assessment", "model": "trainingexample"}}, {"model": "contenttypes.contenttype", "pk": 230, "fields": {"app_label": "assessment", "model": "studenttrainingworkflow"}}, {"model": "contenttypes.contenttype", "pk": 231, "fields": {"app_label": "assessment", "model": "studenttrainingworkflowitem"}}, {"model": "contenttypes.contenttype", "pk": 232, "fields": {"app_label": "assessment", "model": "staffworkflow"}}, {"model": "contenttypes.contenttype", "pk": 233, "fields": {"app_label": "workflow", "model": "assessmentworkflow"}}, {"model": "contenttypes.contenttype", "pk": 234, "fields": {"app_label": "workflow", "model": "assessmentworkflowstep"}}, {"model": "contenttypes.contenttype", "pk": 235, "fields": {"app_label": "workflow", "model": "assessmentworkflowcancellation"}}, {"model": "contenttypes.contenttype", "pk": 236, "fields": {"app_label": "edxval", "model": "profile"}}, {"model": "contenttypes.contenttype", "pk": 237, "fields": {"app_label": "edxval", "model": "video"}}, {"model": "contenttypes.contenttype", "pk": 238, "fields": {"app_label": "edxval", "model": "coursevideo"}}, {"model": "contenttypes.contenttype", "pk": 239, "fields": {"app_label": "edxval", "model": "encodedvideo"}}, {"model": "contenttypes.contenttype", "pk": 240, "fields": {"app_label": "edxval", "model": "videoimage"}}, {"model": "contenttypes.contenttype", "pk": 241, "fields": {"app_label": "edxval", "model": "videotranscript"}}, {"model": "contenttypes.contenttype", "pk": 242, "fields": {"app_label": "edxval", "model": "transcriptpreference"}}, {"model": "contenttypes.contenttype", "pk": 243, "fields": {"app_label": "edxval", "model": "thirdpartytranscriptcredentialsstate"}}, {"model": "contenttypes.contenttype", "pk": 244, "fields": {"app_label": "course_overviews", "model": "courseoverview"}}, {"model": "contenttypes.contenttype", "pk": 245, "fields": {"app_label": "course_overviews", "model": "courseoverviewtab"}}, {"model": "contenttypes.contenttype", "pk": 246, "fields": {"app_label": "course_overviews", "model": "courseoverviewimageset"}}, {"model": "contenttypes.contenttype", "pk": 247, "fields": {"app_label": "course_overviews", "model": "courseoverviewimageconfig"}}, {"model": "contenttypes.contenttype", "pk": 248, "fields": {"app_label": "course_structures", "model": "coursestructure"}}, {"model": "contenttypes.contenttype", "pk": 249, "fields": {"app_label": "block_structure", "model": "blockstructureconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 250, "fields": {"app_label": "block_structure", "model": "blockstructuremodel"}}, {"model": "contenttypes.contenttype", "pk": 251, "fields": {"app_label": "cors_csrf", "model": "xdomainproxyconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 252, "fields": {"app_label": "commerce", "model": "commerceconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 253, "fields": {"app_label": "credit", "model": "creditprovider"}}, {"model": "contenttypes.contenttype", "pk": 254, "fields": {"app_label": "credit", "model": "creditcourse"}}, {"model": "contenttypes.contenttype", "pk": 255, "fields": {"app_label": "credit", "model": "creditrequirement"}}, {"model": "contenttypes.contenttype", "pk": 256, "fields": {"app_label": "credit", "model": "creditrequirementstatus"}}, {"model": "contenttypes.contenttype", "pk": 257, "fields": {"app_label": "credit", "model": "crediteligibility"}}, {"model": "contenttypes.contenttype", "pk": 258, "fields": {"app_label": "credit", "model": "creditrequest"}}, {"model": "contenttypes.contenttype", "pk": 259, "fields": {"app_label": "credit", "model": "creditconfig"}}, {"model": "contenttypes.contenttype", "pk": 260, "fields": {"app_label": "teams", "model": "courseteam"}}, {"model": "contenttypes.contenttype", "pk": 261, "fields": {"app_label": "teams", "model": "courseteammembership"}}, {"model": "contenttypes.contenttype", "pk": 262, "fields": {"app_label": "xblock_django", "model": "xblockconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 263, "fields": {"app_label": "xblock_django", "model": "xblockstudioconfigurationflag"}}, {"model": "contenttypes.contenttype", "pk": 264, "fields": {"app_label": "xblock_django", "model": "xblockstudioconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 265, "fields": {"app_label": "programs", "model": "programsapiconfig"}}, {"model": "contenttypes.contenttype", "pk": 266, "fields": {"app_label": "catalog", "model": "catalogintegration"}}, {"model": "contenttypes.contenttype", "pk": 267, "fields": {"app_label": "self_paced", "model": "selfpacedconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 268, "fields": {"app_label": "thumbnail", "model": "kvstore"}}, {"model": "contenttypes.contenttype", "pk": 269, "fields": {"app_label": "credentials", "model": "credentialsapiconfig"}}, {"model": "contenttypes.contenttype", "pk": 270, "fields": {"app_label": "milestones", "model": "milestone"}}, {"model": "contenttypes.contenttype", "pk": 271, "fields": {"app_label": "milestones", "model": "milestonerelationshiptype"}}, {"model": "contenttypes.contenttype", "pk": 272, "fields": {"app_label": "milestones", "model": "coursemilestone"}}, {"model": "contenttypes.contenttype", "pk": 273, "fields": {"app_label": "milestones", "model": "coursecontentmilestone"}}, {"model": "contenttypes.contenttype", "pk": 274, "fields": {"app_label": "milestones", "model": "usermilestone"}}, {"model": "contenttypes.contenttype", "pk": 275, "fields": {"app_label": "api_admin", "model": "apiaccessconfig"}}, {"model": "contenttypes.contenttype", "pk": 276, "fields": {"app_label": "api_admin", "model": "catalog"}}, {"model": "contenttypes.contenttype", "pk": 277, "fields": {"app_label": "verified_track_content", "model": "verifiedtrackcohortedcourse"}}, {"model": "contenttypes.contenttype", "pk": 278, "fields": {"app_label": "verified_track_content", "model": "migrateverifiedtrackcohortssetting"}}, {"model": "contenttypes.contenttype", "pk": 279, "fields": {"app_label": "badges", "model": "badgeclass"}}, {"model": "contenttypes.contenttype", "pk": 280, "fields": {"app_label": "badges", "model": "badgeassertion"}}, {"model": "contenttypes.contenttype", "pk": 281, "fields": {"app_label": "badges", "model": "coursecompleteimageconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 282, "fields": {"app_label": "badges", "model": "courseeventbadgesconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 283, "fields": {"app_label": "email_marketing", "model": "emailmarketingconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 284, "fields": {"app_label": "celery_utils", "model": "failedtask"}}, {"model": "contenttypes.contenttype", "pk": 285, "fields": {"app_label": "celery_utils", "model": "chorddata"}}, {"model": "contenttypes.contenttype", "pk": 286, "fields": {"app_label": "crawlers", "model": "crawlersconfig"}}, {"model": "contenttypes.contenttype", "pk": 287, "fields": {"app_label": "waffle_utils", "model": "waffleflagcourseoverridemodel"}}, {"model": "contenttypes.contenttype", "pk": 288, "fields": {"app_label": "schedules", "model": "schedule"}}, {"model": "contenttypes.contenttype", "pk": 289, "fields": {"app_label": "schedules", "model": "scheduleconfig"}}, {"model": "contenttypes.contenttype", "pk": 290, "fields": {"app_label": "schedules", "model": "scheduleexperience"}}, {"model": "contenttypes.contenttype", "pk": 291, "fields": {"app_label": "course_goals", "model": "coursegoal"}}, {"model": "contenttypes.contenttype", "pk": 292, "fields": {"app_label": "completion", "model": "blockcompletion"}}, {"model": "contenttypes.contenttype", "pk": 293, "fields": {"app_label": "experiments", "model": "experimentdata"}}, {"model": "contenttypes.contenttype", "pk": 294, "fields": {"app_label": "experiments", "model": "experimentkeyvalue"}}, {"model": "contenttypes.contenttype", "pk": 295, "fields": {"app_label": "edx_proctoring", "model": "proctoredexam"}}, {"model": "contenttypes.contenttype", "pk": 296, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamreviewpolicy"}}, {"model": "contenttypes.contenttype", "pk": 297, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamreviewpolicyhistory"}}, {"model": "contenttypes.contenttype", "pk": 298, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamstudentattempt"}}, {"model": "contenttypes.contenttype", "pk": 299, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamstudentattempthistory"}}, {"model": "contenttypes.contenttype", "pk": 300, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamstudentallowance"}}, {"model": "contenttypes.contenttype", "pk": 301, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamstudentallowancehistory"}}, {"model": "contenttypes.contenttype", "pk": 302, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamsoftwaresecurereview"}}, {"model": "contenttypes.contenttype", "pk": 303, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamsoftwaresecurereviewhistory"}}, {"model": "contenttypes.contenttype", "pk": 304, "fields": {"app_label": "edx_proctoring", "model": "proctoredexamsoftwaresecurecomment"}}, {"model": "contenttypes.contenttype", "pk": 305, "fields": {"app_label": "organizations", "model": "organization"}}, {"model": "contenttypes.contenttype", "pk": 306, "fields": {"app_label": "organizations", "model": "organizationcourse"}}, {"model": "contenttypes.contenttype", "pk": 307, "fields": {"app_label": "enterprise", "model": "historicalenterprisecustomer"}}, {"model": "contenttypes.contenttype", "pk": 308, "fields": {"app_label": "enterprise", "model": "enterprisecustomer"}}, {"model": "contenttypes.contenttype", "pk": 309, "fields": {"app_label": "enterprise", "model": "enterprisecustomeruser"}}, {"model": "contenttypes.contenttype", "pk": 310, "fields": {"app_label": "enterprise", "model": "pendingenterprisecustomeruser"}}, {"model": "contenttypes.contenttype", "pk": 311, "fields": {"app_label": "enterprise", "model": "pendingenrollment"}}, {"model": "contenttypes.contenttype", "pk": 312, "fields": {"app_label": "enterprise", "model": "enterprisecustomerbrandingconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 313, "fields": {"app_label": "enterprise", "model": "enterprisecustomeridentityprovider"}}, {"model": "contenttypes.contenttype", "pk": 314, "fields": {"app_label": "enterprise", "model": "historicalenterprisecustomerentitlement"}}, {"model": "contenttypes.contenttype", "pk": 315, "fields": {"app_label": "enterprise", "model": "enterprisecustomerentitlement"}}, {"model": "contenttypes.contenttype", "pk": 316, "fields": {"app_label": "enterprise", "model": "historicalenterprisecourseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 317, "fields": {"app_label": "enterprise", "model": "enterprisecourseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 318, "fields": {"app_label": "enterprise", "model": "historicalenterprisecustomercatalog"}}, {"model": "contenttypes.contenttype", "pk": 319, "fields": {"app_label": "enterprise", "model": "enterprisecustomercatalog"}}, {"model": "contenttypes.contenttype", "pk": 320, "fields": {"app_label": "enterprise", "model": "historicalenrollmentnotificationemailtemplate"}}, {"model": "contenttypes.contenttype", "pk": 321, "fields": {"app_label": "enterprise", "model": "enrollmentnotificationemailtemplate"}}, {"model": "contenttypes.contenttype", "pk": 322, "fields": {"app_label": "enterprise", "model": "enterprisecustomerreportingconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 323, "fields": {"app_label": "consent", "model": "historicaldatasharingconsent"}}, {"model": "contenttypes.contenttype", "pk": 324, "fields": {"app_label": "consent", "model": "datasharingconsent"}}, {"model": "contenttypes.contenttype", "pk": 325, "fields": {"app_label": "integrated_channel", "model": "learnerdatatransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 326, "fields": {"app_label": "integrated_channel", "model": "catalogtransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 327, "fields": {"app_label": "degreed", "model": "degreedglobalconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 328, "fields": {"app_label": "degreed", "model": "historicaldegreedenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 329, "fields": {"app_label": "degreed", "model": "degreedenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 330, "fields": {"app_label": "degreed", "model": "degreedlearnerdatatransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 331, "fields": {"app_label": "sap_success_factors", "model": "sapsuccessfactorsglobalconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 332, "fields": {"app_label": "sap_success_factors", "model": "historicalsapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 333, "fields": {"app_label": "sap_success_factors", "model": "sapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 334, "fields": {"app_label": "sap_success_factors", "model": "sapsuccessfactorslearnerdatatransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 335, "fields": {"app_label": "ccx", "model": "customcourseforedx"}}, {"model": "contenttypes.contenttype", "pk": 336, "fields": {"app_label": "ccx", "model": "ccxfieldoverride"}}, {"model": "contenttypes.contenttype", "pk": 337, "fields": {"app_label": "ccxcon", "model": "ccxcon"}}, {"model": "contenttypes.contenttype", "pk": 338, "fields": {"app_label": "coursewarehistoryextended", "model": "studentmodulehistoryextended"}}, {"model": "contenttypes.contenttype", "pk": 339, "fields": {"app_label": "contentstore", "model": "videouploadconfig"}}, {"model": "contenttypes.contenttype", "pk": 340, "fields": {"app_label": "contentstore", "model": "pushnotificationconfig"}}, {"model": "contenttypes.contenttype", "pk": 341, "fields": {"app_label": "contentstore", "model": "newassetspageflag"}}, {"model": "contenttypes.contenttype", "pk": 342, "fields": {"app_label": "contentstore", "model": "coursenewassetspageflag"}}, {"model": "contenttypes.contenttype", "pk": 343, "fields": {"app_label": "course_creators", "model": "coursecreator"}}, {"model": "contenttypes.contenttype", "pk": 344, "fields": {"app_label": "xblock_config", "model": "studioconfig"}}, {"model": "contenttypes.contenttype", "pk": 345, "fields": {"app_label": "xblock_config", "model": "courseeditltifieldsenabledflag"}}, {"model": "contenttypes.contenttype", "pk": 346, "fields": {"app_label": "tagging", "model": "tagcategories"}}, {"model": "contenttypes.contenttype", "pk": 347, "fields": {"app_label": "tagging", "model": "tagavailablevalues"}}, {"model": "contenttypes.contenttype", "pk": 348, "fields": {"app_label": "user_tasks", "model": "usertaskstatus"}}, {"model": "contenttypes.contenttype", "pk": 349, "fields": {"app_label": "user_tasks", "model": "usertaskartifact"}}, {"model": "contenttypes.contenttype", "pk": 350, "fields": {"app_label": "entitlements", "model": "courseentitlementpolicy"}}, {"model": "contenttypes.contenttype", "pk": 351, "fields": {"app_label": "entitlements", "model": "courseentitlementsupportdetail"}}, {"model": "contenttypes.contenttype", "pk": 352, "fields": {"app_label": "integrated_channel", "model": "contentmetadataitemtransmission"}}, {"model": "contenttypes.contenttype", "pk": 353, "fields": {"app_label": "video_config", "model": "transcriptmigrationsetting"}}, {"model": "contenttypes.contenttype", "pk": 354, "fields": {"app_label": "verify_student", "model": "ssoverification"}}, {"model": "contenttypes.contenttype", "pk": 355, "fields": {"app_label": "user_api", "model": "userretirementstatus"}}, {"model": "contenttypes.contenttype", "pk": 356, "fields": {"app_label": "user_api", "model": "retirementstate"}}, {"model": "contenttypes.contenttype", "pk": 357, "fields": {"app_label": "consent", "model": "datasharingconsenttextoverrides"}}, {"model": "contenttypes.contenttype", "pk": 358, "fields": {"app_label": "user_api", "model": "userretirementrequest"}}, {"model": "contenttypes.contenttype", "pk": 359, "fields": {"app_label": "django_comment_common", "model": "discussionsidmapping"}}, {"model": "contenttypes.contenttype", "pk": 360, "fields": {"app_label": "oauth_dispatch", "model": "scopedapplication"}}, {"model": "contenttypes.contenttype", "pk": 361, "fields": {"app_label": "oauth_dispatch", "model": "scopedapplicationorganization"}}, {"model": "contenttypes.contenttype", "pk": 362, "fields": {"app_label": "user_api", "model": "userretirementpartnerreportingstatus"}}, {"model": "contenttypes.contenttype", "pk": 363, "fields": {"app_label": "verify_student", "model": "manualverification"}}, {"model": "contenttypes.contenttype", "pk": 364, "fields": {"app_label": "oauth_dispatch", "model": "applicationorganization"}}, {"model": "contenttypes.contenttype", "pk": 365, "fields": {"app_label": "oauth_dispatch", "model": "applicationaccess"}}, {"model": "contenttypes.contenttype", "pk": 366, "fields": {"app_label": "video_config", "model": "migrationenqueuedcourse"}}, {"model": "contenttypes.contenttype", "pk": 367, "fields": {"app_label": "xapi", "model": "xapilrsconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 368, "fields": {"app_label": "credentials", "model": "notifycredentialsconfig"}}, {"model": "contenttypes.contenttype", "pk": 369, "fields": {"app_label": "video_config", "model": "updatedcoursevideos"}}, {"model": "contenttypes.contenttype", "pk": 370, "fields": {"app_label": "video_config", "model": "videothumbnailsetting"}}, {"model": "contenttypes.contenttype", "pk": 371, "fields": {"app_label": "course_duration_limits", "model": "coursedurationlimitconfig"}}, {"model": "contenttypes.contenttype", "pk": 372, "fields": {"app_label": "content_type_gating", "model": "contenttypegatingconfig"}}, {"model": "contenttypes.contenttype", "pk": 373, "fields": {"app_label": "grades", "model": "persistentsubsectiongradeoverridehistory"}}, {"model": "contenttypes.contenttype", "pk": 374, "fields": {"app_label": "student", "model": "accountrecovery"}}, {"model": "contenttypes.contenttype", "pk": 375, "fields": {"app_label": "enterprise", "model": "enterprisecustomertype"}}, {"model": "contenttypes.contenttype", "pk": 376, "fields": {"app_label": "student", "model": "pendingsecondaryemailchange"}}, {"model": "contenttypes.contenttype", "pk": 377, "fields": {"app_label": "lti_provider", "model": "lticonsumer"}}, {"model": "contenttypes.contenttype", "pk": 378, "fields": {"app_label": "lti_provider", "model": "gradedassignment"}}, {"model": "contenttypes.contenttype", "pk": 379, "fields": {"app_label": "lti_provider", "model": "ltiuser"}}, {"model": "contenttypes.contenttype", "pk": 380, "fields": {"app_label": "lti_provider", "model": "outcomeservice"}}, {"model": "contenttypes.contenttype", "pk": 381, "fields": {"app_label": "enterprise", "model": "systemwideenterpriserole"}}, {"model": "contenttypes.contenttype", "pk": 382, "fields": {"app_label": "enterprise", "model": "systemwideenterpriseuserroleassignment"}}, {"model": "contenttypes.contenttype", "pk": 383, "fields": {"app_label": "announcements", "model": "announcement"}}, {"model": "contenttypes.contenttype", "pk": 753, "fields": {"app_label": "enterprise", "model": "enterprisefeatureuserroleassignment"}}, {"model": "contenttypes.contenttype", "pk": 754, "fields": {"app_label": "enterprise", "model": "enterprisefeaturerole"}}, {"model": "contenttypes.contenttype", "pk": 755, "fields": {"app_label": "program_enrollments", "model": "programenrollment"}}, {"model": "contenttypes.contenttype", "pk": 756, "fields": {"app_label": "program_enrollments", "model": "historicalprogramenrollment"}}, {"model": "contenttypes.contenttype", "pk": 757, "fields": {"app_label": "program_enrollments", "model": "programcourseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 758, "fields": {"app_label": "program_enrollments", "model": "historicalprogramcourseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 759, "fields": {"app_label": "edx_when", "model": "contentdate"}}, {"model": "contenttypes.contenttype", "pk": 760, "fields": {"app_label": "edx_when", "model": "userdate"}}, {"model": "contenttypes.contenttype", "pk": 761, "fields": {"app_label": "edx_when", "model": "datepolicy"}}, {"model": "contenttypes.contenttype", "pk": 762, "fields": {"app_label": "student", "model": "historicalcourseenrollment"}}, {"model": "contenttypes.contenttype", "pk": 763, "fields": {"app_label": "cornerstone", "model": "cornerstoneglobalconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 764, "fields": {"app_label": "cornerstone", "model": "historicalcornerstoneenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 765, "fields": {"app_label": "cornerstone", "model": "cornerstonelearnerdatatransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 766, "fields": {"app_label": "cornerstone", "model": "cornerstoneenterprisecustomerconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 767, "fields": {"app_label": "discounts", "model": "discountrestrictionconfig"}}, {"model": "contenttypes.contenttype", "pk": 768, "fields": {"app_label": "entitlements", "model": "historicalcourseentitlement"}}, {"model": "contenttypes.contenttype", "pk": 769, "fields": {"app_label": "organizations", "model": "historicalorganization"}}, {"model": "contenttypes.contenttype", "pk": 770, "fields": {"app_label": "grades", "model": "historicalpersistentsubsectiongradeoverride"}}, {"model": "contenttypes.contenttype", "pk": 771, "fields": {"app_label": "super_csv", "model": "csvoperation"}}, {"model": "contenttypes.contenttype", "pk": 772, "fields": {"app_label": "bulk_grades", "model": "scoreoverrider"}}, {"model": "contenttypes.contenttype", "pk": 773, "fields": {"app_label": "course_modes", "model": "historicalcoursemode"}}, {"model": "contenttypes.contenttype", "pk": 774, "fields": {"app_label": "course_overviews", "model": "historicalcourseoverview"}}, {"model": "contenttypes.contenttype", "pk": 775, "fields": {"app_label": "system_wide_roles", "model": "systemwiderole"}}, {"model": "contenttypes.contenttype", "pk": 776, "fields": {"app_label": "system_wide_roles", "model": "systemwideroleassignment"}}, {"model": "contenttypes.contenttype", "pk": 777, "fields": {"app_label": "enterprise", "model": "enterprisecatalogquery"}}, {"model": "contenttypes.contenttype", "pk": 778, "fields": {"app_label": "enterprise", "model": "historicalpendingenrollment"}}, {"model": "contenttypes.contenttype", "pk": 779, "fields": {"app_label": "enterprise", "model": "historicalpendingenterprisecustomeruser"}}, {"model": "contenttypes.contenttype", "pk": 780, "fields": {"app_label": "xapi", "model": "xapilearnerdatatransmissionaudit"}}, {"model": "contenttypes.contenttype", "pk": 781, "fields": {"app_label": "video_config", "model": "courseyoutubeblockedflag"}}, {"model": "contenttypes.contenttype", "pk": 782, "fields": {"app_label": "content_libraries", "model": "contentlibrary"}}, {"model": "contenttypes.contenttype", "pk": 783, "fields": {"app_label": "content_libraries", "model": "contentlibrarypermission"}}, {"model": "contenttypes.contenttype", "pk": 784, "fields": {"app_label": "course_overviews", "model": "simulatecoursepublishconfig"}}, {"model": "contenttypes.contenttype", "pk": 785, "fields": {"app_label": "student", "model": "bulkunenrollconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 786, "fields": {"app_label": "discounts", "model": "discountpercentageconfig"}}, {"model": "contenttypes.contenttype", "pk": 787, "fields": {"app_label": "student", "model": "fbeenrollmentexclusion"}}, {"model": "contenttypes.contenttype", "pk": 788, "fields": {"app_label": "student", "model": "allowedauthuser"}}, {"model": "contenttypes.contenttype", "pk": 789, "fields": {"app_label": "enterprise", "model": "enterpriseenrollmentsource"}}, {"model": "contenttypes.contenttype", "pk": 790, "fields": {"app_label": "verify_student", "model": "sspverificationretryconfig"}}, {"model": "contenttypes.contenttype", "pk": 791, "fields": {"app_label": "programs", "model": "customprogramsconfig"}}, {"model": "contenttypes.contenttype", "pk": 792, "fields": {"app_label": "assessment", "model": "historicalsharedfileupload"}}, {"model": "contenttypes.contenttype", "pk": 793, "fields": {"app_label": "assessment", "model": "sharedfileupload"}}, {"model": "contenttypes.contenttype", "pk": 794, "fields": {"app_label": "certificates", "model": "historicalgeneratedcertificate"}}, {"model": "contenttypes.contenttype", "pk": 795, "fields": {"app_label": "entitlements", "model": "historicalcourseentitlementsupportdetail"}}, {"model": "contenttypes.contenttype", "pk": 796, "fields": {"app_label": "student", "model": "historicalmanualenrollmentaudit"}}, {"model": "contenttypes.contenttype", "pk": 797, "fields": {"app_label": "external_user_ids", "model": "historicalexternalid"}}, {"model": "contenttypes.contenttype", "pk": 798, "fields": {"app_label": "external_user_ids", "model": "historicalexternalidtype"}}, {"model": "contenttypes.contenttype", "pk": 799, "fields": {"app_label": "external_user_ids", "model": "externalid"}}, {"model": "contenttypes.contenttype", "pk": 800, "fields": {"app_label": "external_user_ids", "model": "externalidtype"}}, {"model": "contenttypes.contenttype", "pk": 801, "fields": {"app_label": "course_date_signals", "model": "selfpacedrelativedatesconfig"}}, {"model": "contenttypes.contenttype", "pk": 802, "fields": {"app_label": "calendar_sync", "model": "historicalusercalendarsyncconfig"}}, {"model": "contenttypes.contenttype", "pk": 803, "fields": {"app_label": "calendar_sync", "model": "usercalendarsyncconfig"}}, {"model": "contenttypes.contenttype", "pk": 804, "fields": {"app_label": "experiments", "model": "historicalexperimentkeyvalue"}}, {"model": "contenttypes.contenttype", "pk": 805, "fields": {"app_label": "schedules", "model": "historicalschedule"}}, {"model": "contenttypes.contenttype", "pk": 806, "fields": {"app_label": "student", "model": "accountrecoveryconfiguration"}}, {"model": "contenttypes.contenttype", "pk": 807, "fields": {"app_label": "edxval", "model": "transcriptcredentials"}}, {"model": "contenttypes.contenttype", "pk": 808, "fields": {"app_label": "assessment", "model": "teamstaffworkflow"}}, {"model": "contenttypes.contenttype", "pk": 809, "fields": {"app_label": "workflow", "model": "teamassessmentworkflow"}}, {"model": "contenttypes.contenttype", "pk": 810, "fields": {"app_label": "program_enrollments", "model": "courseaccessroleassignment"}}, {"model": "contenttypes.contenttype", "pk": 811, "fields": {"app_label": "submissions", "model": "teamsubmission"}}, {"model": "contenttypes.contenttype", "pk": 812, "fields": {"app_label": "video_pipeline", "model": "vempipelineintegration"}}, {"model": "contenttypes.contenttype", "pk": 813, "fields": {"app_label": "learning_sequences", "model": "coursesectionsequence"}}, {"model": "contenttypes.contenttype", "pk": 814, "fields": {"app_label": "learning_sequences", "model": "learningsequence"}}, {"model": "contenttypes.contenttype", "pk": 815, "fields": {"app_label": "learning_sequences", "model": "coursesection"}}, {"model": "contenttypes.contenttype", "pk": 816, "fields": {"app_label": "learning_sequences", "model": "learningcontext"}}, {"model": "contenttypes.contenttype", "pk": 817, "fields": {"app_label": "student", "model": "courseenrollmentcelebration"}}, {"model": "sites.site", "pk": 1, "fields": {"domain": "example.com", "name": "example.com"}}, {"model": "waffle.sample", "pk": 1, "fields": {"name": "use_enterprise_catalog", "percent": "0.0", "note": "", "created": "2020-04-10T22:07:16.651Z", "modified": "2020-04-10T22:07:16.651Z"}}, {"model": "bulk_email.courseemailtemplate", "pk": 1, "fields": {"html_template": "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html xmlns:fb='http://www.facebook.com/2008/fbml' xmlns:og='http://opengraph.org/schema/'> <head><meta property='og:title' content='Update from {course_title}'/><meta property='fb:page_id' content='43929265776' /> <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'> <title>Update from {course_title}</title> </head> <body leftmargin='0' marginwidth='0' topmargin='0' marginheight='0' offset='0' style='margin: 0;padding: 0;background-color: #ffffff;'> <center> <table align='center' border='0' cellpadding='0' cellspacing='0' height='100%' width='100%' id='bodyTable' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;margin: 0;padding: 0;background-color: #ffffff;height: 100% !important;width: 100% !important;'> <tr> <td align='center' valign='top' id='bodyCell' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;margin: 0;padding: 0;border-top: 0;height: 100% !important;width: 100% !important;'> <!-- BEGIN TEMPLATE // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN PREHEADER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templatePreheader' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='preheaderContainer' style='padding-top: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='366' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-left: 18px;padding-bottom: 9px;padding-right: 0;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 11px;line-height: 125%;text-align: left;'> <br> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END PREHEADER --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN HEADER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateHeader' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='headerContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnImageBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnImageBlockOuter'> <tr> <td valign='top' style='padding: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;' class='mcnImageBlockInner'> <table align='left' width='100%' border='0' cellpadding='0' cellspacing='0' class='mcnImageContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td class='mcnImageContent' valign='top' style='padding-right: 9px;padding-left: 9px;padding-top: 0;padding-bottom: 0;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <a href='http://edx.org' title='' class='' target='_self' style='word-wrap: break-word !important;'> <img align='left' alt='edX' src='http://courses.edx.org/static/images/bulk_email/edXHeaderImage.jpg' width='564.0000152587891' style='max-width: 600px;padding-bottom: 0;display: inline !important;vertical-align: bottom;border: 0;line-height: 100%;outline: none;text-decoration: none;height: auto !important;' class='mcnImage'> </a> </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='599' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 15px;line-height: 150%;text-align: left;'> <div style='text-align: right;'><span style='font-size:11px;'><span style='color:#00a0e3;'>Connect with edX:</span></span> <a href='http://facebook.com/edxonline' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/FacebookIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://twitter.com/edxonline' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/TwitterIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='https://plus.google.com/108235383044095082735' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/GooglePlusIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://www.meetup.com/edX-Communities/' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/MeetupIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a></div> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END HEADER --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN BODY // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateBody' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='bodyContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnCaptionBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnCaptionBlockOuter'> <tr> <td class='mcnCaptionBlockInner' valign='top' style='padding: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' class='mcnCaptionLeftContentOuter' width='100%' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnCaptionLeftContentInner' style='padding: 0 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='right' border='0' cellpadding='0' cellspacing='0' class='mcnCaptionLeftImageContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td class='mcnCaptionLeftImageContent' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <img alt='' src='{course_image_url}' width='176' style='max-width: 180px;border: 0;line-height: 100%;outline: none;text-decoration: none;vertical-align: bottom;height: auto !important;' class='mcnImage'> </td> </tr> </tbody></table> <table class='mcnCaptionLeftTextContentContainer' align='left' border='0' cellpadding='0' cellspacing='0' width='352' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> <h3 class='null' style='display: block;font-family: Helvetica;font-size: 18px;font-style: normal;font-weight: bold;line-height: 125%;letter-spacing: -.5px;margin: 0;text-align: left;color: #606060 !important;'><strong style='font-size: 22px;'>{course_title}</strong><br></h3><br> </td> </tr> </tbody></table> </td> </tr></tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> {{message_body}} </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnDividerBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnDividerBlockOuter'> <tr> <td class='mcnDividerBlockInner' style='padding: 18px 18px 3px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table class='mcnDividerContent' border='0' cellpadding='0' cellspacing='0' width='100%' style='border-top-width: 1px;border-top-style: solid;border-top-color: #666666;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <span></span> </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> <div style='text-align: right;'><a href='http://facebook.com/edxonline' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/FacebookIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://twitter.com/edxonline' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/TwitterIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='https://plus.google.com/108235383044095082735' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/GooglePlusIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://www.meetup.com/edX-Communities/' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/MeetupIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a></div> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END BODY --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN FOOTER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateFooter' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #9FCFE8;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='footerContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #f2f2f2;font-family: Helvetica;font-size: 11px;line-height: 125%;text-align: left;'> <em>Copyright \u00a9 2013 edX, All rights reserved.</em><br><br><br> <b>Our mailing address is:</b><br> edX<br> 11 Cambridge Center, Suite 101<br> Cambridge, MA, USA 02142<br><br><br>This email was automatically sent from {platform_name}. <br>You are receiving this email at address {email} because you are enrolled in <a href='{course_url}'>{course_title}</a>.<br>To stop receiving email like this, update your course email settings <a href='{email_settings_url}'>here</a>. <br> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END FOOTER --> </td> </tr> </table> <!-- // END TEMPLATE --> </td> </tr> </table> </center> </body> </body> </html>", "plain_template": "{course_title}\n\n{{message_body}}\r\n----\r\nCopyright 2013 edX, All rights reserved.\r\n----\r\nConnect with edX:\r\nFacebook (http://facebook.com/edxonline)\r\nTwitter (http://twitter.com/edxonline)\r\nGoogle+ (https://plus.google.com/108235383044095082735)\r\nMeetup (http://www.meetup.com/edX-Communities/)\r\n----\r\nThis email was automatically sent from {platform_name}.\r\nYou are receiving this email at address {email} because you are enrolled in {course_title}\r\n(URL: {course_url} ).\r\nTo stop receiving email like this, update your course email settings at {email_settings_url}.\r\n", "name": null}}, {"model": "bulk_email.courseemailtemplate", "pk": 2, "fields": {"html_template": "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html xmlns:fb='http://www.facebook.com/2008/fbml' xmlns:og='http://opengraph.org/schema/'> <head><meta property='og:title' content='Update from {course_title}'/><meta property='fb:page_id' content='43929265776' /> <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'> THIS IS A BRANDED HTML TEMPLATE <title>Update from {course_title}</title> </head> <body leftmargin='0' marginwidth='0' topmargin='0' marginheight='0' offset='0' style='margin: 0;padding: 0;background-color: #ffffff;'> <center> <table align='center' border='0' cellpadding='0' cellspacing='0' height='100%' width='100%' id='bodyTable' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;margin: 0;padding: 0;background-color: #ffffff;height: 100% !important;width: 100% !important;'> <tr> <td align='center' valign='top' id='bodyCell' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;margin: 0;padding: 0;border-top: 0;height: 100% !important;width: 100% !important;'> <!-- BEGIN TEMPLATE // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN PREHEADER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templatePreheader' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='preheaderContainer' style='padding-top: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='366' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-left: 18px;padding-bottom: 9px;padding-right: 0;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 11px;line-height: 125%;text-align: left;'> <br> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END PREHEADER --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN HEADER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateHeader' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='headerContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnImageBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnImageBlockOuter'> <tr> <td valign='top' style='padding: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;' class='mcnImageBlockInner'> <table align='left' width='100%' border='0' cellpadding='0' cellspacing='0' class='mcnImageContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td class='mcnImageContent' valign='top' style='padding-right: 9px;padding-left: 9px;padding-top: 0;padding-bottom: 0;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <a href='http://edx.org' title='' class='' target='_self' style='word-wrap: break-word !important;'> <img align='left' alt='edX' src='http://courses.edx.org/static/images/bulk_email/edXHeaderImage.jpg' width='564.0000152587891' style='max-width: 600px;padding-bottom: 0;display: inline !important;vertical-align: bottom;border: 0;line-height: 100%;outline: none;text-decoration: none;height: auto !important;' class='mcnImage'> </a> </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='599' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 15px;line-height: 150%;text-align: left;'> <div style='text-align: right;'><span style='font-size:11px;'><span style='color:#00a0e3;'>Connect with edX:</span></span> <a href='http://facebook.com/edxonline' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/FacebookIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://twitter.com/edxonline' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/TwitterIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='https://plus.google.com/108235383044095082735' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/GooglePlusIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://www.meetup.com/edX-Communities/' target='_blank' style='color: #6DC6DD;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/MeetupIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a></div> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END HEADER --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN BODY // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateBody' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #fcfcfc;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='bodyContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnCaptionBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnCaptionBlockOuter'> <tr> <td class='mcnCaptionBlockInner' valign='top' style='padding: 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' class='mcnCaptionLeftContentOuter' width='100%' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnCaptionLeftContentInner' style='padding: 0 9px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='right' border='0' cellpadding='0' cellspacing='0' class='mcnCaptionLeftImageContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td class='mcnCaptionLeftImageContent' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <img alt='' src='{course_image_url}' width='176' style='max-width: 180px;border: 0;line-height: 100%;outline: none;text-decoration: none;vertical-align: bottom;height: auto !important;' class='mcnImage'> </td> </tr> </tbody></table> <table class='mcnCaptionLeftTextContentContainer' align='left' border='0' cellpadding='0' cellspacing='0' width='352' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> <h3 class='null' style='display: block;font-family: Helvetica;font-size: 18px;font-style: normal;font-weight: bold;line-height: 125%;letter-spacing: -.5px;margin: 0;text-align: left;color: #606060 !important;'><strong style='font-size: 22px;'>{course_title}</strong><br></h3><br> </td> </tr> </tbody></table> </td> </tr></tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> {{message_body}} </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnDividerBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnDividerBlockOuter'> <tr> <td class='mcnDividerBlockInner' style='padding: 18px 18px 3px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table class='mcnDividerContent' border='0' cellpadding='0' cellspacing='0' width='100%' style='border-top-width: 1px;border-top-style: solid;border-top-color: #666666;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <span></span> </td> </tr> </tbody></table> </td> </tr> </tbody></table><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #606060;font-family: Helvetica;font-size: 14px;line-height: 150%;text-align: left;'> <div style='text-align: right;'><a href='http://facebook.com/edxonline' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/FacebookIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://twitter.com/edxonline' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/TwitterIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='https://plus.google.com/108235383044095082735' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/GooglePlusIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a> <a href='http://www.meetup.com/edX-Communities/' target='_blank' style='color: #2f73bc;font-weight: normal;text-decoration: underline;word-wrap: break-word !important;'><img align='none' height='16' src='http://courses.edx.org/static/images/bulk_email/MeetupIcon.png' style='width: 16px;height: 16px;border: 0;line-height: 100%;outline: none;text-decoration: none;' width='16'></a></div> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END BODY --> </td> </tr> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <!-- BEGIN FOOTER // --> <table border='0' cellpadding='0' cellspacing='0' width='100%' id='templateFooter' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;background-color: #9FCFE8;border-top: 0;border-bottom: 0;'> <tr> <td align='center' valign='top' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table border='0' cellpadding='0' cellspacing='0' width='600' class='templateContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tr> <td valign='top' class='footerContainer' style='padding-top: 10px;padding-right: 18px;padding-bottom: 10px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'><table border='0' cellpadding='0' cellspacing='0' width='100%' class='mcnTextBlock' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody class='mcnTextBlockOuter'> <tr> <td valign='top' class='mcnTextBlockInner' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <table align='left' border='0' cellpadding='0' cellspacing='0' width='600' class='mcnTextContentContainer' style='border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;'> <tbody><tr> <td valign='top' class='mcnTextContent' style='padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;color: #f2f2f2;font-family: Helvetica;font-size: 11px;line-height: 125%;text-align: left;'> <em>Copyright \u00a9 2013 edX, All rights reserved.</em><br><br><br> <b>Our mailing address is:</b><br> edX<br> 11 Cambridge Center, Suite 101<br> Cambridge, MA, USA 02142<br><br><br>This email was automatically sent from {platform_name}. <br>You are receiving this email at address {email} because you are enrolled in <a href='{course_url}'>{course_title}</a>.<br>To stop receiving email like this, update your course email settings <a href='{email_settings_url}'>here</a>. <br> </td> </tr> </tbody></table> </td> </tr> </tbody></table></td> </tr> </table> </td> </tr> </table> <!-- // END FOOTER --> </td> </tr> </table> <!-- // END TEMPLATE --> </td> </tr> </table> </center> </body> </body> </html>", "plain_template": "THIS IS A BRANDED TEXT TEMPLATE. {course_title}\n\n{{message_body}}\r\n----\r\nCopyright 2013 edX, All rights reserved.\r\n----\r\nConnect with edX:\r\nFacebook (http://facebook.com/edxonline)\r\nTwitter (http://twitter.com/edxonline)\r\nGoogle+ (https://plus.google.com/108235383044095082735)\r\nMeetup (http://www.meetup.com/edX-Communities/)\r\n----\r\nThis email was automatically sent from {platform_name}.\r\nYou are receiving this email at address {email} because you are enrolled in {course_title}\r\n(URL: {course_url} ).\r\nTo stop receiving email like this, update your course email settings at {email_settings_url}.\r\n", "name": "branded.template"}}, {"model": "system_wide_roles.systemwiderole", "pk": 1, "fields": {"created": "2019-08-16T20:33:10.090Z", "modified": "2019-08-16T20:33:10.090Z", "name": "student_support_admin", "description": null}}, {"model": "embargo.country", "pk": 1, "fields": {"country": "AF"}}, {"model": "embargo.country", "pk": 2, "fields": {"country": "AX"}}, {"model": "embargo.country", "pk": 3, "fields": {"country": "AL"}}, {"model": "embargo.country", "pk": 4, "fields": {"country": "DZ"}}, {"model": "embargo.country", "pk": 5, "fields": {"country": "AS"}}, {"model": "embargo.country", "pk": 6, "fields": {"country": "AD"}}, {"model": "embargo.country", "pk": 7, "fields": {"country": "AO"}}, {"model": "embargo.country", "pk": 8, "fields": {"country": "AI"}}, {"model": "embargo.country", "pk": 9, "fields": {"country": "AQ"}}, {"model": "embargo.country", "pk": 10, "fields": {"country": "AG"}}, {"model": "embargo.country", "pk": 11, "fields": {"country": "AR"}}, {"model": "embargo.country", "pk": 12, "fields": {"country": "AM"}}, {"model": "embargo.country", "pk": 13, "fields": {"country": "AW"}}, {"model": "embargo.country", "pk": 14, "fields": {"country": "AU"}}, {"model": "embargo.country", "pk": 15, "fields": {"country": "AT"}}, {"model": "embargo.country", "pk": 16, "fields": {"country": "AZ"}}, {"model": "embargo.country", "pk": 17, "fields": {"country": "BS"}}, {"model": "embargo.country", "pk": 18, "fields": {"country": "BH"}}, {"model": "embargo.country", "pk": 19, "fields": {"country": "BD"}}, {"model": "embargo.country", "pk": 20, "fields": {"country": "BB"}}, {"model": "embargo.country", "pk": 21, "fields": {"country": "BY"}}, {"model": "embargo.country", "pk": 22, "fields": {"country": "BE"}}, {"model": "embargo.country", "pk": 23, "fields": {"country": "BZ"}}, {"model": "embargo.country", "pk": 24, "fields": {"country": "BJ"}}, {"model": "embargo.country", "pk": 25, "fields": {"country": "BM"}}, {"model": "embargo.country", "pk": 26, "fields": {"country": "BT"}}, {"model": "embargo.country", "pk": 27, "fields": {"country": "BO"}}, {"model": "embargo.country", "pk": 28, "fields": {"country": "BQ"}}, {"model": "embargo.country", "pk": 29, "fields": {"country": "BA"}}, {"model": "embargo.country", "pk": 30, "fields": {"country": "BW"}}, {"model": "embargo.country", "pk": 31, "fields": {"country": "BV"}}, {"model": "embargo.country", "pk": 32, "fields": {"country": "BR"}}, {"model": "embargo.country", "pk": 33, "fields": {"country": "IO"}}, {"model": "embargo.country", "pk": 34, "fields": {"country": "BN"}}, {"model": "embargo.country", "pk": 35, "fields": {"country": "BG"}}, {"model": "embargo.country", "pk": 36, "fields": {"country": "BF"}}, {"model": "embargo.country", "pk": 37, "fields": {"country": "BI"}}, {"model": "embargo.country", "pk": 38, "fields": {"country": "CV"}}, {"model": "embargo.country", "pk": 39, "fields": {"country": "KH"}}, {"model": "embargo.country", "pk": 40, "fields": {"country": "CM"}}, {"model": "embargo.country", "pk": 41, "fields": {"country": "CA"}}, {"model": "embargo.country", "pk": 42, "fields": {"country": "KY"}}, {"model": "embargo.country", "pk": 43, "fields": {"country": "CF"}}, {"model": "embargo.country", "pk": 44, "fields": {"country": "TD"}}, {"model": "embargo.country", "pk": 45, "fields": {"country": "CL"}}, {"model": "embargo.country", "pk": 46, "fields": {"country": "CN"}}, {"model": "embargo.country", "pk": 47, "fields": {"country": "CX"}}, {"model": "embargo.country", "pk": 48, "fields": {"country": "CC"}}, {"model": "embargo.country", "pk": 49, "fields": {"country": "CO"}}, {"model": "embargo.country", "pk": 50, "fields": {"country": "KM"}}, {"model": "embargo.country", "pk": 51, "fields": {"country": "CG"}}, {"model": "embargo.country", "pk": 52, "fields": {"country": "CD"}}, {"model": "embargo.country", "pk": 53, "fields": {"country": "CK"}}, {"model": "embargo.country", "pk": 54, "fields": {"country": "CR"}}, {"model": "embargo.country", "pk": 55, "fields": {"country": "CI"}}, {"model": "embargo.country", "pk": 56, "fields": {"country": "HR"}}, {"model": "embargo.country", "pk": 57, "fields": {"country": "CU"}}, {"model": "embargo.country", "pk": 58, "fields": {"country": "CW"}}, {"model": "embargo.country", "pk": 59, "fields": {"country": "CY"}}, {"model": "embargo.country", "pk": 60, "fields": {"country": "CZ"}}, {"model": "embargo.country", "pk": 61, "fields": {"country": "DK"}}, {"model": "embargo.country", "pk": 62, "fields": {"country": "DJ"}}, {"model": "embargo.country", "pk": 63, "fields": {"country": "DM"}}, {"model": "embargo.country", "pk": 64, "fields": {"country": "DO"}}, {"model": "embargo.country", "pk": 65, "fields": {"country": "EC"}}, {"model": "embargo.country", "pk": 66, "fields": {"country": "EG"}}, {"model": "embargo.country", "pk": 67, "fields": {"country": "SV"}}, {"model": "embargo.country", "pk": 68, "fields": {"country": "GQ"}}, {"model": "embargo.country", "pk": 69, "fields": {"country": "ER"}}, {"model": "embargo.country", "pk": 70, "fields": {"country": "EE"}}, {"model": "embargo.country", "pk": 71, "fields": {"country": "ET"}}, {"model": "embargo.country", "pk": 72, "fields": {"country": "FK"}}, {"model": "embargo.country", "pk": 73, "fields": {"country": "FO"}}, {"model": "embargo.country", "pk": 74, "fields": {"country": "FJ"}}, {"model": "embargo.country", "pk": 75, "fields": {"country": "FI"}}, {"model": "embargo.country", "pk": 76, "fields": {"country": "FR"}}, {"model": "embargo.country", "pk": 77, "fields": {"country": "GF"}}, {"model": "embargo.country", "pk": 78, "fields": {"country": "PF"}}, {"model": "embargo.country", "pk": 79, "fields": {"country": "TF"}}, {"model": "embargo.country", "pk": 80, "fields": {"country": "GA"}}, {"model": "embargo.country", "pk": 81, "fields": {"country": "GM"}}, {"model": "embargo.country", "pk": 82, "fields": {"country": "GE"}}, {"model": "embargo.country", "pk": 83, "fields": {"country": "DE"}}, {"model": "embargo.country", "pk": 84, "fields": {"country": "GH"}}, {"model": "embargo.country", "pk": 85, "fields": {"country": "GI"}}, {"model": "embargo.country", "pk": 86, "fields": {"country": "GR"}}, {"model": "embargo.country", "pk": 87, "fields": {"country": "GL"}}, {"model": "embargo.country", "pk": 88, "fields": {"country": "GD"}}, {"model": "embargo.country", "pk": 89, "fields": {"country": "GP"}}, {"model": "embargo.country", "pk": 90, "fields": {"country": "GU"}}, {"model": "embargo.country", "pk": 91, "fields": {"country": "GT"}}, {"model": "embargo.country", "pk": 92, "fields": {"country": "GG"}}, {"model": "embargo.country", "pk": 93, "fields": {"country": "GN"}}, {"model": "embargo.country", "pk": 94, "fields": {"country": "GW"}}, {"model": "embargo.country", "pk": 95, "fields": {"country": "GY"}}, {"model": "embargo.country", "pk": 96, "fields": {"country": "HT"}}, {"model": "embargo.country", "pk": 97, "fields": {"country": "HM"}}, {"model": "embargo.country", "pk": 98, "fields": {"country": "VA"}}, {"model": "embargo.country", "pk": 99, "fields": {"country": "HN"}}, {"model": "embargo.country", "pk": 100, "fields": {"country": "HK"}}, {"model": "embargo.country", "pk": 101, "fields": {"country": "HU"}}, {"model": "embargo.country", "pk": 102, "fields": {"country": "IS"}}, {"model": "embargo.country", "pk": 103, "fields": {"country": "IN"}}, {"model": "embargo.country", "pk": 104, "fields": {"country": "ID"}}, {"model": "embargo.country", "pk": 105, "fields": {"country": "IR"}}, {"model": "embargo.country", "pk": 106, "fields": {"country": "IQ"}}, {"model": "embargo.country", "pk": 107, "fields": {"country": "IE"}}, {"model": "embargo.country", "pk": 108, "fields": {"country": "IM"}}, {"model": "embargo.country", "pk": 109, "fields": {"country": "IL"}}, {"model": "embargo.country", "pk": 110, "fields": {"country": "IT"}}, {"model": "embargo.country", "pk": 111, "fields": {"country": "JM"}}, {"model": "embargo.country", "pk": 112, "fields": {"country": "JP"}}, {"model": "embargo.country", "pk": 113, "fields": {"country": "JE"}}, {"model": "embargo.country", "pk": 114, "fields": {"country": "JO"}}, {"model": "embargo.country", "pk": 115, "fields": {"country": "KZ"}}, {"model": "embargo.country", "pk": 116, "fields": {"country": "KE"}}, {"model": "embargo.country", "pk": 117, "fields": {"country": "KI"}}, {"model": "embargo.country", "pk": 118, "fields": {"country": "XK"}}, {"model": "embargo.country", "pk": 119, "fields": {"country": "KW"}}, {"model": "embargo.country", "pk": 120, "fields": {"country": "KG"}}, {"model": "embargo.country", "pk": 121, "fields": {"country": "LA"}}, {"model": "embargo.country", "pk": 122, "fields": {"country": "LV"}}, {"model": "embargo.country", "pk": 123, "fields": {"country": "LB"}}, {"model": "embargo.country", "pk": 124, "fields": {"country": "LS"}}, {"model": "embargo.country", "pk": 125, "fields": {"country": "LR"}}, {"model": "embargo.country", "pk": 126, "fields": {"country": "LY"}}, {"model": "embargo.country", "pk": 127, "fields": {"country": "LI"}}, {"model": "embargo.country", "pk": 128, "fields": {"country": "LT"}}, {"model": "embargo.country", "pk": 129, "fields": {"country": "LU"}}, {"model": "embargo.country", "pk": 130, "fields": {"country": "MO"}}, {"model": "embargo.country", "pk": 131, "fields": {"country": "MK"}}, {"model": "embargo.country", "pk": 132, "fields": {"country": "MG"}}, {"model": "embargo.country", "pk": 133, "fields": {"country": "MW"}}, {"model": "embargo.country", "pk": 134, "fields": {"country": "MY"}}, {"model": "embargo.country", "pk": 135, "fields": {"country": "MV"}}, {"model": "embargo.country", "pk": 136, "fields": {"country": "ML"}}, {"model": "embargo.country", "pk": 137, "fields": {"country": "MT"}}, {"model": "embargo.country", "pk": 138, "fields": {"country": "MH"}}, {"model": "embargo.country", "pk": 139, "fields": {"country": "MQ"}}, {"model": "embargo.country", "pk": 140, "fields": {"country": "MR"}}, {"model": "embargo.country", "pk": 141, "fields": {"country": "MU"}}, {"model": "embargo.country", "pk": 142, "fields": {"country": "YT"}}, {"model": "embargo.country", "pk": 143, "fields": {"country": "MX"}}, {"model": "embargo.country", "pk": 144, "fields": {"country": "FM"}}, {"model": "embargo.country", "pk": 145, "fields": {"country": "MD"}}, {"model": "embargo.country", "pk": 146, "fields": {"country": "MC"}}, {"model": "embargo.country", "pk": 147, "fields": {"country": "MN"}}, {"model": "embargo.country", "pk": 148, "fields": {"country": "ME"}}, {"model": "embargo.country", "pk": 149, "fields": {"country": "MS"}}, {"model": "embargo.country", "pk": 150, "fields": {"country": "MA"}}, {"model": "embargo.country", "pk": 151, "fields": {"country": "MZ"}}, {"model": "embargo.country", "pk": 152, "fields": {"country": "MM"}}, {"model": "embargo.country", "pk": 153, "fields": {"country": "NA"}}, {"model": "embargo.country", "pk": 154, "fields": {"country": "NR"}}, {"model": "embargo.country", "pk": 155, "fields": {"country": "NP"}}, {"model": "embargo.country", "pk": 156, "fields": {"country": "NL"}}, {"model": "embargo.country", "pk": 157, "fields": {"country": "NC"}}, {"model": "embargo.country", "pk": 158, "fields": {"country": "NZ"}}, {"model": "embargo.country", "pk": 159, "fields": {"country": "NI"}}, {"model": "embargo.country", "pk": 160, "fields": {"country": "NE"}}, {"model": "embargo.country", "pk": 161, "fields": {"country": "NG"}}, {"model": "embargo.country", "pk": 162, "fields": {"country": "NU"}}, {"model": "embargo.country", "pk": 163, "fields": {"country": "NF"}}, {"model": "embargo.country", "pk": 164, "fields": {"country": "KP"}}, {"model": "embargo.country", "pk": 165, "fields": {"country": "MP"}}, {"model": "embargo.country", "pk": 166, "fields": {"country": "NO"}}, {"model": "embargo.country", "pk": 167, "fields": {"country": "OM"}}, {"model": "embargo.country", "pk": 168, "fields": {"country": "PK"}}, {"model": "embargo.country", "pk": 169, "fields": {"country": "PW"}}, {"model": "embargo.country", "pk": 170, "fields": {"country": "PS"}}, {"model": "embargo.country", "pk": 171, "fields": {"country": "PA"}}, {"model": "embargo.country", "pk": 172, "fields": {"country": "PG"}}, {"model": "embargo.country", "pk": 173, "fields": {"country": "PY"}}, {"model": "embargo.country", "pk": 174, "fields": {"country": "PE"}}, {"model": "embargo.country", "pk": 175, "fields": {"country": "PH"}}, {"model": "embargo.country", "pk": 176, "fields": {"country": "PN"}}, {"model": "embargo.country", "pk": 177, "fields": {"country": "PL"}}, {"model": "embargo.country", "pk": 178, "fields": {"country": "PT"}}, {"model": "embargo.country", "pk": 179, "fields": {"country": "PR"}}, {"model": "embargo.country", "pk": 180, "fields": {"country": "QA"}}, {"model": "embargo.country", "pk": 181, "fields": {"country": "RE"}}, {"model": "embargo.country", "pk": 182, "fields": {"country": "RO"}}, {"model": "embargo.country", "pk": 183, "fields": {"country": "RU"}}, {"model": "embargo.country", "pk": 184, "fields": {"country": "RW"}}, {"model": "embargo.country", "pk": 185, "fields": {"country": "BL"}}, {"model": "embargo.country", "pk": 186, "fields": {"country": "SH"}}, {"model": "embargo.country", "pk": 187, "fields": {"country": "KN"}}, {"model": "embargo.country", "pk": 188, "fields": {"country": "LC"}}, {"model": "embargo.country", "pk": 189, "fields": {"country": "MF"}}, {"model": "embargo.country", "pk": 190, "fields": {"country": "PM"}}, {"model": "embargo.country", "pk": 191, "fields": {"country": "VC"}}, {"model": "embargo.country", "pk": 192, "fields": {"country": "WS"}}, {"model": "embargo.country", "pk": 193, "fields": {"country": "SM"}}, {"model": "embargo.country", "pk": 194, "fields": {"country": "ST"}}, {"model": "embargo.country", "pk": 195, "fields": {"country": "SA"}}, {"model": "embargo.country", "pk": 196, "fields": {"country": "SN"}}, {"model": "embargo.country", "pk": 197, "fields": {"country": "RS"}}, {"model": "embargo.country", "pk": 198, "fields": {"country": "SC"}}, {"model": "embargo.country", "pk": 199, "fields": {"country": "SL"}}, {"model": "embargo.country", "pk": 200, "fields": {"country": "SG"}}, {"model": "embargo.country", "pk": 201, "fields": {"country": "SX"}}, {"model": "embargo.country", "pk": 202, "fields": {"country": "SK"}}, {"model": "embargo.country", "pk": 203, "fields": {"country": "SI"}}, {"model": "embargo.country", "pk": 204, "fields": {"country": "SB"}}, {"model": "embargo.country", "pk": 205, "fields": {"country": "SO"}}, {"model": "embargo.country", "pk": 206, "fields": {"country": "ZA"}}, {"model": "embargo.country", "pk": 207, "fields": {"country": "GS"}}, {"model": "embargo.country", "pk": 208, "fields": {"country": "KR"}}, {"model": "embargo.country", "pk": 209, "fields": {"country": "SS"}}, {"model": "embargo.country", "pk": 210, "fields": {"country": "ES"}}, {"model": "embargo.country", "pk": 211, "fields": {"country": "LK"}}, {"model": "embargo.country", "pk": 212, "fields": {"country": "SD"}}, {"model": "embargo.country", "pk": 213, "fields": {"country": "SR"}}, {"model": "embargo.country", "pk": 214, "fields": {"country": "SJ"}}, {"model": "embargo.country", "pk": 215, "fields": {"country": "SZ"}}, {"model": "embargo.country", "pk": 216, "fields": {"country": "SE"}}, {"model": "embargo.country", "pk": 217, "fields": {"country": "CH"}}, {"model": "embargo.country", "pk": 218, "fields": {"country": "SY"}}, {"model": "embargo.country", "pk": 219, "fields": {"country": "TW"}}, {"model": "embargo.country", "pk": 220, "fields": {"country": "TJ"}}, {"model": "embargo.country", "pk": 221, "fields": {"country": "TZ"}}, {"model": "embargo.country", "pk": 222, "fields": {"country": "TH"}}, {"model": "embargo.country", "pk": 223, "fields": {"country": "TL"}}, {"model": "embargo.country", "pk": 224, "fields": {"country": "TG"}}, {"model": "embargo.country", "pk": 225, "fields": {"country": "TK"}}, {"model": "embargo.country", "pk": 226, "fields": {"country": "TO"}}, {"model": "embargo.country", "pk": 227, "fields": {"country": "TT"}}, {"model": "embargo.country", "pk": 228, "fields": {"country": "TN"}}, {"model": "embargo.country", "pk": 229, "fields": {"country": "TR"}}, {"model": "embargo.country", "pk": 230, "fields": {"country": "TM"}}, {"model": "embargo.country", "pk": 231, "fields": {"country": "TC"}}, {"model": "embargo.country", "pk": 232, "fields": {"country": "TV"}}, {"model": "embargo.country", "pk": 233, "fields": {"country": "UG"}}, {"model": "embargo.country", "pk": 234, "fields": {"country": "UA"}}, {"model": "embargo.country", "pk": 235, "fields": {"country": "AE"}}, {"model": "embargo.country", "pk": 236, "fields": {"country": "GB"}}, {"model": "embargo.country", "pk": 237, "fields": {"country": "UM"}}, {"model": "embargo.country", "pk": 238, "fields": {"country": "US"}}, {"model": "embargo.country", "pk": 239, "fields": {"country": "UY"}}, {"model": "embargo.country", "pk": 240, "fields": {"country": "UZ"}}, {"model": "embargo.country", "pk": 241, "fields": {"country": "VU"}}, {"model": "embargo.country", "pk": 242, "fields": {"country": "VE"}}, {"model": "embargo.country", "pk": 243, "fields": {"country": "VN"}}, {"model": "embargo.country", "pk": 244, "fields": {"country": "VG"}}, {"model": "embargo.country", "pk": 245, "fields": {"country": "VI"}}, {"model": "embargo.country", "pk": 246, "fields": {"country": "WF"}}, {"model": "embargo.country", "pk": 247, "fields": {"country": "EH"}}, {"model": "embargo.country", "pk": 248, "fields": {"country": "YE"}}, {"model": "embargo.country", "pk": 249, "fields": {"country": "ZM"}}, {"model": "embargo.country", "pk": 250, "fields": {"country": "ZW"}}, {"model": "edxval.profile", "pk": 1, "fields": {"profile_name": "desktop_mp4"}}, {"model": "edxval.profile", "pk": 2, "fields": {"profile_name": "desktop_webm"}}, {"model": "edxval.profile", "pk": 3, "fields": {"profile_name": "mobile_high"}}, {"model": "edxval.profile", "pk": 4, "fields": {"profile_name": "mobile_low"}}, {"model": "edxval.profile", "pk": 5, "fields": {"profile_name": "youtube"}}, {"model": "edxval.profile", "pk": 6, "fields": {"profile_name": "hls"}}, {"model": "edxval.profile", "pk": 7, "fields": {"profile_name": "audio_mp3"}}, {"model": "milestones.milestonerelationshiptype", "pk": 1, "fields": {"created": "2017-12-06T02:29:37.764Z", "modified": "2017-12-06T02:29:37.764Z", "name": "fulfills", "description": "Autogenerated milestone relationship type \"fulfills\"", "active": true}}, {"model": "milestones.milestonerelationshiptype", "pk": 2, "fields": {"created": "2017-12-06T02:29:37.767Z", "modified": "2017-12-06T02:29:37.767Z", "name": "requires", "description": "Autogenerated milestone relationship type \"requires\"", "active": true}}, {"model": "badges.coursecompleteimageconfiguration", "pk": 1, "fields": {"mode": "honor", "icon": "badges/honor_MYTwjzI.png", "default": false}}, {"model": "badges.coursecompleteimageconfiguration", "pk": 2, "fields": {"mode": "verified", "icon": "badges/verified_VzaI0PC.png", "default": false}}, {"model": "badges.coursecompleteimageconfiguration", "pk": 3, "fields": {"mode": "professional", "icon": "badges/professional_g7d5Aru.png", "default": false}}, {"model": "external_user_ids.externalidtype", "pk": 1, "fields": {"created": "2020-02-11T13:55:31.885Z", "modified": "2020-02-11T13:55:31.885Z", "name": "mb_coaching", "description": "MicroBachelors Coaching"}}, {"model": "external_user_ids.externalidtype", "pk": 2, "fields": {"created": "2020-05-04T10:59:26.906Z", "modified": "2020-05-04T10:59:26.906Z", "name": "lti", "description": "LTI Xblock launches"}}, {"model": "enterprise.enterprisecustomertype", "pk": 1, "fields": {"created": "2018-12-19T16:43:27.202Z", "modified": "2018-12-19T16:43:27.202Z", "name": "Enterprise"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 1, "fields": {"created": "2019-11-15T09:41:34.937Z", "modified": "2019-11-15T09:41:34.938Z", "name": "Enterprise Enrollment URL", "slug": "enrollment_url"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 2, "fields": {"created": "2019-11-15T09:41:34.939Z", "modified": "2019-11-25T17:51:47.271Z", "name": "Enterprise User Enrollment Background Task", "slug": "enrollment_task"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 3, "fields": {"created": "2019-11-15T09:41:34.941Z", "modified": "2019-11-15T09:41:34.941Z", "name": "Manual Enterprise Enrollment", "slug": "manual"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 4, "fields": {"created": "2019-11-15T09:41:34.942Z", "modified": "2019-11-15T09:41:34.942Z", "name": "Enterprise API Enrollment", "slug": "enterprise_api"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 5, "fields": {"created": "2019-11-15T09:41:34.943Z", "modified": "2019-11-15T09:41:34.944Z", "name": "Enterprise Offer Redemption", "slug": "offer_redemption"}}, {"model": "enterprise.enterpriseenrollmentsource", "pk": 6, "fields": {"created": "2019-12-03T20:57:24.395Z", "modified": "2019-12-03T20:57:24.396Z", "name": "Enterprise management command enrollment", "slug": "management_command"}}, {"model": "enterprise.systemwideenterpriserole", "pk": 1, "fields": {"created": "2019-03-08T15:47:17.791Z", "modified": "2019-03-08T15:47:17.792Z", "name": "enterprise_admin", "description": null}}, {"model": "enterprise.systemwideenterpriserole", "pk": 2, "fields": {"created": "2019-03-08T15:47:17.794Z", "modified": "2019-03-08T15:47:17.794Z", "name": "enterprise_learner", "description": null}}, {"model": "enterprise.systemwideenterpriserole", "pk": 3, "fields": {"created": "2019-03-28T19:29:40.175Z", "modified": "2019-03-28T19:29:40.175Z", "name": "enterprise_openedx_operator", "description": null}}, {"model": "enterprise.systemwideenterpriserole", "pk": 4, "fields": {"created": "2020-05-13T22:12:12.343Z", "modified": "2020-05-13T22:12:12.343Z", "name": "enterprise_catalog_admin", "description": "Role for access to endpoints in the enterprise catalog service"}}, {"model": "enterprise.enterprisefeaturerole", "pk": 1, "fields": {"created": "2019-03-28T19:29:40.102Z", "modified": "2019-03-28T19:29:40.103Z", "name": "catalog_admin", "description": null}}, {"model": "enterprise.enterprisefeaturerole", "pk": 2, "fields": {"created": "2019-03-28T19:29:40.105Z", "modified": "2019-03-28T19:29:40.105Z", "name": "dashboard_admin", "description": null}}, {"model": "enterprise.enterprisefeaturerole", "pk": 3, "fields": {"created": "2019-03-28T19:29:40.108Z", "modified": "2019-03-28T19:29:40.108Z", "name": "enrollment_api_admin", "description": null}}, {"model": "enterprise.enterprisefeaturerole", "pk": 4, "fields": {"created": "2019-08-30T19:28:00.560Z", "modified": "2019-08-30T19:28:00.560Z", "name": "reporting_config_admin", "description": null}}, {"model": "auth.permission", "pk": 1, "fields": {"name": "Can add permission", "content_type": 2, "codename": "add_permission"}}, {"model": "auth.permission", "pk": 2, "fields": {"name": "Can change permission", "content_type": 2, "codename": "change_permission"}}, {"model": "auth.permission", "pk": 3, "fields": {"name": "Can delete permission", "content_type": 2, "codename": "delete_permission"}}, {"model": "auth.permission", "pk": 4, "fields": {"name": "Can add group", "content_type": 3, "codename": "add_group"}}, {"model": "auth.permission", "pk": 5, "fields": {"name": "Can change group", "content_type": 3, "codename": "change_group"}}, {"model": "auth.permission", "pk": 6, "fields": {"name": "Can delete group", "content_type": 3, "codename": "delete_group"}}, {"model": "auth.permission", "pk": 7, "fields": {"name": "Can add user", "content_type": 4, "codename": "add_user"}}, {"model": "auth.permission", "pk": 8, "fields": {"name": "Can change user", "content_type": 4, "codename": "change_user"}}, {"model": "auth.permission", "pk": 9, "fields": {"name": "Can delete user", "content_type": 4, "codename": "delete_user"}}, {"model": "auth.permission", "pk": 10, "fields": {"name": "Can add content type", "content_type": 5, "codename": "add_contenttype"}}, {"model": "auth.permission", "pk": 11, "fields": {"name": "Can change content type", "content_type": 5, "codename": "change_contenttype"}}, {"model": "auth.permission", "pk": 12, "fields": {"name": "Can delete content type", "content_type": 5, "codename": "delete_contenttype"}}, {"model": "auth.permission", "pk": 13, "fields": {"name": "Can add redirect", "content_type": 6, "codename": "add_redirect"}}, {"model": "auth.permission", "pk": 14, "fields": {"name": "Can change redirect", "content_type": 6, "codename": "change_redirect"}}, {"model": "auth.permission", "pk": 15, "fields": {"name": "Can delete redirect", "content_type": 6, "codename": "delete_redirect"}}, {"model": "auth.permission", "pk": 16, "fields": {"name": "Can add session", "content_type": 7, "codename": "add_session"}}, {"model": "auth.permission", "pk": 17, "fields": {"name": "Can change session", "content_type": 7, "codename": "change_session"}}, {"model": "auth.permission", "pk": 18, "fields": {"name": "Can delete session", "content_type": 7, "codename": "delete_session"}}, {"model": "auth.permission", "pk": 19, "fields": {"name": "Can add site", "content_type": 8, "codename": "add_site"}}, {"model": "auth.permission", "pk": 20, "fields": {"name": "Can change site", "content_type": 8, "codename": "change_site"}}, {"model": "auth.permission", "pk": 21, "fields": {"name": "Can delete site", "content_type": 8, "codename": "delete_site"}}, {"model": "auth.permission", "pk": 22, "fields": {"name": "Can add task state", "content_type": 9, "codename": "add_taskmeta"}}, {"model": "auth.permission", "pk": 23, "fields": {"name": "Can change task state", "content_type": 9, "codename": "change_taskmeta"}}, {"model": "auth.permission", "pk": 24, "fields": {"name": "Can delete task state", "content_type": 9, "codename": "delete_taskmeta"}}, {"model": "auth.permission", "pk": 25, "fields": {"name": "Can add saved group result", "content_type": 10, "codename": "add_tasksetmeta"}}, {"model": "auth.permission", "pk": 26, "fields": {"name": "Can change saved group result", "content_type": 10, "codename": "change_tasksetmeta"}}, {"model": "auth.permission", "pk": 27, "fields": {"name": "Can delete saved group result", "content_type": 10, "codename": "delete_tasksetmeta"}}, {"model": "auth.permission", "pk": 28, "fields": {"name": "Can add interval", "content_type": 11, "codename": "add_intervalschedule"}}, {"model": "auth.permission", "pk": 29, "fields": {"name": "Can change interval", "content_type": 11, "codename": "change_intervalschedule"}}, {"model": "auth.permission", "pk": 30, "fields": {"name": "Can delete interval", "content_type": 11, "codename": "delete_intervalschedule"}}, {"model": "auth.permission", "pk": 31, "fields": {"name": "Can add crontab", "content_type": 12, "codename": "add_crontabschedule"}}, {"model": "auth.permission", "pk": 32, "fields": {"name": "Can change crontab", "content_type": 12, "codename": "change_crontabschedule"}}, {"model": "auth.permission", "pk": 33, "fields": {"name": "Can delete crontab", "content_type": 12, "codename": "delete_crontabschedule"}}, {"model": "auth.permission", "pk": 34, "fields": {"name": "Can add periodic tasks", "content_type": 13, "codename": "add_periodictasks"}}, {"model": "auth.permission", "pk": 35, "fields": {"name": "Can change periodic tasks", "content_type": 13, "codename": "change_periodictasks"}}, {"model": "auth.permission", "pk": 36, "fields": {"name": "Can delete periodic tasks", "content_type": 13, "codename": "delete_periodictasks"}}, {"model": "auth.permission", "pk": 37, "fields": {"name": "Can add periodic task", "content_type": 14, "codename": "add_periodictask"}}, {"model": "auth.permission", "pk": 38, "fields": {"name": "Can change periodic task", "content_type": 14, "codename": "change_periodictask"}}, {"model": "auth.permission", "pk": 39, "fields": {"name": "Can delete periodic task", "content_type": 14, "codename": "delete_periodictask"}}, {"model": "auth.permission", "pk": 40, "fields": {"name": "Can add worker", "content_type": 15, "codename": "add_workerstate"}}, {"model": "auth.permission", "pk": 41, "fields": {"name": "Can change worker", "content_type": 15, "codename": "change_workerstate"}}, {"model": "auth.permission", "pk": 42, "fields": {"name": "Can delete worker", "content_type": 15, "codename": "delete_workerstate"}}, {"model": "auth.permission", "pk": 43, "fields": {"name": "Can add task", "content_type": 16, "codename": "add_taskstate"}}, {"model": "auth.permission", "pk": 44, "fields": {"name": "Can change task", "content_type": 16, "codename": "change_taskstate"}}, {"model": "auth.permission", "pk": 45, "fields": {"name": "Can delete task", "content_type": 16, "codename": "delete_taskstate"}}, {"model": "auth.permission", "pk": 46, "fields": {"name": "Can add flag", "content_type": 17, "codename": "add_flag"}}, {"model": "auth.permission", "pk": 47, "fields": {"name": "Can change flag", "content_type": 17, "codename": "change_flag"}}, {"model": "auth.permission", "pk": 48, "fields": {"name": "Can delete flag", "content_type": 17, "codename": "delete_flag"}}, {"model": "auth.permission", "pk": 49, "fields": {"name": "Can add switch", "content_type": 18, "codename": "add_switch"}}, {"model": "auth.permission", "pk": 50, "fields": {"name": "Can change switch", "content_type": 18, "codename": "change_switch"}}, {"model": "auth.permission", "pk": 51, "fields": {"name": "Can delete switch", "content_type": 18, "codename": "delete_switch"}}, {"model": "auth.permission", "pk": 52, "fields": {"name": "Can add sample", "content_type": 19, "codename": "add_sample"}}, {"model": "auth.permission", "pk": 53, "fields": {"name": "Can change sample", "content_type": 19, "codename": "change_sample"}}, {"model": "auth.permission", "pk": 54, "fields": {"name": "Can delete sample", "content_type": 19, "codename": "delete_sample"}}, {"model": "auth.permission", "pk": 55, "fields": {"name": "Can add global status message", "content_type": 20, "codename": "add_globalstatusmessage"}}, {"model": "auth.permission", "pk": 56, "fields": {"name": "Can change global status message", "content_type": 20, "codename": "change_globalstatusmessage"}}, {"model": "auth.permission", "pk": 57, "fields": {"name": "Can delete global status message", "content_type": 20, "codename": "delete_globalstatusmessage"}}, {"model": "auth.permission", "pk": 58, "fields": {"name": "Can add course message", "content_type": 21, "codename": "add_coursemessage"}}, {"model": "auth.permission", "pk": 59, "fields": {"name": "Can change course message", "content_type": 21, "codename": "change_coursemessage"}}, {"model": "auth.permission", "pk": 60, "fields": {"name": "Can delete course message", "content_type": 21, "codename": "delete_coursemessage"}}, {"model": "auth.permission", "pk": 61, "fields": {"name": "Can add asset base url config", "content_type": 22, "codename": "add_assetbaseurlconfig"}}, {"model": "auth.permission", "pk": 62, "fields": {"name": "Can change asset base url config", "content_type": 22, "codename": "change_assetbaseurlconfig"}}, {"model": "auth.permission", "pk": 63, "fields": {"name": "Can delete asset base url config", "content_type": 22, "codename": "delete_assetbaseurlconfig"}}, {"model": "auth.permission", "pk": 64, "fields": {"name": "Can add asset excluded extensions config", "content_type": 23, "codename": "add_assetexcludedextensionsconfig"}}, {"model": "auth.permission", "pk": 65, "fields": {"name": "Can change asset excluded extensions config", "content_type": 23, "codename": "change_assetexcludedextensionsconfig"}}, {"model": "auth.permission", "pk": 66, "fields": {"name": "Can delete asset excluded extensions config", "content_type": 23, "codename": "delete_assetexcludedextensionsconfig"}}, {"model": "auth.permission", "pk": 67, "fields": {"name": "Can add course asset cache ttl config", "content_type": 24, "codename": "add_courseassetcachettlconfig"}}, {"model": "auth.permission", "pk": 68, "fields": {"name": "Can change course asset cache ttl config", "content_type": 24, "codename": "change_courseassetcachettlconfig"}}, {"model": "auth.permission", "pk": 69, "fields": {"name": "Can delete course asset cache ttl config", "content_type": 24, "codename": "delete_courseassetcachettlconfig"}}, {"model": "auth.permission", "pk": 70, "fields": {"name": "Can add cdn user agents config", "content_type": 25, "codename": "add_cdnuseragentsconfig"}}, {"model": "auth.permission", "pk": 71, "fields": {"name": "Can change cdn user agents config", "content_type": 25, "codename": "change_cdnuseragentsconfig"}}, {"model": "auth.permission", "pk": 72, "fields": {"name": "Can delete cdn user agents config", "content_type": 25, "codename": "delete_cdnuseragentsconfig"}}, {"model": "auth.permission", "pk": 73, "fields": {"name": "Can add site theme", "content_type": 26, "codename": "add_sitetheme"}}, {"model": "auth.permission", "pk": 74, "fields": {"name": "Can change site theme", "content_type": 26, "codename": "change_sitetheme"}}, {"model": "auth.permission", "pk": 75, "fields": {"name": "Can delete site theme", "content_type": 26, "codename": "delete_sitetheme"}}, {"model": "auth.permission", "pk": 76, "fields": {"name": "Can add site configuration", "content_type": 27, "codename": "add_siteconfiguration"}}, {"model": "auth.permission", "pk": 77, "fields": {"name": "Can change site configuration", "content_type": 27, "codename": "change_siteconfiguration"}}, {"model": "auth.permission", "pk": 78, "fields": {"name": "Can delete site configuration", "content_type": 27, "codename": "delete_siteconfiguration"}}, {"model": "auth.permission", "pk": 79, "fields": {"name": "Can add site configuration history", "content_type": 28, "codename": "add_siteconfigurationhistory"}}, {"model": "auth.permission", "pk": 80, "fields": {"name": "Can change site configuration history", "content_type": 28, "codename": "change_siteconfigurationhistory"}}, {"model": "auth.permission", "pk": 81, "fields": {"name": "Can delete site configuration history", "content_type": 28, "codename": "delete_siteconfigurationhistory"}}, {"model": "auth.permission", "pk": 82, "fields": {"name": "Can add hls playback enabled flag", "content_type": 29, "codename": "add_hlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 83, "fields": {"name": "Can change hls playback enabled flag", "content_type": 29, "codename": "change_hlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 84, "fields": {"name": "Can delete hls playback enabled flag", "content_type": 29, "codename": "delete_hlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 85, "fields": {"name": "Can add course hls playback enabled flag", "content_type": 30, "codename": "add_coursehlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 86, "fields": {"name": "Can change course hls playback enabled flag", "content_type": 30, "codename": "change_coursehlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 87, "fields": {"name": "Can delete course hls playback enabled flag", "content_type": 30, "codename": "delete_coursehlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 88, "fields": {"name": "Can add video transcript enabled flag", "content_type": 31, "codename": "add_videotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 89, "fields": {"name": "Can change video transcript enabled flag", "content_type": 31, "codename": "change_videotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 90, "fields": {"name": "Can delete video transcript enabled flag", "content_type": 31, "codename": "delete_videotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 91, "fields": {"name": "Can add course video transcript enabled flag", "content_type": 32, "codename": "add_coursevideotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 92, "fields": {"name": "Can change course video transcript enabled flag", "content_type": 32, "codename": "change_coursevideotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 93, "fields": {"name": "Can delete course video transcript enabled flag", "content_type": 32, "codename": "delete_coursevideotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 94, "fields": {"name": "Can add video pipeline integration", "content_type": 33, "codename": "add_videopipelineintegration"}}, {"model": "auth.permission", "pk": 95, "fields": {"name": "Can change video pipeline integration", "content_type": 33, "codename": "change_videopipelineintegration"}}, {"model": "auth.permission", "pk": 96, "fields": {"name": "Can delete video pipeline integration", "content_type": 33, "codename": "delete_videopipelineintegration"}}, {"model": "auth.permission", "pk": 97, "fields": {"name": "Can add video uploads enabled by default", "content_type": 34, "codename": "add_videouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 98, "fields": {"name": "Can change video uploads enabled by default", "content_type": 34, "codename": "change_videouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 99, "fields": {"name": "Can delete video uploads enabled by default", "content_type": 34, "codename": "delete_videouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 100, "fields": {"name": "Can add course video uploads enabled by default", "content_type": 35, "codename": "add_coursevideouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 101, "fields": {"name": "Can change course video uploads enabled by default", "content_type": 35, "codename": "change_coursevideouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 102, "fields": {"name": "Can delete course video uploads enabled by default", "content_type": 35, "codename": "delete_coursevideouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 103, "fields": {"name": "Can add bookmark", "content_type": 36, "codename": "add_bookmark"}}, {"model": "auth.permission", "pk": 104, "fields": {"name": "Can change bookmark", "content_type": 36, "codename": "change_bookmark"}}, {"model": "auth.permission", "pk": 105, "fields": {"name": "Can delete bookmark", "content_type": 36, "codename": "delete_bookmark"}}, {"model": "auth.permission", "pk": 106, "fields": {"name": "Can add x block cache", "content_type": 37, "codename": "add_xblockcache"}}, {"model": "auth.permission", "pk": 107, "fields": {"name": "Can change x block cache", "content_type": 37, "codename": "change_xblockcache"}}, {"model": "auth.permission", "pk": 108, "fields": {"name": "Can delete x block cache", "content_type": 37, "codename": "delete_xblockcache"}}, {"model": "auth.permission", "pk": 109, "fields": {"name": "Can add student module", "content_type": 38, "codename": "add_studentmodule"}}, {"model": "auth.permission", "pk": 110, "fields": {"name": "Can change student module", "content_type": 38, "codename": "change_studentmodule"}}, {"model": "auth.permission", "pk": 111, "fields": {"name": "Can delete student module", "content_type": 38, "codename": "delete_studentmodule"}}, {"model": "auth.permission", "pk": 112, "fields": {"name": "Can add student module history", "content_type": 39, "codename": "add_studentmodulehistory"}}, {"model": "auth.permission", "pk": 113, "fields": {"name": "Can change student module history", "content_type": 39, "codename": "change_studentmodulehistory"}}, {"model": "auth.permission", "pk": 114, "fields": {"name": "Can delete student module history", "content_type": 39, "codename": "delete_studentmodulehistory"}}, {"model": "auth.permission", "pk": 115, "fields": {"name": "Can add x module user state summary field", "content_type": 40, "codename": "add_xmoduleuserstatesummaryfield"}}, {"model": "auth.permission", "pk": 116, "fields": {"name": "Can change x module user state summary field", "content_type": 40, "codename": "change_xmoduleuserstatesummaryfield"}}, {"model": "auth.permission", "pk": 117, "fields": {"name": "Can delete x module user state summary field", "content_type": 40, "codename": "delete_xmoduleuserstatesummaryfield"}}, {"model": "auth.permission", "pk": 118, "fields": {"name": "Can add x module student prefs field", "content_type": 41, "codename": "add_xmodulestudentprefsfield"}}, {"model": "auth.permission", "pk": 119, "fields": {"name": "Can change x module student prefs field", "content_type": 41, "codename": "change_xmodulestudentprefsfield"}}, {"model": "auth.permission", "pk": 120, "fields": {"name": "Can delete x module student prefs field", "content_type": 41, "codename": "delete_xmodulestudentprefsfield"}}, {"model": "auth.permission", "pk": 121, "fields": {"name": "Can add x module student info field", "content_type": 42, "codename": "add_xmodulestudentinfofield"}}, {"model": "auth.permission", "pk": 122, "fields": {"name": "Can change x module student info field", "content_type": 42, "codename": "change_xmodulestudentinfofield"}}, {"model": "auth.permission", "pk": 123, "fields": {"name": "Can delete x module student info field", "content_type": 42, "codename": "delete_xmodulestudentinfofield"}}, {"model": "auth.permission", "pk": 124, "fields": {"name": "Can add offline computed grade", "content_type": 43, "codename": "add_offlinecomputedgrade"}}, {"model": "auth.permission", "pk": 125, "fields": {"name": "Can change offline computed grade", "content_type": 43, "codename": "change_offlinecomputedgrade"}}, {"model": "auth.permission", "pk": 126, "fields": {"name": "Can delete offline computed grade", "content_type": 43, "codename": "delete_offlinecomputedgrade"}}, {"model": "auth.permission", "pk": 127, "fields": {"name": "Can add offline computed grade log", "content_type": 44, "codename": "add_offlinecomputedgradelog"}}, {"model": "auth.permission", "pk": 128, "fields": {"name": "Can change offline computed grade log", "content_type": 44, "codename": "change_offlinecomputedgradelog"}}, {"model": "auth.permission", "pk": 129, "fields": {"name": "Can delete offline computed grade log", "content_type": 44, "codename": "delete_offlinecomputedgradelog"}}, {"model": "auth.permission", "pk": 130, "fields": {"name": "Can add student field override", "content_type": 45, "codename": "add_studentfieldoverride"}}, {"model": "auth.permission", "pk": 131, "fields": {"name": "Can change student field override", "content_type": 45, "codename": "change_studentfieldoverride"}}, {"model": "auth.permission", "pk": 132, "fields": {"name": "Can delete student field override", "content_type": 45, "codename": "delete_studentfieldoverride"}}, {"model": "auth.permission", "pk": 133, "fields": {"name": "Can add dynamic upgrade deadline configuration", "content_type": 46, "codename": "add_dynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 134, "fields": {"name": "Can change dynamic upgrade deadline configuration", "content_type": 46, "codename": "change_dynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 135, "fields": {"name": "Can delete dynamic upgrade deadline configuration", "content_type": 46, "codename": "delete_dynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 136, "fields": {"name": "Can add course dynamic upgrade deadline configuration", "content_type": 47, "codename": "add_coursedynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 137, "fields": {"name": "Can change course dynamic upgrade deadline configuration", "content_type": 47, "codename": "change_coursedynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 138, "fields": {"name": "Can delete course dynamic upgrade deadline configuration", "content_type": 47, "codename": "delete_coursedynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 139, "fields": {"name": "Can add org dynamic upgrade deadline configuration", "content_type": 48, "codename": "add_orgdynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 140, "fields": {"name": "Can change org dynamic upgrade deadline configuration", "content_type": 48, "codename": "change_orgdynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 141, "fields": {"name": "Can delete org dynamic upgrade deadline configuration", "content_type": 48, "codename": "delete_orgdynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 142, "fields": {"name": "Can add anonymous user id", "content_type": 49, "codename": "add_anonymoususerid"}}, {"model": "auth.permission", "pk": 143, "fields": {"name": "Can change anonymous user id", "content_type": 49, "codename": "change_anonymoususerid"}}, {"model": "auth.permission", "pk": 144, "fields": {"name": "Can delete anonymous user id", "content_type": 49, "codename": "delete_anonymoususerid"}}, {"model": "auth.permission", "pk": 145, "fields": {"name": "Can add user standing", "content_type": 50, "codename": "add_userstanding"}}, {"model": "auth.permission", "pk": 146, "fields": {"name": "Can change user standing", "content_type": 50, "codename": "change_userstanding"}}, {"model": "auth.permission", "pk": 147, "fields": {"name": "Can delete user standing", "content_type": 50, "codename": "delete_userstanding"}}, {"model": "auth.permission", "pk": 148, "fields": {"name": "Can add user profile", "content_type": 51, "codename": "add_userprofile"}}, {"model": "auth.permission", "pk": 149, "fields": {"name": "Can change user profile", "content_type": 51, "codename": "change_userprofile"}}, {"model": "auth.permission", "pk": 150, "fields": {"name": "Can delete user profile", "content_type": 51, "codename": "delete_userprofile"}}, {"model": "auth.permission", "pk": 151, "fields": {"name": "Can deactivate, but NOT delete users", "content_type": 51, "codename": "can_deactivate_users"}}, {"model": "auth.permission", "pk": 152, "fields": {"name": "Can add user signup source", "content_type": 52, "codename": "add_usersignupsource"}}, {"model": "auth.permission", "pk": 153, "fields": {"name": "Can change user signup source", "content_type": 52, "codename": "change_usersignupsource"}}, {"model": "auth.permission", "pk": 154, "fields": {"name": "Can delete user signup source", "content_type": 52, "codename": "delete_usersignupsource"}}, {"model": "auth.permission", "pk": 155, "fields": {"name": "Can add user test group", "content_type": 53, "codename": "add_usertestgroup"}}, {"model": "auth.permission", "pk": 156, "fields": {"name": "Can change user test group", "content_type": 53, "codename": "change_usertestgroup"}}, {"model": "auth.permission", "pk": 157, "fields": {"name": "Can delete user test group", "content_type": 53, "codename": "delete_usertestgroup"}}, {"model": "auth.permission", "pk": 158, "fields": {"name": "Can add registration", "content_type": 54, "codename": "add_registration"}}, {"model": "auth.permission", "pk": 159, "fields": {"name": "Can change registration", "content_type": 54, "codename": "change_registration"}}, {"model": "auth.permission", "pk": 160, "fields": {"name": "Can delete registration", "content_type": 54, "codename": "delete_registration"}}, {"model": "auth.permission", "pk": 161, "fields": {"name": "Can add pending name change", "content_type": 55, "codename": "add_pendingnamechange"}}, {"model": "auth.permission", "pk": 162, "fields": {"name": "Can change pending name change", "content_type": 55, "codename": "change_pendingnamechange"}}, {"model": "auth.permission", "pk": 163, "fields": {"name": "Can delete pending name change", "content_type": 55, "codename": "delete_pendingnamechange"}}, {"model": "auth.permission", "pk": 164, "fields": {"name": "Can add pending email change", "content_type": 56, "codename": "add_pendingemailchange"}}, {"model": "auth.permission", "pk": 165, "fields": {"name": "Can change pending email change", "content_type": 56, "codename": "change_pendingemailchange"}}, {"model": "auth.permission", "pk": 166, "fields": {"name": "Can delete pending email change", "content_type": 56, "codename": "delete_pendingemailchange"}}, {"model": "auth.permission", "pk": 167, "fields": {"name": "Can add password history", "content_type": 57, "codename": "add_passwordhistory"}}, {"model": "auth.permission", "pk": 168, "fields": {"name": "Can change password history", "content_type": 57, "codename": "change_passwordhistory"}}, {"model": "auth.permission", "pk": 169, "fields": {"name": "Can delete password history", "content_type": 57, "codename": "delete_passwordhistory"}}, {"model": "auth.permission", "pk": 170, "fields": {"name": "Can add login failures", "content_type": 58, "codename": "add_loginfailures"}}, {"model": "auth.permission", "pk": 171, "fields": {"name": "Can change login failures", "content_type": 58, "codename": "change_loginfailures"}}, {"model": "auth.permission", "pk": 172, "fields": {"name": "Can delete login failures", "content_type": 58, "codename": "delete_loginfailures"}}, {"model": "auth.permission", "pk": 173, "fields": {"name": "Can add course enrollment", "content_type": 59, "codename": "add_courseenrollment"}}, {"model": "auth.permission", "pk": 174, "fields": {"name": "Can change course enrollment", "content_type": 59, "codename": "change_courseenrollment"}}, {"model": "auth.permission", "pk": 175, "fields": {"name": "Can delete course enrollment", "content_type": 59, "codename": "delete_courseenrollment"}}, {"model": "auth.permission", "pk": 176, "fields": {"name": "Can add manual enrollment audit", "content_type": 60, "codename": "add_manualenrollmentaudit"}}, {"model": "auth.permission", "pk": 177, "fields": {"name": "Can change manual enrollment audit", "content_type": 60, "codename": "change_manualenrollmentaudit"}}, {"model": "auth.permission", "pk": 178, "fields": {"name": "Can delete manual enrollment audit", "content_type": 60, "codename": "delete_manualenrollmentaudit"}}, {"model": "auth.permission", "pk": 179, "fields": {"name": "Can add course enrollment allowed", "content_type": 61, "codename": "add_courseenrollmentallowed"}}, {"model": "auth.permission", "pk": 180, "fields": {"name": "Can change course enrollment allowed", "content_type": 61, "codename": "change_courseenrollmentallowed"}}, {"model": "auth.permission", "pk": 181, "fields": {"name": "Can delete course enrollment allowed", "content_type": 61, "codename": "delete_courseenrollmentallowed"}}, {"model": "auth.permission", "pk": 182, "fields": {"name": "Can add course access role", "content_type": 62, "codename": "add_courseaccessrole"}}, {"model": "auth.permission", "pk": 183, "fields": {"name": "Can change course access role", "content_type": 62, "codename": "change_courseaccessrole"}}, {"model": "auth.permission", "pk": 184, "fields": {"name": "Can delete course access role", "content_type": 62, "codename": "delete_courseaccessrole"}}, {"model": "auth.permission", "pk": 185, "fields": {"name": "Can add dashboard configuration", "content_type": 63, "codename": "add_dashboardconfiguration"}}, {"model": "auth.permission", "pk": 186, "fields": {"name": "Can change dashboard configuration", "content_type": 63, "codename": "change_dashboardconfiguration"}}, {"model": "auth.permission", "pk": 187, "fields": {"name": "Can delete dashboard configuration", "content_type": 63, "codename": "delete_dashboardconfiguration"}}, {"model": "auth.permission", "pk": 188, "fields": {"name": "Can add linked in add to profile configuration", "content_type": 64, "codename": "add_linkedinaddtoprofileconfiguration"}}, {"model": "auth.permission", "pk": 189, "fields": {"name": "Can change linked in add to profile configuration", "content_type": 64, "codename": "change_linkedinaddtoprofileconfiguration"}}, {"model": "auth.permission", "pk": 190, "fields": {"name": "Can delete linked in add to profile configuration", "content_type": 64, "codename": "delete_linkedinaddtoprofileconfiguration"}}, {"model": "auth.permission", "pk": 191, "fields": {"name": "Can add entrance exam configuration", "content_type": 65, "codename": "add_entranceexamconfiguration"}}, {"model": "auth.permission", "pk": 192, "fields": {"name": "Can change entrance exam configuration", "content_type": 65, "codename": "change_entranceexamconfiguration"}}, {"model": "auth.permission", "pk": 193, "fields": {"name": "Can delete entrance exam configuration", "content_type": 65, "codename": "delete_entranceexamconfiguration"}}, {"model": "auth.permission", "pk": 194, "fields": {"name": "Can add language proficiency", "content_type": 66, "codename": "add_languageproficiency"}}, {"model": "auth.permission", "pk": 195, "fields": {"name": "Can change language proficiency", "content_type": 66, "codename": "change_languageproficiency"}}, {"model": "auth.permission", "pk": 196, "fields": {"name": "Can delete language proficiency", "content_type": 66, "codename": "delete_languageproficiency"}}, {"model": "auth.permission", "pk": 197, "fields": {"name": "Can add social link", "content_type": 67, "codename": "add_sociallink"}}, {"model": "auth.permission", "pk": 198, "fields": {"name": "Can change social link", "content_type": 67, "codename": "change_sociallink"}}, {"model": "auth.permission", "pk": 199, "fields": {"name": "Can delete social link", "content_type": 67, "codename": "delete_sociallink"}}, {"model": "auth.permission", "pk": 200, "fields": {"name": "Can add course enrollment attribute", "content_type": 68, "codename": "add_courseenrollmentattribute"}}, {"model": "auth.permission", "pk": 201, "fields": {"name": "Can change course enrollment attribute", "content_type": 68, "codename": "change_courseenrollmentattribute"}}, {"model": "auth.permission", "pk": 202, "fields": {"name": "Can delete course enrollment attribute", "content_type": 68, "codename": "delete_courseenrollmentattribute"}}, {"model": "auth.permission", "pk": 203, "fields": {"name": "Can add enrollment refund configuration", "content_type": 69, "codename": "add_enrollmentrefundconfiguration"}}, {"model": "auth.permission", "pk": 204, "fields": {"name": "Can change enrollment refund configuration", "content_type": 69, "codename": "change_enrollmentrefundconfiguration"}}, {"model": "auth.permission", "pk": 205, "fields": {"name": "Can delete enrollment refund configuration", "content_type": 69, "codename": "delete_enrollmentrefundconfiguration"}}, {"model": "auth.permission", "pk": 206, "fields": {"name": "Can add registration cookie configuration", "content_type": 70, "codename": "add_registrationcookieconfiguration"}}, {"model": "auth.permission", "pk": 207, "fields": {"name": "Can change registration cookie configuration", "content_type": 70, "codename": "change_registrationcookieconfiguration"}}, {"model": "auth.permission", "pk": 208, "fields": {"name": "Can delete registration cookie configuration", "content_type": 70, "codename": "delete_registrationcookieconfiguration"}}, {"model": "auth.permission", "pk": 209, "fields": {"name": "Can add user attribute", "content_type": 71, "codename": "add_userattribute"}}, {"model": "auth.permission", "pk": 210, "fields": {"name": "Can change user attribute", "content_type": 71, "codename": "change_userattribute"}}, {"model": "auth.permission", "pk": 211, "fields": {"name": "Can delete user attribute", "content_type": 71, "codename": "delete_userattribute"}}, {"model": "auth.permission", "pk": 212, "fields": {"name": "Can add logout view configuration", "content_type": 72, "codename": "add_logoutviewconfiguration"}}, {"model": "auth.permission", "pk": 213, "fields": {"name": "Can change logout view configuration", "content_type": 72, "codename": "change_logoutviewconfiguration"}}, {"model": "auth.permission", "pk": 214, "fields": {"name": "Can delete logout view configuration", "content_type": 72, "codename": "delete_logoutviewconfiguration"}}, {"model": "auth.permission", "pk": 215, "fields": {"name": "Can add tracking log", "content_type": 73, "codename": "add_trackinglog"}}, {"model": "auth.permission", "pk": 216, "fields": {"name": "Can change tracking log", "content_type": 73, "codename": "change_trackinglog"}}, {"model": "auth.permission", "pk": 217, "fields": {"name": "Can delete tracking log", "content_type": 73, "codename": "delete_trackinglog"}}, {"model": "auth.permission", "pk": 218, "fields": {"name": "Can add rate limit configuration", "content_type": 74, "codename": "add_ratelimitconfiguration"}}, {"model": "auth.permission", "pk": 219, "fields": {"name": "Can change rate limit configuration", "content_type": 74, "codename": "change_ratelimitconfiguration"}}, {"model": "auth.permission", "pk": 220, "fields": {"name": "Can delete rate limit configuration", "content_type": 74, "codename": "delete_ratelimitconfiguration"}}, {"model": "auth.permission", "pk": 221, "fields": {"name": "Can add certificate whitelist", "content_type": 75, "codename": "add_certificatewhitelist"}}, {"model": "auth.permission", "pk": 222, "fields": {"name": "Can change certificate whitelist", "content_type": 75, "codename": "change_certificatewhitelist"}}, {"model": "auth.permission", "pk": 223, "fields": {"name": "Can delete certificate whitelist", "content_type": 75, "codename": "delete_certificatewhitelist"}}, {"model": "auth.permission", "pk": 224, "fields": {"name": "Can add generated certificate", "content_type": 76, "codename": "add_generatedcertificate"}}, {"model": "auth.permission", "pk": 225, "fields": {"name": "Can change generated certificate", "content_type": 76, "codename": "change_generatedcertificate"}}, {"model": "auth.permission", "pk": 226, "fields": {"name": "Can delete generated certificate", "content_type": 76, "codename": "delete_generatedcertificate"}}, {"model": "auth.permission", "pk": 227, "fields": {"name": "Can add certificate generation history", "content_type": 77, "codename": "add_certificategenerationhistory"}}, {"model": "auth.permission", "pk": 228, "fields": {"name": "Can change certificate generation history", "content_type": 77, "codename": "change_certificategenerationhistory"}}, {"model": "auth.permission", "pk": 229, "fields": {"name": "Can delete certificate generation history", "content_type": 77, "codename": "delete_certificategenerationhistory"}}, {"model": "auth.permission", "pk": 230, "fields": {"name": "Can add certificate invalidation", "content_type": 78, "codename": "add_certificateinvalidation"}}, {"model": "auth.permission", "pk": 231, "fields": {"name": "Can change certificate invalidation", "content_type": 78, "codename": "change_certificateinvalidation"}}, {"model": "auth.permission", "pk": 232, "fields": {"name": "Can delete certificate invalidation", "content_type": 78, "codename": "delete_certificateinvalidation"}}, {"model": "auth.permission", "pk": 233, "fields": {"name": "Can add example certificate set", "content_type": 79, "codename": "add_examplecertificateset"}}, {"model": "auth.permission", "pk": 234, "fields": {"name": "Can change example certificate set", "content_type": 79, "codename": "change_examplecertificateset"}}, {"model": "auth.permission", "pk": 235, "fields": {"name": "Can delete example certificate set", "content_type": 79, "codename": "delete_examplecertificateset"}}, {"model": "auth.permission", "pk": 236, "fields": {"name": "Can add example certificate", "content_type": 80, "codename": "add_examplecertificate"}}, {"model": "auth.permission", "pk": 237, "fields": {"name": "Can change example certificate", "content_type": 80, "codename": "change_examplecertificate"}}, {"model": "auth.permission", "pk": 238, "fields": {"name": "Can delete example certificate", "content_type": 80, "codename": "delete_examplecertificate"}}, {"model": "auth.permission", "pk": 239, "fields": {"name": "Can add certificate generation course setting", "content_type": 81, "codename": "add_certificategenerationcoursesetting"}}, {"model": "auth.permission", "pk": 240, "fields": {"name": "Can change certificate generation course setting", "content_type": 81, "codename": "change_certificategenerationcoursesetting"}}, {"model": "auth.permission", "pk": 241, "fields": {"name": "Can delete certificate generation course setting", "content_type": 81, "codename": "delete_certificategenerationcoursesetting"}}, {"model": "auth.permission", "pk": 242, "fields": {"name": "Can add certificate generation configuration", "content_type": 82, "codename": "add_certificategenerationconfiguration"}}, {"model": "auth.permission", "pk": 243, "fields": {"name": "Can change certificate generation configuration", "content_type": 82, "codename": "change_certificategenerationconfiguration"}}, {"model": "auth.permission", "pk": 244, "fields": {"name": "Can delete certificate generation configuration", "content_type": 82, "codename": "delete_certificategenerationconfiguration"}}, {"model": "auth.permission", "pk": 245, "fields": {"name": "Can add certificate html view configuration", "content_type": 83, "codename": "add_certificatehtmlviewconfiguration"}}, {"model": "auth.permission", "pk": 246, "fields": {"name": "Can change certificate html view configuration", "content_type": 83, "codename": "change_certificatehtmlviewconfiguration"}}, {"model": "auth.permission", "pk": 247, "fields": {"name": "Can delete certificate html view configuration", "content_type": 83, "codename": "delete_certificatehtmlviewconfiguration"}}, {"model": "auth.permission", "pk": 248, "fields": {"name": "Can add certificate template", "content_type": 84, "codename": "add_certificatetemplate"}}, {"model": "auth.permission", "pk": 249, "fields": {"name": "Can change certificate template", "content_type": 84, "codename": "change_certificatetemplate"}}, {"model": "auth.permission", "pk": 250, "fields": {"name": "Can delete certificate template", "content_type": 84, "codename": "delete_certificatetemplate"}}, {"model": "auth.permission", "pk": 251, "fields": {"name": "Can add certificate template asset", "content_type": 85, "codename": "add_certificatetemplateasset"}}, {"model": "auth.permission", "pk": 252, "fields": {"name": "Can change certificate template asset", "content_type": 85, "codename": "change_certificatetemplateasset"}}, {"model": "auth.permission", "pk": 253, "fields": {"name": "Can delete certificate template asset", "content_type": 85, "codename": "delete_certificatetemplateasset"}}, {"model": "auth.permission", "pk": 254, "fields": {"name": "Can add instructor task", "content_type": 86, "codename": "add_instructortask"}}, {"model": "auth.permission", "pk": 255, "fields": {"name": "Can change instructor task", "content_type": 86, "codename": "change_instructortask"}}, {"model": "auth.permission", "pk": 256, "fields": {"name": "Can delete instructor task", "content_type": 86, "codename": "delete_instructortask"}}, {"model": "auth.permission", "pk": 257, "fields": {"name": "Can add grade report setting", "content_type": 87, "codename": "add_gradereportsetting"}}, {"model": "auth.permission", "pk": 258, "fields": {"name": "Can change grade report setting", "content_type": 87, "codename": "change_gradereportsetting"}}, {"model": "auth.permission", "pk": 259, "fields": {"name": "Can delete grade report setting", "content_type": 87, "codename": "delete_gradereportsetting"}}, {"model": "auth.permission", "pk": 260, "fields": {"name": "Can add course user group", "content_type": 88, "codename": "add_courseusergroup"}}, {"model": "auth.permission", "pk": 261, "fields": {"name": "Can change course user group", "content_type": 88, "codename": "change_courseusergroup"}}, {"model": "auth.permission", "pk": 262, "fields": {"name": "Can delete course user group", "content_type": 88, "codename": "delete_courseusergroup"}}, {"model": "auth.permission", "pk": 263, "fields": {"name": "Can add cohort membership", "content_type": 89, "codename": "add_cohortmembership"}}, {"model": "auth.permission", "pk": 264, "fields": {"name": "Can change cohort membership", "content_type": 89, "codename": "change_cohortmembership"}}, {"model": "auth.permission", "pk": 265, "fields": {"name": "Can delete cohort membership", "content_type": 89, "codename": "delete_cohortmembership"}}, {"model": "auth.permission", "pk": 266, "fields": {"name": "Can add course user group partition group", "content_type": 90, "codename": "add_courseusergrouppartitiongroup"}}, {"model": "auth.permission", "pk": 267, "fields": {"name": "Can change course user group partition group", "content_type": 90, "codename": "change_courseusergrouppartitiongroup"}}, {"model": "auth.permission", "pk": 268, "fields": {"name": "Can delete course user group partition group", "content_type": 90, "codename": "delete_courseusergrouppartitiongroup"}}, {"model": "auth.permission", "pk": 269, "fields": {"name": "Can add course cohorts settings", "content_type": 91, "codename": "add_coursecohortssettings"}}, {"model": "auth.permission", "pk": 270, "fields": {"name": "Can change course cohorts settings", "content_type": 91, "codename": "change_coursecohortssettings"}}, {"model": "auth.permission", "pk": 271, "fields": {"name": "Can delete course cohorts settings", "content_type": 91, "codename": "delete_coursecohortssettings"}}, {"model": "auth.permission", "pk": 272, "fields": {"name": "Can add course cohort", "content_type": 92, "codename": "add_coursecohort"}}, {"model": "auth.permission", "pk": 273, "fields": {"name": "Can change course cohort", "content_type": 92, "codename": "change_coursecohort"}}, {"model": "auth.permission", "pk": 274, "fields": {"name": "Can delete course cohort", "content_type": 92, "codename": "delete_coursecohort"}}, {"model": "auth.permission", "pk": 275, "fields": {"name": "Can add unregistered learner cohort assignments", "content_type": 93, "codename": "add_unregisteredlearnercohortassignments"}}, {"model": "auth.permission", "pk": 276, "fields": {"name": "Can change unregistered learner cohort assignments", "content_type": 93, "codename": "change_unregisteredlearnercohortassignments"}}, {"model": "auth.permission", "pk": 277, "fields": {"name": "Can delete unregistered learner cohort assignments", "content_type": 93, "codename": "delete_unregisteredlearnercohortassignments"}}, {"model": "auth.permission", "pk": 278, "fields": {"name": "Can add target", "content_type": 94, "codename": "add_target"}}, {"model": "auth.permission", "pk": 279, "fields": {"name": "Can change target", "content_type": 94, "codename": "change_target"}}, {"model": "auth.permission", "pk": 280, "fields": {"name": "Can delete target", "content_type": 94, "codename": "delete_target"}}, {"model": "auth.permission", "pk": 281, "fields": {"name": "Can add cohort target", "content_type": 95, "codename": "add_cohorttarget"}}, {"model": "auth.permission", "pk": 282, "fields": {"name": "Can change cohort target", "content_type": 95, "codename": "change_cohorttarget"}}, {"model": "auth.permission", "pk": 283, "fields": {"name": "Can delete cohort target", "content_type": 95, "codename": "delete_cohorttarget"}}, {"model": "auth.permission", "pk": 284, "fields": {"name": "Can add course mode target", "content_type": 96, "codename": "add_coursemodetarget"}}, {"model": "auth.permission", "pk": 285, "fields": {"name": "Can change course mode target", "content_type": 96, "codename": "change_coursemodetarget"}}, {"model": "auth.permission", "pk": 286, "fields": {"name": "Can delete course mode target", "content_type": 96, "codename": "delete_coursemodetarget"}}, {"model": "auth.permission", "pk": 287, "fields": {"name": "Can add course email", "content_type": 97, "codename": "add_courseemail"}}, {"model": "auth.permission", "pk": 288, "fields": {"name": "Can change course email", "content_type": 97, "codename": "change_courseemail"}}, {"model": "auth.permission", "pk": 289, "fields": {"name": "Can delete course email", "content_type": 97, "codename": "delete_courseemail"}}, {"model": "auth.permission", "pk": 290, "fields": {"name": "Can add optout", "content_type": 98, "codename": "add_optout"}}, {"model": "auth.permission", "pk": 291, "fields": {"name": "Can change optout", "content_type": 98, "codename": "change_optout"}}, {"model": "auth.permission", "pk": 292, "fields": {"name": "Can delete optout", "content_type": 98, "codename": "delete_optout"}}, {"model": "auth.permission", "pk": 293, "fields": {"name": "Can add course email template", "content_type": 99, "codename": "add_courseemailtemplate"}}, {"model": "auth.permission", "pk": 294, "fields": {"name": "Can change course email template", "content_type": 99, "codename": "change_courseemailtemplate"}}, {"model": "auth.permission", "pk": 295, "fields": {"name": "Can delete course email template", "content_type": 99, "codename": "delete_courseemailtemplate"}}, {"model": "auth.permission", "pk": 296, "fields": {"name": "Can add course authorization", "content_type": 100, "codename": "add_courseauthorization"}}, {"model": "auth.permission", "pk": 297, "fields": {"name": "Can change course authorization", "content_type": 100, "codename": "change_courseauthorization"}}, {"model": "auth.permission", "pk": 298, "fields": {"name": "Can delete course authorization", "content_type": 100, "codename": "delete_courseauthorization"}}, {"model": "auth.permission", "pk": 299, "fields": {"name": "Can add bulk email flag", "content_type": 101, "codename": "add_bulkemailflag"}}, {"model": "auth.permission", "pk": 300, "fields": {"name": "Can change bulk email flag", "content_type": 101, "codename": "change_bulkemailflag"}}, {"model": "auth.permission", "pk": 301, "fields": {"name": "Can delete bulk email flag", "content_type": 101, "codename": "delete_bulkemailflag"}}, {"model": "auth.permission", "pk": 302, "fields": {"name": "Can add branding info config", "content_type": 102, "codename": "add_brandinginfoconfig"}}, {"model": "auth.permission", "pk": 303, "fields": {"name": "Can change branding info config", "content_type": 102, "codename": "change_brandinginfoconfig"}}, {"model": "auth.permission", "pk": 304, "fields": {"name": "Can delete branding info config", "content_type": 102, "codename": "delete_brandinginfoconfig"}}, {"model": "auth.permission", "pk": 305, "fields": {"name": "Can add branding api config", "content_type": 103, "codename": "add_brandingapiconfig"}}, {"model": "auth.permission", "pk": 306, "fields": {"name": "Can change branding api config", "content_type": 103, "codename": "change_brandingapiconfig"}}, {"model": "auth.permission", "pk": 307, "fields": {"name": "Can delete branding api config", "content_type": 103, "codename": "delete_brandingapiconfig"}}, {"model": "auth.permission", "pk": 308, "fields": {"name": "Can add visible blocks", "content_type": 104, "codename": "add_visibleblocks"}}, {"model": "auth.permission", "pk": 309, "fields": {"name": "Can change visible blocks", "content_type": 104, "codename": "change_visibleblocks"}}, {"model": "auth.permission", "pk": 310, "fields": {"name": "Can delete visible blocks", "content_type": 104, "codename": "delete_visibleblocks"}}, {"model": "auth.permission", "pk": 311, "fields": {"name": "Can add persistent subsection grade", "content_type": 105, "codename": "add_persistentsubsectiongrade"}}, {"model": "auth.permission", "pk": 312, "fields": {"name": "Can change persistent subsection grade", "content_type": 105, "codename": "change_persistentsubsectiongrade"}}, {"model": "auth.permission", "pk": 313, "fields": {"name": "Can delete persistent subsection grade", "content_type": 105, "codename": "delete_persistentsubsectiongrade"}}, {"model": "auth.permission", "pk": 314, "fields": {"name": "Can add persistent course grade", "content_type": 106, "codename": "add_persistentcoursegrade"}}, {"model": "auth.permission", "pk": 315, "fields": {"name": "Can change persistent course grade", "content_type": 106, "codename": "change_persistentcoursegrade"}}, {"model": "auth.permission", "pk": 316, "fields": {"name": "Can delete persistent course grade", "content_type": 106, "codename": "delete_persistentcoursegrade"}}, {"model": "auth.permission", "pk": 317, "fields": {"name": "Can add persistent subsection grade override", "content_type": 107, "codename": "add_persistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 318, "fields": {"name": "Can change persistent subsection grade override", "content_type": 107, "codename": "change_persistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 319, "fields": {"name": "Can delete persistent subsection grade override", "content_type": 107, "codename": "delete_persistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 320, "fields": {"name": "Can add persistent grades enabled flag", "content_type": 108, "codename": "add_persistentgradesenabledflag"}}, {"model": "auth.permission", "pk": 321, "fields": {"name": "Can change persistent grades enabled flag", "content_type": 108, "codename": "change_persistentgradesenabledflag"}}, {"model": "auth.permission", "pk": 322, "fields": {"name": "Can delete persistent grades enabled flag", "content_type": 108, "codename": "delete_persistentgradesenabledflag"}}, {"model": "auth.permission", "pk": 323, "fields": {"name": "Can add course persistent grades flag", "content_type": 109, "codename": "add_coursepersistentgradesflag"}}, {"model": "auth.permission", "pk": 324, "fields": {"name": "Can change course persistent grades flag", "content_type": 109, "codename": "change_coursepersistentgradesflag"}}, {"model": "auth.permission", "pk": 325, "fields": {"name": "Can delete course persistent grades flag", "content_type": 109, "codename": "delete_coursepersistentgradesflag"}}, {"model": "auth.permission", "pk": 326, "fields": {"name": "Can add compute grades setting", "content_type": 110, "codename": "add_computegradessetting"}}, {"model": "auth.permission", "pk": 327, "fields": {"name": "Can change compute grades setting", "content_type": 110, "codename": "change_computegradessetting"}}, {"model": "auth.permission", "pk": 328, "fields": {"name": "Can delete compute grades setting", "content_type": 110, "codename": "delete_computegradessetting"}}, {"model": "auth.permission", "pk": 329, "fields": {"name": "Can add external auth map", "content_type": 111, "codename": "add_externalauthmap"}}, {"model": "auth.permission", "pk": 330, "fields": {"name": "Can change external auth map", "content_type": 111, "codename": "change_externalauthmap"}}, {"model": "auth.permission", "pk": 331, "fields": {"name": "Can delete external auth map", "content_type": 111, "codename": "delete_externalauthmap"}}, {"model": "auth.permission", "pk": 332, "fields": {"name": "Can add nonce", "content_type": 112, "codename": "add_nonce"}}, {"model": "auth.permission", "pk": 333, "fields": {"name": "Can change nonce", "content_type": 112, "codename": "change_nonce"}}, {"model": "auth.permission", "pk": 334, "fields": {"name": "Can delete nonce", "content_type": 112, "codename": "delete_nonce"}}, {"model": "auth.permission", "pk": 335, "fields": {"name": "Can add association", "content_type": 113, "codename": "add_association"}}, {"model": "auth.permission", "pk": 336, "fields": {"name": "Can change association", "content_type": 113, "codename": "change_association"}}, {"model": "auth.permission", "pk": 337, "fields": {"name": "Can delete association", "content_type": 113, "codename": "delete_association"}}, {"model": "auth.permission", "pk": 338, "fields": {"name": "Can add user open id", "content_type": 114, "codename": "add_useropenid"}}, {"model": "auth.permission", "pk": 339, "fields": {"name": "Can change user open id", "content_type": 114, "codename": "change_useropenid"}}, {"model": "auth.permission", "pk": 340, "fields": {"name": "Can delete user open id", "content_type": 114, "codename": "delete_useropenid"}}, {"model": "auth.permission", "pk": 341, "fields": {"name": "The OpenID has been verified", "content_type": 114, "codename": "account_verified"}}, {"model": "auth.permission", "pk": 342, "fields": {"name": "Can add client", "content_type": 115, "codename": "add_client"}}, {"model": "auth.permission", "pk": 343, "fields": {"name": "Can change client", "content_type": 115, "codename": "change_client"}}, {"model": "auth.permission", "pk": 344, "fields": {"name": "Can delete client", "content_type": 115, "codename": "delete_client"}}, {"model": "auth.permission", "pk": 345, "fields": {"name": "Can add grant", "content_type": 116, "codename": "add_grant"}}, {"model": "auth.permission", "pk": 346, "fields": {"name": "Can change grant", "content_type": 116, "codename": "change_grant"}}, {"model": "auth.permission", "pk": 347, "fields": {"name": "Can delete grant", "content_type": 116, "codename": "delete_grant"}}, {"model": "auth.permission", "pk": 348, "fields": {"name": "Can add access token", "content_type": 117, "codename": "add_accesstoken"}}, {"model": "auth.permission", "pk": 349, "fields": {"name": "Can change access token", "content_type": 117, "codename": "change_accesstoken"}}, {"model": "auth.permission", "pk": 350, "fields": {"name": "Can delete access token", "content_type": 117, "codename": "delete_accesstoken"}}, {"model": "auth.permission", "pk": 351, "fields": {"name": "Can add refresh token", "content_type": 118, "codename": "add_refreshtoken"}}, {"model": "auth.permission", "pk": 352, "fields": {"name": "Can change refresh token", "content_type": 118, "codename": "change_refreshtoken"}}, {"model": "auth.permission", "pk": 353, "fields": {"name": "Can delete refresh token", "content_type": 118, "codename": "delete_refreshtoken"}}, {"model": "auth.permission", "pk": 354, "fields": {"name": "Can add trusted client", "content_type": 119, "codename": "add_trustedclient"}}, {"model": "auth.permission", "pk": 355, "fields": {"name": "Can change trusted client", "content_type": 119, "codename": "change_trustedclient"}}, {"model": "auth.permission", "pk": 356, "fields": {"name": "Can delete trusted client", "content_type": 119, "codename": "delete_trustedclient"}}, {"model": "auth.permission", "pk": 357, "fields": {"name": "Can add application", "content_type": 120, "codename": "add_application"}}, {"model": "auth.permission", "pk": 358, "fields": {"name": "Can change application", "content_type": 120, "codename": "change_application"}}, {"model": "auth.permission", "pk": 359, "fields": {"name": "Can delete application", "content_type": 120, "codename": "delete_application"}}, {"model": "auth.permission", "pk": 360, "fields": {"name": "Can add grant", "content_type": 121, "codename": "add_grant"}}, {"model": "auth.permission", "pk": 361, "fields": {"name": "Can change grant", "content_type": 121, "codename": "change_grant"}}, {"model": "auth.permission", "pk": 362, "fields": {"name": "Can delete grant", "content_type": 121, "codename": "delete_grant"}}, {"model": "auth.permission", "pk": 363, "fields": {"name": "Can add access token", "content_type": 122, "codename": "add_accesstoken"}}, {"model": "auth.permission", "pk": 364, "fields": {"name": "Can change access token", "content_type": 122, "codename": "change_accesstoken"}}, {"model": "auth.permission", "pk": 365, "fields": {"name": "Can delete access token", "content_type": 122, "codename": "delete_accesstoken"}}, {"model": "auth.permission", "pk": 366, "fields": {"name": "Can add refresh token", "content_type": 123, "codename": "add_refreshtoken"}}, {"model": "auth.permission", "pk": 367, "fields": {"name": "Can change refresh token", "content_type": 123, "codename": "change_refreshtoken"}}, {"model": "auth.permission", "pk": 368, "fields": {"name": "Can delete refresh token", "content_type": 123, "codename": "delete_refreshtoken"}}, {"model": "auth.permission", "pk": 369, "fields": {"name": "Can add restricted application", "content_type": 124, "codename": "add_restrictedapplication"}}, {"model": "auth.permission", "pk": 370, "fields": {"name": "Can change restricted application", "content_type": 124, "codename": "change_restrictedapplication"}}, {"model": "auth.permission", "pk": 371, "fields": {"name": "Can delete restricted application", "content_type": 124, "codename": "delete_restrictedapplication"}}, {"model": "auth.permission", "pk": 372, "fields": {"name": "Can add Provider Configuration (OAuth)", "content_type": 125, "codename": "add_oauth2providerconfig"}}, {"model": "auth.permission", "pk": 373, "fields": {"name": "Can change Provider Configuration (OAuth)", "content_type": 125, "codename": "change_oauth2providerconfig"}}, {"model": "auth.permission", "pk": 374, "fields": {"name": "Can delete Provider Configuration (OAuth)", "content_type": 125, "codename": "delete_oauth2providerconfig"}}, {"model": "auth.permission", "pk": 375, "fields": {"name": "Can add Provider Configuration (SAML IdP)", "content_type": 126, "codename": "add_samlproviderconfig"}}, {"model": "auth.permission", "pk": 376, "fields": {"name": "Can change Provider Configuration (SAML IdP)", "content_type": 126, "codename": "change_samlproviderconfig"}}, {"model": "auth.permission", "pk": 377, "fields": {"name": "Can delete Provider Configuration (SAML IdP)", "content_type": 126, "codename": "delete_samlproviderconfig"}}, {"model": "auth.permission", "pk": 378, "fields": {"name": "Can add SAML Configuration", "content_type": 127, "codename": "add_samlconfiguration"}}, {"model": "auth.permission", "pk": 379, "fields": {"name": "Can change SAML Configuration", "content_type": 127, "codename": "change_samlconfiguration"}}, {"model": "auth.permission", "pk": 380, "fields": {"name": "Can delete SAML Configuration", "content_type": 127, "codename": "delete_samlconfiguration"}}, {"model": "auth.permission", "pk": 381, "fields": {"name": "Can add SAML Provider Data", "content_type": 128, "codename": "add_samlproviderdata"}}, {"model": "auth.permission", "pk": 382, "fields": {"name": "Can change SAML Provider Data", "content_type": 128, "codename": "change_samlproviderdata"}}, {"model": "auth.permission", "pk": 383, "fields": {"name": "Can delete SAML Provider Data", "content_type": 128, "codename": "delete_samlproviderdata"}}, {"model": "auth.permission", "pk": 384, "fields": {"name": "Can add Provider Configuration (LTI)", "content_type": 129, "codename": "add_ltiproviderconfig"}}, {"model": "auth.permission", "pk": 385, "fields": {"name": "Can change Provider Configuration (LTI)", "content_type": 129, "codename": "change_ltiproviderconfig"}}, {"model": "auth.permission", "pk": 386, "fields": {"name": "Can delete Provider Configuration (LTI)", "content_type": 129, "codename": "delete_ltiproviderconfig"}}, {"model": "auth.permission", "pk": 387, "fields": {"name": "Can add Provider API Permission", "content_type": 130, "codename": "add_providerapipermissions"}}, {"model": "auth.permission", "pk": 388, "fields": {"name": "Can change Provider API Permission", "content_type": 130, "codename": "change_providerapipermissions"}}, {"model": "auth.permission", "pk": 389, "fields": {"name": "Can delete Provider API Permission", "content_type": 130, "codename": "delete_providerapipermissions"}}, {"model": "auth.permission", "pk": 390, "fields": {"name": "Can add nonce", "content_type": 131, "codename": "add_nonce"}}, {"model": "auth.permission", "pk": 391, "fields": {"name": "Can change nonce", "content_type": 131, "codename": "change_nonce"}}, {"model": "auth.permission", "pk": 392, "fields": {"name": "Can delete nonce", "content_type": 131, "codename": "delete_nonce"}}, {"model": "auth.permission", "pk": 393, "fields": {"name": "Can add scope", "content_type": 132, "codename": "add_scope"}}, {"model": "auth.permission", "pk": 394, "fields": {"name": "Can change scope", "content_type": 132, "codename": "change_scope"}}, {"model": "auth.permission", "pk": 395, "fields": {"name": "Can delete scope", "content_type": 132, "codename": "delete_scope"}}, {"model": "auth.permission", "pk": 396, "fields": {"name": "Can add resource", "content_type": 132, "codename": "add_resource"}}, {"model": "auth.permission", "pk": 397, "fields": {"name": "Can change resource", "content_type": 132, "codename": "change_resource"}}, {"model": "auth.permission", "pk": 398, "fields": {"name": "Can delete resource", "content_type": 132, "codename": "delete_resource"}}, {"model": "auth.permission", "pk": 399, "fields": {"name": "Can add consumer", "content_type": 133, "codename": "add_consumer"}}, {"model": "auth.permission", "pk": 400, "fields": {"name": "Can change consumer", "content_type": 133, "codename": "change_consumer"}}, {"model": "auth.permission", "pk": 401, "fields": {"name": "Can delete consumer", "content_type": 133, "codename": "delete_consumer"}}, {"model": "auth.permission", "pk": 402, "fields": {"name": "Can add token", "content_type": 134, "codename": "add_token"}}, {"model": "auth.permission", "pk": 403, "fields": {"name": "Can change token", "content_type": 134, "codename": "change_token"}}, {"model": "auth.permission", "pk": 404, "fields": {"name": "Can delete token", "content_type": 134, "codename": "delete_token"}}, {"model": "auth.permission", "pk": 405, "fields": {"name": "Can add article", "content_type": 136, "codename": "add_article"}}, {"model": "auth.permission", "pk": 406, "fields": {"name": "Can change article", "content_type": 136, "codename": "change_article"}}, {"model": "auth.permission", "pk": 407, "fields": {"name": "Can delete article", "content_type": 136, "codename": "delete_article"}}, {"model": "auth.permission", "pk": 408, "fields": {"name": "Can edit all articles and lock/unlock/restore", "content_type": 136, "codename": "moderate"}}, {"model": "auth.permission", "pk": 409, "fields": {"name": "Can change ownership of any article", "content_type": 136, "codename": "assign"}}, {"model": "auth.permission", "pk": 410, "fields": {"name": "Can assign permissions to other users", "content_type": 136, "codename": "grant"}}, {"model": "auth.permission", "pk": 411, "fields": {"name": "Can add Article for object", "content_type": 137, "codename": "add_articleforobject"}}, {"model": "auth.permission", "pk": 412, "fields": {"name": "Can change Article for object", "content_type": 137, "codename": "change_articleforobject"}}, {"model": "auth.permission", "pk": 413, "fields": {"name": "Can delete Article for object", "content_type": 137, "codename": "delete_articleforobject"}}, {"model": "auth.permission", "pk": 414, "fields": {"name": "Can add article revision", "content_type": 138, "codename": "add_articlerevision"}}, {"model": "auth.permission", "pk": 415, "fields": {"name": "Can change article revision", "content_type": 138, "codename": "change_articlerevision"}}, {"model": "auth.permission", "pk": 416, "fields": {"name": "Can delete article revision", "content_type": 138, "codename": "delete_articlerevision"}}, {"model": "auth.permission", "pk": 417, "fields": {"name": "Can add article plugin", "content_type": 139, "codename": "add_articleplugin"}}, {"model": "auth.permission", "pk": 418, "fields": {"name": "Can change article plugin", "content_type": 139, "codename": "change_articleplugin"}}, {"model": "auth.permission", "pk": 419, "fields": {"name": "Can delete article plugin", "content_type": 139, "codename": "delete_articleplugin"}}, {"model": "auth.permission", "pk": 420, "fields": {"name": "Can add reusable plugin", "content_type": 140, "codename": "add_reusableplugin"}}, {"model": "auth.permission", "pk": 421, "fields": {"name": "Can change reusable plugin", "content_type": 140, "codename": "change_reusableplugin"}}, {"model": "auth.permission", "pk": 422, "fields": {"name": "Can delete reusable plugin", "content_type": 140, "codename": "delete_reusableplugin"}}, {"model": "auth.permission", "pk": 423, "fields": {"name": "Can add simple plugin", "content_type": 141, "codename": "add_simpleplugin"}}, {"model": "auth.permission", "pk": 424, "fields": {"name": "Can change simple plugin", "content_type": 141, "codename": "change_simpleplugin"}}, {"model": "auth.permission", "pk": 425, "fields": {"name": "Can delete simple plugin", "content_type": 141, "codename": "delete_simpleplugin"}}, {"model": "auth.permission", "pk": 426, "fields": {"name": "Can add revision plugin", "content_type": 142, "codename": "add_revisionplugin"}}, {"model": "auth.permission", "pk": 427, "fields": {"name": "Can change revision plugin", "content_type": 142, "codename": "change_revisionplugin"}}, {"model": "auth.permission", "pk": 428, "fields": {"name": "Can delete revision plugin", "content_type": 142, "codename": "delete_revisionplugin"}}, {"model": "auth.permission", "pk": 429, "fields": {"name": "Can add revision plugin revision", "content_type": 143, "codename": "add_revisionpluginrevision"}}, {"model": "auth.permission", "pk": 430, "fields": {"name": "Can change revision plugin revision", "content_type": 143, "codename": "change_revisionpluginrevision"}}, {"model": "auth.permission", "pk": 431, "fields": {"name": "Can delete revision plugin revision", "content_type": 143, "codename": "delete_revisionpluginrevision"}}, {"model": "auth.permission", "pk": 432, "fields": {"name": "Can add URL path", "content_type": 144, "codename": "add_urlpath"}}, {"model": "auth.permission", "pk": 433, "fields": {"name": "Can change URL path", "content_type": 144, "codename": "change_urlpath"}}, {"model": "auth.permission", "pk": 434, "fields": {"name": "Can delete URL path", "content_type": 144, "codename": "delete_urlpath"}}, {"model": "auth.permission", "pk": 435, "fields": {"name": "Can add type", "content_type": 145, "codename": "add_notificationtype"}}, {"model": "auth.permission", "pk": 436, "fields": {"name": "Can change type", "content_type": 145, "codename": "change_notificationtype"}}, {"model": "auth.permission", "pk": 437, "fields": {"name": "Can delete type", "content_type": 145, "codename": "delete_notificationtype"}}, {"model": "auth.permission", "pk": 438, "fields": {"name": "Can add settings", "content_type": 146, "codename": "add_settings"}}, {"model": "auth.permission", "pk": 439, "fields": {"name": "Can change settings", "content_type": 146, "codename": "change_settings"}}, {"model": "auth.permission", "pk": 440, "fields": {"name": "Can delete settings", "content_type": 146, "codename": "delete_settings"}}, {"model": "auth.permission", "pk": 441, "fields": {"name": "Can add subscription", "content_type": 147, "codename": "add_subscription"}}, {"model": "auth.permission", "pk": 442, "fields": {"name": "Can change subscription", "content_type": 147, "codename": "change_subscription"}}, {"model": "auth.permission", "pk": 443, "fields": {"name": "Can delete subscription", "content_type": 147, "codename": "delete_subscription"}}, {"model": "auth.permission", "pk": 444, "fields": {"name": "Can add notification", "content_type": 148, "codename": "add_notification"}}, {"model": "auth.permission", "pk": 445, "fields": {"name": "Can change notification", "content_type": 148, "codename": "change_notification"}}, {"model": "auth.permission", "pk": 446, "fields": {"name": "Can delete notification", "content_type": 148, "codename": "delete_notification"}}, {"model": "auth.permission", "pk": 447, "fields": {"name": "Can add log entry", "content_type": 149, "codename": "add_logentry"}}, {"model": "auth.permission", "pk": 448, "fields": {"name": "Can change log entry", "content_type": 149, "codename": "change_logentry"}}, {"model": "auth.permission", "pk": 449, "fields": {"name": "Can delete log entry", "content_type": 149, "codename": "delete_logentry"}}, {"model": "auth.permission", "pk": 450, "fields": {"name": "Can add role", "content_type": 150, "codename": "add_role"}}, {"model": "auth.permission", "pk": 451, "fields": {"name": "Can change role", "content_type": 150, "codename": "change_role"}}, {"model": "auth.permission", "pk": 452, "fields": {"name": "Can delete role", "content_type": 150, "codename": "delete_role"}}, {"model": "auth.permission", "pk": 453, "fields": {"name": "Can add permission", "content_type": 151, "codename": "add_permission"}}, {"model": "auth.permission", "pk": 454, "fields": {"name": "Can change permission", "content_type": 151, "codename": "change_permission"}}, {"model": "auth.permission", "pk": 455, "fields": {"name": "Can delete permission", "content_type": 151, "codename": "delete_permission"}}, {"model": "auth.permission", "pk": 456, "fields": {"name": "Can add forums config", "content_type": 152, "codename": "add_forumsconfig"}}, {"model": "auth.permission", "pk": 457, "fields": {"name": "Can change forums config", "content_type": 152, "codename": "change_forumsconfig"}}, {"model": "auth.permission", "pk": 458, "fields": {"name": "Can delete forums config", "content_type": 152, "codename": "delete_forumsconfig"}}, {"model": "auth.permission", "pk": 459, "fields": {"name": "Can add course discussion settings", "content_type": 153, "codename": "add_coursediscussionsettings"}}, {"model": "auth.permission", "pk": 460, "fields": {"name": "Can change course discussion settings", "content_type": 153, "codename": "change_coursediscussionsettings"}}, {"model": "auth.permission", "pk": 461, "fields": {"name": "Can delete course discussion settings", "content_type": 153, "codename": "delete_coursediscussionsettings"}}, {"model": "auth.permission", "pk": 462, "fields": {"name": "Can add note", "content_type": 154, "codename": "add_note"}}, {"model": "auth.permission", "pk": 463, "fields": {"name": "Can change note", "content_type": 154, "codename": "change_note"}}, {"model": "auth.permission", "pk": 464, "fields": {"name": "Can delete note", "content_type": 154, "codename": "delete_note"}}, {"model": "auth.permission", "pk": 465, "fields": {"name": "Can add splash config", "content_type": 155, "codename": "add_splashconfig"}}, {"model": "auth.permission", "pk": 466, "fields": {"name": "Can change splash config", "content_type": 155, "codename": "change_splashconfig"}}, {"model": "auth.permission", "pk": 467, "fields": {"name": "Can delete splash config", "content_type": 155, "codename": "delete_splashconfig"}}, {"model": "auth.permission", "pk": 468, "fields": {"name": "Can add user preference", "content_type": 156, "codename": "add_userpreference"}}, {"model": "auth.permission", "pk": 469, "fields": {"name": "Can change user preference", "content_type": 156, "codename": "change_userpreference"}}, {"model": "auth.permission", "pk": 470, "fields": {"name": "Can delete user preference", "content_type": 156, "codename": "delete_userpreference"}}, {"model": "auth.permission", "pk": 471, "fields": {"name": "Can add user course tag", "content_type": 157, "codename": "add_usercoursetag"}}, {"model": "auth.permission", "pk": 472, "fields": {"name": "Can change user course tag", "content_type": 157, "codename": "change_usercoursetag"}}, {"model": "auth.permission", "pk": 473, "fields": {"name": "Can delete user course tag", "content_type": 157, "codename": "delete_usercoursetag"}}, {"model": "auth.permission", "pk": 474, "fields": {"name": "Can add user org tag", "content_type": 158, "codename": "add_userorgtag"}}, {"model": "auth.permission", "pk": 475, "fields": {"name": "Can change user org tag", "content_type": 158, "codename": "change_userorgtag"}}, {"model": "auth.permission", "pk": 476, "fields": {"name": "Can delete user org tag", "content_type": 158, "codename": "delete_userorgtag"}}, {"model": "auth.permission", "pk": 477, "fields": {"name": "Can add order", "content_type": 159, "codename": "add_order"}}, {"model": "auth.permission", "pk": 478, "fields": {"name": "Can change order", "content_type": 159, "codename": "change_order"}}, {"model": "auth.permission", "pk": 479, "fields": {"name": "Can delete order", "content_type": 159, "codename": "delete_order"}}, {"model": "auth.permission", "pk": 480, "fields": {"name": "Can add order item", "content_type": 160, "codename": "add_orderitem"}}, {"model": "auth.permission", "pk": 481, "fields": {"name": "Can change order item", "content_type": 160, "codename": "change_orderitem"}}, {"model": "auth.permission", "pk": 482, "fields": {"name": "Can delete order item", "content_type": 160, "codename": "delete_orderitem"}}, {"model": "auth.permission", "pk": 483, "fields": {"name": "Can add invoice", "content_type": 161, "codename": "add_invoice"}}, {"model": "auth.permission", "pk": 484, "fields": {"name": "Can change invoice", "content_type": 161, "codename": "change_invoice"}}, {"model": "auth.permission", "pk": 485, "fields": {"name": "Can delete invoice", "content_type": 161, "codename": "delete_invoice"}}, {"model": "auth.permission", "pk": 486, "fields": {"name": "Can add invoice transaction", "content_type": 162, "codename": "add_invoicetransaction"}}, {"model": "auth.permission", "pk": 487, "fields": {"name": "Can change invoice transaction", "content_type": 162, "codename": "change_invoicetransaction"}}, {"model": "auth.permission", "pk": 488, "fields": {"name": "Can delete invoice transaction", "content_type": 162, "codename": "delete_invoicetransaction"}}, {"model": "auth.permission", "pk": 489, "fields": {"name": "Can add invoice item", "content_type": 163, "codename": "add_invoiceitem"}}, {"model": "auth.permission", "pk": 490, "fields": {"name": "Can change invoice item", "content_type": 163, "codename": "change_invoiceitem"}}, {"model": "auth.permission", "pk": 491, "fields": {"name": "Can delete invoice item", "content_type": 163, "codename": "delete_invoiceitem"}}, {"model": "auth.permission", "pk": 492, "fields": {"name": "Can add course registration code invoice item", "content_type": 164, "codename": "add_courseregistrationcodeinvoiceitem"}}, {"model": "auth.permission", "pk": 493, "fields": {"name": "Can change course registration code invoice item", "content_type": 164, "codename": "change_courseregistrationcodeinvoiceitem"}}, {"model": "auth.permission", "pk": 494, "fields": {"name": "Can delete course registration code invoice item", "content_type": 164, "codename": "delete_courseregistrationcodeinvoiceitem"}}, {"model": "auth.permission", "pk": 495, "fields": {"name": "Can add invoice history", "content_type": 165, "codename": "add_invoicehistory"}}, {"model": "auth.permission", "pk": 496, "fields": {"name": "Can change invoice history", "content_type": 165, "codename": "change_invoicehistory"}}, {"model": "auth.permission", "pk": 497, "fields": {"name": "Can delete invoice history", "content_type": 165, "codename": "delete_invoicehistory"}}, {"model": "auth.permission", "pk": 498, "fields": {"name": "Can add course registration code", "content_type": 166, "codename": "add_courseregistrationcode"}}, {"model": "auth.permission", "pk": 499, "fields": {"name": "Can change course registration code", "content_type": 166, "codename": "change_courseregistrationcode"}}, {"model": "auth.permission", "pk": 500, "fields": {"name": "Can delete course registration code", "content_type": 166, "codename": "delete_courseregistrationcode"}}, {"model": "auth.permission", "pk": 501, "fields": {"name": "Can add registration code redemption", "content_type": 167, "codename": "add_registrationcoderedemption"}}, {"model": "auth.permission", "pk": 502, "fields": {"name": "Can change registration code redemption", "content_type": 167, "codename": "change_registrationcoderedemption"}}, {"model": "auth.permission", "pk": 503, "fields": {"name": "Can delete registration code redemption", "content_type": 167, "codename": "delete_registrationcoderedemption"}}, {"model": "auth.permission", "pk": 504, "fields": {"name": "Can add coupon", "content_type": 168, "codename": "add_coupon"}}, {"model": "auth.permission", "pk": 505, "fields": {"name": "Can change coupon", "content_type": 168, "codename": "change_coupon"}}, {"model": "auth.permission", "pk": 506, "fields": {"name": "Can delete coupon", "content_type": 168, "codename": "delete_coupon"}}, {"model": "auth.permission", "pk": 507, "fields": {"name": "Can add coupon redemption", "content_type": 169, "codename": "add_couponredemption"}}, {"model": "auth.permission", "pk": 508, "fields": {"name": "Can change coupon redemption", "content_type": 169, "codename": "change_couponredemption"}}, {"model": "auth.permission", "pk": 509, "fields": {"name": "Can delete coupon redemption", "content_type": 169, "codename": "delete_couponredemption"}}, {"model": "auth.permission", "pk": 510, "fields": {"name": "Can add paid course registration", "content_type": 170, "codename": "add_paidcourseregistration"}}, {"model": "auth.permission", "pk": 511, "fields": {"name": "Can change paid course registration", "content_type": 170, "codename": "change_paidcourseregistration"}}, {"model": "auth.permission", "pk": 512, "fields": {"name": "Can delete paid course registration", "content_type": 170, "codename": "delete_paidcourseregistration"}}, {"model": "auth.permission", "pk": 513, "fields": {"name": "Can add course reg code item", "content_type": 171, "codename": "add_courseregcodeitem"}}, {"model": "auth.permission", "pk": 514, "fields": {"name": "Can change course reg code item", "content_type": 171, "codename": "change_courseregcodeitem"}}, {"model": "auth.permission", "pk": 515, "fields": {"name": "Can delete course reg code item", "content_type": 171, "codename": "delete_courseregcodeitem"}}, {"model": "auth.permission", "pk": 516, "fields": {"name": "Can add course reg code item annotation", "content_type": 172, "codename": "add_courseregcodeitemannotation"}}, {"model": "auth.permission", "pk": 517, "fields": {"name": "Can change course reg code item annotation", "content_type": 172, "codename": "change_courseregcodeitemannotation"}}, {"model": "auth.permission", "pk": 518, "fields": {"name": "Can delete course reg code item annotation", "content_type": 172, "codename": "delete_courseregcodeitemannotation"}}, {"model": "auth.permission", "pk": 519, "fields": {"name": "Can add paid course registration annotation", "content_type": 173, "codename": "add_paidcourseregistrationannotation"}}, {"model": "auth.permission", "pk": 520, "fields": {"name": "Can change paid course registration annotation", "content_type": 173, "codename": "change_paidcourseregistrationannotation"}}, {"model": "auth.permission", "pk": 521, "fields": {"name": "Can delete paid course registration annotation", "content_type": 173, "codename": "delete_paidcourseregistrationannotation"}}, {"model": "auth.permission", "pk": 522, "fields": {"name": "Can add certificate item", "content_type": 174, "codename": "add_certificateitem"}}, {"model": "auth.permission", "pk": 523, "fields": {"name": "Can change certificate item", "content_type": 174, "codename": "change_certificateitem"}}, {"model": "auth.permission", "pk": 524, "fields": {"name": "Can delete certificate item", "content_type": 174, "codename": "delete_certificateitem"}}, {"model": "auth.permission", "pk": 525, "fields": {"name": "Can add donation configuration", "content_type": 175, "codename": "add_donationconfiguration"}}, {"model": "auth.permission", "pk": 526, "fields": {"name": "Can change donation configuration", "content_type": 175, "codename": "change_donationconfiguration"}}, {"model": "auth.permission", "pk": 527, "fields": {"name": "Can delete donation configuration", "content_type": 175, "codename": "delete_donationconfiguration"}}, {"model": "auth.permission", "pk": 528, "fields": {"name": "Can add donation", "content_type": 176, "codename": "add_donation"}}, {"model": "auth.permission", "pk": 529, "fields": {"name": "Can change donation", "content_type": 176, "codename": "change_donation"}}, {"model": "auth.permission", "pk": 530, "fields": {"name": "Can delete donation", "content_type": 176, "codename": "delete_donation"}}, {"model": "auth.permission", "pk": 531, "fields": {"name": "Can add course mode", "content_type": 177, "codename": "add_coursemode"}}, {"model": "auth.permission", "pk": 532, "fields": {"name": "Can change course mode", "content_type": 177, "codename": "change_coursemode"}}, {"model": "auth.permission", "pk": 533, "fields": {"name": "Can delete course mode", "content_type": 177, "codename": "delete_coursemode"}}, {"model": "auth.permission", "pk": 534, "fields": {"name": "Can add course modes archive", "content_type": 178, "codename": "add_coursemodesarchive"}}, {"model": "auth.permission", "pk": 535, "fields": {"name": "Can change course modes archive", "content_type": 178, "codename": "change_coursemodesarchive"}}, {"model": "auth.permission", "pk": 536, "fields": {"name": "Can delete course modes archive", "content_type": 178, "codename": "delete_coursemodesarchive"}}, {"model": "auth.permission", "pk": 537, "fields": {"name": "Can add course mode expiration config", "content_type": 179, "codename": "add_coursemodeexpirationconfig"}}, {"model": "auth.permission", "pk": 538, "fields": {"name": "Can change course mode expiration config", "content_type": 179, "codename": "change_coursemodeexpirationconfig"}}, {"model": "auth.permission", "pk": 539, "fields": {"name": "Can delete course mode expiration config", "content_type": 179, "codename": "delete_coursemodeexpirationconfig"}}, {"model": "auth.permission", "pk": 540, "fields": {"name": "Can add course entitlement", "content_type": 180, "codename": "add_courseentitlement"}}, {"model": "auth.permission", "pk": 541, "fields": {"name": "Can change course entitlement", "content_type": 180, "codename": "change_courseentitlement"}}, {"model": "auth.permission", "pk": 542, "fields": {"name": "Can delete course entitlement", "content_type": 180, "codename": "delete_courseentitlement"}}, {"model": "auth.permission", "pk": 543, "fields": {"name": "Can add software secure photo verification", "content_type": 181, "codename": "add_softwaresecurephotoverification"}}, {"model": "auth.permission", "pk": 544, "fields": {"name": "Can change software secure photo verification", "content_type": 181, "codename": "change_softwaresecurephotoverification"}}, {"model": "auth.permission", "pk": 545, "fields": {"name": "Can delete software secure photo verification", "content_type": 181, "codename": "delete_softwaresecurephotoverification"}}, {"model": "auth.permission", "pk": 546, "fields": {"name": "Can add verification deadline", "content_type": 182, "codename": "add_verificationdeadline"}}, {"model": "auth.permission", "pk": 547, "fields": {"name": "Can change verification deadline", "content_type": 182, "codename": "change_verificationdeadline"}}, {"model": "auth.permission", "pk": 548, "fields": {"name": "Can delete verification deadline", "content_type": 182, "codename": "delete_verificationdeadline"}}, {"model": "auth.permission", "pk": 549, "fields": {"name": "Can add verification checkpoint", "content_type": 183, "codename": "add_verificationcheckpoint"}}, {"model": "auth.permission", "pk": 550, "fields": {"name": "Can change verification checkpoint", "content_type": 183, "codename": "change_verificationcheckpoint"}}, {"model": "auth.permission", "pk": 551, "fields": {"name": "Can delete verification checkpoint", "content_type": 183, "codename": "delete_verificationcheckpoint"}}, {"model": "auth.permission", "pk": 552, "fields": {"name": "Can add Verification Status", "content_type": 184, "codename": "add_verificationstatus"}}, {"model": "auth.permission", "pk": 553, "fields": {"name": "Can change Verification Status", "content_type": 184, "codename": "change_verificationstatus"}}, {"model": "auth.permission", "pk": 554, "fields": {"name": "Can delete Verification Status", "content_type": 184, "codename": "delete_verificationstatus"}}, {"model": "auth.permission", "pk": 555, "fields": {"name": "Can add in course reverification configuration", "content_type": 185, "codename": "add_incoursereverificationconfiguration"}}, {"model": "auth.permission", "pk": 556, "fields": {"name": "Can change in course reverification configuration", "content_type": 185, "codename": "change_incoursereverificationconfiguration"}}, {"model": "auth.permission", "pk": 557, "fields": {"name": "Can delete in course reverification configuration", "content_type": 185, "codename": "delete_incoursereverificationconfiguration"}}, {"model": "auth.permission", "pk": 558, "fields": {"name": "Can add icrv status emails configuration", "content_type": 186, "codename": "add_icrvstatusemailsconfiguration"}}, {"model": "auth.permission", "pk": 559, "fields": {"name": "Can change icrv status emails configuration", "content_type": 186, "codename": "change_icrvstatusemailsconfiguration"}}, {"model": "auth.permission", "pk": 560, "fields": {"name": "Can delete icrv status emails configuration", "content_type": 186, "codename": "delete_icrvstatusemailsconfiguration"}}, {"model": "auth.permission", "pk": 561, "fields": {"name": "Can add skipped reverification", "content_type": 187, "codename": "add_skippedreverification"}}, {"model": "auth.permission", "pk": 562, "fields": {"name": "Can change skipped reverification", "content_type": 187, "codename": "change_skippedreverification"}}, {"model": "auth.permission", "pk": 563, "fields": {"name": "Can delete skipped reverification", "content_type": 187, "codename": "delete_skippedreverification"}}, {"model": "auth.permission", "pk": 564, "fields": {"name": "Can add dark lang config", "content_type": 188, "codename": "add_darklangconfig"}}, {"model": "auth.permission", "pk": 565, "fields": {"name": "Can change dark lang config", "content_type": 188, "codename": "change_darklangconfig"}}, {"model": "auth.permission", "pk": 566, "fields": {"name": "Can delete dark lang config", "content_type": 188, "codename": "delete_darklangconfig"}}, {"model": "auth.permission", "pk": 567, "fields": {"name": "Can add microsite", "content_type": 189, "codename": "add_microsite"}}, {"model": "auth.permission", "pk": 568, "fields": {"name": "Can change microsite", "content_type": 189, "codename": "change_microsite"}}, {"model": "auth.permission", "pk": 569, "fields": {"name": "Can delete microsite", "content_type": 189, "codename": "delete_microsite"}}, {"model": "auth.permission", "pk": 570, "fields": {"name": "Can add microsite history", "content_type": 190, "codename": "add_micrositehistory"}}, {"model": "auth.permission", "pk": 571, "fields": {"name": "Can change microsite history", "content_type": 190, "codename": "change_micrositehistory"}}, {"model": "auth.permission", "pk": 572, "fields": {"name": "Can delete microsite history", "content_type": 190, "codename": "delete_micrositehistory"}}, {"model": "auth.permission", "pk": 573, "fields": {"name": "Can add microsite organization mapping", "content_type": 191, "codename": "add_micrositeorganizationmapping"}}, {"model": "auth.permission", "pk": 574, "fields": {"name": "Can change microsite organization mapping", "content_type": 191, "codename": "change_micrositeorganizationmapping"}}, {"model": "auth.permission", "pk": 575, "fields": {"name": "Can delete microsite organization mapping", "content_type": 191, "codename": "delete_micrositeorganizationmapping"}}, {"model": "auth.permission", "pk": 576, "fields": {"name": "Can add microsite template", "content_type": 192, "codename": "add_micrositetemplate"}}, {"model": "auth.permission", "pk": 577, "fields": {"name": "Can change microsite template", "content_type": 192, "codename": "change_micrositetemplate"}}, {"model": "auth.permission", "pk": 578, "fields": {"name": "Can delete microsite template", "content_type": 192, "codename": "delete_micrositetemplate"}}, {"model": "auth.permission", "pk": 579, "fields": {"name": "Can add whitelisted rss url", "content_type": 193, "codename": "add_whitelistedrssurl"}}, {"model": "auth.permission", "pk": 580, "fields": {"name": "Can change whitelisted rss url", "content_type": 193, "codename": "change_whitelistedrssurl"}}, {"model": "auth.permission", "pk": 581, "fields": {"name": "Can delete whitelisted rss url", "content_type": 193, "codename": "delete_whitelistedrssurl"}}, {"model": "auth.permission", "pk": 582, "fields": {"name": "Can add embargoed course", "content_type": 194, "codename": "add_embargoedcourse"}}, {"model": "auth.permission", "pk": 583, "fields": {"name": "Can change embargoed course", "content_type": 194, "codename": "change_embargoedcourse"}}, {"model": "auth.permission", "pk": 584, "fields": {"name": "Can delete embargoed course", "content_type": 194, "codename": "delete_embargoedcourse"}}, {"model": "auth.permission", "pk": 585, "fields": {"name": "Can add embargoed state", "content_type": 195, "codename": "add_embargoedstate"}}, {"model": "auth.permission", "pk": 586, "fields": {"name": "Can change embargoed state", "content_type": 195, "codename": "change_embargoedstate"}}, {"model": "auth.permission", "pk": 587, "fields": {"name": "Can delete embargoed state", "content_type": 195, "codename": "delete_embargoedstate"}}, {"model": "auth.permission", "pk": 588, "fields": {"name": "Can add restricted course", "content_type": 196, "codename": "add_restrictedcourse"}}, {"model": "auth.permission", "pk": 589, "fields": {"name": "Can change restricted course", "content_type": 196, "codename": "change_restrictedcourse"}}, {"model": "auth.permission", "pk": 590, "fields": {"name": "Can delete restricted course", "content_type": 196, "codename": "delete_restrictedcourse"}}, {"model": "auth.permission", "pk": 591, "fields": {"name": "Can add country", "content_type": 197, "codename": "add_country"}}, {"model": "auth.permission", "pk": 592, "fields": {"name": "Can change country", "content_type": 197, "codename": "change_country"}}, {"model": "auth.permission", "pk": 593, "fields": {"name": "Can delete country", "content_type": 197, "codename": "delete_country"}}, {"model": "auth.permission", "pk": 594, "fields": {"name": "Can add country access rule", "content_type": 198, "codename": "add_countryaccessrule"}}, {"model": "auth.permission", "pk": 595, "fields": {"name": "Can change country access rule", "content_type": 198, "codename": "change_countryaccessrule"}}, {"model": "auth.permission", "pk": 596, "fields": {"name": "Can delete country access rule", "content_type": 198, "codename": "delete_countryaccessrule"}}, {"model": "auth.permission", "pk": 597, "fields": {"name": "Can add course access rule history", "content_type": 199, "codename": "add_courseaccessrulehistory"}}, {"model": "auth.permission", "pk": 598, "fields": {"name": "Can change course access rule history", "content_type": 199, "codename": "change_courseaccessrulehistory"}}, {"model": "auth.permission", "pk": 599, "fields": {"name": "Can delete course access rule history", "content_type": 199, "codename": "delete_courseaccessrulehistory"}}, {"model": "auth.permission", "pk": 600, "fields": {"name": "Can add ip filter", "content_type": 200, "codename": "add_ipfilter"}}, {"model": "auth.permission", "pk": 601, "fields": {"name": "Can change ip filter", "content_type": 200, "codename": "change_ipfilter"}}, {"model": "auth.permission", "pk": 602, "fields": {"name": "Can delete ip filter", "content_type": 200, "codename": "delete_ipfilter"}}, {"model": "auth.permission", "pk": 603, "fields": {"name": "Can add course rerun state", "content_type": 201, "codename": "add_coursererunstate"}}, {"model": "auth.permission", "pk": 604, "fields": {"name": "Can change course rerun state", "content_type": 201, "codename": "change_coursererunstate"}}, {"model": "auth.permission", "pk": 605, "fields": {"name": "Can delete course rerun state", "content_type": 201, "codename": "delete_coursererunstate"}}, {"model": "auth.permission", "pk": 606, "fields": {"name": "Can add mobile api config", "content_type": 202, "codename": "add_mobileapiconfig"}}, {"model": "auth.permission", "pk": 607, "fields": {"name": "Can change mobile api config", "content_type": 202, "codename": "change_mobileapiconfig"}}, {"model": "auth.permission", "pk": 608, "fields": {"name": "Can delete mobile api config", "content_type": 202, "codename": "delete_mobileapiconfig"}}, {"model": "auth.permission", "pk": 609, "fields": {"name": "Can add app version config", "content_type": 203, "codename": "add_appversionconfig"}}, {"model": "auth.permission", "pk": 610, "fields": {"name": "Can change app version config", "content_type": 203, "codename": "change_appversionconfig"}}, {"model": "auth.permission", "pk": 611, "fields": {"name": "Can delete app version config", "content_type": 203, "codename": "delete_appversionconfig"}}, {"model": "auth.permission", "pk": 612, "fields": {"name": "Can add ignore mobile available flag config", "content_type": 204, "codename": "add_ignoremobileavailableflagconfig"}}, {"model": "auth.permission", "pk": 613, "fields": {"name": "Can change ignore mobile available flag config", "content_type": 204, "codename": "change_ignoremobileavailableflagconfig"}}, {"model": "auth.permission", "pk": 614, "fields": {"name": "Can delete ignore mobile available flag config", "content_type": 204, "codename": "delete_ignoremobileavailableflagconfig"}}, {"model": "auth.permission", "pk": 615, "fields": {"name": "Can add user social auth", "content_type": 205, "codename": "add_usersocialauth"}}, {"model": "auth.permission", "pk": 616, "fields": {"name": "Can change user social auth", "content_type": 205, "codename": "change_usersocialauth"}}, {"model": "auth.permission", "pk": 617, "fields": {"name": "Can delete user social auth", "content_type": 205, "codename": "delete_usersocialauth"}}, {"model": "auth.permission", "pk": 618, "fields": {"name": "Can add nonce", "content_type": 206, "codename": "add_nonce"}}, {"model": "auth.permission", "pk": 619, "fields": {"name": "Can change nonce", "content_type": 206, "codename": "change_nonce"}}, {"model": "auth.permission", "pk": 620, "fields": {"name": "Can delete nonce", "content_type": 206, "codename": "delete_nonce"}}, {"model": "auth.permission", "pk": 621, "fields": {"name": "Can add association", "content_type": 207, "codename": "add_association"}}, {"model": "auth.permission", "pk": 622, "fields": {"name": "Can change association", "content_type": 207, "codename": "change_association"}}, {"model": "auth.permission", "pk": 623, "fields": {"name": "Can delete association", "content_type": 207, "codename": "delete_association"}}, {"model": "auth.permission", "pk": 624, "fields": {"name": "Can add code", "content_type": 208, "codename": "add_code"}}, {"model": "auth.permission", "pk": 625, "fields": {"name": "Can change code", "content_type": 208, "codename": "change_code"}}, {"model": "auth.permission", "pk": 626, "fields": {"name": "Can delete code", "content_type": 208, "codename": "delete_code"}}, {"model": "auth.permission", "pk": 627, "fields": {"name": "Can add partial", "content_type": 209, "codename": "add_partial"}}, {"model": "auth.permission", "pk": 628, "fields": {"name": "Can change partial", "content_type": 209, "codename": "change_partial"}}, {"model": "auth.permission", "pk": 629, "fields": {"name": "Can delete partial", "content_type": 209, "codename": "delete_partial"}}, {"model": "auth.permission", "pk": 630, "fields": {"name": "Can add survey form", "content_type": 210, "codename": "add_surveyform"}}, {"model": "auth.permission", "pk": 631, "fields": {"name": "Can change survey form", "content_type": 210, "codename": "change_surveyform"}}, {"model": "auth.permission", "pk": 632, "fields": {"name": "Can delete survey form", "content_type": 210, "codename": "delete_surveyform"}}, {"model": "auth.permission", "pk": 633, "fields": {"name": "Can add survey answer", "content_type": 211, "codename": "add_surveyanswer"}}, {"model": "auth.permission", "pk": 634, "fields": {"name": "Can change survey answer", "content_type": 211, "codename": "change_surveyanswer"}}, {"model": "auth.permission", "pk": 635, "fields": {"name": "Can delete survey answer", "content_type": 211, "codename": "delete_surveyanswer"}}, {"model": "auth.permission", "pk": 636, "fields": {"name": "Can add x block asides config", "content_type": 212, "codename": "add_xblockasidesconfig"}}, {"model": "auth.permission", "pk": 637, "fields": {"name": "Can change x block asides config", "content_type": 212, "codename": "change_xblockasidesconfig"}}, {"model": "auth.permission", "pk": 638, "fields": {"name": "Can delete x block asides config", "content_type": 212, "codename": "delete_xblockasidesconfig"}}, {"model": "auth.permission", "pk": 639, "fields": {"name": "Can add answer", "content_type": 213, "codename": "add_answer"}}, {"model": "auth.permission", "pk": 640, "fields": {"name": "Can change answer", "content_type": 213, "codename": "change_answer"}}, {"model": "auth.permission", "pk": 641, "fields": {"name": "Can delete answer", "content_type": 213, "codename": "delete_answer"}}, {"model": "auth.permission", "pk": 642, "fields": {"name": "Can add share", "content_type": 214, "codename": "add_share"}}, {"model": "auth.permission", "pk": 643, "fields": {"name": "Can change share", "content_type": 214, "codename": "change_share"}}, {"model": "auth.permission", "pk": 644, "fields": {"name": "Can delete share", "content_type": 214, "codename": "delete_share"}}, {"model": "auth.permission", "pk": 645, "fields": {"name": "Can add student item", "content_type": 215, "codename": "add_studentitem"}}, {"model": "auth.permission", "pk": 646, "fields": {"name": "Can change student item", "content_type": 215, "codename": "change_studentitem"}}, {"model": "auth.permission", "pk": 647, "fields": {"name": "Can delete student item", "content_type": 215, "codename": "delete_studentitem"}}, {"model": "auth.permission", "pk": 648, "fields": {"name": "Can add submission", "content_type": 216, "codename": "add_submission"}}, {"model": "auth.permission", "pk": 649, "fields": {"name": "Can change submission", "content_type": 216, "codename": "change_submission"}}, {"model": "auth.permission", "pk": 650, "fields": {"name": "Can delete submission", "content_type": 216, "codename": "delete_submission"}}, {"model": "auth.permission", "pk": 651, "fields": {"name": "Can add score", "content_type": 217, "codename": "add_score"}}, {"model": "auth.permission", "pk": 652, "fields": {"name": "Can change score", "content_type": 217, "codename": "change_score"}}, {"model": "auth.permission", "pk": 653, "fields": {"name": "Can delete score", "content_type": 217, "codename": "delete_score"}}, {"model": "auth.permission", "pk": 654, "fields": {"name": "Can add score summary", "content_type": 218, "codename": "add_scoresummary"}}, {"model": "auth.permission", "pk": 655, "fields": {"name": "Can change score summary", "content_type": 218, "codename": "change_scoresummary"}}, {"model": "auth.permission", "pk": 656, "fields": {"name": "Can delete score summary", "content_type": 218, "codename": "delete_scoresummary"}}, {"model": "auth.permission", "pk": 657, "fields": {"name": "Can add score annotation", "content_type": 219, "codename": "add_scoreannotation"}}, {"model": "auth.permission", "pk": 658, "fields": {"name": "Can change score annotation", "content_type": 219, "codename": "change_scoreannotation"}}, {"model": "auth.permission", "pk": 659, "fields": {"name": "Can delete score annotation", "content_type": 219, "codename": "delete_scoreannotation"}}, {"model": "auth.permission", "pk": 660, "fields": {"name": "Can add rubric", "content_type": 220, "codename": "add_rubric"}}, {"model": "auth.permission", "pk": 661, "fields": {"name": "Can change rubric", "content_type": 220, "codename": "change_rubric"}}, {"model": "auth.permission", "pk": 662, "fields": {"name": "Can delete rubric", "content_type": 220, "codename": "delete_rubric"}}, {"model": "auth.permission", "pk": 663, "fields": {"name": "Can add criterion", "content_type": 221, "codename": "add_criterion"}}, {"model": "auth.permission", "pk": 664, "fields": {"name": "Can change criterion", "content_type": 221, "codename": "change_criterion"}}, {"model": "auth.permission", "pk": 665, "fields": {"name": "Can delete criterion", "content_type": 221, "codename": "delete_criterion"}}, {"model": "auth.permission", "pk": 666, "fields": {"name": "Can add criterion option", "content_type": 222, "codename": "add_criterionoption"}}, {"model": "auth.permission", "pk": 667, "fields": {"name": "Can change criterion option", "content_type": 222, "codename": "change_criterionoption"}}, {"model": "auth.permission", "pk": 668, "fields": {"name": "Can delete criterion option", "content_type": 222, "codename": "delete_criterionoption"}}, {"model": "auth.permission", "pk": 669, "fields": {"name": "Can add assessment", "content_type": 223, "codename": "add_assessment"}}, {"model": "auth.permission", "pk": 670, "fields": {"name": "Can change assessment", "content_type": 223, "codename": "change_assessment"}}, {"model": "auth.permission", "pk": 671, "fields": {"name": "Can delete assessment", "content_type": 223, "codename": "delete_assessment"}}, {"model": "auth.permission", "pk": 672, "fields": {"name": "Can add assessment part", "content_type": 224, "codename": "add_assessmentpart"}}, {"model": "auth.permission", "pk": 673, "fields": {"name": "Can change assessment part", "content_type": 224, "codename": "change_assessmentpart"}}, {"model": "auth.permission", "pk": 674, "fields": {"name": "Can delete assessment part", "content_type": 224, "codename": "delete_assessmentpart"}}, {"model": "auth.permission", "pk": 675, "fields": {"name": "Can add assessment feedback option", "content_type": 225, "codename": "add_assessmentfeedbackoption"}}, {"model": "auth.permission", "pk": 676, "fields": {"name": "Can change assessment feedback option", "content_type": 225, "codename": "change_assessmentfeedbackoption"}}, {"model": "auth.permission", "pk": 677, "fields": {"name": "Can delete assessment feedback option", "content_type": 225, "codename": "delete_assessmentfeedbackoption"}}, {"model": "auth.permission", "pk": 678, "fields": {"name": "Can add assessment feedback", "content_type": 226, "codename": "add_assessmentfeedback"}}, {"model": "auth.permission", "pk": 679, "fields": {"name": "Can change assessment feedback", "content_type": 226, "codename": "change_assessmentfeedback"}}, {"model": "auth.permission", "pk": 680, "fields": {"name": "Can delete assessment feedback", "content_type": 226, "codename": "delete_assessmentfeedback"}}, {"model": "auth.permission", "pk": 681, "fields": {"name": "Can add peer workflow", "content_type": 227, "codename": "add_peerworkflow"}}, {"model": "auth.permission", "pk": 682, "fields": {"name": "Can change peer workflow", "content_type": 227, "codename": "change_peerworkflow"}}, {"model": "auth.permission", "pk": 683, "fields": {"name": "Can delete peer workflow", "content_type": 227, "codename": "delete_peerworkflow"}}, {"model": "auth.permission", "pk": 684, "fields": {"name": "Can add peer workflow item", "content_type": 228, "codename": "add_peerworkflowitem"}}, {"model": "auth.permission", "pk": 685, "fields": {"name": "Can change peer workflow item", "content_type": 228, "codename": "change_peerworkflowitem"}}, {"model": "auth.permission", "pk": 686, "fields": {"name": "Can delete peer workflow item", "content_type": 228, "codename": "delete_peerworkflowitem"}}, {"model": "auth.permission", "pk": 687, "fields": {"name": "Can add training example", "content_type": 229, "codename": "add_trainingexample"}}, {"model": "auth.permission", "pk": 688, "fields": {"name": "Can change training example", "content_type": 229, "codename": "change_trainingexample"}}, {"model": "auth.permission", "pk": 689, "fields": {"name": "Can delete training example", "content_type": 229, "codename": "delete_trainingexample"}}, {"model": "auth.permission", "pk": 690, "fields": {"name": "Can add student training workflow", "content_type": 230, "codename": "add_studenttrainingworkflow"}}, {"model": "auth.permission", "pk": 691, "fields": {"name": "Can change student training workflow", "content_type": 230, "codename": "change_studenttrainingworkflow"}}, {"model": "auth.permission", "pk": 692, "fields": {"name": "Can delete student training workflow", "content_type": 230, "codename": "delete_studenttrainingworkflow"}}, {"model": "auth.permission", "pk": 693, "fields": {"name": "Can add student training workflow item", "content_type": 231, "codename": "add_studenttrainingworkflowitem"}}, {"model": "auth.permission", "pk": 694, "fields": {"name": "Can change student training workflow item", "content_type": 231, "codename": "change_studenttrainingworkflowitem"}}, {"model": "auth.permission", "pk": 695, "fields": {"name": "Can delete student training workflow item", "content_type": 231, "codename": "delete_studenttrainingworkflowitem"}}, {"model": "auth.permission", "pk": 696, "fields": {"name": "Can add staff workflow", "content_type": 232, "codename": "add_staffworkflow"}}, {"model": "auth.permission", "pk": 697, "fields": {"name": "Can change staff workflow", "content_type": 232, "codename": "change_staffworkflow"}}, {"model": "auth.permission", "pk": 698, "fields": {"name": "Can delete staff workflow", "content_type": 232, "codename": "delete_staffworkflow"}}, {"model": "auth.permission", "pk": 699, "fields": {"name": "Can add assessment workflow", "content_type": 233, "codename": "add_assessmentworkflow"}}, {"model": "auth.permission", "pk": 700, "fields": {"name": "Can change assessment workflow", "content_type": 233, "codename": "change_assessmentworkflow"}}, {"model": "auth.permission", "pk": 701, "fields": {"name": "Can delete assessment workflow", "content_type": 233, "codename": "delete_assessmentworkflow"}}, {"model": "auth.permission", "pk": 702, "fields": {"name": "Can add assessment workflow step", "content_type": 234, "codename": "add_assessmentworkflowstep"}}, {"model": "auth.permission", "pk": 703, "fields": {"name": "Can change assessment workflow step", "content_type": 234, "codename": "change_assessmentworkflowstep"}}, {"model": "auth.permission", "pk": 704, "fields": {"name": "Can delete assessment workflow step", "content_type": 234, "codename": "delete_assessmentworkflowstep"}}, {"model": "auth.permission", "pk": 705, "fields": {"name": "Can add assessment workflow cancellation", "content_type": 235, "codename": "add_assessmentworkflowcancellation"}}, {"model": "auth.permission", "pk": 706, "fields": {"name": "Can change assessment workflow cancellation", "content_type": 235, "codename": "change_assessmentworkflowcancellation"}}, {"model": "auth.permission", "pk": 707, "fields": {"name": "Can delete assessment workflow cancellation", "content_type": 235, "codename": "delete_assessmentworkflowcancellation"}}, {"model": "auth.permission", "pk": 708, "fields": {"name": "Can add profile", "content_type": 236, "codename": "add_profile"}}, {"model": "auth.permission", "pk": 709, "fields": {"name": "Can change profile", "content_type": 236, "codename": "change_profile"}}, {"model": "auth.permission", "pk": 710, "fields": {"name": "Can delete profile", "content_type": 236, "codename": "delete_profile"}}, {"model": "auth.permission", "pk": 711, "fields": {"name": "Can add video", "content_type": 237, "codename": "add_video"}}, {"model": "auth.permission", "pk": 712, "fields": {"name": "Can change video", "content_type": 237, "codename": "change_video"}}, {"model": "auth.permission", "pk": 713, "fields": {"name": "Can delete video", "content_type": 237, "codename": "delete_video"}}, {"model": "auth.permission", "pk": 714, "fields": {"name": "Can add course video", "content_type": 238, "codename": "add_coursevideo"}}, {"model": "auth.permission", "pk": 715, "fields": {"name": "Can change course video", "content_type": 238, "codename": "change_coursevideo"}}, {"model": "auth.permission", "pk": 716, "fields": {"name": "Can delete course video", "content_type": 238, "codename": "delete_coursevideo"}}, {"model": "auth.permission", "pk": 717, "fields": {"name": "Can add encoded video", "content_type": 239, "codename": "add_encodedvideo"}}, {"model": "auth.permission", "pk": 718, "fields": {"name": "Can change encoded video", "content_type": 239, "codename": "change_encodedvideo"}}, {"model": "auth.permission", "pk": 719, "fields": {"name": "Can delete encoded video", "content_type": 239, "codename": "delete_encodedvideo"}}, {"model": "auth.permission", "pk": 720, "fields": {"name": "Can add video image", "content_type": 240, "codename": "add_videoimage"}}, {"model": "auth.permission", "pk": 721, "fields": {"name": "Can change video image", "content_type": 240, "codename": "change_videoimage"}}, {"model": "auth.permission", "pk": 722, "fields": {"name": "Can delete video image", "content_type": 240, "codename": "delete_videoimage"}}, {"model": "auth.permission", "pk": 723, "fields": {"name": "Can add video transcript", "content_type": 241, "codename": "add_videotranscript"}}, {"model": "auth.permission", "pk": 724, "fields": {"name": "Can change video transcript", "content_type": 241, "codename": "change_videotranscript"}}, {"model": "auth.permission", "pk": 725, "fields": {"name": "Can delete video transcript", "content_type": 241, "codename": "delete_videotranscript"}}, {"model": "auth.permission", "pk": 726, "fields": {"name": "Can add transcript preference", "content_type": 242, "codename": "add_transcriptpreference"}}, {"model": "auth.permission", "pk": 727, "fields": {"name": "Can change transcript preference", "content_type": 242, "codename": "change_transcriptpreference"}}, {"model": "auth.permission", "pk": 728, "fields": {"name": "Can delete transcript preference", "content_type": 242, "codename": "delete_transcriptpreference"}}, {"model": "auth.permission", "pk": 729, "fields": {"name": "Can add third party transcript credentials state", "content_type": 243, "codename": "add_thirdpartytranscriptcredentialsstate"}}, {"model": "auth.permission", "pk": 730, "fields": {"name": "Can change third party transcript credentials state", "content_type": 243, "codename": "change_thirdpartytranscriptcredentialsstate"}}, {"model": "auth.permission", "pk": 731, "fields": {"name": "Can delete third party transcript credentials state", "content_type": 243, "codename": "delete_thirdpartytranscriptcredentialsstate"}}, {"model": "auth.permission", "pk": 732, "fields": {"name": "Can add course overview", "content_type": 244, "codename": "add_courseoverview"}}, {"model": "auth.permission", "pk": 733, "fields": {"name": "Can change course overview", "content_type": 244, "codename": "change_courseoverview"}}, {"model": "auth.permission", "pk": 734, "fields": {"name": "Can delete course overview", "content_type": 244, "codename": "delete_courseoverview"}}, {"model": "auth.permission", "pk": 735, "fields": {"name": "Can add course overview tab", "content_type": 245, "codename": "add_courseoverviewtab"}}, {"model": "auth.permission", "pk": 736, "fields": {"name": "Can change course overview tab", "content_type": 245, "codename": "change_courseoverviewtab"}}, {"model": "auth.permission", "pk": 737, "fields": {"name": "Can delete course overview tab", "content_type": 245, "codename": "delete_courseoverviewtab"}}, {"model": "auth.permission", "pk": 738, "fields": {"name": "Can add course overview image set", "content_type": 246, "codename": "add_courseoverviewimageset"}}, {"model": "auth.permission", "pk": 739, "fields": {"name": "Can change course overview image set", "content_type": 246, "codename": "change_courseoverviewimageset"}}, {"model": "auth.permission", "pk": 740, "fields": {"name": "Can delete course overview image set", "content_type": 246, "codename": "delete_courseoverviewimageset"}}, {"model": "auth.permission", "pk": 741, "fields": {"name": "Can add course overview image config", "content_type": 247, "codename": "add_courseoverviewimageconfig"}}, {"model": "auth.permission", "pk": 742, "fields": {"name": "Can change course overview image config", "content_type": 247, "codename": "change_courseoverviewimageconfig"}}, {"model": "auth.permission", "pk": 743, "fields": {"name": "Can delete course overview image config", "content_type": 247, "codename": "delete_courseoverviewimageconfig"}}, {"model": "auth.permission", "pk": 744, "fields": {"name": "Can add course structure", "content_type": 248, "codename": "add_coursestructure"}}, {"model": "auth.permission", "pk": 745, "fields": {"name": "Can change course structure", "content_type": 248, "codename": "change_coursestructure"}}, {"model": "auth.permission", "pk": 746, "fields": {"name": "Can delete course structure", "content_type": 248, "codename": "delete_coursestructure"}}, {"model": "auth.permission", "pk": 747, "fields": {"name": "Can add block structure configuration", "content_type": 249, "codename": "add_blockstructureconfiguration"}}, {"model": "auth.permission", "pk": 748, "fields": {"name": "Can change block structure configuration", "content_type": 249, "codename": "change_blockstructureconfiguration"}}, {"model": "auth.permission", "pk": 749, "fields": {"name": "Can delete block structure configuration", "content_type": 249, "codename": "delete_blockstructureconfiguration"}}, {"model": "auth.permission", "pk": 750, "fields": {"name": "Can add block structure model", "content_type": 250, "codename": "add_blockstructuremodel"}}, {"model": "auth.permission", "pk": 751, "fields": {"name": "Can change block structure model", "content_type": 250, "codename": "change_blockstructuremodel"}}, {"model": "auth.permission", "pk": 752, "fields": {"name": "Can delete block structure model", "content_type": 250, "codename": "delete_blockstructuremodel"}}, {"model": "auth.permission", "pk": 753, "fields": {"name": "Can add x domain proxy configuration", "content_type": 251, "codename": "add_xdomainproxyconfiguration"}}, {"model": "auth.permission", "pk": 754, "fields": {"name": "Can change x domain proxy configuration", "content_type": 251, "codename": "change_xdomainproxyconfiguration"}}, {"model": "auth.permission", "pk": 755, "fields": {"name": "Can delete x domain proxy configuration", "content_type": 251, "codename": "delete_xdomainproxyconfiguration"}}, {"model": "auth.permission", "pk": 756, "fields": {"name": "Can add commerce configuration", "content_type": 252, "codename": "add_commerceconfiguration"}}, {"model": "auth.permission", "pk": 757, "fields": {"name": "Can change commerce configuration", "content_type": 252, "codename": "change_commerceconfiguration"}}, {"model": "auth.permission", "pk": 758, "fields": {"name": "Can delete commerce configuration", "content_type": 252, "codename": "delete_commerceconfiguration"}}, {"model": "auth.permission", "pk": 759, "fields": {"name": "Can add credit provider", "content_type": 253, "codename": "add_creditprovider"}}, {"model": "auth.permission", "pk": 760, "fields": {"name": "Can change credit provider", "content_type": 253, "codename": "change_creditprovider"}}, {"model": "auth.permission", "pk": 761, "fields": {"name": "Can delete credit provider", "content_type": 253, "codename": "delete_creditprovider"}}, {"model": "auth.permission", "pk": 762, "fields": {"name": "Can add credit course", "content_type": 254, "codename": "add_creditcourse"}}, {"model": "auth.permission", "pk": 763, "fields": {"name": "Can change credit course", "content_type": 254, "codename": "change_creditcourse"}}, {"model": "auth.permission", "pk": 764, "fields": {"name": "Can delete credit course", "content_type": 254, "codename": "delete_creditcourse"}}, {"model": "auth.permission", "pk": 765, "fields": {"name": "Can add credit requirement", "content_type": 255, "codename": "add_creditrequirement"}}, {"model": "auth.permission", "pk": 766, "fields": {"name": "Can change credit requirement", "content_type": 255, "codename": "change_creditrequirement"}}, {"model": "auth.permission", "pk": 767, "fields": {"name": "Can delete credit requirement", "content_type": 255, "codename": "delete_creditrequirement"}}, {"model": "auth.permission", "pk": 768, "fields": {"name": "Can add credit requirement status", "content_type": 256, "codename": "add_creditrequirementstatus"}}, {"model": "auth.permission", "pk": 769, "fields": {"name": "Can change credit requirement status", "content_type": 256, "codename": "change_creditrequirementstatus"}}, {"model": "auth.permission", "pk": 770, "fields": {"name": "Can delete credit requirement status", "content_type": 256, "codename": "delete_creditrequirementstatus"}}, {"model": "auth.permission", "pk": 771, "fields": {"name": "Can add credit eligibility", "content_type": 257, "codename": "add_crediteligibility"}}, {"model": "auth.permission", "pk": 772, "fields": {"name": "Can change credit eligibility", "content_type": 257, "codename": "change_crediteligibility"}}, {"model": "auth.permission", "pk": 773, "fields": {"name": "Can delete credit eligibility", "content_type": 257, "codename": "delete_crediteligibility"}}, {"model": "auth.permission", "pk": 774, "fields": {"name": "Can add credit request", "content_type": 258, "codename": "add_creditrequest"}}, {"model": "auth.permission", "pk": 775, "fields": {"name": "Can change credit request", "content_type": 258, "codename": "change_creditrequest"}}, {"model": "auth.permission", "pk": 776, "fields": {"name": "Can delete credit request", "content_type": 258, "codename": "delete_creditrequest"}}, {"model": "auth.permission", "pk": 777, "fields": {"name": "Can add credit config", "content_type": 259, "codename": "add_creditconfig"}}, {"model": "auth.permission", "pk": 778, "fields": {"name": "Can change credit config", "content_type": 259, "codename": "change_creditconfig"}}, {"model": "auth.permission", "pk": 779, "fields": {"name": "Can delete credit config", "content_type": 259, "codename": "delete_creditconfig"}}, {"model": "auth.permission", "pk": 780, "fields": {"name": "Can add course team", "content_type": 260, "codename": "add_courseteam"}}, {"model": "auth.permission", "pk": 781, "fields": {"name": "Can change course team", "content_type": 260, "codename": "change_courseteam"}}, {"model": "auth.permission", "pk": 782, "fields": {"name": "Can delete course team", "content_type": 260, "codename": "delete_courseteam"}}, {"model": "auth.permission", "pk": 783, "fields": {"name": "Can add course team membership", "content_type": 261, "codename": "add_courseteammembership"}}, {"model": "auth.permission", "pk": 784, "fields": {"name": "Can change course team membership", "content_type": 261, "codename": "change_courseteammembership"}}, {"model": "auth.permission", "pk": 785, "fields": {"name": "Can delete course team membership", "content_type": 261, "codename": "delete_courseteammembership"}}, {"model": "auth.permission", "pk": 786, "fields": {"name": "Can add x block configuration", "content_type": 262, "codename": "add_xblockconfiguration"}}, {"model": "auth.permission", "pk": 787, "fields": {"name": "Can change x block configuration", "content_type": 262, "codename": "change_xblockconfiguration"}}, {"model": "auth.permission", "pk": 788, "fields": {"name": "Can delete x block configuration", "content_type": 262, "codename": "delete_xblockconfiguration"}}, {"model": "auth.permission", "pk": 789, "fields": {"name": "Can add x block studio configuration flag", "content_type": 263, "codename": "add_xblockstudioconfigurationflag"}}, {"model": "auth.permission", "pk": 790, "fields": {"name": "Can change x block studio configuration flag", "content_type": 263, "codename": "change_xblockstudioconfigurationflag"}}, {"model": "auth.permission", "pk": 791, "fields": {"name": "Can delete x block studio configuration flag", "content_type": 263, "codename": "delete_xblockstudioconfigurationflag"}}, {"model": "auth.permission", "pk": 792, "fields": {"name": "Can add x block studio configuration", "content_type": 264, "codename": "add_xblockstudioconfiguration"}}, {"model": "auth.permission", "pk": 793, "fields": {"name": "Can change x block studio configuration", "content_type": 264, "codename": "change_xblockstudioconfiguration"}}, {"model": "auth.permission", "pk": 794, "fields": {"name": "Can delete x block studio configuration", "content_type": 264, "codename": "delete_xblockstudioconfiguration"}}, {"model": "auth.permission", "pk": 795, "fields": {"name": "Can add programs api config", "content_type": 265, "codename": "add_programsapiconfig"}}, {"model": "auth.permission", "pk": 796, "fields": {"name": "Can change programs api config", "content_type": 265, "codename": "change_programsapiconfig"}}, {"model": "auth.permission", "pk": 797, "fields": {"name": "Can delete programs api config", "content_type": 265, "codename": "delete_programsapiconfig"}}, {"model": "auth.permission", "pk": 798, "fields": {"name": "Can add catalog integration", "content_type": 266, "codename": "add_catalogintegration"}}, {"model": "auth.permission", "pk": 799, "fields": {"name": "Can change catalog integration", "content_type": 266, "codename": "change_catalogintegration"}}, {"model": "auth.permission", "pk": 800, "fields": {"name": "Can delete catalog integration", "content_type": 266, "codename": "delete_catalogintegration"}}, {"model": "auth.permission", "pk": 801, "fields": {"name": "Can add self paced configuration", "content_type": 267, "codename": "add_selfpacedconfiguration"}}, {"model": "auth.permission", "pk": 802, "fields": {"name": "Can change self paced configuration", "content_type": 267, "codename": "change_selfpacedconfiguration"}}, {"model": "auth.permission", "pk": 803, "fields": {"name": "Can delete self paced configuration", "content_type": 267, "codename": "delete_selfpacedconfiguration"}}, {"model": "auth.permission", "pk": 804, "fields": {"name": "Can add kv store", "content_type": 268, "codename": "add_kvstore"}}, {"model": "auth.permission", "pk": 805, "fields": {"name": "Can change kv store", "content_type": 268, "codename": "change_kvstore"}}, {"model": "auth.permission", "pk": 806, "fields": {"name": "Can delete kv store", "content_type": 268, "codename": "delete_kvstore"}}, {"model": "auth.permission", "pk": 807, "fields": {"name": "Can add credentials api config", "content_type": 269, "codename": "add_credentialsapiconfig"}}, {"model": "auth.permission", "pk": 808, "fields": {"name": "Can change credentials api config", "content_type": 269, "codename": "change_credentialsapiconfig"}}, {"model": "auth.permission", "pk": 809, "fields": {"name": "Can delete credentials api config", "content_type": 269, "codename": "delete_credentialsapiconfig"}}, {"model": "auth.permission", "pk": 810, "fields": {"name": "Can add milestone", "content_type": 270, "codename": "add_milestone"}}, {"model": "auth.permission", "pk": 811, "fields": {"name": "Can change milestone", "content_type": 270, "codename": "change_milestone"}}, {"model": "auth.permission", "pk": 812, "fields": {"name": "Can delete milestone", "content_type": 270, "codename": "delete_milestone"}}, {"model": "auth.permission", "pk": 813, "fields": {"name": "Can add milestone relationship type", "content_type": 271, "codename": "add_milestonerelationshiptype"}}, {"model": "auth.permission", "pk": 814, "fields": {"name": "Can change milestone relationship type", "content_type": 271, "codename": "change_milestonerelationshiptype"}}, {"model": "auth.permission", "pk": 815, "fields": {"name": "Can delete milestone relationship type", "content_type": 271, "codename": "delete_milestonerelationshiptype"}}, {"model": "auth.permission", "pk": 816, "fields": {"name": "Can add course milestone", "content_type": 272, "codename": "add_coursemilestone"}}, {"model": "auth.permission", "pk": 817, "fields": {"name": "Can change course milestone", "content_type": 272, "codename": "change_coursemilestone"}}, {"model": "auth.permission", "pk": 818, "fields": {"name": "Can delete course milestone", "content_type": 272, "codename": "delete_coursemilestone"}}, {"model": "auth.permission", "pk": 819, "fields": {"name": "Can add course content milestone", "content_type": 273, "codename": "add_coursecontentmilestone"}}, {"model": "auth.permission", "pk": 820, "fields": {"name": "Can change course content milestone", "content_type": 273, "codename": "change_coursecontentmilestone"}}, {"model": "auth.permission", "pk": 821, "fields": {"name": "Can delete course content milestone", "content_type": 273, "codename": "delete_coursecontentmilestone"}}, {"model": "auth.permission", "pk": 822, "fields": {"name": "Can add user milestone", "content_type": 274, "codename": "add_usermilestone"}}, {"model": "auth.permission", "pk": 823, "fields": {"name": "Can change user milestone", "content_type": 274, "codename": "change_usermilestone"}}, {"model": "auth.permission", "pk": 824, "fields": {"name": "Can delete user milestone", "content_type": 274, "codename": "delete_usermilestone"}}, {"model": "auth.permission", "pk": 825, "fields": {"name": "Can add api access request", "content_type": 1, "codename": "add_apiaccessrequest"}}, {"model": "auth.permission", "pk": 826, "fields": {"name": "Can change api access request", "content_type": 1, "codename": "change_apiaccessrequest"}}, {"model": "auth.permission", "pk": 827, "fields": {"name": "Can delete api access request", "content_type": 1, "codename": "delete_apiaccessrequest"}}, {"model": "auth.permission", "pk": 828, "fields": {"name": "Can add api access config", "content_type": 275, "codename": "add_apiaccessconfig"}}, {"model": "auth.permission", "pk": 829, "fields": {"name": "Can change api access config", "content_type": 275, "codename": "change_apiaccessconfig"}}, {"model": "auth.permission", "pk": 830, "fields": {"name": "Can delete api access config", "content_type": 275, "codename": "delete_apiaccessconfig"}}, {"model": "auth.permission", "pk": 831, "fields": {"name": "Can add catalog", "content_type": 276, "codename": "add_catalog"}}, {"model": "auth.permission", "pk": 832, "fields": {"name": "Can change catalog", "content_type": 276, "codename": "change_catalog"}}, {"model": "auth.permission", "pk": 833, "fields": {"name": "Can delete catalog", "content_type": 276, "codename": "delete_catalog"}}, {"model": "auth.permission", "pk": 834, "fields": {"name": "Can add verified track cohorted course", "content_type": 277, "codename": "add_verifiedtrackcohortedcourse"}}, {"model": "auth.permission", "pk": 835, "fields": {"name": "Can change verified track cohorted course", "content_type": 277, "codename": "change_verifiedtrackcohortedcourse"}}, {"model": "auth.permission", "pk": 836, "fields": {"name": "Can delete verified track cohorted course", "content_type": 277, "codename": "delete_verifiedtrackcohortedcourse"}}, {"model": "auth.permission", "pk": 837, "fields": {"name": "Can add migrate verified track cohorts setting", "content_type": 278, "codename": "add_migrateverifiedtrackcohortssetting"}}, {"model": "auth.permission", "pk": 838, "fields": {"name": "Can change migrate verified track cohorts setting", "content_type": 278, "codename": "change_migrateverifiedtrackcohortssetting"}}, {"model": "auth.permission", "pk": 839, "fields": {"name": "Can delete migrate verified track cohorts setting", "content_type": 278, "codename": "delete_migrateverifiedtrackcohortssetting"}}, {"model": "auth.permission", "pk": 840, "fields": {"name": "Can add badge class", "content_type": 279, "codename": "add_badgeclass"}}, {"model": "auth.permission", "pk": 841, "fields": {"name": "Can change badge class", "content_type": 279, "codename": "change_badgeclass"}}, {"model": "auth.permission", "pk": 842, "fields": {"name": "Can delete badge class", "content_type": 279, "codename": "delete_badgeclass"}}, {"model": "auth.permission", "pk": 843, "fields": {"name": "Can add badge assertion", "content_type": 280, "codename": "add_badgeassertion"}}, {"model": "auth.permission", "pk": 844, "fields": {"name": "Can change badge assertion", "content_type": 280, "codename": "change_badgeassertion"}}, {"model": "auth.permission", "pk": 845, "fields": {"name": "Can delete badge assertion", "content_type": 280, "codename": "delete_badgeassertion"}}, {"model": "auth.permission", "pk": 846, "fields": {"name": "Can add course complete image configuration", "content_type": 281, "codename": "add_coursecompleteimageconfiguration"}}, {"model": "auth.permission", "pk": 847, "fields": {"name": "Can change course complete image configuration", "content_type": 281, "codename": "change_coursecompleteimageconfiguration"}}, {"model": "auth.permission", "pk": 848, "fields": {"name": "Can delete course complete image configuration", "content_type": 281, "codename": "delete_coursecompleteimageconfiguration"}}, {"model": "auth.permission", "pk": 849, "fields": {"name": "Can add course event badges configuration", "content_type": 282, "codename": "add_courseeventbadgesconfiguration"}}, {"model": "auth.permission", "pk": 850, "fields": {"name": "Can change course event badges configuration", "content_type": 282, "codename": "change_courseeventbadgesconfiguration"}}, {"model": "auth.permission", "pk": 851, "fields": {"name": "Can delete course event badges configuration", "content_type": 282, "codename": "delete_courseeventbadgesconfiguration"}}, {"model": "auth.permission", "pk": 852, "fields": {"name": "Can add email marketing configuration", "content_type": 283, "codename": "add_emailmarketingconfiguration"}}, {"model": "auth.permission", "pk": 853, "fields": {"name": "Can change email marketing configuration", "content_type": 283, "codename": "change_emailmarketingconfiguration"}}, {"model": "auth.permission", "pk": 854, "fields": {"name": "Can delete email marketing configuration", "content_type": 283, "codename": "delete_emailmarketingconfiguration"}}, {"model": "auth.permission", "pk": 855, "fields": {"name": "Can add failed task", "content_type": 284, "codename": "add_failedtask"}}, {"model": "auth.permission", "pk": 856, "fields": {"name": "Can change failed task", "content_type": 284, "codename": "change_failedtask"}}, {"model": "auth.permission", "pk": 857, "fields": {"name": "Can delete failed task", "content_type": 284, "codename": "delete_failedtask"}}, {"model": "auth.permission", "pk": 858, "fields": {"name": "Can add chord data", "content_type": 285, "codename": "add_chorddata"}}, {"model": "auth.permission", "pk": 859, "fields": {"name": "Can change chord data", "content_type": 285, "codename": "change_chorddata"}}, {"model": "auth.permission", "pk": 860, "fields": {"name": "Can delete chord data", "content_type": 285, "codename": "delete_chorddata"}}, {"model": "auth.permission", "pk": 861, "fields": {"name": "Can add crawlers config", "content_type": 286, "codename": "add_crawlersconfig"}}, {"model": "auth.permission", "pk": 862, "fields": {"name": "Can change crawlers config", "content_type": 286, "codename": "change_crawlersconfig"}}, {"model": "auth.permission", "pk": 863, "fields": {"name": "Can delete crawlers config", "content_type": 286, "codename": "delete_crawlersconfig"}}, {"model": "auth.permission", "pk": 864, "fields": {"name": "Can add Waffle flag course override", "content_type": 287, "codename": "add_waffleflagcourseoverridemodel"}}, {"model": "auth.permission", "pk": 865, "fields": {"name": "Can change Waffle flag course override", "content_type": 287, "codename": "change_waffleflagcourseoverridemodel"}}, {"model": "auth.permission", "pk": 866, "fields": {"name": "Can delete Waffle flag course override", "content_type": 287, "codename": "delete_waffleflagcourseoverridemodel"}}, {"model": "auth.permission", "pk": 867, "fields": {"name": "Can add Schedule", "content_type": 288, "codename": "add_schedule"}}, {"model": "auth.permission", "pk": 868, "fields": {"name": "Can change Schedule", "content_type": 288, "codename": "change_schedule"}}, {"model": "auth.permission", "pk": 869, "fields": {"name": "Can delete Schedule", "content_type": 288, "codename": "delete_schedule"}}, {"model": "auth.permission", "pk": 870, "fields": {"name": "Can add schedule config", "content_type": 289, "codename": "add_scheduleconfig"}}, {"model": "auth.permission", "pk": 871, "fields": {"name": "Can change schedule config", "content_type": 289, "codename": "change_scheduleconfig"}}, {"model": "auth.permission", "pk": 872, "fields": {"name": "Can delete schedule config", "content_type": 289, "codename": "delete_scheduleconfig"}}, {"model": "auth.permission", "pk": 873, "fields": {"name": "Can add schedule experience", "content_type": 290, "codename": "add_scheduleexperience"}}, {"model": "auth.permission", "pk": 874, "fields": {"name": "Can change schedule experience", "content_type": 290, "codename": "change_scheduleexperience"}}, {"model": "auth.permission", "pk": 875, "fields": {"name": "Can delete schedule experience", "content_type": 290, "codename": "delete_scheduleexperience"}}, {"model": "auth.permission", "pk": 876, "fields": {"name": "Can add course goal", "content_type": 291, "codename": "add_coursegoal"}}, {"model": "auth.permission", "pk": 877, "fields": {"name": "Can change course goal", "content_type": 291, "codename": "change_coursegoal"}}, {"model": "auth.permission", "pk": 878, "fields": {"name": "Can delete course goal", "content_type": 291, "codename": "delete_coursegoal"}}, {"model": "auth.permission", "pk": 879, "fields": {"name": "Can add block completion", "content_type": 292, "codename": "add_blockcompletion"}}, {"model": "auth.permission", "pk": 880, "fields": {"name": "Can change block completion", "content_type": 292, "codename": "change_blockcompletion"}}, {"model": "auth.permission", "pk": 881, "fields": {"name": "Can delete block completion", "content_type": 292, "codename": "delete_blockcompletion"}}, {"model": "auth.permission", "pk": 882, "fields": {"name": "Can add Experiment Data", "content_type": 293, "codename": "add_experimentdata"}}, {"model": "auth.permission", "pk": 883, "fields": {"name": "Can change Experiment Data", "content_type": 293, "codename": "change_experimentdata"}}, {"model": "auth.permission", "pk": 884, "fields": {"name": "Can delete Experiment Data", "content_type": 293, "codename": "delete_experimentdata"}}, {"model": "auth.permission", "pk": 885, "fields": {"name": "Can add Experiment Key-Value Pair", "content_type": 294, "codename": "add_experimentkeyvalue"}}, {"model": "auth.permission", "pk": 886, "fields": {"name": "Can change Experiment Key-Value Pair", "content_type": 294, "codename": "change_experimentkeyvalue"}}, {"model": "auth.permission", "pk": 887, "fields": {"name": "Can delete Experiment Key-Value Pair", "content_type": 294, "codename": "delete_experimentkeyvalue"}}, {"model": "auth.permission", "pk": 888, "fields": {"name": "Can add proctored exam", "content_type": 295, "codename": "add_proctoredexam"}}, {"model": "auth.permission", "pk": 889, "fields": {"name": "Can change proctored exam", "content_type": 295, "codename": "change_proctoredexam"}}, {"model": "auth.permission", "pk": 890, "fields": {"name": "Can delete proctored exam", "content_type": 295, "codename": "delete_proctoredexam"}}, {"model": "auth.permission", "pk": 891, "fields": {"name": "Can add Proctored exam review policy", "content_type": 296, "codename": "add_proctoredexamreviewpolicy"}}, {"model": "auth.permission", "pk": 892, "fields": {"name": "Can change Proctored exam review policy", "content_type": 296, "codename": "change_proctoredexamreviewpolicy"}}, {"model": "auth.permission", "pk": 893, "fields": {"name": "Can delete Proctored exam review policy", "content_type": 296, "codename": "delete_proctoredexamreviewpolicy"}}, {"model": "auth.permission", "pk": 894, "fields": {"name": "Can add proctored exam review policy history", "content_type": 297, "codename": "add_proctoredexamreviewpolicyhistory"}}, {"model": "auth.permission", "pk": 895, "fields": {"name": "Can change proctored exam review policy history", "content_type": 297, "codename": "change_proctoredexamreviewpolicyhistory"}}, {"model": "auth.permission", "pk": 896, "fields": {"name": "Can delete proctored exam review policy history", "content_type": 297, "codename": "delete_proctoredexamreviewpolicyhistory"}}, {"model": "auth.permission", "pk": 897, "fields": {"name": "Can add proctored exam attempt", "content_type": 298, "codename": "add_proctoredexamstudentattempt"}}, {"model": "auth.permission", "pk": 898, "fields": {"name": "Can change proctored exam attempt", "content_type": 298, "codename": "change_proctoredexamstudentattempt"}}, {"model": "auth.permission", "pk": 899, "fields": {"name": "Can delete proctored exam attempt", "content_type": 298, "codename": "delete_proctoredexamstudentattempt"}}, {"model": "auth.permission", "pk": 900, "fields": {"name": "Can add proctored exam attempt history", "content_type": 299, "codename": "add_proctoredexamstudentattempthistory"}}, {"model": "auth.permission", "pk": 901, "fields": {"name": "Can change proctored exam attempt history", "content_type": 299, "codename": "change_proctoredexamstudentattempthistory"}}, {"model": "auth.permission", "pk": 902, "fields": {"name": "Can delete proctored exam attempt history", "content_type": 299, "codename": "delete_proctoredexamstudentattempthistory"}}, {"model": "auth.permission", "pk": 903, "fields": {"name": "Can add proctored allowance", "content_type": 300, "codename": "add_proctoredexamstudentallowance"}}, {"model": "auth.permission", "pk": 904, "fields": {"name": "Can change proctored allowance", "content_type": 300, "codename": "change_proctoredexamstudentallowance"}}, {"model": "auth.permission", "pk": 905, "fields": {"name": "Can delete proctored allowance", "content_type": 300, "codename": "delete_proctoredexamstudentallowance"}}, {"model": "auth.permission", "pk": 906, "fields": {"name": "Can add proctored allowance history", "content_type": 301, "codename": "add_proctoredexamstudentallowancehistory"}}, {"model": "auth.permission", "pk": 907, "fields": {"name": "Can change proctored allowance history", "content_type": 301, "codename": "change_proctoredexamstudentallowancehistory"}}, {"model": "auth.permission", "pk": 908, "fields": {"name": "Can delete proctored allowance history", "content_type": 301, "codename": "delete_proctoredexamstudentallowancehistory"}}, {"model": "auth.permission", "pk": 909, "fields": {"name": "Can add Proctored exam software secure review", "content_type": 302, "codename": "add_proctoredexamsoftwaresecurereview"}}, {"model": "auth.permission", "pk": 910, "fields": {"name": "Can change Proctored exam software secure review", "content_type": 302, "codename": "change_proctoredexamsoftwaresecurereview"}}, {"model": "auth.permission", "pk": 911, "fields": {"name": "Can delete Proctored exam software secure review", "content_type": 302, "codename": "delete_proctoredexamsoftwaresecurereview"}}, {"model": "auth.permission", "pk": 912, "fields": {"name": "Can add Proctored exam review archive", "content_type": 303, "codename": "add_proctoredexamsoftwaresecurereviewhistory"}}, {"model": "auth.permission", "pk": 913, "fields": {"name": "Can change Proctored exam review archive", "content_type": 303, "codename": "change_proctoredexamsoftwaresecurereviewhistory"}}, {"model": "auth.permission", "pk": 914, "fields": {"name": "Can delete Proctored exam review archive", "content_type": 303, "codename": "delete_proctoredexamsoftwaresecurereviewhistory"}}, {"model": "auth.permission", "pk": 915, "fields": {"name": "Can add proctored exam software secure comment", "content_type": 304, "codename": "add_proctoredexamsoftwaresecurecomment"}}, {"model": "auth.permission", "pk": 916, "fields": {"name": "Can change proctored exam software secure comment", "content_type": 304, "codename": "change_proctoredexamsoftwaresecurecomment"}}, {"model": "auth.permission", "pk": 917, "fields": {"name": "Can delete proctored exam software secure comment", "content_type": 304, "codename": "delete_proctoredexamsoftwaresecurecomment"}}, {"model": "auth.permission", "pk": 918, "fields": {"name": "Can add organization", "content_type": 305, "codename": "add_organization"}}, {"model": "auth.permission", "pk": 919, "fields": {"name": "Can change organization", "content_type": 305, "codename": "change_organization"}}, {"model": "auth.permission", "pk": 920, "fields": {"name": "Can delete organization", "content_type": 305, "codename": "delete_organization"}}, {"model": "auth.permission", "pk": 921, "fields": {"name": "Can add Link Course", "content_type": 306, "codename": "add_organizationcourse"}}, {"model": "auth.permission", "pk": 922, "fields": {"name": "Can change Link Course", "content_type": 306, "codename": "change_organizationcourse"}}, {"model": "auth.permission", "pk": 923, "fields": {"name": "Can delete Link Course", "content_type": 306, "codename": "delete_organizationcourse"}}, {"model": "auth.permission", "pk": 924, "fields": {"name": "Can add historical Enterprise Customer", "content_type": 307, "codename": "add_historicalenterprisecustomer"}}, {"model": "auth.permission", "pk": 925, "fields": {"name": "Can change historical Enterprise Customer", "content_type": 307, "codename": "change_historicalenterprisecustomer"}}, {"model": "auth.permission", "pk": 926, "fields": {"name": "Can delete historical Enterprise Customer", "content_type": 307, "codename": "delete_historicalenterprisecustomer"}}, {"model": "auth.permission", "pk": 927, "fields": {"name": "Can add Enterprise Customer", "content_type": 308, "codename": "add_enterprisecustomer"}}, {"model": "auth.permission", "pk": 928, "fields": {"name": "Can change Enterprise Customer", "content_type": 308, "codename": "change_enterprisecustomer"}}, {"model": "auth.permission", "pk": 929, "fields": {"name": "Can delete Enterprise Customer", "content_type": 308, "codename": "delete_enterprisecustomer"}}, {"model": "auth.permission", "pk": 930, "fields": {"name": "Can add Enterprise Customer Learner", "content_type": 309, "codename": "add_enterprisecustomeruser"}}, {"model": "auth.permission", "pk": 931, "fields": {"name": "Can change Enterprise Customer Learner", "content_type": 309, "codename": "change_enterprisecustomeruser"}}, {"model": "auth.permission", "pk": 932, "fields": {"name": "Can delete Enterprise Customer Learner", "content_type": 309, "codename": "delete_enterprisecustomeruser"}}, {"model": "auth.permission", "pk": 933, "fields": {"name": "Can add pending enterprise customer user", "content_type": 310, "codename": "add_pendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 934, "fields": {"name": "Can change pending enterprise customer user", "content_type": 310, "codename": "change_pendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 935, "fields": {"name": "Can delete pending enterprise customer user", "content_type": 310, "codename": "delete_pendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 936, "fields": {"name": "Can add pending enrollment", "content_type": 311, "codename": "add_pendingenrollment"}}, {"model": "auth.permission", "pk": 937, "fields": {"name": "Can change pending enrollment", "content_type": 311, "codename": "change_pendingenrollment"}}, {"model": "auth.permission", "pk": 938, "fields": {"name": "Can delete pending enrollment", "content_type": 311, "codename": "delete_pendingenrollment"}}, {"model": "auth.permission", "pk": 939, "fields": {"name": "Can add Branding Configuration", "content_type": 312, "codename": "add_enterprisecustomerbrandingconfiguration"}}, {"model": "auth.permission", "pk": 940, "fields": {"name": "Can change Branding Configuration", "content_type": 312, "codename": "change_enterprisecustomerbrandingconfiguration"}}, {"model": "auth.permission", "pk": 941, "fields": {"name": "Can delete Branding Configuration", "content_type": 312, "codename": "delete_enterprisecustomerbrandingconfiguration"}}, {"model": "auth.permission", "pk": 942, "fields": {"name": "Can add enterprise customer identity provider", "content_type": 313, "codename": "add_enterprisecustomeridentityprovider"}}, {"model": "auth.permission", "pk": 943, "fields": {"name": "Can change enterprise customer identity provider", "content_type": 313, "codename": "change_enterprisecustomeridentityprovider"}}, {"model": "auth.permission", "pk": 944, "fields": {"name": "Can delete enterprise customer identity provider", "content_type": 313, "codename": "delete_enterprisecustomeridentityprovider"}}, {"model": "auth.permission", "pk": 945, "fields": {"name": "Can add historical Enterprise Customer Entitlement", "content_type": 314, "codename": "add_historicalenterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 946, "fields": {"name": "Can change historical Enterprise Customer Entitlement", "content_type": 314, "codename": "change_historicalenterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 947, "fields": {"name": "Can delete historical Enterprise Customer Entitlement", "content_type": 314, "codename": "delete_historicalenterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 948, "fields": {"name": "Can add Enterprise Customer Entitlement", "content_type": 315, "codename": "add_enterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 949, "fields": {"name": "Can change Enterprise Customer Entitlement", "content_type": 315, "codename": "change_enterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 950, "fields": {"name": "Can delete Enterprise Customer Entitlement", "content_type": 315, "codename": "delete_enterprisecustomerentitlement"}}, {"model": "auth.permission", "pk": 951, "fields": {"name": "Can add historical enterprise course enrollment", "content_type": 316, "codename": "add_historicalenterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 952, "fields": {"name": "Can change historical enterprise course enrollment", "content_type": 316, "codename": "change_historicalenterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 953, "fields": {"name": "Can delete historical enterprise course enrollment", "content_type": 316, "codename": "delete_historicalenterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 954, "fields": {"name": "Can add enterprise course enrollment", "content_type": 317, "codename": "add_enterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 955, "fields": {"name": "Can change enterprise course enrollment", "content_type": 317, "codename": "change_enterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 956, "fields": {"name": "Can delete enterprise course enrollment", "content_type": 317, "codename": "delete_enterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 957, "fields": {"name": "Can add historical Enterprise Customer Catalog", "content_type": 318, "codename": "add_historicalenterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 958, "fields": {"name": "Can change historical Enterprise Customer Catalog", "content_type": 318, "codename": "change_historicalenterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 959, "fields": {"name": "Can delete historical Enterprise Customer Catalog", "content_type": 318, "codename": "delete_historicalenterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 960, "fields": {"name": "Can add Enterprise Customer Catalog", "content_type": 319, "codename": "add_enterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 961, "fields": {"name": "Can change Enterprise Customer Catalog", "content_type": 319, "codename": "change_enterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 962, "fields": {"name": "Can delete Enterprise Customer Catalog", "content_type": 319, "codename": "delete_enterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 963, "fields": {"name": "Can add historical enrollment notification email template", "content_type": 320, "codename": "add_historicalenrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 964, "fields": {"name": "Can change historical enrollment notification email template", "content_type": 320, "codename": "change_historicalenrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 965, "fields": {"name": "Can delete historical enrollment notification email template", "content_type": 320, "codename": "delete_historicalenrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 966, "fields": {"name": "Can add enrollment notification email template", "content_type": 321, "codename": "add_enrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 967, "fields": {"name": "Can change enrollment notification email template", "content_type": 321, "codename": "change_enrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 968, "fields": {"name": "Can delete enrollment notification email template", "content_type": 321, "codename": "delete_enrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 969, "fields": {"name": "Can add enterprise customer reporting configuration", "content_type": 322, "codename": "add_enterprisecustomerreportingconfiguration"}}, {"model": "auth.permission", "pk": 970, "fields": {"name": "Can change enterprise customer reporting configuration", "content_type": 322, "codename": "change_enterprisecustomerreportingconfiguration"}}, {"model": "auth.permission", "pk": 971, "fields": {"name": "Can delete enterprise customer reporting configuration", "content_type": 322, "codename": "delete_enterprisecustomerreportingconfiguration"}}, {"model": "auth.permission", "pk": 972, "fields": {"name": "Can add historical Data Sharing Consent Record", "content_type": 323, "codename": "add_historicaldatasharingconsent"}}, {"model": "auth.permission", "pk": 973, "fields": {"name": "Can change historical Data Sharing Consent Record", "content_type": 323, "codename": "change_historicaldatasharingconsent"}}, {"model": "auth.permission", "pk": 974, "fields": {"name": "Can delete historical Data Sharing Consent Record", "content_type": 323, "codename": "delete_historicaldatasharingconsent"}}, {"model": "auth.permission", "pk": 975, "fields": {"name": "Can add Data Sharing Consent Record", "content_type": 324, "codename": "add_datasharingconsent"}}, {"model": "auth.permission", "pk": 976, "fields": {"name": "Can change Data Sharing Consent Record", "content_type": 324, "codename": "change_datasharingconsent"}}, {"model": "auth.permission", "pk": 977, "fields": {"name": "Can delete Data Sharing Consent Record", "content_type": 324, "codename": "delete_datasharingconsent"}}, {"model": "auth.permission", "pk": 978, "fields": {"name": "Can add learner data transmission audit", "content_type": 325, "codename": "add_learnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 979, "fields": {"name": "Can change learner data transmission audit", "content_type": 325, "codename": "change_learnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 980, "fields": {"name": "Can delete learner data transmission audit", "content_type": 325, "codename": "delete_learnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 981, "fields": {"name": "Can add catalog transmission audit", "content_type": 326, "codename": "add_catalogtransmissionaudit"}}, {"model": "auth.permission", "pk": 982, "fields": {"name": "Can change catalog transmission audit", "content_type": 326, "codename": "change_catalogtransmissionaudit"}}, {"model": "auth.permission", "pk": 983, "fields": {"name": "Can delete catalog transmission audit", "content_type": 326, "codename": "delete_catalogtransmissionaudit"}}, {"model": "auth.permission", "pk": 984, "fields": {"name": "Can add degreed global configuration", "content_type": 327, "codename": "add_degreedglobalconfiguration"}}, {"model": "auth.permission", "pk": 985, "fields": {"name": "Can change degreed global configuration", "content_type": 327, "codename": "change_degreedglobalconfiguration"}}, {"model": "auth.permission", "pk": 986, "fields": {"name": "Can delete degreed global configuration", "content_type": 327, "codename": "delete_degreedglobalconfiguration"}}, {"model": "auth.permission", "pk": 987, "fields": {"name": "Can add historical degreed enterprise customer configuration", "content_type": 328, "codename": "add_historicaldegreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 988, "fields": {"name": "Can change historical degreed enterprise customer configuration", "content_type": 328, "codename": "change_historicaldegreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 989, "fields": {"name": "Can delete historical degreed enterprise customer configuration", "content_type": 328, "codename": "delete_historicaldegreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 990, "fields": {"name": "Can add degreed enterprise customer configuration", "content_type": 329, "codename": "add_degreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 991, "fields": {"name": "Can change degreed enterprise customer configuration", "content_type": 329, "codename": "change_degreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 992, "fields": {"name": "Can delete degreed enterprise customer configuration", "content_type": 329, "codename": "delete_degreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 993, "fields": {"name": "Can add degreed learner data transmission audit", "content_type": 330, "codename": "add_degreedlearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 994, "fields": {"name": "Can change degreed learner data transmission audit", "content_type": 330, "codename": "change_degreedlearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 995, "fields": {"name": "Can delete degreed learner data transmission audit", "content_type": 330, "codename": "delete_degreedlearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 996, "fields": {"name": "Can add sap success factors global configuration", "content_type": 331, "codename": "add_sapsuccessfactorsglobalconfiguration"}}, {"model": "auth.permission", "pk": 997, "fields": {"name": "Can change sap success factors global configuration", "content_type": 331, "codename": "change_sapsuccessfactorsglobalconfiguration"}}, {"model": "auth.permission", "pk": 998, "fields": {"name": "Can delete sap success factors global configuration", "content_type": 331, "codename": "delete_sapsuccessfactorsglobalconfiguration"}}, {"model": "auth.permission", "pk": 999, "fields": {"name": "Can add historical sap success factors enterprise customer configuration", "content_type": 332, "codename": "add_historicalsapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1000, "fields": {"name": "Can change historical sap success factors enterprise customer configuration", "content_type": 332, "codename": "change_historicalsapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1001, "fields": {"name": "Can delete historical sap success factors enterprise customer configuration", "content_type": 332, "codename": "delete_historicalsapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1002, "fields": {"name": "Can add sap success factors enterprise customer configuration", "content_type": 333, "codename": "add_sapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1003, "fields": {"name": "Can change sap success factors enterprise customer configuration", "content_type": 333, "codename": "change_sapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1004, "fields": {"name": "Can delete sap success factors enterprise customer configuration", "content_type": 333, "codename": "delete_sapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 1005, "fields": {"name": "Can add sap success factors learner data transmission audit", "content_type": 334, "codename": "add_sapsuccessfactorslearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 1006, "fields": {"name": "Can change sap success factors learner data transmission audit", "content_type": 334, "codename": "change_sapsuccessfactorslearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 1007, "fields": {"name": "Can delete sap success factors learner data transmission audit", "content_type": 334, "codename": "delete_sapsuccessfactorslearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 1008, "fields": {"name": "Can add custom course for ed x", "content_type": 335, "codename": "add_customcourseforedx"}}, {"model": "auth.permission", "pk": 1009, "fields": {"name": "Can change custom course for ed x", "content_type": 335, "codename": "change_customcourseforedx"}}, {"model": "auth.permission", "pk": 1010, "fields": {"name": "Can delete custom course for ed x", "content_type": 335, "codename": "delete_customcourseforedx"}}, {"model": "auth.permission", "pk": 1011, "fields": {"name": "Can add ccx field override", "content_type": 336, "codename": "add_ccxfieldoverride"}}, {"model": "auth.permission", "pk": 1012, "fields": {"name": "Can change ccx field override", "content_type": 336, "codename": "change_ccxfieldoverride"}}, {"model": "auth.permission", "pk": 1013, "fields": {"name": "Can delete ccx field override", "content_type": 336, "codename": "delete_ccxfieldoverride"}}, {"model": "auth.permission", "pk": 1014, "fields": {"name": "Can add CCX Connector", "content_type": 337, "codename": "add_ccxcon"}}, {"model": "auth.permission", "pk": 1015, "fields": {"name": "Can change CCX Connector", "content_type": 337, "codename": "change_ccxcon"}}, {"model": "auth.permission", "pk": 1016, "fields": {"name": "Can delete CCX Connector", "content_type": 337, "codename": "delete_ccxcon"}}, {"model": "auth.permission", "pk": 1017, "fields": {"name": "Can add student module history extended", "content_type": 338, "codename": "add_studentmodulehistoryextended"}}, {"model": "auth.permission", "pk": 1018, "fields": {"name": "Can change student module history extended", "content_type": 338, "codename": "change_studentmodulehistoryextended"}}, {"model": "auth.permission", "pk": 1019, "fields": {"name": "Can delete student module history extended", "content_type": 338, "codename": "delete_studentmodulehistoryextended"}}, {"model": "auth.permission", "pk": 1020, "fields": {"name": "Can add video upload config", "content_type": 339, "codename": "add_videouploadconfig"}}, {"model": "auth.permission", "pk": 1021, "fields": {"name": "Can change video upload config", "content_type": 339, "codename": "change_videouploadconfig"}}, {"model": "auth.permission", "pk": 1022, "fields": {"name": "Can delete video upload config", "content_type": 339, "codename": "delete_videouploadconfig"}}, {"model": "auth.permission", "pk": 1023, "fields": {"name": "Can add push notification config", "content_type": 340, "codename": "add_pushnotificationconfig"}}, {"model": "auth.permission", "pk": 1024, "fields": {"name": "Can change push notification config", "content_type": 340, "codename": "change_pushnotificationconfig"}}, {"model": "auth.permission", "pk": 1025, "fields": {"name": "Can delete push notification config", "content_type": 340, "codename": "delete_pushnotificationconfig"}}, {"model": "auth.permission", "pk": 1026, "fields": {"name": "Can add new assets page flag", "content_type": 341, "codename": "add_newassetspageflag"}}, {"model": "auth.permission", "pk": 1027, "fields": {"name": "Can change new assets page flag", "content_type": 341, "codename": "change_newassetspageflag"}}, {"model": "auth.permission", "pk": 1028, "fields": {"name": "Can delete new assets page flag", "content_type": 341, "codename": "delete_newassetspageflag"}}, {"model": "auth.permission", "pk": 1029, "fields": {"name": "Can add course new assets page flag", "content_type": 342, "codename": "add_coursenewassetspageflag"}}, {"model": "auth.permission", "pk": 1030, "fields": {"name": "Can change course new assets page flag", "content_type": 342, "codename": "change_coursenewassetspageflag"}}, {"model": "auth.permission", "pk": 1031, "fields": {"name": "Can delete course new assets page flag", "content_type": 342, "codename": "delete_coursenewassetspageflag"}}, {"model": "auth.permission", "pk": 1032, "fields": {"name": "Can add course creator", "content_type": 343, "codename": "add_coursecreator"}}, {"model": "auth.permission", "pk": 1033, "fields": {"name": "Can change course creator", "content_type": 343, "codename": "change_coursecreator"}}, {"model": "auth.permission", "pk": 1034, "fields": {"name": "Can delete course creator", "content_type": 343, "codename": "delete_coursecreator"}}, {"model": "auth.permission", "pk": 1035, "fields": {"name": "Can add studio config", "content_type": 344, "codename": "add_studioconfig"}}, {"model": "auth.permission", "pk": 1036, "fields": {"name": "Can change studio config", "content_type": 344, "codename": "change_studioconfig"}}, {"model": "auth.permission", "pk": 1037, "fields": {"name": "Can delete studio config", "content_type": 344, "codename": "delete_studioconfig"}}, {"model": "auth.permission", "pk": 1038, "fields": {"name": "Can add course edit lti fields enabled flag", "content_type": 345, "codename": "add_courseeditltifieldsenabledflag"}}, {"model": "auth.permission", "pk": 1039, "fields": {"name": "Can change course edit lti fields enabled flag", "content_type": 345, "codename": "change_courseeditltifieldsenabledflag"}}, {"model": "auth.permission", "pk": 1040, "fields": {"name": "Can delete course edit lti fields enabled flag", "content_type": 345, "codename": "delete_courseeditltifieldsenabledflag"}}, {"model": "auth.permission", "pk": 1041, "fields": {"name": "Can add tag category", "content_type": 346, "codename": "add_tagcategories"}}, {"model": "auth.permission", "pk": 1042, "fields": {"name": "Can change tag category", "content_type": 346, "codename": "change_tagcategories"}}, {"model": "auth.permission", "pk": 1043, "fields": {"name": "Can delete tag category", "content_type": 346, "codename": "delete_tagcategories"}}, {"model": "auth.permission", "pk": 1044, "fields": {"name": "Can add available tag value", "content_type": 347, "codename": "add_tagavailablevalues"}}, {"model": "auth.permission", "pk": 1045, "fields": {"name": "Can change available tag value", "content_type": 347, "codename": "change_tagavailablevalues"}}, {"model": "auth.permission", "pk": 1046, "fields": {"name": "Can delete available tag value", "content_type": 347, "codename": "delete_tagavailablevalues"}}, {"model": "auth.permission", "pk": 1047, "fields": {"name": "Can add user task status", "content_type": 348, "codename": "add_usertaskstatus"}}, {"model": "auth.permission", "pk": 1048, "fields": {"name": "Can change user task status", "content_type": 348, "codename": "change_usertaskstatus"}}, {"model": "auth.permission", "pk": 1049, "fields": {"name": "Can delete user task status", "content_type": 348, "codename": "delete_usertaskstatus"}}, {"model": "auth.permission", "pk": 1050, "fields": {"name": "Can add user task artifact", "content_type": 349, "codename": "add_usertaskartifact"}}, {"model": "auth.permission", "pk": 1051, "fields": {"name": "Can change user task artifact", "content_type": 349, "codename": "change_usertaskartifact"}}, {"model": "auth.permission", "pk": 1052, "fields": {"name": "Can delete user task artifact", "content_type": 349, "codename": "delete_usertaskartifact"}}, {"model": "auth.permission", "pk": 1053, "fields": {"name": "Can add course entitlement policy", "content_type": 350, "codename": "add_courseentitlementpolicy"}}, {"model": "auth.permission", "pk": 1054, "fields": {"name": "Can change course entitlement policy", "content_type": 350, "codename": "change_courseentitlementpolicy"}}, {"model": "auth.permission", "pk": 1055, "fields": {"name": "Can delete course entitlement policy", "content_type": 350, "codename": "delete_courseentitlementpolicy"}}, {"model": "auth.permission", "pk": 1056, "fields": {"name": "Can add course entitlement support detail", "content_type": 351, "codename": "add_courseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 1057, "fields": {"name": "Can change course entitlement support detail", "content_type": 351, "codename": "change_courseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 1058, "fields": {"name": "Can delete course entitlement support detail", "content_type": 351, "codename": "delete_courseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 1059, "fields": {"name": "Can add content metadata item transmission", "content_type": 352, "codename": "add_contentmetadataitemtransmission"}}, {"model": "auth.permission", "pk": 1060, "fields": {"name": "Can change content metadata item transmission", "content_type": 352, "codename": "change_contentmetadataitemtransmission"}}, {"model": "auth.permission", "pk": 1061, "fields": {"name": "Can delete content metadata item transmission", "content_type": 352, "codename": "delete_contentmetadataitemtransmission"}}, {"model": "auth.permission", "pk": 1062, "fields": {"name": "Can add transcript migration setting", "content_type": 353, "codename": "add_transcriptmigrationsetting"}}, {"model": "auth.permission", "pk": 1063, "fields": {"name": "Can change transcript migration setting", "content_type": 353, "codename": "change_transcriptmigrationsetting"}}, {"model": "auth.permission", "pk": 1064, "fields": {"name": "Can delete transcript migration setting", "content_type": 353, "codename": "delete_transcriptmigrationsetting"}}, {"model": "auth.permission", "pk": 1065, "fields": {"name": "Can add sso verification", "content_type": 354, "codename": "add_ssoverification"}}, {"model": "auth.permission", "pk": 1066, "fields": {"name": "Can change sso verification", "content_type": 354, "codename": "change_ssoverification"}}, {"model": "auth.permission", "pk": 1067, "fields": {"name": "Can delete sso verification", "content_type": 354, "codename": "delete_ssoverification"}}, {"model": "auth.permission", "pk": 1068, "fields": {"name": "Can add User Retirement Status", "content_type": 355, "codename": "add_userretirementstatus"}}, {"model": "auth.permission", "pk": 1069, "fields": {"name": "Can change User Retirement Status", "content_type": 355, "codename": "change_userretirementstatus"}}, {"model": "auth.permission", "pk": 1070, "fields": {"name": "Can delete User Retirement Status", "content_type": 355, "codename": "delete_userretirementstatus"}}, {"model": "auth.permission", "pk": 1071, "fields": {"name": "Can add retirement state", "content_type": 356, "codename": "add_retirementstate"}}, {"model": "auth.permission", "pk": 1072, "fields": {"name": "Can change retirement state", "content_type": 356, "codename": "change_retirementstate"}}, {"model": "auth.permission", "pk": 1073, "fields": {"name": "Can delete retirement state", "content_type": 356, "codename": "delete_retirementstate"}}, {"model": "auth.permission", "pk": 1074, "fields": {"name": "Can add data sharing consent text overrides", "content_type": 357, "codename": "add_datasharingconsenttextoverrides"}}, {"model": "auth.permission", "pk": 1075, "fields": {"name": "Can change data sharing consent text overrides", "content_type": 357, "codename": "change_datasharingconsenttextoverrides"}}, {"model": "auth.permission", "pk": 1076, "fields": {"name": "Can delete data sharing consent text overrides", "content_type": 357, "codename": "delete_datasharingconsenttextoverrides"}}, {"model": "auth.permission", "pk": 1077, "fields": {"name": "Can add User Retirement Request", "content_type": 358, "codename": "add_userretirementrequest"}}, {"model": "auth.permission", "pk": 1078, "fields": {"name": "Can change User Retirement Request", "content_type": 358, "codename": "change_userretirementrequest"}}, {"model": "auth.permission", "pk": 1079, "fields": {"name": "Can delete User Retirement Request", "content_type": 358, "codename": "delete_userretirementrequest"}}, {"model": "auth.permission", "pk": 1080, "fields": {"name": "Can add discussions id mapping", "content_type": 359, "codename": "add_discussionsidmapping"}}, {"model": "auth.permission", "pk": 1081, "fields": {"name": "Can change discussions id mapping", "content_type": 359, "codename": "change_discussionsidmapping"}}, {"model": "auth.permission", "pk": 1082, "fields": {"name": "Can delete discussions id mapping", "content_type": 359, "codename": "delete_discussionsidmapping"}}, {"model": "auth.permission", "pk": 1083, "fields": {"name": "Can add scoped application", "content_type": 360, "codename": "add_scopedapplication"}}, {"model": "auth.permission", "pk": 1084, "fields": {"name": "Can change scoped application", "content_type": 360, "codename": "change_scopedapplication"}}, {"model": "auth.permission", "pk": 1085, "fields": {"name": "Can delete scoped application", "content_type": 360, "codename": "delete_scopedapplication"}}, {"model": "auth.permission", "pk": 1086, "fields": {"name": "Can add scoped application organization", "content_type": 361, "codename": "add_scopedapplicationorganization"}}, {"model": "auth.permission", "pk": 1087, "fields": {"name": "Can change scoped application organization", "content_type": 361, "codename": "change_scopedapplicationorganization"}}, {"model": "auth.permission", "pk": 1088, "fields": {"name": "Can delete scoped application organization", "content_type": 361, "codename": "delete_scopedapplicationorganization"}}, {"model": "auth.permission", "pk": 1089, "fields": {"name": "Can add User Retirement Reporting Status", "content_type": 362, "codename": "add_userretirementpartnerreportingstatus"}}, {"model": "auth.permission", "pk": 1090, "fields": {"name": "Can change User Retirement Reporting Status", "content_type": 362, "codename": "change_userretirementpartnerreportingstatus"}}, {"model": "auth.permission", "pk": 1091, "fields": {"name": "Can delete User Retirement Reporting Status", "content_type": 362, "codename": "delete_userretirementpartnerreportingstatus"}}, {"model": "auth.permission", "pk": 1092, "fields": {"name": "Can add manual verification", "content_type": 363, "codename": "add_manualverification"}}, {"model": "auth.permission", "pk": 1093, "fields": {"name": "Can change manual verification", "content_type": 363, "codename": "change_manualverification"}}, {"model": "auth.permission", "pk": 1094, "fields": {"name": "Can delete manual verification", "content_type": 363, "codename": "delete_manualverification"}}, {"model": "auth.permission", "pk": 1095, "fields": {"name": "Can add application organization", "content_type": 364, "codename": "add_applicationorganization"}}, {"model": "auth.permission", "pk": 1096, "fields": {"name": "Can change application organization", "content_type": 364, "codename": "change_applicationorganization"}}, {"model": "auth.permission", "pk": 1097, "fields": {"name": "Can delete application organization", "content_type": 364, "codename": "delete_applicationorganization"}}, {"model": "auth.permission", "pk": 1098, "fields": {"name": "Can add application access", "content_type": 365, "codename": "add_applicationaccess"}}, {"model": "auth.permission", "pk": 1099, "fields": {"name": "Can change application access", "content_type": 365, "codename": "change_applicationaccess"}}, {"model": "auth.permission", "pk": 1100, "fields": {"name": "Can delete application access", "content_type": 365, "codename": "delete_applicationaccess"}}, {"model": "auth.permission", "pk": 1101, "fields": {"name": "Can add migration enqueued course", "content_type": 366, "codename": "add_migrationenqueuedcourse"}}, {"model": "auth.permission", "pk": 1102, "fields": {"name": "Can change migration enqueued course", "content_type": 366, "codename": "change_migrationenqueuedcourse"}}, {"model": "auth.permission", "pk": 1103, "fields": {"name": "Can delete migration enqueued course", "content_type": 366, "codename": "delete_migrationenqueuedcourse"}}, {"model": "auth.permission", "pk": 1104, "fields": {"name": "Can add xapilrs configuration", "content_type": 367, "codename": "add_xapilrsconfiguration"}}, {"model": "auth.permission", "pk": 1105, "fields": {"name": "Can change xapilrs configuration", "content_type": 367, "codename": "change_xapilrsconfiguration"}}, {"model": "auth.permission", "pk": 1106, "fields": {"name": "Can delete xapilrs configuration", "content_type": 367, "codename": "delete_xapilrsconfiguration"}}, {"model": "auth.permission", "pk": 1107, "fields": {"name": "Can add notify_credentials argument", "content_type": 368, "codename": "add_notifycredentialsconfig"}}, {"model": "auth.permission", "pk": 1108, "fields": {"name": "Can change notify_credentials argument", "content_type": 368, "codename": "change_notifycredentialsconfig"}}, {"model": "auth.permission", "pk": 1109, "fields": {"name": "Can delete notify_credentials argument", "content_type": 368, "codename": "delete_notifycredentialsconfig"}}, {"model": "auth.permission", "pk": 1110, "fields": {"name": "Can add updated course videos", "content_type": 369, "codename": "add_updatedcoursevideos"}}, {"model": "auth.permission", "pk": 1111, "fields": {"name": "Can change updated course videos", "content_type": 369, "codename": "change_updatedcoursevideos"}}, {"model": "auth.permission", "pk": 1112, "fields": {"name": "Can delete updated course videos", "content_type": 369, "codename": "delete_updatedcoursevideos"}}, {"model": "auth.permission", "pk": 1113, "fields": {"name": "Can add video thumbnail setting", "content_type": 370, "codename": "add_videothumbnailsetting"}}, {"model": "auth.permission", "pk": 1114, "fields": {"name": "Can change video thumbnail setting", "content_type": 370, "codename": "change_videothumbnailsetting"}}, {"model": "auth.permission", "pk": 1115, "fields": {"name": "Can delete video thumbnail setting", "content_type": 370, "codename": "delete_videothumbnailsetting"}}, {"model": "auth.permission", "pk": 1116, "fields": {"name": "Can add course duration limit config", "content_type": 371, "codename": "add_coursedurationlimitconfig"}}, {"model": "auth.permission", "pk": 1117, "fields": {"name": "Can change course duration limit config", "content_type": 371, "codename": "change_coursedurationlimitconfig"}}, {"model": "auth.permission", "pk": 1118, "fields": {"name": "Can delete course duration limit config", "content_type": 371, "codename": "delete_coursedurationlimitconfig"}}, {"model": "auth.permission", "pk": 1119, "fields": {"name": "Can add content type gating config", "content_type": 372, "codename": "add_contenttypegatingconfig"}}, {"model": "auth.permission", "pk": 1120, "fields": {"name": "Can change content type gating config", "content_type": 372, "codename": "change_contenttypegatingconfig"}}, {"model": "auth.permission", "pk": 1121, "fields": {"name": "Can delete content type gating config", "content_type": 372, "codename": "delete_contenttypegatingconfig"}}, {"model": "auth.permission", "pk": 1122, "fields": {"name": "Can add persistent subsection grade override history", "content_type": 373, "codename": "add_persistentsubsectiongradeoverridehistory"}}, {"model": "auth.permission", "pk": 1123, "fields": {"name": "Can change persistent subsection grade override history", "content_type": 373, "codename": "change_persistentsubsectiongradeoverridehistory"}}, {"model": "auth.permission", "pk": 1124, "fields": {"name": "Can delete persistent subsection grade override history", "content_type": 373, "codename": "delete_persistentsubsectiongradeoverridehistory"}}, {"model": "auth.permission", "pk": 1125, "fields": {"name": "Can add account recovery", "content_type": 374, "codename": "add_accountrecovery"}}, {"model": "auth.permission", "pk": 1126, "fields": {"name": "Can change account recovery", "content_type": 374, "codename": "change_accountrecovery"}}, {"model": "auth.permission", "pk": 1127, "fields": {"name": "Can delete account recovery", "content_type": 374, "codename": "delete_accountrecovery"}}, {"model": "auth.permission", "pk": 1128, "fields": {"name": "Can add Enterprise Customer Type", "content_type": 375, "codename": "add_enterprisecustomertype"}}, {"model": "auth.permission", "pk": 1129, "fields": {"name": "Can change Enterprise Customer Type", "content_type": 375, "codename": "change_enterprisecustomertype"}}, {"model": "auth.permission", "pk": 1130, "fields": {"name": "Can delete Enterprise Customer Type", "content_type": 375, "codename": "delete_enterprisecustomertype"}}, {"model": "auth.permission", "pk": 1131, "fields": {"name": "Can add pending secondary email change", "content_type": 376, "codename": "add_pendingsecondaryemailchange"}}, {"model": "auth.permission", "pk": 1132, "fields": {"name": "Can change pending secondary email change", "content_type": 376, "codename": "change_pendingsecondaryemailchange"}}, {"model": "auth.permission", "pk": 1133, "fields": {"name": "Can delete pending secondary email change", "content_type": 376, "codename": "delete_pendingsecondaryemailchange"}}, {"model": "auth.permission", "pk": 1134, "fields": {"name": "Can add lti consumer", "content_type": 377, "codename": "add_lticonsumer"}}, {"model": "auth.permission", "pk": 1135, "fields": {"name": "Can change lti consumer", "content_type": 377, "codename": "change_lticonsumer"}}, {"model": "auth.permission", "pk": 1136, "fields": {"name": "Can delete lti consumer", "content_type": 377, "codename": "delete_lticonsumer"}}, {"model": "auth.permission", "pk": 1137, "fields": {"name": "Can add graded assignment", "content_type": 378, "codename": "add_gradedassignment"}}, {"model": "auth.permission", "pk": 1138, "fields": {"name": "Can change graded assignment", "content_type": 378, "codename": "change_gradedassignment"}}, {"model": "auth.permission", "pk": 1139, "fields": {"name": "Can delete graded assignment", "content_type": 378, "codename": "delete_gradedassignment"}}, {"model": "auth.permission", "pk": 1140, "fields": {"name": "Can add lti user", "content_type": 379, "codename": "add_ltiuser"}}, {"model": "auth.permission", "pk": 1141, "fields": {"name": "Can change lti user", "content_type": 379, "codename": "change_ltiuser"}}, {"model": "auth.permission", "pk": 1142, "fields": {"name": "Can delete lti user", "content_type": 379, "codename": "delete_ltiuser"}}, {"model": "auth.permission", "pk": 1143, "fields": {"name": "Can add outcome service", "content_type": 380, "codename": "add_outcomeservice"}}, {"model": "auth.permission", "pk": 1144, "fields": {"name": "Can change outcome service", "content_type": 380, "codename": "change_outcomeservice"}}, {"model": "auth.permission", "pk": 1145, "fields": {"name": "Can delete outcome service", "content_type": 380, "codename": "delete_outcomeservice"}}, {"model": "auth.permission", "pk": 1146, "fields": {"name": "Can add system wide enterprise role", "content_type": 381, "codename": "add_systemwideenterpriserole"}}, {"model": "auth.permission", "pk": 1147, "fields": {"name": "Can change system wide enterprise role", "content_type": 381, "codename": "change_systemwideenterpriserole"}}, {"model": "auth.permission", "pk": 1148, "fields": {"name": "Can delete system wide enterprise role", "content_type": 381, "codename": "delete_systemwideenterpriserole"}}, {"model": "auth.permission", "pk": 1149, "fields": {"name": "Can add system wide enterprise user role assignment", "content_type": 382, "codename": "add_systemwideenterpriseuserroleassignment"}}, {"model": "auth.permission", "pk": 1150, "fields": {"name": "Can change system wide enterprise user role assignment", "content_type": 382, "codename": "change_systemwideenterpriseuserroleassignment"}}, {"model": "auth.permission", "pk": 1151, "fields": {"name": "Can delete system wide enterprise user role assignment", "content_type": 382, "codename": "delete_systemwideenterpriseuserroleassignment"}}, {"model": "auth.permission", "pk": 1152, "fields": {"name": "Can add announcement", "content_type": 383, "codename": "add_announcement"}}, {"model": "auth.permission", "pk": 1153, "fields": {"name": "Can change announcement", "content_type": 383, "codename": "change_announcement"}}, {"model": "auth.permission", "pk": 1154, "fields": {"name": "Can delete announcement", "content_type": 383, "codename": "delete_announcement"}}, {"model": "auth.permission", "pk": 2267, "fields": {"name": "Can add enterprise feature user role assignment", "content_type": 753, "codename": "add_enterprisefeatureuserroleassignment"}}, {"model": "auth.permission", "pk": 2268, "fields": {"name": "Can change enterprise feature user role assignment", "content_type": 753, "codename": "change_enterprisefeatureuserroleassignment"}}, {"model": "auth.permission", "pk": 2269, "fields": {"name": "Can delete enterprise feature user role assignment", "content_type": 753, "codename": "delete_enterprisefeatureuserroleassignment"}}, {"model": "auth.permission", "pk": 2270, "fields": {"name": "Can add enterprise feature role", "content_type": 754, "codename": "add_enterprisefeaturerole"}}, {"model": "auth.permission", "pk": 2271, "fields": {"name": "Can change enterprise feature role", "content_type": 754, "codename": "change_enterprisefeaturerole"}}, {"model": "auth.permission", "pk": 2272, "fields": {"name": "Can delete enterprise feature role", "content_type": 754, "codename": "delete_enterprisefeaturerole"}}, {"model": "auth.permission", "pk": 2273, "fields": {"name": "Can add program enrollment", "content_type": 755, "codename": "add_programenrollment"}}, {"model": "auth.permission", "pk": 2274, "fields": {"name": "Can change program enrollment", "content_type": 755, "codename": "change_programenrollment"}}, {"model": "auth.permission", "pk": 2275, "fields": {"name": "Can delete program enrollment", "content_type": 755, "codename": "delete_programenrollment"}}, {"model": "auth.permission", "pk": 2276, "fields": {"name": "Can add historical program enrollment", "content_type": 756, "codename": "add_historicalprogramenrollment"}}, {"model": "auth.permission", "pk": 2277, "fields": {"name": "Can change historical program enrollment", "content_type": 756, "codename": "change_historicalprogramenrollment"}}, {"model": "auth.permission", "pk": 2278, "fields": {"name": "Can delete historical program enrollment", "content_type": 756, "codename": "delete_historicalprogramenrollment"}}, {"model": "auth.permission", "pk": 2279, "fields": {"name": "Can add program course enrollment", "content_type": 757, "codename": "add_programcourseenrollment"}}, {"model": "auth.permission", "pk": 2280, "fields": {"name": "Can change program course enrollment", "content_type": 757, "codename": "change_programcourseenrollment"}}, {"model": "auth.permission", "pk": 2281, "fields": {"name": "Can delete program course enrollment", "content_type": 757, "codename": "delete_programcourseenrollment"}}, {"model": "auth.permission", "pk": 2282, "fields": {"name": "Can add historical program course enrollment", "content_type": 758, "codename": "add_historicalprogramcourseenrollment"}}, {"model": "auth.permission", "pk": 2283, "fields": {"name": "Can change historical program course enrollment", "content_type": 758, "codename": "change_historicalprogramcourseenrollment"}}, {"model": "auth.permission", "pk": 2284, "fields": {"name": "Can delete historical program course enrollment", "content_type": 758, "codename": "delete_historicalprogramcourseenrollment"}}, {"model": "auth.permission", "pk": 2285, "fields": {"name": "Can add content date", "content_type": 759, "codename": "add_contentdate"}}, {"model": "auth.permission", "pk": 2286, "fields": {"name": "Can change content date", "content_type": 759, "codename": "change_contentdate"}}, {"model": "auth.permission", "pk": 2287, "fields": {"name": "Can delete content date", "content_type": 759, "codename": "delete_contentdate"}}, {"model": "auth.permission", "pk": 2288, "fields": {"name": "Can add user date", "content_type": 760, "codename": "add_userdate"}}, {"model": "auth.permission", "pk": 2289, "fields": {"name": "Can change user date", "content_type": 760, "codename": "change_userdate"}}, {"model": "auth.permission", "pk": 2290, "fields": {"name": "Can delete user date", "content_type": 760, "codename": "delete_userdate"}}, {"model": "auth.permission", "pk": 2291, "fields": {"name": "Can add date policy", "content_type": 761, "codename": "add_datepolicy"}}, {"model": "auth.permission", "pk": 2292, "fields": {"name": "Can change date policy", "content_type": 761, "codename": "change_datepolicy"}}, {"model": "auth.permission", "pk": 2293, "fields": {"name": "Can delete date policy", "content_type": 761, "codename": "delete_datepolicy"}}, {"model": "auth.permission", "pk": 2294, "fields": {"name": "Can add historical course enrollment", "content_type": 762, "codename": "add_historicalcourseenrollment"}}, {"model": "auth.permission", "pk": 2295, "fields": {"name": "Can change historical course enrollment", "content_type": 762, "codename": "change_historicalcourseenrollment"}}, {"model": "auth.permission", "pk": 2296, "fields": {"name": "Can delete historical course enrollment", "content_type": 762, "codename": "delete_historicalcourseenrollment"}}, {"model": "auth.permission", "pk": 2297, "fields": {"name": "Can add cornerstone global configuration", "content_type": 763, "codename": "add_cornerstoneglobalconfiguration"}}, {"model": "auth.permission", "pk": 2298, "fields": {"name": "Can change cornerstone global configuration", "content_type": 763, "codename": "change_cornerstoneglobalconfiguration"}}, {"model": "auth.permission", "pk": 2299, "fields": {"name": "Can delete cornerstone global configuration", "content_type": 763, "codename": "delete_cornerstoneglobalconfiguration"}}, {"model": "auth.permission", "pk": 2300, "fields": {"name": "Can add historical cornerstone enterprise customer configuration", "content_type": 764, "codename": "add_historicalcornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2301, "fields": {"name": "Can change historical cornerstone enterprise customer configuration", "content_type": 764, "codename": "change_historicalcornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2302, "fields": {"name": "Can delete historical cornerstone enterprise customer configuration", "content_type": 764, "codename": "delete_historicalcornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2303, "fields": {"name": "Can add cornerstone learner data transmission audit", "content_type": 765, "codename": "add_cornerstonelearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2304, "fields": {"name": "Can change cornerstone learner data transmission audit", "content_type": 765, "codename": "change_cornerstonelearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2305, "fields": {"name": "Can delete cornerstone learner data transmission audit", "content_type": 765, "codename": "delete_cornerstonelearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2306, "fields": {"name": "Can add cornerstone enterprise customer configuration", "content_type": 766, "codename": "add_cornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2307, "fields": {"name": "Can change cornerstone enterprise customer configuration", "content_type": 766, "codename": "change_cornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2308, "fields": {"name": "Can delete cornerstone enterprise customer configuration", "content_type": 766, "codename": "delete_cornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2309, "fields": {"name": "Can add discount restriction config", "content_type": 767, "codename": "add_discountrestrictionconfig"}}, {"model": "auth.permission", "pk": 2310, "fields": {"name": "Can change discount restriction config", "content_type": 767, "codename": "change_discountrestrictionconfig"}}, {"model": "auth.permission", "pk": 2311, "fields": {"name": "Can delete discount restriction config", "content_type": 767, "codename": "delete_discountrestrictionconfig"}}, {"model": "auth.permission", "pk": 2312, "fields": {"name": "Can add historical course entitlement", "content_type": 768, "codename": "add_historicalcourseentitlement"}}, {"model": "auth.permission", "pk": 2313, "fields": {"name": "Can change historical course entitlement", "content_type": 768, "codename": "change_historicalcourseentitlement"}}, {"model": "auth.permission", "pk": 2314, "fields": {"name": "Can delete historical course entitlement", "content_type": 768, "codename": "delete_historicalcourseentitlement"}}, {"model": "auth.permission", "pk": 2315, "fields": {"name": "Can add historical organization", "content_type": 769, "codename": "add_historicalorganization"}}, {"model": "auth.permission", "pk": 2316, "fields": {"name": "Can change historical organization", "content_type": 769, "codename": "change_historicalorganization"}}, {"model": "auth.permission", "pk": 2317, "fields": {"name": "Can delete historical organization", "content_type": 769, "codename": "delete_historicalorganization"}}, {"model": "auth.permission", "pk": 2318, "fields": {"name": "Can add historical persistent subsection grade override", "content_type": 770, "codename": "add_historicalpersistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 2319, "fields": {"name": "Can change historical persistent subsection grade override", "content_type": 770, "codename": "change_historicalpersistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 2320, "fields": {"name": "Can delete historical persistent subsection grade override", "content_type": 770, "codename": "delete_historicalpersistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 2321, "fields": {"name": "Can add csv operation", "content_type": 771, "codename": "add_csvoperation"}}, {"model": "auth.permission", "pk": 2322, "fields": {"name": "Can change csv operation", "content_type": 771, "codename": "change_csvoperation"}}, {"model": "auth.permission", "pk": 2323, "fields": {"name": "Can delete csv operation", "content_type": 771, "codename": "delete_csvoperation"}}, {"model": "auth.permission", "pk": 2324, "fields": {"name": "Can add score overrider", "content_type": 772, "codename": "add_scoreoverrider"}}, {"model": "auth.permission", "pk": 2325, "fields": {"name": "Can change score overrider", "content_type": 772, "codename": "change_scoreoverrider"}}, {"model": "auth.permission", "pk": 2326, "fields": {"name": "Can delete score overrider", "content_type": 772, "codename": "delete_scoreoverrider"}}, {"model": "auth.permission", "pk": 2327, "fields": {"name": "Can add historical course mode", "content_type": 773, "codename": "add_historicalcoursemode"}}, {"model": "auth.permission", "pk": 2328, "fields": {"name": "Can change historical course mode", "content_type": 773, "codename": "change_historicalcoursemode"}}, {"model": "auth.permission", "pk": 2329, "fields": {"name": "Can delete historical course mode", "content_type": 773, "codename": "delete_historicalcoursemode"}}, {"model": "auth.permission", "pk": 2330, "fields": {"name": "Can add historical course overview", "content_type": 774, "codename": "add_historicalcourseoverview"}}, {"model": "auth.permission", "pk": 2331, "fields": {"name": "Can change historical course overview", "content_type": 774, "codename": "change_historicalcourseoverview"}}, {"model": "auth.permission", "pk": 2332, "fields": {"name": "Can delete historical course overview", "content_type": 774, "codename": "delete_historicalcourseoverview"}}, {"model": "auth.permission", "pk": 2333, "fields": {"name": "Can add system wide role", "content_type": 775, "codename": "add_systemwiderole"}}, {"model": "auth.permission", "pk": 2334, "fields": {"name": "Can change system wide role", "content_type": 775, "codename": "change_systemwiderole"}}, {"model": "auth.permission", "pk": 2335, "fields": {"name": "Can delete system wide role", "content_type": 775, "codename": "delete_systemwiderole"}}, {"model": "auth.permission", "pk": 2336, "fields": {"name": "Can add system wide role assignment", "content_type": 776, "codename": "add_systemwideroleassignment"}}, {"model": "auth.permission", "pk": 2337, "fields": {"name": "Can change system wide role assignment", "content_type": 776, "codename": "change_systemwideroleassignment"}}, {"model": "auth.permission", "pk": 2338, "fields": {"name": "Can delete system wide role assignment", "content_type": 776, "codename": "delete_systemwideroleassignment"}}, {"model": "auth.permission", "pk": 2339, "fields": {"name": "Can add Enterprise Catalog Query", "content_type": 777, "codename": "add_enterprisecatalogquery"}}, {"model": "auth.permission", "pk": 2340, "fields": {"name": "Can change Enterprise Catalog Query", "content_type": 777, "codename": "change_enterprisecatalogquery"}}, {"model": "auth.permission", "pk": 2341, "fields": {"name": "Can delete Enterprise Catalog Query", "content_type": 777, "codename": "delete_enterprisecatalogquery"}}, {"model": "auth.permission", "pk": 2342, "fields": {"name": "Can add historical pending enrollment", "content_type": 778, "codename": "add_historicalpendingenrollment"}}, {"model": "auth.permission", "pk": 2343, "fields": {"name": "Can change historical pending enrollment", "content_type": 778, "codename": "change_historicalpendingenrollment"}}, {"model": "auth.permission", "pk": 2344, "fields": {"name": "Can delete historical pending enrollment", "content_type": 778, "codename": "delete_historicalpendingenrollment"}}, {"model": "auth.permission", "pk": 2345, "fields": {"name": "Can add historical pending enterprise customer user", "content_type": 779, "codename": "add_historicalpendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 2346, "fields": {"name": "Can change historical pending enterprise customer user", "content_type": 779, "codename": "change_historicalpendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 2347, "fields": {"name": "Can delete historical pending enterprise customer user", "content_type": 779, "codename": "delete_historicalpendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 2348, "fields": {"name": "Can add xapi learner data transmission audit", "content_type": 780, "codename": "add_xapilearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2349, "fields": {"name": "Can change xapi learner data transmission audit", "content_type": 780, "codename": "change_xapilearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2350, "fields": {"name": "Can delete xapi learner data transmission audit", "content_type": 780, "codename": "delete_xapilearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2351, "fields": {"name": "Can add course youtube blocked flag", "content_type": 781, "codename": "add_courseyoutubeblockedflag"}}, {"model": "auth.permission", "pk": 2352, "fields": {"name": "Can change course youtube blocked flag", "content_type": 781, "codename": "change_courseyoutubeblockedflag"}}, {"model": "auth.permission", "pk": 2353, "fields": {"name": "Can delete course youtube blocked flag", "content_type": 781, "codename": "delete_courseyoutubeblockedflag"}}, {"model": "auth.permission", "pk": 2354, "fields": {"name": "Can add content library", "content_type": 782, "codename": "add_contentlibrary"}}, {"model": "auth.permission", "pk": 2355, "fields": {"name": "Can change content library", "content_type": 782, "codename": "change_contentlibrary"}}, {"model": "auth.permission", "pk": 2356, "fields": {"name": "Can delete content library", "content_type": 782, "codename": "delete_contentlibrary"}}, {"model": "auth.permission", "pk": 2357, "fields": {"name": "Can add content library permission", "content_type": 783, "codename": "add_contentlibrarypermission"}}, {"model": "auth.permission", "pk": 2358, "fields": {"name": "Can change content library permission", "content_type": 783, "codename": "change_contentlibrarypermission"}}, {"model": "auth.permission", "pk": 2359, "fields": {"name": "Can delete content library permission", "content_type": 783, "codename": "delete_contentlibrarypermission"}}, {"model": "auth.permission", "pk": 2360, "fields": {"name": "Can add simulate_publish argument", "content_type": 784, "codename": "add_simulatecoursepublishconfig"}}, {"model": "auth.permission", "pk": 2361, "fields": {"name": "Can change simulate_publish argument", "content_type": 784, "codename": "change_simulatecoursepublishconfig"}}, {"model": "auth.permission", "pk": 2362, "fields": {"name": "Can delete simulate_publish argument", "content_type": 784, "codename": "delete_simulatecoursepublishconfig"}}, {"model": "auth.permission", "pk": 2363, "fields": {"name": "Can add bulk unenroll configuration", "content_type": 785, "codename": "add_bulkunenrollconfiguration"}}, {"model": "auth.permission", "pk": 2364, "fields": {"name": "Can change bulk unenroll configuration", "content_type": 785, "codename": "change_bulkunenrollconfiguration"}}, {"model": "auth.permission", "pk": 2365, "fields": {"name": "Can delete bulk unenroll configuration", "content_type": 785, "codename": "delete_bulkunenrollconfiguration"}}, {"model": "auth.permission", "pk": 2366, "fields": {"name": "Can add discount percentage config", "content_type": 786, "codename": "add_discountpercentageconfig"}}, {"model": "auth.permission", "pk": 2367, "fields": {"name": "Can change discount percentage config", "content_type": 786, "codename": "change_discountpercentageconfig"}}, {"model": "auth.permission", "pk": 2368, "fields": {"name": "Can delete discount percentage config", "content_type": 786, "codename": "delete_discountpercentageconfig"}}, {"model": "auth.permission", "pk": 2369, "fields": {"name": "Can add fbe enrollment exclusion", "content_type": 787, "codename": "add_fbeenrollmentexclusion"}}, {"model": "auth.permission", "pk": 2370, "fields": {"name": "Can change fbe enrollment exclusion", "content_type": 787, "codename": "change_fbeenrollmentexclusion"}}, {"model": "auth.permission", "pk": 2371, "fields": {"name": "Can delete fbe enrollment exclusion", "content_type": 787, "codename": "delete_fbeenrollmentexclusion"}}, {"model": "auth.permission", "pk": 2372, "fields": {"name": "Can add allowed auth user", "content_type": 788, "codename": "add_allowedauthuser"}}, {"model": "auth.permission", "pk": 2373, "fields": {"name": "Can change allowed auth user", "content_type": 788, "codename": "change_allowedauthuser"}}, {"model": "auth.permission", "pk": 2374, "fields": {"name": "Can delete allowed auth user", "content_type": 788, "codename": "delete_allowedauthuser"}}, {"model": "auth.permission", "pk": 2375, "fields": {"name": "Can add enterprise enrollment source", "content_type": 789, "codename": "add_enterpriseenrollmentsource"}}, {"model": "auth.permission", "pk": 2376, "fields": {"name": "Can change enterprise enrollment source", "content_type": 789, "codename": "change_enterpriseenrollmentsource"}}, {"model": "auth.permission", "pk": 2377, "fields": {"name": "Can delete enterprise enrollment source", "content_type": 789, "codename": "delete_enterpriseenrollmentsource"}}, {"model": "auth.permission", "pk": 2378, "fields": {"name": "Can add sspv retry student argument", "content_type": 790, "codename": "add_sspverificationretryconfig"}}, {"model": "auth.permission", "pk": 2379, "fields": {"name": "Can change sspv retry student argument", "content_type": 790, "codename": "change_sspverificationretryconfig"}}, {"model": "auth.permission", "pk": 2380, "fields": {"name": "Can delete sspv retry student argument", "content_type": 790, "codename": "delete_sspverificationretryconfig"}}, {"model": "auth.permission", "pk": 2381, "fields": {"name": "Can add backpopulate_program_credentials argument", "content_type": 791, "codename": "add_customprogramsconfig"}}, {"model": "auth.permission", "pk": 2382, "fields": {"name": "Can change backpopulate_program_credentials argument", "content_type": 791, "codename": "change_customprogramsconfig"}}, {"model": "auth.permission", "pk": 2383, "fields": {"name": "Can delete backpopulate_program_credentials argument", "content_type": 791, "codename": "delete_customprogramsconfig"}}, {"model": "auth.permission", "pk": 2384, "fields": {"name": "Can add historical shared file upload", "content_type": 792, "codename": "add_historicalsharedfileupload"}}, {"model": "auth.permission", "pk": 2385, "fields": {"name": "Can change historical shared file upload", "content_type": 792, "codename": "change_historicalsharedfileupload"}}, {"model": "auth.permission", "pk": 2386, "fields": {"name": "Can delete historical shared file upload", "content_type": 792, "codename": "delete_historicalsharedfileupload"}}, {"model": "auth.permission", "pk": 2387, "fields": {"name": "Can add shared file upload", "content_type": 793, "codename": "add_sharedfileupload"}}, {"model": "auth.permission", "pk": 2388, "fields": {"name": "Can change shared file upload", "content_type": 793, "codename": "change_sharedfileupload"}}, {"model": "auth.permission", "pk": 2389, "fields": {"name": "Can delete shared file upload", "content_type": 793, "codename": "delete_sharedfileupload"}}, {"model": "auth.permission", "pk": 2390, "fields": {"name": "Can add historical generated certificate", "content_type": 794, "codename": "add_historicalgeneratedcertificate"}}, {"model": "auth.permission", "pk": 2391, "fields": {"name": "Can change historical generated certificate", "content_type": 794, "codename": "change_historicalgeneratedcertificate"}}, {"model": "auth.permission", "pk": 2392, "fields": {"name": "Can delete historical generated certificate", "content_type": 794, "codename": "delete_historicalgeneratedcertificate"}}, {"model": "auth.permission", "pk": 2393, "fields": {"name": "Can add historical course entitlement support detail", "content_type": 795, "codename": "add_historicalcourseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 2394, "fields": {"name": "Can change historical course entitlement support detail", "content_type": 795, "codename": "change_historicalcourseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 2395, "fields": {"name": "Can delete historical course entitlement support detail", "content_type": 795, "codename": "delete_historicalcourseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 2396, "fields": {"name": "Can add historical manual enrollment audit", "content_type": 796, "codename": "add_historicalmanualenrollmentaudit"}}, {"model": "auth.permission", "pk": 2397, "fields": {"name": "Can change historical manual enrollment audit", "content_type": 796, "codename": "change_historicalmanualenrollmentaudit"}}, {"model": "auth.permission", "pk": 2398, "fields": {"name": "Can delete historical manual enrollment audit", "content_type": 796, "codename": "delete_historicalmanualenrollmentaudit"}}, {"model": "auth.permission", "pk": 2399, "fields": {"name": "Can add historical external id", "content_type": 797, "codename": "add_historicalexternalid"}}, {"model": "auth.permission", "pk": 2400, "fields": {"name": "Can change historical external id", "content_type": 797, "codename": "change_historicalexternalid"}}, {"model": "auth.permission", "pk": 2401, "fields": {"name": "Can delete historical external id", "content_type": 797, "codename": "delete_historicalexternalid"}}, {"model": "auth.permission", "pk": 2402, "fields": {"name": "Can add historical external id type", "content_type": 798, "codename": "add_historicalexternalidtype"}}, {"model": "auth.permission", "pk": 2403, "fields": {"name": "Can change historical external id type", "content_type": 798, "codename": "change_historicalexternalidtype"}}, {"model": "auth.permission", "pk": 2404, "fields": {"name": "Can delete historical external id type", "content_type": 798, "codename": "delete_historicalexternalidtype"}}, {"model": "auth.permission", "pk": 2405, "fields": {"name": "Can add external id", "content_type": 799, "codename": "add_externalid"}}, {"model": "auth.permission", "pk": 2406, "fields": {"name": "Can change external id", "content_type": 799, "codename": "change_externalid"}}, {"model": "auth.permission", "pk": 2407, "fields": {"name": "Can delete external id", "content_type": 799, "codename": "delete_externalid"}}, {"model": "auth.permission", "pk": 2408, "fields": {"name": "Can add external id type", "content_type": 800, "codename": "add_externalidtype"}}, {"model": "auth.permission", "pk": 2409, "fields": {"name": "Can change external id type", "content_type": 800, "codename": "change_externalidtype"}}, {"model": "auth.permission", "pk": 2410, "fields": {"name": "Can delete external id type", "content_type": 800, "codename": "delete_externalidtype"}}, {"model": "auth.permission", "pk": 2411, "fields": {"name": "Can add self paced relative dates config", "content_type": 801, "codename": "add_selfpacedrelativedatesconfig"}}, {"model": "auth.permission", "pk": 2412, "fields": {"name": "Can change self paced relative dates config", "content_type": 801, "codename": "change_selfpacedrelativedatesconfig"}}, {"model": "auth.permission", "pk": 2413, "fields": {"name": "Can delete self paced relative dates config", "content_type": 801, "codename": "delete_selfpacedrelativedatesconfig"}}, {"model": "auth.permission", "pk": 2414, "fields": {"name": "Can add historical user calendar sync config", "content_type": 802, "codename": "add_historicalusercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2415, "fields": {"name": "Can change historical user calendar sync config", "content_type": 802, "codename": "change_historicalusercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2416, "fields": {"name": "Can delete historical user calendar sync config", "content_type": 802, "codename": "delete_historicalusercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2417, "fields": {"name": "Can add user calendar sync config", "content_type": 803, "codename": "add_usercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2418, "fields": {"name": "Can change user calendar sync config", "content_type": 803, "codename": "change_usercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2419, "fields": {"name": "Can delete user calendar sync config", "content_type": 803, "codename": "delete_usercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2420, "fields": {"name": "Can add historical Experiment Key-Value Pair", "content_type": 804, "codename": "add_historicalexperimentkeyvalue"}}, {"model": "auth.permission", "pk": 2421, "fields": {"name": "Can change historical Experiment Key-Value Pair", "content_type": 804, "codename": "change_historicalexperimentkeyvalue"}}, {"model": "auth.permission", "pk": 2422, "fields": {"name": "Can delete historical Experiment Key-Value Pair", "content_type": 804, "codename": "delete_historicalexperimentkeyvalue"}}, {"model": "auth.permission", "pk": 2423, "fields": {"name": "Can add historical Schedule", "content_type": 805, "codename": "add_historicalschedule"}}, {"model": "auth.permission", "pk": 2424, "fields": {"name": "Can change historical Schedule", "content_type": 805, "codename": "change_historicalschedule"}}, {"model": "auth.permission", "pk": 2425, "fields": {"name": "Can delete historical Schedule", "content_type": 805, "codename": "delete_historicalschedule"}}, {"model": "auth.permission", "pk": 2426, "fields": {"name": "Can add account recovery configuration", "content_type": 806, "codename": "add_accountrecoveryconfiguration"}}, {"model": "auth.permission", "pk": 2427, "fields": {"name": "Can change account recovery configuration", "content_type": 806, "codename": "change_accountrecoveryconfiguration"}}, {"model": "auth.permission", "pk": 2428, "fields": {"name": "Can delete account recovery configuration", "content_type": 806, "codename": "delete_accountrecoveryconfiguration"}}, {"model": "auth.permission", "pk": 2429, "fields": {"name": "Can add transcript credentials", "content_type": 807, "codename": "add_transcriptcredentials"}}, {"model": "auth.permission", "pk": 2430, "fields": {"name": "Can change transcript credentials", "content_type": 807, "codename": "change_transcriptcredentials"}}, {"model": "auth.permission", "pk": 2431, "fields": {"name": "Can delete transcript credentials", "content_type": 807, "codename": "delete_transcriptcredentials"}}, {"model": "auth.permission", "pk": 2432, "fields": {"name": "Can add team staff workflow", "content_type": 808, "codename": "add_teamstaffworkflow"}}, {"model": "auth.permission", "pk": 2433, "fields": {"name": "Can change team staff workflow", "content_type": 808, "codename": "change_teamstaffworkflow"}}, {"model": "auth.permission", "pk": 2434, "fields": {"name": "Can delete team staff workflow", "content_type": 808, "codename": "delete_teamstaffworkflow"}}, {"model": "auth.permission", "pk": 2435, "fields": {"name": "Can add team assessment workflow", "content_type": 809, "codename": "add_teamassessmentworkflow"}}, {"model": "auth.permission", "pk": 2436, "fields": {"name": "Can change team assessment workflow", "content_type": 809, "codename": "change_teamassessmentworkflow"}}, {"model": "auth.permission", "pk": 2437, "fields": {"name": "Can delete team assessment workflow", "content_type": 809, "codename": "delete_teamassessmentworkflow"}}, {"model": "auth.permission", "pk": 2438, "fields": {"name": "Can add course access role assignment", "content_type": 810, "codename": "add_courseaccessroleassignment"}}, {"model": "auth.permission", "pk": 2439, "fields": {"name": "Can change course access role assignment", "content_type": 810, "codename": "change_courseaccessroleassignment"}}, {"model": "auth.permission", "pk": 2440, "fields": {"name": "Can delete course access role assignment", "content_type": 810, "codename": "delete_courseaccessroleassignment"}}, {"model": "auth.permission", "pk": 2441, "fields": {"name": "Can add team submission", "content_type": 811, "codename": "add_teamsubmission"}}, {"model": "auth.permission", "pk": 2442, "fields": {"name": "Can change team submission", "content_type": 811, "codename": "change_teamsubmission"}}, {"model": "auth.permission", "pk": 2443, "fields": {"name": "Can delete team submission", "content_type": 811, "codename": "delete_teamsubmission"}}, {"model": "auth.permission", "pk": 2444, "fields": {"name": "Can view user", "content_type": 4, "codename": "view_user"}}, {"model": "auth.permission", "pk": 2445, "fields": {"name": "Can view permission", "content_type": 2, "codename": "view_permission"}}, {"model": "auth.permission", "pk": 2446, "fields": {"name": "Can view group", "content_type": 3, "codename": "view_group"}}, {"model": "auth.permission", "pk": 2447, "fields": {"name": "Can view content type", "content_type": 5, "codename": "view_contenttype"}}, {"model": "auth.permission", "pk": 2448, "fields": {"name": "Can view redirect", "content_type": 6, "codename": "view_redirect"}}, {"model": "auth.permission", "pk": 2449, "fields": {"name": "Can view session", "content_type": 7, "codename": "view_session"}}, {"model": "auth.permission", "pk": 2450, "fields": {"name": "Can view site", "content_type": 8, "codename": "view_site"}}, {"model": "auth.permission", "pk": 2451, "fields": {"name": "Can view task", "content_type": 16, "codename": "view_taskstate"}}, {"model": "auth.permission", "pk": 2452, "fields": {"name": "Can view task state", "content_type": 9, "codename": "view_taskmeta"}}, {"model": "auth.permission", "pk": 2453, "fields": {"name": "Can view saved group result", "content_type": 10, "codename": "view_tasksetmeta"}}, {"model": "auth.permission", "pk": 2454, "fields": {"name": "Can view crontab", "content_type": 12, "codename": "view_crontabschedule"}}, {"model": "auth.permission", "pk": 2455, "fields": {"name": "Can view periodic tasks", "content_type": 13, "codename": "view_periodictasks"}}, {"model": "auth.permission", "pk": 2456, "fields": {"name": "Can view worker", "content_type": 15, "codename": "view_workerstate"}}, {"model": "auth.permission", "pk": 2457, "fields": {"name": "Can view periodic task", "content_type": 14, "codename": "view_periodictask"}}, {"model": "auth.permission", "pk": 2458, "fields": {"name": "Can view interval", "content_type": 11, "codename": "view_intervalschedule"}}, {"model": "auth.permission", "pk": 2459, "fields": {"name": "Can view Flag", "content_type": 17, "codename": "view_flag"}}, {"model": "auth.permission", "pk": 2460, "fields": {"name": "Can view Switch", "content_type": 18, "codename": "view_switch"}}, {"model": "auth.permission", "pk": 2461, "fields": {"name": "Can view Sample", "content_type": 19, "codename": "view_sample"}}, {"model": "auth.permission", "pk": 2462, "fields": {"name": "Can view global status message", "content_type": 20, "codename": "view_globalstatusmessage"}}, {"model": "auth.permission", "pk": 2463, "fields": {"name": "Can view course message", "content_type": 21, "codename": "view_coursemessage"}}, {"model": "auth.permission", "pk": 2464, "fields": {"name": "Can view asset excluded extensions config", "content_type": 23, "codename": "view_assetexcludedextensionsconfig"}}, {"model": "auth.permission", "pk": 2465, "fields": {"name": "Can view asset base url config", "content_type": 22, "codename": "view_assetbaseurlconfig"}}, {"model": "auth.permission", "pk": 2466, "fields": {"name": "Can view cdn user agents config", "content_type": 25, "codename": "view_cdnuseragentsconfig"}}, {"model": "auth.permission", "pk": 2467, "fields": {"name": "Can view course asset cache ttl config", "content_type": 24, "codename": "view_courseassetcachettlconfig"}}, {"model": "auth.permission", "pk": 2468, "fields": {"name": "Can view site configuration history", "content_type": 28, "codename": "view_siteconfigurationhistory"}}, {"model": "auth.permission", "pk": 2469, "fields": {"name": "Can view site configuration", "content_type": 27, "codename": "view_siteconfiguration"}}, {"model": "auth.permission", "pk": 2470, "fields": {"name": "Can view migration enqueued course", "content_type": 366, "codename": "view_migrationenqueuedcourse"}}, {"model": "auth.permission", "pk": 2471, "fields": {"name": "Can view video thumbnail setting", "content_type": 370, "codename": "view_videothumbnailsetting"}}, {"model": "auth.permission", "pk": 2472, "fields": {"name": "Can view hls playback enabled flag", "content_type": 29, "codename": "view_hlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 2473, "fields": {"name": "Can view transcript migration setting", "content_type": 353, "codename": "view_transcriptmigrationsetting"}}, {"model": "auth.permission", "pk": 2474, "fields": {"name": "Can view course youtube blocked flag", "content_type": 781, "codename": "view_courseyoutubeblockedflag"}}, {"model": "auth.permission", "pk": 2475, "fields": {"name": "Can view video transcript enabled flag", "content_type": 31, "codename": "view_videotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 2476, "fields": {"name": "Can view updated course videos", "content_type": 369, "codename": "view_updatedcoursevideos"}}, {"model": "auth.permission", "pk": 2477, "fields": {"name": "Can view course video transcript enabled flag", "content_type": 32, "codename": "view_coursevideotranscriptenabledflag"}}, {"model": "auth.permission", "pk": 2478, "fields": {"name": "Can view course hls playback enabled flag", "content_type": 30, "codename": "view_coursehlsplaybackenabledflag"}}, {"model": "auth.permission", "pk": 2479, "fields": {"name": "Can view video uploads enabled by default", "content_type": 34, "codename": "view_videouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 2480, "fields": {"name": "Can view course video uploads enabled by default", "content_type": 35, "codename": "view_coursevideouploadsenabledbydefault"}}, {"model": "auth.permission", "pk": 2481, "fields": {"name": "Can view video pipeline integration", "content_type": 33, "codename": "view_videopipelineintegration"}}, {"model": "auth.permission", "pk": 2482, "fields": {"name": "Can view offline computed grade log", "content_type": 44, "codename": "view_offlinecomputedgradelog"}}, {"model": "auth.permission", "pk": 2483, "fields": {"name": "Can view course dynamic upgrade deadline configuration", "content_type": 47, "codename": "view_coursedynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 2484, "fields": {"name": "Can view student field override", "content_type": 45, "codename": "view_studentfieldoverride"}}, {"model": "auth.permission", "pk": 2485, "fields": {"name": "Can view x module student prefs field", "content_type": 41, "codename": "view_xmodulestudentprefsfield"}}, {"model": "auth.permission", "pk": 2486, "fields": {"name": "Can view x module user state summary field", "content_type": 40, "codename": "view_xmoduleuserstatesummaryfield"}}, {"model": "auth.permission", "pk": 2487, "fields": {"name": "Can view student module history", "content_type": 39, "codename": "view_studentmodulehistory"}}, {"model": "auth.permission", "pk": 2488, "fields": {"name": "Can view org dynamic upgrade deadline configuration", "content_type": 48, "codename": "view_orgdynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 2489, "fields": {"name": "Can view dynamic upgrade deadline configuration", "content_type": 46, "codename": "view_dynamicupgradedeadlineconfiguration"}}, {"model": "auth.permission", "pk": 2490, "fields": {"name": "Can view x module student info field", "content_type": 42, "codename": "view_xmodulestudentinfofield"}}, {"model": "auth.permission", "pk": 2491, "fields": {"name": "Can view student module", "content_type": 38, "codename": "view_studentmodule"}}, {"model": "auth.permission", "pk": 2492, "fields": {"name": "Can view offline computed grade", "content_type": 43, "codename": "view_offlinecomputedgrade"}}, {"model": "auth.permission", "pk": 2493, "fields": {"name": "Can view student module history extended", "content_type": 338, "codename": "view_studentmodulehistoryextended"}}, {"model": "auth.permission", "pk": 2494, "fields": {"name": "Can view linked in add to profile configuration", "content_type": 64, "codename": "view_linkedinaddtoprofileconfiguration"}}, {"model": "auth.permission", "pk": 2495, "fields": {"name": "Can view Login Failure", "content_type": 58, "codename": "view_loginfailures"}}, {"model": "auth.permission", "pk": 2496, "fields": {"name": "Can view pending email change", "content_type": 56, "codename": "view_pendingemailchange"}}, {"model": "auth.permission", "pk": 2497, "fields": {"name": "Can view language proficiency", "content_type": 66, "codename": "view_languageproficiency"}}, {"model": "auth.permission", "pk": 2498, "fields": {"name": "Can view allowed auth user", "content_type": 788, "codename": "view_allowedauthuser"}}, {"model": "auth.permission", "pk": 2499, "fields": {"name": "Can view pending secondary email change", "content_type": 376, "codename": "view_pendingsecondaryemailchange"}}, {"model": "auth.permission", "pk": 2500, "fields": {"name": "Can view entrance exam configuration", "content_type": 65, "codename": "view_entranceexamconfiguration"}}, {"model": "auth.permission", "pk": 2501, "fields": {"name": "Can view historical course enrollment", "content_type": 762, "codename": "view_historicalcourseenrollment"}}, {"model": "auth.permission", "pk": 2502, "fields": {"name": "Can view registration cookie configuration", "content_type": 70, "codename": "view_registrationcookieconfiguration"}}, {"model": "auth.permission", "pk": 2503, "fields": {"name": "Can view course access role", "content_type": 62, "codename": "view_courseaccessrole"}}, {"model": "auth.permission", "pk": 2504, "fields": {"name": "Can view bulk unenroll configuration", "content_type": 785, "codename": "view_bulkunenrollconfiguration"}}, {"model": "auth.permission", "pk": 2505, "fields": {"name": "Can view course enrollment", "content_type": 59, "codename": "view_courseenrollment"}}, {"model": "auth.permission", "pk": 2506, "fields": {"name": "Can view historical manual enrollment audit", "content_type": 796, "codename": "view_historicalmanualenrollmentaudit"}}, {"model": "auth.permission", "pk": 2507, "fields": {"name": "Can view registration", "content_type": 54, "codename": "view_registration"}}, {"model": "auth.permission", "pk": 2508, "fields": {"name": "Can view user test group", "content_type": 53, "codename": "view_usertestgroup"}}, {"model": "auth.permission", "pk": 2509, "fields": {"name": "Can view course enrollment attribute", "content_type": 68, "codename": "view_courseenrollmentattribute"}}, {"model": "auth.permission", "pk": 2510, "fields": {"name": "Can view account recovery", "content_type": 374, "codename": "view_accountrecovery"}}, {"model": "auth.permission", "pk": 2511, "fields": {"name": "Can view pending name change", "content_type": 55, "codename": "view_pendingnamechange"}}, {"model": "auth.permission", "pk": 2512, "fields": {"name": "Can view dashboard configuration", "content_type": 63, "codename": "view_dashboardconfiguration"}}, {"model": "auth.permission", "pk": 2513, "fields": {"name": "Can view user signup source", "content_type": 52, "codename": "view_usersignupsource"}}, {"model": "auth.permission", "pk": 2514, "fields": {"name": "Can view anonymous user id", "content_type": 49, "codename": "view_anonymoususerid"}}, {"model": "auth.permission", "pk": 2515, "fields": {"name": "Can view account recovery configuration", "content_type": 806, "codename": "view_accountrecoveryconfiguration"}}, {"model": "auth.permission", "pk": 2516, "fields": {"name": "Can view manual enrollment audit", "content_type": 60, "codename": "view_manualenrollmentaudit"}}, {"model": "auth.permission", "pk": 2517, "fields": {"name": "Can view social link", "content_type": 67, "codename": "view_sociallink"}}, {"model": "auth.permission", "pk": 2518, "fields": {"name": "Can view user profile", "content_type": 51, "codename": "view_userprofile"}}, {"model": "auth.permission", "pk": 2519, "fields": {"name": "Can view enrollment refund configuration", "content_type": 69, "codename": "view_enrollmentrefundconfiguration"}}, {"model": "auth.permission", "pk": 2520, "fields": {"name": "Can view user attribute", "content_type": 71, "codename": "view_userattribute"}}, {"model": "auth.permission", "pk": 2521, "fields": {"name": "Can view fbe enrollment exclusion", "content_type": 787, "codename": "view_fbeenrollmentexclusion"}}, {"model": "auth.permission", "pk": 2522, "fields": {"name": "Can view user standing", "content_type": 50, "codename": "view_userstanding"}}, {"model": "auth.permission", "pk": 2523, "fields": {"name": "Can view course enrollment allowed", "content_type": 61, "codename": "view_courseenrollmentallowed"}}, {"model": "auth.permission", "pk": 2524, "fields": {"name": "Can view rate limit configuration", "content_type": 74, "codename": "view_ratelimitconfiguration"}}, {"model": "auth.permission", "pk": 2525, "fields": {"name": "Can view historical generated certificate", "content_type": 794, "codename": "view_historicalgeneratedcertificate"}}, {"model": "auth.permission", "pk": 2526, "fields": {"name": "Can view certificate generation configuration", "content_type": 82, "codename": "view_certificategenerationconfiguration"}}, {"model": "auth.permission", "pk": 2527, "fields": {"name": "Can view certificate html view configuration", "content_type": 83, "codename": "view_certificatehtmlviewconfiguration"}}, {"model": "auth.permission", "pk": 2528, "fields": {"name": "Can view generated certificate", "content_type": 76, "codename": "view_generatedcertificate"}}, {"model": "auth.permission", "pk": 2529, "fields": {"name": "Can view certificate invalidation", "content_type": 78, "codename": "view_certificateinvalidation"}}, {"model": "auth.permission", "pk": 2530, "fields": {"name": "Can view example certificate set", "content_type": 79, "codename": "view_examplecertificateset"}}, {"model": "auth.permission", "pk": 2531, "fields": {"name": "Can view certificate generation course setting", "content_type": 81, "codename": "view_certificategenerationcoursesetting"}}, {"model": "auth.permission", "pk": 2532, "fields": {"name": "Can view certificate template asset", "content_type": 85, "codename": "view_certificatetemplateasset"}}, {"model": "auth.permission", "pk": 2533, "fields": {"name": "Can view certificate generation history", "content_type": 77, "codename": "view_certificategenerationhistory"}}, {"model": "auth.permission", "pk": 2534, "fields": {"name": "Can view example certificate", "content_type": 80, "codename": "view_examplecertificate"}}, {"model": "auth.permission", "pk": 2535, "fields": {"name": "Can view certificate template", "content_type": 84, "codename": "view_certificatetemplate"}}, {"model": "auth.permission", "pk": 2536, "fields": {"name": "Can view certificate whitelist", "content_type": 75, "codename": "view_certificatewhitelist"}}, {"model": "auth.permission", "pk": 2537, "fields": {"name": "Can view instructor task", "content_type": 86, "codename": "view_instructortask"}}, {"model": "auth.permission", "pk": 2538, "fields": {"name": "Can view grade report setting", "content_type": 87, "codename": "view_gradereportsetting"}}, {"model": "auth.permission", "pk": 2539, "fields": {"name": "Can view course cohorts settings", "content_type": 91, "codename": "view_coursecohortssettings"}}, {"model": "auth.permission", "pk": 2540, "fields": {"name": "Can view cohort membership", "content_type": 89, "codename": "view_cohortmembership"}}, {"model": "auth.permission", "pk": 2541, "fields": {"name": "Can view course user group partition group", "content_type": 90, "codename": "view_courseusergrouppartitiongroup"}}, {"model": "auth.permission", "pk": 2542, "fields": {"name": "Can view course cohort", "content_type": 92, "codename": "view_coursecohort"}}, {"model": "auth.permission", "pk": 2543, "fields": {"name": "Can view course user group", "content_type": 88, "codename": "view_courseusergroup"}}, {"model": "auth.permission", "pk": 2544, "fields": {"name": "Can view unregistered learner cohort assignments", "content_type": 93, "codename": "view_unregisteredlearnercohortassignments"}}, {"model": "auth.permission", "pk": 2545, "fields": {"name": "Can view bulk email flag", "content_type": 101, "codename": "view_bulkemailflag"}}, {"model": "auth.permission", "pk": 2546, "fields": {"name": "Can view optout", "content_type": 98, "codename": "view_optout"}}, {"model": "auth.permission", "pk": 2547, "fields": {"name": "Can view target", "content_type": 94, "codename": "view_target"}}, {"model": "auth.permission", "pk": 2548, "fields": {"name": "Can view course authorization", "content_type": 100, "codename": "view_courseauthorization"}}, {"model": "auth.permission", "pk": 2549, "fields": {"name": "Can view cohort target", "content_type": 95, "codename": "view_cohorttarget"}}, {"model": "auth.permission", "pk": 2550, "fields": {"name": "Can view course email", "content_type": 97, "codename": "view_courseemail"}}, {"model": "auth.permission", "pk": 2551, "fields": {"name": "Can view course email template", "content_type": 99, "codename": "view_courseemailtemplate"}}, {"model": "auth.permission", "pk": 2552, "fields": {"name": "Can view course mode target", "content_type": 96, "codename": "view_coursemodetarget"}}, {"model": "auth.permission", "pk": 2553, "fields": {"name": "Can view branding info config", "content_type": 102, "codename": "view_brandinginfoconfig"}}, {"model": "auth.permission", "pk": 2554, "fields": {"name": "Can view branding api config", "content_type": 103, "codename": "view_brandingapiconfig"}}, {"model": "auth.permission", "pk": 2555, "fields": {"name": "Can view access token", "content_type": 122, "codename": "view_accesstoken"}}, {"model": "auth.permission", "pk": 2556, "fields": {"name": "Can view refresh token", "content_type": 123, "codename": "view_refreshtoken"}}, {"model": "auth.permission", "pk": 2557, "fields": {"name": "Can view grant", "content_type": 121, "codename": "view_grant"}}, {"model": "auth.permission", "pk": 2558, "fields": {"name": "Can view application", "content_type": 120, "codename": "view_application"}}, {"model": "auth.permission", "pk": 2559, "fields": {"name": "Can view application access", "content_type": 365, "codename": "view_applicationaccess"}}, {"model": "auth.permission", "pk": 2560, "fields": {"name": "Can view restricted application", "content_type": 124, "codename": "view_restrictedapplication"}}, {"model": "auth.permission", "pk": 2561, "fields": {"name": "Can view application organization", "content_type": 364, "codename": "view_applicationorganization"}}, {"model": "auth.permission", "pk": 2562, "fields": {"name": "Can view Provider Configuration (OAuth)", "content_type": 125, "codename": "view_oauth2providerconfig"}}, {"model": "auth.permission", "pk": 2563, "fields": {"name": "Can view Provider Configuration (LTI)", "content_type": 129, "codename": "view_ltiproviderconfig"}}, {"model": "auth.permission", "pk": 2564, "fields": {"name": "Can view Provider Configuration (SAML IdP)", "content_type": 126, "codename": "view_samlproviderconfig"}}, {"model": "auth.permission", "pk": 2565, "fields": {"name": "Can view SAML Configuration", "content_type": 127, "codename": "view_samlconfiguration"}}, {"model": "auth.permission", "pk": 2566, "fields": {"name": "Can view SAML Provider Data", "content_type": 128, "codename": "view_samlproviderdata"}}, {"model": "auth.permission", "pk": 2567, "fields": {"name": "Can view system wide role assignment", "content_type": 776, "codename": "view_systemwideroleassignment"}}, {"model": "auth.permission", "pk": 2568, "fields": {"name": "Can view system wide role", "content_type": 775, "codename": "view_systemwiderole"}}, {"model": "auth.permission", "pk": 2569, "fields": {"name": "Can view article", "content_type": 136, "codename": "view_article"}}, {"model": "auth.permission", "pk": 2570, "fields": {"name": "Can view article plugin", "content_type": 139, "codename": "view_articleplugin"}}, {"model": "auth.permission", "pk": 2571, "fields": {"name": "Can view article revision", "content_type": 138, "codename": "view_articlerevision"}}, {"model": "auth.permission", "pk": 2572, "fields": {"name": "Can view revision plugin revision", "content_type": 143, "codename": "view_revisionpluginrevision"}}, {"model": "auth.permission", "pk": 2573, "fields": {"name": "Can view URL path", "content_type": 144, "codename": "view_urlpath"}}, {"model": "auth.permission", "pk": 2574, "fields": {"name": "Can view simple plugin", "content_type": 141, "codename": "view_simpleplugin"}}, {"model": "auth.permission", "pk": 2575, "fields": {"name": "Can view revision plugin", "content_type": 142, "codename": "view_revisionplugin"}}, {"model": "auth.permission", "pk": 2576, "fields": {"name": "Can view Article for object", "content_type": 137, "codename": "view_articleforobject"}}, {"model": "auth.permission", "pk": 2577, "fields": {"name": "Can view reusable plugin", "content_type": 140, "codename": "view_reusableplugin"}}, {"model": "auth.permission", "pk": 2578, "fields": {"name": "Can view subscription", "content_type": 147, "codename": "view_subscription"}}, {"model": "auth.permission", "pk": 2579, "fields": {"name": "Can view type", "content_type": 145, "codename": "view_notificationtype"}}, {"model": "auth.permission", "pk": 2580, "fields": {"name": "Can view settings", "content_type": 146, "codename": "view_settings"}}, {"model": "auth.permission", "pk": 2581, "fields": {"name": "Can view notification", "content_type": 148, "codename": "view_notification"}}, {"model": "auth.permission", "pk": 2582, "fields": {"name": "Can view log entry", "content_type": 149, "codename": "view_logentry"}}, {"model": "auth.permission", "pk": 2583, "fields": {"name": "Can view discussions id mapping", "content_type": 359, "codename": "view_discussionsidmapping"}}, {"model": "auth.permission", "pk": 2584, "fields": {"name": "Can view permission", "content_type": 151, "codename": "view_permission"}}, {"model": "auth.permission", "pk": 2585, "fields": {"name": "Can view course discussion settings", "content_type": 153, "codename": "view_coursediscussionsettings"}}, {"model": "auth.permission", "pk": 2586, "fields": {"name": "Can view forums config", "content_type": 152, "codename": "view_forumsconfig"}}, {"model": "auth.permission", "pk": 2587, "fields": {"name": "Can view role", "content_type": 150, "codename": "view_role"}}, {"model": "auth.permission", "pk": 2588, "fields": {"name": "Can view splash config", "content_type": 155, "codename": "view_splashconfig"}}, {"model": "auth.permission", "pk": 2589, "fields": {"name": "Can view User Retirement Reporting Status", "content_type": 362, "codename": "view_userretirementpartnerreportingstatus"}}, {"model": "auth.permission", "pk": 2590, "fields": {"name": "Can view User Retirement Request", "content_type": 358, "codename": "view_userretirementrequest"}}, {"model": "auth.permission", "pk": 2591, "fields": {"name": "Can view user preference", "content_type": 156, "codename": "view_userpreference"}}, {"model": "auth.permission", "pk": 2592, "fields": {"name": "Can view user org tag", "content_type": 158, "codename": "view_userorgtag"}}, {"model": "auth.permission", "pk": 2593, "fields": {"name": "Can view user course tag", "content_type": 157, "codename": "view_usercoursetag"}}, {"model": "auth.permission", "pk": 2594, "fields": {"name": "Can view retirement state", "content_type": 356, "codename": "view_retirementstate"}}, {"model": "auth.permission", "pk": 2595, "fields": {"name": "Can view User Retirement Status", "content_type": 355, "codename": "view_userretirementstatus"}}, {"model": "auth.permission", "pk": 2596, "fields": {"name": "Can view invoice item", "content_type": 163, "codename": "view_invoiceitem"}}, {"model": "auth.permission", "pk": 2597, "fields": {"name": "Can view invoice history", "content_type": 165, "codename": "view_invoicehistory"}}, {"model": "auth.permission", "pk": 2598, "fields": {"name": "Can view course reg code item annotation", "content_type": 172, "codename": "view_courseregcodeitemannotation"}}, {"model": "auth.permission", "pk": 2599, "fields": {"name": "Can view coupon", "content_type": 168, "codename": "view_coupon"}}, {"model": "auth.permission", "pk": 2600, "fields": {"name": "Can view course registration code", "content_type": 166, "codename": "view_courseregistrationcode"}}, {"model": "auth.permission", "pk": 2601, "fields": {"name": "Can view invoice transaction", "content_type": 162, "codename": "view_invoicetransaction"}}, {"model": "auth.permission", "pk": 2602, "fields": {"name": "Can view coupon redemption", "content_type": 169, "codename": "view_couponredemption"}}, {"model": "auth.permission", "pk": 2603, "fields": {"name": "Can view course registration code invoice item", "content_type": 164, "codename": "view_courseregistrationcodeinvoiceitem"}}, {"model": "auth.permission", "pk": 2604, "fields": {"name": "Can view order item", "content_type": 160, "codename": "view_orderitem"}}, {"model": "auth.permission", "pk": 2605, "fields": {"name": "Can view order", "content_type": 159, "codename": "view_order"}}, {"model": "auth.permission", "pk": 2606, "fields": {"name": "Can view invoice", "content_type": 161, "codename": "view_invoice"}}, {"model": "auth.permission", "pk": 2607, "fields": {"name": "Can view paid course registration annotation", "content_type": 173, "codename": "view_paidcourseregistrationannotation"}}, {"model": "auth.permission", "pk": 2608, "fields": {"name": "Can view registration code redemption", "content_type": 167, "codename": "view_registrationcoderedemption"}}, {"model": "auth.permission", "pk": 2609, "fields": {"name": "Can view donation configuration", "content_type": 175, "codename": "view_donationconfiguration"}}, {"model": "auth.permission", "pk": 2610, "fields": {"name": "Can view certificate item", "content_type": 174, "codename": "view_certificateitem"}}, {"model": "auth.permission", "pk": 2611, "fields": {"name": "Can view donation", "content_type": 176, "codename": "view_donation"}}, {"model": "auth.permission", "pk": 2612, "fields": {"name": "Can view course reg code item", "content_type": 171, "codename": "view_courseregcodeitem"}}, {"model": "auth.permission", "pk": 2613, "fields": {"name": "Can view paid course registration", "content_type": 170, "codename": "view_paidcourseregistration"}}, {"model": "auth.permission", "pk": 2614, "fields": {"name": "Can view course mode expiration config", "content_type": 179, "codename": "view_coursemodeexpirationconfig"}}, {"model": "auth.permission", "pk": 2615, "fields": {"name": "Can view historical course mode", "content_type": 773, "codename": "view_historicalcoursemode"}}, {"model": "auth.permission", "pk": 2616, "fields": {"name": "Can view course mode", "content_type": 177, "codename": "view_coursemode"}}, {"model": "auth.permission", "pk": 2617, "fields": {"name": "Can view course modes archive", "content_type": 178, "codename": "view_coursemodesarchive"}}, {"model": "auth.permission", "pk": 2618, "fields": {"name": "Can view course entitlement support detail", "content_type": 351, "codename": "view_courseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 2619, "fields": {"name": "Can view course entitlement policy", "content_type": 350, "codename": "view_courseentitlementpolicy"}}, {"model": "auth.permission", "pk": 2620, "fields": {"name": "Can view historical course entitlement", "content_type": 768, "codename": "view_historicalcourseentitlement"}}, {"model": "auth.permission", "pk": 2621, "fields": {"name": "Can view course entitlement", "content_type": 180, "codename": "view_courseentitlement"}}, {"model": "auth.permission", "pk": 2622, "fields": {"name": "Can view historical course entitlement support detail", "content_type": 795, "codename": "view_historicalcourseentitlementsupportdetail"}}, {"model": "auth.permission", "pk": 2623, "fields": {"name": "Can view manual verification", "content_type": 363, "codename": "view_manualverification"}}, {"model": "auth.permission", "pk": 2624, "fields": {"name": "Can view software secure photo verification", "content_type": 181, "codename": "view_softwaresecurephotoverification"}}, {"model": "auth.permission", "pk": 2625, "fields": {"name": "Can view verification deadline", "content_type": 182, "codename": "view_verificationdeadline"}}, {"model": "auth.permission", "pk": 2626, "fields": {"name": "Can view sso verification", "content_type": 354, "codename": "view_ssoverification"}}, {"model": "auth.permission", "pk": 2627, "fields": {"name": "Can view sspv retry student argument", "content_type": 790, "codename": "view_sspverificationretryconfig"}}, {"model": "auth.permission", "pk": 2628, "fields": {"name": "Can view dark lang config", "content_type": 188, "codename": "view_darklangconfig"}}, {"model": "auth.permission", "pk": 2629, "fields": {"name": "Can view whitelisted rss url", "content_type": 193, "codename": "view_whitelistedrssurl"}}, {"model": "auth.permission", "pk": 2630, "fields": {"name": "Can view course access rule history", "content_type": 199, "codename": "view_courseaccessrulehistory"}}, {"model": "auth.permission", "pk": 2631, "fields": {"name": "Can view embargoed state", "content_type": 195, "codename": "view_embargoedstate"}}, {"model": "auth.permission", "pk": 2632, "fields": {"name": "Can view country access rule", "content_type": 198, "codename": "view_countryaccessrule"}}, {"model": "auth.permission", "pk": 2633, "fields": {"name": "Can view country", "content_type": 197, "codename": "view_country"}}, {"model": "auth.permission", "pk": 2634, "fields": {"name": "Can view restricted course", "content_type": 196, "codename": "view_restrictedcourse"}}, {"model": "auth.permission", "pk": 2635, "fields": {"name": "Can view embargoed course", "content_type": 194, "codename": "view_embargoedcourse"}}, {"model": "auth.permission", "pk": 2636, "fields": {"name": "Can view ip filter", "content_type": 200, "codename": "view_ipfilter"}}, {"model": "auth.permission", "pk": 2637, "fields": {"name": "Can view course rerun state", "content_type": 201, "codename": "view_coursererunstate"}}, {"model": "auth.permission", "pk": 2638, "fields": {"name": "Can view ignore mobile available flag config", "content_type": 204, "codename": "view_ignoremobileavailableflagconfig"}}, {"model": "auth.permission", "pk": 2639, "fields": {"name": "Can view mobile api config", "content_type": 202, "codename": "view_mobileapiconfig"}}, {"model": "auth.permission", "pk": 2640, "fields": {"name": "Can view app version config", "content_type": 203, "codename": "view_appversionconfig"}}, {"model": "auth.permission", "pk": 2641, "fields": {"name": "Can view nonce", "content_type": 206, "codename": "view_nonce"}}, {"model": "auth.permission", "pk": 2642, "fields": {"name": "Can view code", "content_type": 208, "codename": "view_code"}}, {"model": "auth.permission", "pk": 2643, "fields": {"name": "Can view association", "content_type": 207, "codename": "view_association"}}, {"model": "auth.permission", "pk": 2644, "fields": {"name": "Can view partial", "content_type": 209, "codename": "view_partial"}}, {"model": "auth.permission", "pk": 2645, "fields": {"name": "Can view user social auth", "content_type": 205, "codename": "view_usersocialauth"}}, {"model": "auth.permission", "pk": 2646, "fields": {"name": "Can view survey form", "content_type": 210, "codename": "view_surveyform"}}, {"model": "auth.permission", "pk": 2647, "fields": {"name": "Can view survey answer", "content_type": 211, "codename": "view_surveyanswer"}}, {"model": "auth.permission", "pk": 2648, "fields": {"name": "Can view x block asides config", "content_type": 212, "codename": "view_xblockasidesconfig"}}, {"model": "auth.permission", "pk": 2649, "fields": {"name": "Can view submission", "content_type": 216, "codename": "view_submission"}}, {"model": "auth.permission", "pk": 2650, "fields": {"name": "Can view score annotation", "content_type": 219, "codename": "view_scoreannotation"}}, {"model": "auth.permission", "pk": 2651, "fields": {"name": "Can view score", "content_type": 217, "codename": "view_score"}}, {"model": "auth.permission", "pk": 2652, "fields": {"name": "Can view score summary", "content_type": 218, "codename": "view_scoresummary"}}, {"model": "auth.permission", "pk": 2653, "fields": {"name": "Can view student item", "content_type": 215, "codename": "view_studentitem"}}, {"model": "auth.permission", "pk": 2654, "fields": {"name": "Can view team submission", "content_type": 811, "codename": "view_teamsubmission"}}, {"model": "auth.permission", "pk": 2655, "fields": {"name": "Can view historical shared file upload", "content_type": 792, "codename": "view_historicalsharedfileupload"}}, {"model": "auth.permission", "pk": 2656, "fields": {"name": "Can view peer workflow", "content_type": 227, "codename": "view_peerworkflow"}}, {"model": "auth.permission", "pk": 2657, "fields": {"name": "Can view peer workflow item", "content_type": 228, "codename": "view_peerworkflowitem"}}, {"model": "auth.permission", "pk": 2658, "fields": {"name": "Can view assessment part", "content_type": 224, "codename": "view_assessmentpart"}}, {"model": "auth.permission", "pk": 2659, "fields": {"name": "Can view assessment", "content_type": 223, "codename": "view_assessment"}}, {"model": "auth.permission", "pk": 2660, "fields": {"name": "Can view criterion option", "content_type": 222, "codename": "view_criterionoption"}}, {"model": "auth.permission", "pk": 2661, "fields": {"name": "Can view criterion", "content_type": 221, "codename": "view_criterion"}}, {"model": "auth.permission", "pk": 2662, "fields": {"name": "Can view shared file upload", "content_type": 793, "codename": "view_sharedfileupload"}}, {"model": "auth.permission", "pk": 2663, "fields": {"name": "Can view rubric", "content_type": 220, "codename": "view_rubric"}}, {"model": "auth.permission", "pk": 2664, "fields": {"name": "Can view training example", "content_type": 229, "codename": "view_trainingexample"}}, {"model": "auth.permission", "pk": 2665, "fields": {"name": "Can view student training workflow item", "content_type": 231, "codename": "view_studenttrainingworkflowitem"}}, {"model": "auth.permission", "pk": 2666, "fields": {"name": "Can view assessment feedback option", "content_type": 225, "codename": "view_assessmentfeedbackoption"}}, {"model": "auth.permission", "pk": 2667, "fields": {"name": "Can view assessment feedback", "content_type": 226, "codename": "view_assessmentfeedback"}}, {"model": "auth.permission", "pk": 2668, "fields": {"name": "Can view student training workflow", "content_type": 230, "codename": "view_studenttrainingworkflow"}}, {"model": "auth.permission", "pk": 2669, "fields": {"name": "Can view staff workflow", "content_type": 232, "codename": "view_staffworkflow"}}, {"model": "auth.permission", "pk": 2670, "fields": {"name": "Can view team staff workflow", "content_type": 808, "codename": "view_teamstaffworkflow"}}, {"model": "auth.permission", "pk": 2671, "fields": {"name": "Can view assessment workflow", "content_type": 233, "codename": "view_assessmentworkflow"}}, {"model": "auth.permission", "pk": 2672, "fields": {"name": "Can view assessment workflow cancellation", "content_type": 235, "codename": "view_assessmentworkflowcancellation"}}, {"model": "auth.permission", "pk": 2673, "fields": {"name": "Can view assessment workflow step", "content_type": 234, "codename": "view_assessmentworkflowstep"}}, {"model": "auth.permission", "pk": 2674, "fields": {"name": "Can view team assessment workflow", "content_type": 809, "codename": "view_teamassessmentworkflow"}}, {"model": "auth.permission", "pk": 2675, "fields": {"name": "Can view profile", "content_type": 236, "codename": "view_profile"}}, {"model": "auth.permission", "pk": 2676, "fields": {"name": "Can view video transcript", "content_type": 241, "codename": "view_videotranscript"}}, {"model": "auth.permission", "pk": 2677, "fields": {"name": "Can view video image", "content_type": 240, "codename": "view_videoimage"}}, {"model": "auth.permission", "pk": 2678, "fields": {"name": "Can view course video", "content_type": 238, "codename": "view_coursevideo"}}, {"model": "auth.permission", "pk": 2679, "fields": {"name": "Can view third party transcript credentials state", "content_type": 243, "codename": "view_thirdpartytranscriptcredentialsstate"}}, {"model": "auth.permission", "pk": 2680, "fields": {"name": "Can view video", "content_type": 237, "codename": "view_video"}}, {"model": "auth.permission", "pk": 2681, "fields": {"name": "Can view encoded video", "content_type": 239, "codename": "view_encodedvideo"}}, {"model": "auth.permission", "pk": 2682, "fields": {"name": "Can view transcript preference", "content_type": 242, "codename": "view_transcriptpreference"}}, {"model": "auth.permission", "pk": 2683, "fields": {"name": "Can view transcript credentials", "content_type": 807, "codename": "view_transcriptcredentials"}}, {"model": "auth.permission", "pk": 2684, "fields": {"name": "Can view course overview", "content_type": 244, "codename": "view_courseoverview"}}, {"model": "auth.permission", "pk": 2685, "fields": {"name": "Can view course overview image set", "content_type": 246, "codename": "view_courseoverviewimageset"}}, {"model": "auth.permission", "pk": 2686, "fields": {"name": "Can view course overview tab", "content_type": 245, "codename": "view_courseoverviewtab"}}, {"model": "auth.permission", "pk": 2687, "fields": {"name": "Can view historical course overview", "content_type": 774, "codename": "view_historicalcourseoverview"}}, {"model": "auth.permission", "pk": 2688, "fields": {"name": "Can view course overview image config", "content_type": 247, "codename": "view_courseoverviewimageconfig"}}, {"model": "auth.permission", "pk": 2689, "fields": {"name": "Can view simulate_publish argument", "content_type": 784, "codename": "view_simulatecoursepublishconfig"}}, {"model": "auth.permission", "pk": 2690, "fields": {"name": "Can view block structure configuration", "content_type": 249, "codename": "view_blockstructureconfiguration"}}, {"model": "auth.permission", "pk": 2691, "fields": {"name": "Can view block structure model", "content_type": 250, "codename": "view_blockstructuremodel"}}, {"model": "auth.permission", "pk": 2692, "fields": {"name": "Can view x domain proxy configuration", "content_type": 251, "codename": "view_xdomainproxyconfiguration"}}, {"model": "auth.permission", "pk": 2693, "fields": {"name": "Can view commerce configuration", "content_type": 252, "codename": "view_commerceconfiguration"}}, {"model": "auth.permission", "pk": 2694, "fields": {"name": "Can view credit config", "content_type": 259, "codename": "view_creditconfig"}}, {"model": "auth.permission", "pk": 2695, "fields": {"name": "Can view credit requirement", "content_type": 255, "codename": "view_creditrequirement"}}, {"model": "auth.permission", "pk": 2696, "fields": {"name": "Can view credit request", "content_type": 258, "codename": "view_creditrequest"}}, {"model": "auth.permission", "pk": 2697, "fields": {"name": "Can view credit course", "content_type": 254, "codename": "view_creditcourse"}}, {"model": "auth.permission", "pk": 2698, "fields": {"name": "Can view credit eligibility", "content_type": 257, "codename": "view_crediteligibility"}}, {"model": "auth.permission", "pk": 2699, "fields": {"name": "Can view credit requirement status", "content_type": 256, "codename": "view_creditrequirementstatus"}}, {"model": "auth.permission", "pk": 2700, "fields": {"name": "Can view credit provider", "content_type": 253, "codename": "view_creditprovider"}}, {"model": "auth.permission", "pk": 2701, "fields": {"name": "Can view course team membership", "content_type": 261, "codename": "view_courseteammembership"}}, {"model": "auth.permission", "pk": 2702, "fields": {"name": "Can view course team", "content_type": 260, "codename": "view_courseteam"}}, {"model": "auth.permission", "pk": 2703, "fields": {"name": "Can view x block studio configuration", "content_type": 264, "codename": "view_xblockstudioconfiguration"}}, {"model": "auth.permission", "pk": 2704, "fields": {"name": "Can view x block configuration", "content_type": 262, "codename": "view_xblockconfiguration"}}, {"model": "auth.permission", "pk": 2705, "fields": {"name": "Can view x block studio configuration flag", "content_type": 263, "codename": "view_xblockstudioconfigurationflag"}}, {"model": "auth.permission", "pk": 2706, "fields": {"name": "Can view backpopulate_program_credentials argument", "content_type": 791, "codename": "view_customprogramsconfig"}}, {"model": "auth.permission", "pk": 2707, "fields": {"name": "Can view programs api config", "content_type": 265, "codename": "view_programsapiconfig"}}, {"model": "auth.permission", "pk": 2708, "fields": {"name": "Can view catalog integration", "content_type": 266, "codename": "view_catalogintegration"}}, {"model": "auth.permission", "pk": 2709, "fields": {"name": "Can view self paced configuration", "content_type": 267, "codename": "view_selfpacedconfiguration"}}, {"model": "auth.permission", "pk": 2710, "fields": {"name": "Can view kv store", "content_type": 268, "codename": "view_kvstore"}}, {"model": "auth.permission", "pk": 2711, "fields": {"name": "Can view course milestone", "content_type": 272, "codename": "view_coursemilestone"}}, {"model": "auth.permission", "pk": 2712, "fields": {"name": "Can view milestone", "content_type": 270, "codename": "view_milestone"}}, {"model": "auth.permission", "pk": 2713, "fields": {"name": "Can view milestone relationship type", "content_type": 271, "codename": "view_milestonerelationshiptype"}}, {"model": "auth.permission", "pk": 2714, "fields": {"name": "Can view user milestone", "content_type": 274, "codename": "view_usermilestone"}}, {"model": "auth.permission", "pk": 2715, "fields": {"name": "Can view course content milestone", "content_type": 273, "codename": "view_coursecontentmilestone"}}, {"model": "auth.permission", "pk": 2716, "fields": {"name": "Can view catalog", "content_type": 276, "codename": "view_catalog"}}, {"model": "auth.permission", "pk": 2717, "fields": {"name": "Can view api access config", "content_type": 275, "codename": "view_apiaccessconfig"}}, {"model": "auth.permission", "pk": 2718, "fields": {"name": "Can view api access request", "content_type": 1, "codename": "view_apiaccessrequest"}}, {"model": "auth.permission", "pk": 2719, "fields": {"name": "Can view verified track cohorted course", "content_type": 277, "codename": "view_verifiedtrackcohortedcourse"}}, {"model": "auth.permission", "pk": 2720, "fields": {"name": "Can view migrate verified track cohorts setting", "content_type": 278, "codename": "view_migrateverifiedtrackcohortssetting"}}, {"model": "auth.permission", "pk": 2721, "fields": {"name": "Can view course complete image configuration", "content_type": 281, "codename": "view_coursecompleteimageconfiguration"}}, {"model": "auth.permission", "pk": 2722, "fields": {"name": "Can view course event badges configuration", "content_type": 282, "codename": "view_courseeventbadgesconfiguration"}}, {"model": "auth.permission", "pk": 2723, "fields": {"name": "Can view badge class", "content_type": 279, "codename": "view_badgeclass"}}, {"model": "auth.permission", "pk": 2724, "fields": {"name": "Can view badge assertion", "content_type": 280, "codename": "view_badgeassertion"}}, {"model": "auth.permission", "pk": 2725, "fields": {"name": "Can view email marketing configuration", "content_type": 283, "codename": "view_emailmarketingconfiguration"}}, {"model": "auth.permission", "pk": 2726, "fields": {"name": "Can view failed task", "content_type": 284, "codename": "view_failedtask"}}, {"model": "auth.permission", "pk": 2727, "fields": {"name": "Can view crawlers config", "content_type": 286, "codename": "view_crawlersconfig"}}, {"model": "auth.permission", "pk": 2728, "fields": {"name": "Can view Waffle flag course override", "content_type": 287, "codename": "view_waffleflagcourseoverridemodel"}}, {"model": "auth.permission", "pk": 2729, "fields": {"name": "Can view course goal", "content_type": 291, "codename": "view_coursegoal"}}, {"model": "auth.permission", "pk": 2730, "fields": {"name": "Can view user calendar sync config", "content_type": 803, "codename": "view_usercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2731, "fields": {"name": "Can view historical user calendar sync config", "content_type": 802, "codename": "view_historicalusercalendarsyncconfig"}}, {"model": "auth.permission", "pk": 2732, "fields": {"name": "Can view course duration limit config", "content_type": 371, "codename": "view_coursedurationlimitconfig"}}, {"model": "auth.permission", "pk": 2733, "fields": {"name": "Can view content type gating config", "content_type": 372, "codename": "view_contenttypegatingconfig"}}, {"model": "auth.permission", "pk": 2734, "fields": {"name": "Can view discount percentage config", "content_type": 786, "codename": "view_discountpercentageconfig"}}, {"model": "auth.permission", "pk": 2735, "fields": {"name": "Can view discount restriction config", "content_type": 767, "codename": "view_discountrestrictionconfig"}}, {"model": "auth.permission", "pk": 2736, "fields": {"name": "Can view historical Experiment Key-Value Pair", "content_type": 804, "codename": "view_historicalexperimentkeyvalue"}}, {"model": "auth.permission", "pk": 2737, "fields": {"name": "Can view Experiment Data", "content_type": 293, "codename": "view_experimentdata"}}, {"model": "auth.permission", "pk": 2738, "fields": {"name": "Can view Experiment Key-Value Pair", "content_type": 294, "codename": "view_experimentkeyvalue"}}, {"model": "auth.permission", "pk": 2739, "fields": {"name": "Can view self paced relative dates config", "content_type": 801, "codename": "view_selfpacedrelativedatesconfig"}}, {"model": "auth.permission", "pk": 2740, "fields": {"name": "Can view external id", "content_type": 799, "codename": "view_externalid"}}, {"model": "auth.permission", "pk": 2741, "fields": {"name": "Can view historical external id", "content_type": 797, "codename": "view_historicalexternalid"}}, {"model": "auth.permission", "pk": 2742, "fields": {"name": "Can view external id type", "content_type": 800, "codename": "view_externalidtype"}}, {"model": "auth.permission", "pk": 2743, "fields": {"name": "Can view historical external id type", "content_type": 798, "codename": "view_historicalexternalidtype"}}, {"model": "auth.permission", "pk": 2744, "fields": {"name": "Can view schedule experience", "content_type": 290, "codename": "view_scheduleexperience"}}, {"model": "auth.permission", "pk": 2745, "fields": {"name": "Can view historical Schedule", "content_type": 805, "codename": "view_historicalschedule"}}, {"model": "auth.permission", "pk": 2746, "fields": {"name": "Can view Schedule", "content_type": 288, "codename": "view_schedule"}}, {"model": "auth.permission", "pk": 2747, "fields": {"name": "Can view schedule config", "content_type": 289, "codename": "view_scheduleconfig"}}, {"model": "auth.permission", "pk": 2748, "fields": {"name": "Can view historical organization", "content_type": 769, "codename": "view_historicalorganization"}}, {"model": "auth.permission", "pk": 2749, "fields": {"name": "Can view organization", "content_type": 305, "codename": "view_organization"}}, {"model": "auth.permission", "pk": 2750, "fields": {"name": "Can view Link Course", "content_type": 306, "codename": "view_organizationcourse"}}, {"model": "auth.permission", "pk": 2751, "fields": {"name": "Can view enterprise enrollment source", "content_type": 789, "codename": "view_enterpriseenrollmentsource"}}, {"model": "auth.permission", "pk": 2752, "fields": {"name": "Can view system wide enterprise role", "content_type": 381, "codename": "view_systemwideenterpriserole"}}, {"model": "auth.permission", "pk": 2753, "fields": {"name": "Can view system wide enterprise user role assignment", "content_type": 382, "codename": "view_systemwideenterpriseuserroleassignment"}}, {"model": "auth.permission", "pk": 2754, "fields": {"name": "Can view enrollment notification email template", "content_type": 321, "codename": "view_enrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 2755, "fields": {"name": "Can view Enterprise Customer Catalog", "content_type": 319, "codename": "view_enterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 2756, "fields": {"name": "Can view historical enterprise course enrollment", "content_type": 316, "codename": "view_historicalenterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 2757, "fields": {"name": "Can view historical enrollment notification email template", "content_type": 320, "codename": "view_historicalenrollmentnotificationemailtemplate"}}, {"model": "auth.permission", "pk": 2758, "fields": {"name": "Can view historical Enterprise Customer", "content_type": 307, "codename": "view_historicalenterprisecustomer"}}, {"model": "auth.permission", "pk": 2759, "fields": {"name": "Can view enterprise feature role", "content_type": 754, "codename": "view_enterprisefeaturerole"}}, {"model": "auth.permission", "pk": 2760, "fields": {"name": "Can view pending enterprise customer user", "content_type": 310, "codename": "view_pendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 2761, "fields": {"name": "Can view Enterprise Catalog Query", "content_type": 777, "codename": "view_enterprisecatalogquery"}}, {"model": "auth.permission", "pk": 2762, "fields": {"name": "Can view enterprise course enrollment", "content_type": 317, "codename": "view_enterprisecourseenrollment"}}, {"model": "auth.permission", "pk": 2763, "fields": {"name": "Can view enterprise feature user role assignment", "content_type": 753, "codename": "view_enterprisefeatureuserroleassignment"}}, {"model": "auth.permission", "pk": 2764, "fields": {"name": "Can view historical pending enterprise customer user", "content_type": 779, "codename": "view_historicalpendingenterprisecustomeruser"}}, {"model": "auth.permission", "pk": 2765, "fields": {"name": "Can view Enterprise Customer Type", "content_type": 375, "codename": "view_enterprisecustomertype"}}, {"model": "auth.permission", "pk": 2766, "fields": {"name": "Can view pending enrollment", "content_type": 311, "codename": "view_pendingenrollment"}}, {"model": "auth.permission", "pk": 2767, "fields": {"name": "Can view historical Enterprise Customer Catalog", "content_type": 318, "codename": "view_historicalenterprisecustomercatalog"}}, {"model": "auth.permission", "pk": 2768, "fields": {"name": "Can view enterprise customer reporting configuration", "content_type": 322, "codename": "view_enterprisecustomerreportingconfiguration"}}, {"model": "auth.permission", "pk": 2769, "fields": {"name": "Can view Branding Configuration", "content_type": 312, "codename": "view_enterprisecustomerbrandingconfiguration"}}, {"model": "auth.permission", "pk": 2770, "fields": {"name": "Can view historical pending enrollment", "content_type": 778, "codename": "view_historicalpendingenrollment"}}, {"model": "auth.permission", "pk": 2771, "fields": {"name": "Can view Enterprise Customer", "content_type": 308, "codename": "view_enterprisecustomer"}}, {"model": "auth.permission", "pk": 2772, "fields": {"name": "Can view enterprise customer identity provider", "content_type": 313, "codename": "view_enterprisecustomeridentityprovider"}}, {"model": "auth.permission", "pk": 2773, "fields": {"name": "Can view Enterprise Customer Learner", "content_type": 309, "codename": "view_enterprisecustomeruser"}}, {"model": "auth.permission", "pk": 2774, "fields": {"name": "Can view Data Sharing Consent Record", "content_type": 324, "codename": "view_datasharingconsent"}}, {"model": "auth.permission", "pk": 2775, "fields": {"name": "Can view data sharing consent text overrides", "content_type": 357, "codename": "view_datasharingconsenttextoverrides"}}, {"model": "auth.permission", "pk": 2776, "fields": {"name": "Can view historical Data Sharing Consent Record", "content_type": 323, "codename": "view_historicaldatasharingconsent"}}, {"model": "auth.permission", "pk": 2777, "fields": {"name": "Can view learner data transmission audit", "content_type": 325, "codename": "view_learnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2778, "fields": {"name": "Can view content metadata item transmission", "content_type": 352, "codename": "view_contentmetadataitemtransmission"}}, {"model": "auth.permission", "pk": 2779, "fields": {"name": "Can view historical degreed enterprise customer configuration", "content_type": 328, "codename": "view_historicaldegreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2780, "fields": {"name": "Can view degreed enterprise customer configuration", "content_type": 329, "codename": "view_degreedenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2781, "fields": {"name": "Can view degreed global configuration", "content_type": 327, "codename": "view_degreedglobalconfiguration"}}, {"model": "auth.permission", "pk": 2782, "fields": {"name": "Can view degreed learner data transmission audit", "content_type": 330, "codename": "view_degreedlearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2783, "fields": {"name": "Can view sap success factors learner data transmission audit", "content_type": 334, "codename": "view_sapsuccessfactorslearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2784, "fields": {"name": "Can view sap success factors global configuration", "content_type": 331, "codename": "view_sapsuccessfactorsglobalconfiguration"}}, {"model": "auth.permission", "pk": 2785, "fields": {"name": "Can view sap success factors enterprise customer configuration", "content_type": 333, "codename": "view_sapsuccessfactorsenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2786, "fields": {"name": "Can view historical cornerstone enterprise customer configuration", "content_type": 764, "codename": "view_historicalcornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2787, "fields": {"name": "Can view cornerstone learner data transmission audit", "content_type": 765, "codename": "view_cornerstonelearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2788, "fields": {"name": "Can view cornerstone global configuration", "content_type": 763, "codename": "view_cornerstoneglobalconfiguration"}}, {"model": "auth.permission", "pk": 2789, "fields": {"name": "Can view cornerstone enterprise customer configuration", "content_type": 766, "codename": "view_cornerstoneenterprisecustomerconfiguration"}}, {"model": "auth.permission", "pk": 2790, "fields": {"name": "Can view xapi learner data transmission audit", "content_type": 780, "codename": "view_xapilearnerdatatransmissionaudit"}}, {"model": "auth.permission", "pk": 2791, "fields": {"name": "Can view xapilrs configuration", "content_type": 367, "codename": "view_xapilrsconfiguration"}}, {"model": "auth.permission", "pk": 2792, "fields": {"name": "Can view program enrollment", "content_type": 755, "codename": "view_programenrollment"}}, {"model": "auth.permission", "pk": 2793, "fields": {"name": "Can view historical program course enrollment", "content_type": 758, "codename": "view_historicalprogramcourseenrollment"}}, {"model": "auth.permission", "pk": 2794, "fields": {"name": "Can view program course enrollment", "content_type": 757, "codename": "view_programcourseenrollment"}}, {"model": "auth.permission", "pk": 2795, "fields": {"name": "Can view course access role assignment", "content_type": 810, "codename": "view_courseaccessroleassignment"}}, {"model": "auth.permission", "pk": 2796, "fields": {"name": "Can view historical program enrollment", "content_type": 756, "codename": "view_historicalprogramenrollment"}}, {"model": "auth.permission", "pk": 2797, "fields": {"name": "Can view bookmark", "content_type": 36, "codename": "view_bookmark"}}, {"model": "auth.permission", "pk": 2798, "fields": {"name": "Can view x block cache", "content_type": 37, "codename": "view_xblockcache"}}, {"model": "auth.permission", "pk": 2799, "fields": {"name": "Can view persistent grades enabled flag", "content_type": 108, "codename": "view_persistentgradesenabledflag"}}, {"model": "auth.permission", "pk": 2800, "fields": {"name": "Can view course persistent grades flag", "content_type": 109, "codename": "view_coursepersistentgradesflag"}}, {"model": "auth.permission", "pk": 2801, "fields": {"name": "Can view compute grades setting", "content_type": 110, "codename": "view_computegradessetting"}}, {"model": "auth.permission", "pk": 2802, "fields": {"name": "Can view historical persistent subsection grade override", "content_type": 770, "codename": "view_historicalpersistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 2803, "fields": {"name": "Can view persistent subsection grade override", "content_type": 107, "codename": "view_persistentsubsectiongradeoverride"}}, {"model": "auth.permission", "pk": 2804, "fields": {"name": "Can view persistent subsection grade", "content_type": 105, "codename": "view_persistentsubsectiongrade"}}, {"model": "auth.permission", "pk": 2805, "fields": {"name": "Can view visible blocks", "content_type": 104, "codename": "view_visibleblocks"}}, {"model": "auth.permission", "pk": 2806, "fields": {"name": "Can view persistent course grade", "content_type": 106, "codename": "view_persistentcoursegrade"}}, {"model": "auth.permission", "pk": 2807, "fields": {"name": "Can view announcement", "content_type": 383, "codename": "view_announcement"}}, {"model": "auth.permission", "pk": 2808, "fields": {"name": "Can view site theme", "content_type": 26, "codename": "view_sitetheme"}}, {"model": "auth.permission", "pk": 2809, "fields": {"name": "Can view content library", "content_type": 782, "codename": "view_contentlibrary"}}, {"model": "auth.permission", "pk": 2810, "fields": {"name": "Can view content library permission", "content_type": 783, "codename": "view_contentlibrarypermission"}}, {"model": "auth.permission", "pk": 2811, "fields": {"name": "Can view credentials api config", "content_type": 269, "codename": "view_credentialsapiconfig"}}, {"model": "auth.permission", "pk": 2812, "fields": {"name": "Can view notify_credentials argument", "content_type": 368, "codename": "view_notifycredentialsconfig"}}, {"model": "auth.permission", "pk": 2813, "fields": {"name": "Can view csv operation", "content_type": 771, "codename": "view_csvoperation"}}, {"model": "auth.permission", "pk": 2814, "fields": {"name": "Can view user date", "content_type": 760, "codename": "view_userdate"}}, {"model": "auth.permission", "pk": 2815, "fields": {"name": "Can view date policy", "content_type": 761, "codename": "view_datepolicy"}}, {"model": "auth.permission", "pk": 2816, "fields": {"name": "Can view content date", "content_type": 759, "codename": "view_contentdate"}}, {"model": "auth.permission", "pk": 2817, "fields": {"name": "Can view proctored exam review policy history", "content_type": 297, "codename": "view_proctoredexamreviewpolicyhistory"}}, {"model": "auth.permission", "pk": 2818, "fields": {"name": "Can view proctored exam software secure comment", "content_type": 304, "codename": "view_proctoredexamsoftwaresecurecomment"}}, {"model": "auth.permission", "pk": 2819, "fields": {"name": "Can view proctored allowance", "content_type": 300, "codename": "view_proctoredexamstudentallowance"}}, {"model": "auth.permission", "pk": 2820, "fields": {"name": "Can view proctored exam attempt history", "content_type": 299, "codename": "view_proctoredexamstudentattempthistory"}}, {"model": "auth.permission", "pk": 2821, "fields": {"name": "Can view proctored exam attempt", "content_type": 298, "codename": "view_proctoredexamstudentattempt"}}, {"model": "auth.permission", "pk": 2822, "fields": {"name": "Can view proctored exam", "content_type": 295, "codename": "view_proctoredexam"}}, {"model": "auth.permission", "pk": 2823, "fields": {"name": "Can view Proctored exam software secure review", "content_type": 302, "codename": "view_proctoredexamsoftwaresecurereview"}}, {"model": "auth.permission", "pk": 2824, "fields": {"name": "Can view proctored allowance history", "content_type": 301, "codename": "view_proctoredexamstudentallowancehistory"}}, {"model": "auth.permission", "pk": 2825, "fields": {"name": "Can view Proctored exam review policy", "content_type": 296, "codename": "view_proctoredexamreviewpolicy"}}, {"model": "auth.permission", "pk": 2826, "fields": {"name": "Can view Proctored exam review archive", "content_type": 303, "codename": "view_proctoredexamsoftwaresecurereviewhistory"}}, {"model": "auth.permission", "pk": 2827, "fields": {"name": "Can view block completion", "content_type": 292, "codename": "view_blockcompletion"}}, {"model": "auth.permission", "pk": 2828, "fields": {"name": "Can view score overrider", "content_type": 772, "codename": "view_scoreoverrider"}}, {"model": "auth.permission", "pk": 2829, "fields": {"name": "Can view ccx field override", "content_type": 336, "codename": "view_ccxfieldoverride"}}, {"model": "auth.permission", "pk": 2830, "fields": {"name": "Can view custom course for ed x", "content_type": 335, "codename": "view_customcourseforedx"}}, {"model": "auth.permission", "pk": 2831, "fields": {"name": "Can view CCX Connector", "content_type": 337, "codename": "view_ccxcon"}}, {"model": "auth.permission", "pk": 2832, "fields": {"name": "Can view lti user", "content_type": 379, "codename": "view_ltiuser"}}, {"model": "auth.permission", "pk": 2833, "fields": {"name": "Can view outcome service", "content_type": 380, "codename": "view_outcomeservice"}}, {"model": "auth.permission", "pk": 2834, "fields": {"name": "Can view lti consumer", "content_type": 377, "codename": "view_lticonsumer"}}, {"model": "auth.permission", "pk": 2835, "fields": {"name": "Can view graded assignment", "content_type": 378, "codename": "view_gradedassignment"}}, {"model": "auth.permission", "pk": 2836, "fields": {"name": "Can view video upload config", "content_type": 339, "codename": "view_videouploadconfig"}}, {"model": "auth.permission", "pk": 2837, "fields": {"name": "Can view course creator", "content_type": 343, "codename": "view_coursecreator"}}, {"model": "auth.permission", "pk": 2838, "fields": {"name": "Can view course edit lti fields enabled flag", "content_type": 345, "codename": "view_courseeditltifieldsenabledflag"}}, {"model": "auth.permission", "pk": 2839, "fields": {"name": "Can view studio config", "content_type": 344, "codename": "view_studioconfig"}}, {"model": "auth.permission", "pk": 2840, "fields": {"name": "Can view tag category", "content_type": 346, "codename": "view_tagcategories"}}, {"model": "auth.permission", "pk": 2841, "fields": {"name": "Can view available tag value", "content_type": 347, "codename": "view_tagavailablevalues"}}, {"model": "auth.permission", "pk": 2842, "fields": {"name": "Can view user task status", "content_type": 348, "codename": "view_usertaskstatus"}}, {"model": "auth.permission", "pk": 2843, "fields": {"name": "Can view user task artifact", "content_type": 349, "codename": "view_usertaskartifact"}}, {"model": "auth.permission", "pk": 2844, "fields": {"name": "Can add vem pipeline integration", "content_type": 812, "codename": "add_vempipelineintegration"}}, {"model": "auth.permission", "pk": 2845, "fields": {"name": "Can change vem pipeline integration", "content_type": 812, "codename": "change_vempipelineintegration"}}, {"model": "auth.permission", "pk": 2846, "fields": {"name": "Can delete vem pipeline integration", "content_type": 812, "codename": "delete_vempipelineintegration"}}, {"model": "auth.permission", "pk": 2847, "fields": {"name": "Can view vem pipeline integration", "content_type": 812, "codename": "view_vempipelineintegration"}}, {"model": "auth.permission", "pk": 2848, "fields": {"name": "Can add course section", "content_type": 815, "codename": "add_coursesection"}}, {"model": "auth.permission", "pk": 2849, "fields": {"name": "Can change course section", "content_type": 815, "codename": "change_coursesection"}}, {"model": "auth.permission", "pk": 2850, "fields": {"name": "Can delete course section", "content_type": 815, "codename": "delete_coursesection"}}, {"model": "auth.permission", "pk": 2851, "fields": {"name": "Can view course section", "content_type": 815, "codename": "view_coursesection"}}, {"model": "auth.permission", "pk": 2852, "fields": {"name": "Can add course section sequence", "content_type": 813, "codename": "add_coursesectionsequence"}}, {"model": "auth.permission", "pk": 2853, "fields": {"name": "Can change course section sequence", "content_type": 813, "codename": "change_coursesectionsequence"}}, {"model": "auth.permission", "pk": 2854, "fields": {"name": "Can delete course section sequence", "content_type": 813, "codename": "delete_coursesectionsequence"}}, {"model": "auth.permission", "pk": 2855, "fields": {"name": "Can view course section sequence", "content_type": 813, "codename": "view_coursesectionsequence"}}, {"model": "auth.permission", "pk": 2856, "fields": {"name": "Can add learning sequence", "content_type": 814, "codename": "add_learningsequence"}}, {"model": "auth.permission", "pk": 2857, "fields": {"name": "Can change learning sequence", "content_type": 814, "codename": "change_learningsequence"}}, {"model": "auth.permission", "pk": 2858, "fields": {"name": "Can delete learning sequence", "content_type": 814, "codename": "delete_learningsequence"}}, {"model": "auth.permission", "pk": 2859, "fields": {"name": "Can view learning sequence", "content_type": 814, "codename": "view_learningsequence"}}, {"model": "auth.permission", "pk": 2860, "fields": {"name": "Can add learning context", "content_type": 816, "codename": "add_learningcontext"}}, {"model": "auth.permission", "pk": 2861, "fields": {"name": "Can change learning context", "content_type": 816, "codename": "change_learningcontext"}}, {"model": "auth.permission", "pk": 2862, "fields": {"name": "Can delete learning context", "content_type": 816, "codename": "delete_learningcontext"}}, {"model": "auth.permission", "pk": 2863, "fields": {"name": "Can view learning context", "content_type": 816, "codename": "view_learningcontext"}}, {"model": "auth.permission", "pk": 2864, "fields": {"name": "Can add course enrollment celebration", "content_type": 817, "codename": "add_courseenrollmentcelebration"}}, {"model": "auth.permission", "pk": 2865, "fields": {"name": "Can change course enrollment celebration", "content_type": 817, "codename": "change_courseenrollmentcelebration"}}, {"model": "auth.permission", "pk": 2866, "fields": {"name": "Can delete course enrollment celebration", "content_type": 817, "codename": "delete_courseenrollmentcelebration"}}, {"model": "auth.permission", "pk": 2867, "fields": {"name": "Can view course enrollment celebration", "content_type": 817, "codename": "view_courseenrollmentcelebration"}}, {"model": "auth.group", "pk": 1, "fields": {"name": "API Access Request Approvers", "permissions": []}}, {"model": "auth.user", "pk": 1, "fields": {"password": "!FXJJHcjbqdW2yNqrkNvJXSnTXxNZVYIj3SsIt7BB", "last_login": null, "is_superuser": false, "username": "ecommerce_worker", "first_name": "", "last_name": "", "email": "ecommerce_worker@example.com", "is_staff": false, "is_active": true, "date_joined": "2017-12-06T02:20:20.329Z", "groups": [], "user_permissions": []}}, {"model": "auth.user", "pk": 2, "fields": {"password": "!rUv06Bh8BQoqyhkOEl2BtUKUwOX3NlpCVPBSwqBj", "last_login": null, "is_superuser": false, "username": "login_service_user", "first_name": "", "last_name": "", "email": "login_service_user@fake.email", "is_staff": false, "is_active": true, "date_joined": "2018-10-25T14:53:08.044Z", "groups": [], "user_permissions": []}}, {"model": "waffle.flag", "pk": 2, "fields": {"name": "grades.rejected_exam_overrides_grade", "everyone": true, "percent": null, "testing": false, "superusers": true, "staff": false, "authenticated": false, "languages": "", "rollout": false, "note": "", "created": "2020-06-23T18:17:18.349Z", "modified": "2020-06-23T18:17:18.349Z", "groups": [], "users": []}}, {"model": "waffle.flag", "pk": 3, "fields": {"name": "grades.enforce_freeze_grade_after_course_end", "everyone": true, "percent": null, "testing": false, "superusers": true, "staff": false, "authenticated": false, "languages": "", "rollout": false, "note": "", "created": "2020-06-23T18:17:18.351Z", "modified": "2020-06-23T18:17:18.351Z", "groups": [], "users": []}}, {"model": "waffle.flag", "pk": 4, "fields": {"name": "grades.writable_gradebook", "everyone": true, "percent": null, "testing": false, "superusers": true, "staff": false, "authenticated": false, "languages": "", "rollout": false, "note": "", "created": "2020-06-23T18:17:18.352Z", "modified": "2020-06-23T18:17:18.352Z", "groups": [], "users": []}}, {"model": "waffle.flag", "pk": 5, "fields": {"name": "studio.enable_checklists_quality", "everyone": true, "percent": null, "testing": false, "superusers": true, "staff": false, "authenticated": false, "languages": "", "rollout": false, "note": "", "created": "2020-06-23T18:17:25.578Z", "modified": "2020-06-23T18:17:25.578Z", "groups": [], "users": []}}, {"model": "util.ratelimitconfiguration", "pk": 1, "fields": {"change_date": "2017-12-06T02:37:46.125Z", "changed_by": null, "enabled": true}}, {"model": "certificates.certificatehtmlviewconfiguration", "pk": 1, "fields": {"change_date": "2017-12-06T02:19:25.679Z", "changed_by": null, "enabled": false, "configuration": "{\"default\": {\"accomplishment_class_append\": \"accomplishment-certificate\", \"platform_name\": \"Your Platform Name Here\", \"logo_src\": \"/static/certificates/images/logo.png\", \"logo_url\": \"http://www.example.com\", \"company_verified_certificate_url\": \"http://www.example.com/verified-certificate\", \"company_privacy_url\": \"http://www.example.com/privacy-policy\", \"company_tos_url\": \"http://www.example.com/terms-service\", \"company_about_url\": \"http://www.example.com/about-us\"}, \"verified\": {\"certificate_type\": \"Verified\", \"certificate_title\": \"Verified Certificate of Achievement\"}, \"honor\": {\"certificate_type\": \"Honor Code\", \"certificate_title\": \"Certificate of Achievement\"}}"}}, {"model": "oauth2_provider.application", "pk": 2, "fields": {"client_id": "login-service-client-id", "user": 2, "redirect_uris": "", "client_type": "public", "authorization_grant_type": "password", "client_secret": "mpAwLT424Wm3HQfjVydNCceq7ZOERB72jVuzLSo0B7KldmPHqCmYQNyCMS2mklqzJN4XyT7VRcqHG7bHC0KDHIqcOAMpMisuCi7jIigmseHKKLjgjsx6DM9Rem2cOvO6", "name": "Login Service for JWT Cookies", "skip_authorization": false, "created": "2018-10-25T14:53:08.054Z", "updated": "2018-10-25T14:53:08.054Z"}}, {"model": "django_comment_common.forumsconfig", "pk": 1, "fields": {"change_date": "2017-12-06T02:23:41.040Z", "changed_by": null, "enabled": true, "connection_timeout": 5.0}}, {"model": "dark_lang.darklangconfig", "pk": 1, "fields": {"change_date": "2017-12-06T02:22:45.120Z", "changed_by": null, "enabled": true, "released_languages": "", "enable_beta_languages": false, "beta_languages": ""}}] \ No newline at end of file diff --git a/common/test/db_cache/bok_choy_migrations.sha1 b/common/test/db_cache/bok_choy_migrations.sha1 index 1311ee60cfc61a9eb5222c79e06cb11ebbe9c7fa..08072a3c9120a771c6af736111ce5833c78d6584 100644 --- a/common/test/db_cache/bok_choy_migrations.sha1 +++ b/common/test/db_cache/bok_choy_migrations.sha1 @@ -1 +1 @@ -e2be4fc5e35d49a0ec3cff56751740b4bdbcb41b \ No newline at end of file +e42930e39a6b1f89c3afef535915680b96b8f452 \ No newline at end of file diff --git a/common/test/db_cache/bok_choy_migrations_data_default.sql b/common/test/db_cache/bok_choy_migrations_data_default.sql index d8e46dd60c0e3e05abe135314c73106a5beb64ac..76468df736dda699b851ee7bed881d31b1439801 100644 --- a/common/test/db_cache/bok_choy_migrations_data_default.sql +++ b/common/test/db_cache/bok_choy_migrations_data_default.sql @@ -12,7 +12,7 @@ LOCK TABLES `django_migrations` WRITE; /*!40000 ALTER TABLE `django_migrations` DISABLE KEYS */; -INSERT INTO `django_migrations` VALUES (1,'contenttypes','0001_initial','2019-02-06 07:56:07.314317'),(2,'auth','0001_initial','2019-02-06 07:56:07.832368'),(3,'admin','0001_initial','2019-02-06 07:56:07.961256'),(4,'admin','0002_logentry_remove_auto_add','2019-02-06 07:56:08.013912'),(5,'sites','0001_initial','2019-02-06 07:56:08.072888'),(6,'contenttypes','0002_remove_content_type_name','2019-02-06 07:56:08.230528'),(7,'api_admin','0001_initial','2019-02-06 07:56:08.454101'),(8,'api_admin','0002_auto_20160325_1604','2019-02-06 07:56:08.533622'),(9,'api_admin','0003_auto_20160404_1618','2019-02-06 07:56:08.983603'),(10,'api_admin','0004_auto_20160412_1506','2019-02-06 07:56:09.311723'),(11,'api_admin','0005_auto_20160414_1232','2019-02-06 07:56:09.410291'),(12,'api_admin','0006_catalog','2019-02-06 07:56:09.439372'),(13,'api_admin','0007_delete_historical_api_records','2019-02-06 07:56:09.673117'),(14,'assessment','0001_initial','2019-02-06 07:56:11.477983'),(15,'assessment','0002_staffworkflow','2019-02-06 07:56:11.625937'),(16,'assessment','0003_expand_course_id','2019-02-06 07:56:11.815858'),(17,'auth','0002_alter_permission_name_max_length','2019-02-06 07:56:11.891156'),(18,'auth','0003_alter_user_email_max_length','2019-02-06 07:56:11.975525'),(19,'auth','0004_alter_user_username_opts','2019-02-06 07:56:12.013750'),(20,'auth','0005_alter_user_last_login_null','2019-02-06 07:56:12.096481'),(21,'auth','0006_require_contenttypes_0002','2019-02-06 07:56:12.108286'),(22,'auth','0007_alter_validators_add_error_messages','2019-02-06 07:56:12.164989'),(23,'auth','0008_alter_user_username_max_length','2019-02-06 07:56:12.240860'),(24,'instructor_task','0001_initial','2019-02-06 07:56:12.395820'),(25,'certificates','0001_initial','2019-02-06 07:56:13.480164'),(26,'certificates','0002_data__certificatehtmlviewconfiguration_data','2019-02-06 07:56:13.607503'),(27,'certificates','0003_data__default_modes','2019-02-06 07:56:13.751659'),(28,'certificates','0004_certificategenerationhistory','2019-02-06 07:56:13.904399'),(29,'certificates','0005_auto_20151208_0801','2019-02-06 07:56:13.986383'),(30,'certificates','0006_certificatetemplateasset_asset_slug','2019-02-06 07:56:14.058304'),(31,'certificates','0007_certificateinvalidation','2019-02-06 07:56:14.210453'),(32,'badges','0001_initial','2019-02-06 07:56:14.782804'),(33,'badges','0002_data__migrate_assertions','2019-02-06 07:56:15.175628'),(34,'badges','0003_schema__add_event_configuration','2019-02-06 07:56:15.324266'),(35,'block_structure','0001_config','2019-02-06 07:56:15.455000'),(36,'block_structure','0002_blockstructuremodel','2019-02-06 07:56:15.522120'),(37,'block_structure','0003_blockstructuremodel_storage','2019-02-06 07:56:15.564915'),(38,'block_structure','0004_blockstructuremodel_usagekeywithrun','2019-02-06 07:56:15.616240'),(39,'bookmarks','0001_initial','2019-02-06 07:56:16.017402'),(40,'branding','0001_initial','2019-02-06 07:56:16.267188'),(41,'course_modes','0001_initial','2019-02-06 07:56:16.438443'),(42,'course_modes','0002_coursemode_expiration_datetime_is_explicit','2019-02-06 07:56:16.519337'),(43,'course_modes','0003_auto_20151113_1443','2019-02-06 07:56:16.576659'),(44,'course_modes','0004_auto_20151113_1457','2019-02-06 07:56:16.732369'),(45,'course_modes','0005_auto_20151217_0958','2019-02-06 07:56:16.788036'),(46,'course_modes','0006_auto_20160208_1407','2019-02-06 07:56:16.883873'),(47,'course_modes','0007_coursemode_bulk_sku','2019-02-06 07:56:17.029222'),(48,'course_groups','0001_initial','2019-02-06 07:56:18.181254'),(49,'bulk_email','0001_initial','2019-02-06 07:56:18.660435'),(50,'bulk_email','0002_data__load_course_email_template','2019-02-06 07:56:18.937143'),(51,'bulk_email','0003_config_model_feature_flag','2019-02-06 07:56:19.093038'),(52,'bulk_email','0004_add_email_targets','2019-02-06 07:56:19.788595'),(53,'bulk_email','0005_move_target_data','2019-02-06 07:56:19.959402'),(54,'bulk_email','0006_course_mode_targets','2019-02-06 07:56:20.165336'),(55,'catalog','0001_initial','2019-02-06 07:56:20.308745'),(56,'catalog','0002_catalogintegration_username','2019-02-06 07:56:20.439737'),(57,'catalog','0003_catalogintegration_page_size','2019-02-06 07:56:20.584307'),(58,'catalog','0004_auto_20170616_0618','2019-02-06 07:56:20.692298'),(59,'catalog','0005_catalogintegration_long_term_cache_ttl','2019-02-06 07:56:20.821560'),(60,'django_comment_common','0001_initial','2019-02-06 07:56:21.271577'),(61,'django_comment_common','0002_forumsconfig','2019-02-06 07:56:21.463632'),(62,'verified_track_content','0001_initial','2019-02-06 07:56:21.537783'),(63,'course_overviews','0001_initial','2019-02-06 07:56:21.715657'),(64,'course_overviews','0002_add_course_catalog_fields','2019-02-06 07:56:21.984772'),(65,'course_overviews','0003_courseoverviewgeneratedhistory','2019-02-06 07:56:22.053252'),(66,'course_overviews','0004_courseoverview_org','2019-02-06 07:56:22.134954'),(67,'course_overviews','0005_delete_courseoverviewgeneratedhistory','2019-02-06 07:56:22.184071'),(68,'course_overviews','0006_courseoverviewimageset','2019-02-06 07:56:22.290455'),(69,'course_overviews','0007_courseoverviewimageconfig','2019-02-06 07:56:22.466348'),(70,'course_overviews','0008_remove_courseoverview_facebook_url','2019-02-06 07:56:22.484576'),(71,'course_overviews','0009_readd_facebook_url','2019-02-06 07:56:22.501725'),(72,'course_overviews','0010_auto_20160329_2317','2019-02-06 07:56:22.645825'),(73,'ccx','0001_initial','2019-02-06 07:56:23.183002'),(74,'ccx','0002_customcourseforedx_structure_json','2019-02-06 07:56:23.289052'),(75,'ccx','0003_add_master_course_staff_in_ccx','2019-02-06 07:56:23.840989'),(76,'ccx','0004_seed_forum_roles_in_ccx_courses','2019-02-06 07:56:23.988777'),(77,'ccx','0005_change_ccx_coach_to_staff','2019-02-06 07:56:24.160387'),(78,'ccx','0006_set_display_name_as_override','2019-02-06 07:56:24.337876'),(79,'ccxcon','0001_initial_ccxcon_model','2019-02-06 07:56:24.409092'),(80,'ccxcon','0002_auto_20160325_0407','2019-02-06 07:56:24.470172'),(81,'djcelery','0001_initial','2019-02-06 07:56:25.046777'),(82,'celery_utils','0001_initial','2019-02-06 07:56:25.165469'),(83,'celery_utils','0002_chordable_django_backend','2019-02-06 07:56:25.339734'),(84,'certificates','0008_schema__remove_badges','2019-02-06 07:56:25.535263'),(85,'certificates','0009_certificategenerationcoursesetting_language_self_generation','2019-02-06 07:56:25.851268'),(86,'certificates','0010_certificatetemplate_language','2019-02-06 07:56:25.927039'),(87,'certificates','0011_certificatetemplate_alter_unique','2019-02-06 07:56:26.154544'),(88,'certificates','0012_certificategenerationcoursesetting_include_hours_of_effort','2019-02-06 07:56:26.228554'),(89,'certificates','0013_remove_certificategenerationcoursesetting_enabled','2019-02-06 07:56:26.310926'),(90,'certificates','0014_change_eligible_certs_manager','2019-02-06 07:56:26.373051'),(91,'commerce','0001_data__add_ecommerce_service_user','2019-02-06 07:56:26.595906'),(92,'commerce','0002_commerceconfiguration','2019-02-06 07:56:26.698815'),(93,'commerce','0003_auto_20160329_0709','2019-02-06 07:56:26.761254'),(94,'commerce','0004_auto_20160531_0950','2019-02-06 07:56:27.150989'),(95,'commerce','0005_commerceconfiguration_enable_automatic_refund_approval','2019-02-06 07:56:27.241421'),(96,'commerce','0006_auto_20170424_1734','2019-02-06 07:56:27.316222'),(97,'commerce','0007_auto_20180313_0609','2019-02-06 07:56:27.466841'),(98,'completion','0001_initial','2019-02-06 07:56:27.696977'),(99,'completion','0002_auto_20180125_1510','2019-02-06 07:56:27.757853'),(100,'enterprise','0001_initial','2019-02-06 07:56:28.027244'),(101,'enterprise','0002_enterprisecustomerbrandingconfiguration','2019-02-06 07:56:28.117647'),(102,'enterprise','0003_auto_20161104_0937','2019-02-06 07:56:28.428631'),(103,'enterprise','0004_auto_20161114_0434','2019-02-06 07:56:28.594141'),(104,'enterprise','0005_pendingenterprisecustomeruser','2019-02-06 07:56:28.710577'),(105,'enterprise','0006_auto_20161121_0241','2019-02-06 07:56:28.775663'),(106,'enterprise','0007_auto_20161109_1511','2019-02-06 07:56:28.924039'),(107,'enterprise','0008_auto_20161124_2355','2019-02-06 07:56:29.200628'),(108,'enterprise','0009_auto_20161130_1651','2019-02-06 07:56:29.740933'),(109,'enterprise','0010_auto_20161222_1212','2019-02-06 07:56:29.889801'),(110,'enterprise','0011_enterprisecustomerentitlement_historicalenterprisecustomerentitlement','2019-02-06 07:56:30.134143'),(111,'enterprise','0012_auto_20170125_1033','2019-02-06 07:56:30.264122'),(112,'enterprise','0013_auto_20170125_1157','2019-02-06 07:56:30.893749'),(113,'enterprise','0014_enrollmentnotificationemailtemplate_historicalenrollmentnotificationemailtemplate','2019-02-06 07:56:31.215731'),(114,'enterprise','0015_auto_20170130_0003','2019-02-06 07:56:31.450278'),(115,'enterprise','0016_auto_20170405_0647','2019-02-06 07:56:32.231656'),(116,'enterprise','0017_auto_20170508_1341','2019-02-06 07:56:32.492394'),(117,'enterprise','0018_auto_20170511_1357','2019-02-06 07:56:32.686868'),(118,'enterprise','0019_auto_20170606_1853','2019-02-06 07:56:32.884924'),(119,'enterprise','0020_auto_20170624_2316','2019-02-06 07:56:33.722514'),(120,'enterprise','0021_auto_20170711_0712','2019-02-06 07:56:34.290994'),(121,'enterprise','0022_auto_20170720_1543','2019-02-06 07:56:34.459932'),(122,'enterprise','0023_audit_data_reporting_flag','2019-02-06 07:56:34.693710'),(123,'enterprise','0024_enterprisecustomercatalog_historicalenterprisecustomercatalog','2019-02-06 07:56:34.991211'),(124,'enterprise','0025_auto_20170828_1412','2019-02-06 07:56:35.555899'),(125,'enterprise','0026_make_require_account_level_consent_nullable','2019-02-06 07:56:35.765541'),(126,'enterprise','0027_remove_account_level_consent','2019-02-06 07:56:36.799493'),(127,'enterprise','0028_link_enterprise_to_enrollment_template','2019-02-06 07:56:37.434413'),(128,'enterprise','0029_auto_20170925_1909','2019-02-06 07:56:37.650440'),(129,'enterprise','0030_auto_20171005_1600','2019-02-06 07:56:38.219936'),(130,'enterprise','0031_auto_20171012_1249','2019-02-06 07:56:38.438979'),(131,'enterprise','0032_reporting_model','2019-02-06 07:56:38.594362'),(132,'enterprise','0033_add_history_change_reason_field','2019-02-06 07:56:39.182772'),(133,'enterprise','0034_auto_20171023_0727','2019-02-06 07:56:39.321896'),(134,'enterprise','0035_auto_20171212_1129','2019-02-06 07:56:39.517158'),(135,'enterprise','0036_sftp_reporting_support','2019-02-06 07:56:39.958256'),(136,'enterprise','0037_auto_20180110_0450','2019-02-06 07:56:40.144689'),(137,'enterprise','0038_auto_20180122_1427','2019-02-06 07:56:40.326004'),(138,'enterprise','0039_auto_20180129_1034','2019-02-06 07:56:40.539093'),(139,'enterprise','0040_auto_20180129_1428','2019-02-06 07:56:40.854288'),(140,'enterprise','0041_auto_20180212_1507','2019-02-06 07:56:41.037158'),(141,'consent','0001_initial','2019-02-06 07:56:41.608778'),(142,'consent','0002_migrate_to_new_data_sharing_consent','2019-02-06 07:56:42.267785'),(143,'consent','0003_historicaldatasharingconsent_history_change_reason','2019-02-06 07:56:42.405847'),(144,'consent','0004_datasharingconsenttextoverrides','2019-02-06 07:56:42.584250'),(145,'sites','0002_alter_domain_unique','2019-02-06 07:56:42.663878'),(146,'course_overviews','0011_courseoverview_marketing_url','2019-02-06 07:56:42.745921'),(147,'course_overviews','0012_courseoverview_eligible_for_financial_aid','2019-02-06 07:56:42.834692'),(148,'course_overviews','0013_courseoverview_language','2019-02-06 07:56:42.913480'),(149,'course_overviews','0014_courseoverview_certificate_available_date','2019-02-06 07:56:42.991669'),(150,'content_type_gating','0001_initial','2019-02-06 07:56:43.235932'),(151,'content_type_gating','0002_auto_20181119_0959','2019-02-06 07:56:43.426345'),(152,'content_type_gating','0003_auto_20181128_1407','2019-02-06 07:56:43.580657'),(153,'content_type_gating','0004_auto_20181128_1521','2019-02-06 07:56:43.695613'),(154,'contentserver','0001_initial','2019-02-06 07:56:43.851239'),(155,'contentserver','0002_cdnuseragentsconfig','2019-02-06 07:56:44.018561'),(156,'cors_csrf','0001_initial','2019-02-06 07:56:44.181287'),(157,'course_action_state','0001_initial','2019-02-06 07:56:44.503331'),(158,'course_duration_limits','0001_initial','2019-02-06 07:56:44.746279'),(159,'course_duration_limits','0002_auto_20181119_0959','2019-02-06 07:56:44.877465'),(160,'course_duration_limits','0003_auto_20181128_1407','2019-02-06 07:56:45.039785'),(161,'course_duration_limits','0004_auto_20181128_1521','2019-02-06 07:56:45.182919'),(162,'course_goals','0001_initial','2019-02-06 07:56:45.519690'),(163,'course_goals','0002_auto_20171010_1129','2019-02-06 07:56:45.644315'),(164,'course_groups','0002_change_inline_default_cohort_value','2019-02-06 07:56:45.709570'),(165,'course_groups','0003_auto_20170609_1455','2019-02-06 07:56:45.983496'),(166,'course_modes','0008_course_key_field_to_foreign_key','2019-02-06 07:56:46.593883'),(167,'course_modes','0009_suggested_prices_to_charfield','2019-02-06 07:56:46.661433'),(168,'course_modes','0010_archived_suggested_prices_to_charfield','2019-02-06 07:56:46.723034'),(169,'course_modes','0011_change_regex_for_comma_separated_ints','2019-02-06 07:56:46.829468'),(170,'courseware','0001_initial','2019-02-06 07:56:49.952932'),(171,'courseware','0002_coursedynamicupgradedeadlineconfiguration_dynamicupgradedeadlineconfiguration','2019-02-06 07:56:50.721374'),(172,'courseware','0003_auto_20170825_0935','2019-02-06 07:56:50.903279'),(173,'courseware','0004_auto_20171010_1639','2019-02-06 07:56:51.166884'),(174,'courseware','0005_orgdynamicupgradedeadlineconfiguration','2019-02-06 07:56:51.597870'),(175,'courseware','0006_remove_module_id_index','2019-02-06 07:56:51.781895'),(176,'courseware','0007_remove_done_index','2019-02-06 07:56:51.968472'),(177,'coursewarehistoryextended','0001_initial','2019-02-06 07:56:52.632278'),(178,'coursewarehistoryextended','0002_force_studentmodule_index','2019-02-06 07:56:52.709752'),(179,'crawlers','0001_initial','2019-02-06 07:56:53.074661'),(180,'crawlers','0002_auto_20170419_0018','2019-02-06 07:56:53.203552'),(181,'credentials','0001_initial','2019-02-06 07:56:53.404087'),(182,'credentials','0002_auto_20160325_0631','2019-02-06 07:56:53.531754'),(183,'credentials','0003_auto_20170525_1109','2019-02-06 07:56:53.709376'),(184,'credentials','0004_notifycredentialsconfig','2019-02-06 07:56:53.854337'),(185,'credit','0001_initial','2019-02-06 07:56:55.324738'),(186,'credit','0002_creditconfig','2019-02-06 07:56:55.478476'),(187,'credit','0003_auto_20160511_2227','2019-02-06 07:56:55.552916'),(188,'credit','0004_delete_historical_credit_records','2019-02-06 07:56:56.180340'),(189,'dark_lang','0001_initial','2019-02-06 07:56:56.341474'),(190,'dark_lang','0002_data__enable_on_install','2019-02-06 07:56:56.783194'),(191,'dark_lang','0003_auto_20180425_0359','2019-02-06 07:56:57.055067'),(192,'database_fixups','0001_initial','2019-02-06 07:56:57.627927'),(193,'degreed','0001_initial','2019-02-06 07:56:58.969941'),(194,'degreed','0002_auto_20180104_0103','2019-02-06 07:56:59.471941'),(195,'degreed','0003_auto_20180109_0712','2019-02-06 07:56:59.731040'),(196,'degreed','0004_auto_20180306_1251','2019-02-06 07:56:59.997860'),(197,'degreed','0005_auto_20180807_1302','2019-02-06 07:57:02.069830'),(198,'degreed','0006_upgrade_django_simple_history','2019-02-06 07:57:02.273708'),(199,'django_comment_common','0003_enable_forums','2019-02-06 07:57:02.626514'),(200,'django_comment_common','0004_auto_20161117_1209','2019-02-06 07:57:02.820104'),(201,'django_comment_common','0005_coursediscussionsettings','2019-02-06 07:57:02.896624'),(202,'django_comment_common','0006_coursediscussionsettings_discussions_id_map','2019-02-06 07:57:02.998038'),(203,'django_comment_common','0007_discussionsidmapping','2019-02-06 07:57:03.083783'),(204,'django_comment_common','0008_role_user_index','2019-02-06 07:57:03.168933'),(205,'django_notify','0001_initial','2019-02-06 07:57:04.348365'),(206,'django_openid_auth','0001_initial','2019-02-06 07:57:04.778823'),(207,'oauth2','0001_initial','2019-02-06 07:57:06.639640'),(208,'edx_oauth2_provider','0001_initial','2019-02-06 07:57:06.912829'),(209,'edx_proctoring','0001_initial','2019-02-06 07:57:11.833284'),(210,'edx_proctoring','0002_proctoredexamstudentattempt_is_status_acknowledged','2019-02-06 07:57:12.158509'),(211,'edx_proctoring','0003_auto_20160101_0525','2019-02-06 07:57:12.624375'),(212,'edx_proctoring','0004_auto_20160201_0523','2019-02-06 07:57:13.412490'),(213,'edx_proctoring','0005_proctoredexam_hide_after_due','2019-02-06 07:57:13.542482'),(214,'edx_proctoring','0006_allowed_time_limit_mins','2019-02-06 07:57:13.995842'),(215,'edx_proctoring','0007_proctoredexam_backend','2019-02-06 07:57:14.113562'),(216,'edx_proctoring','0008_auto_20181116_1551','2019-02-06 07:57:14.705891'),(217,'edx_proctoring','0009_proctoredexamreviewpolicy_remove_rules','2019-02-06 07:57:15.116276'),(218,'edxval','0001_initial','2019-02-06 07:57:15.863533'),(219,'edxval','0002_data__default_profiles','2019-02-06 07:57:16.818661'),(220,'edxval','0003_coursevideo_is_hidden','2019-02-06 07:57:16.918246'),(221,'edxval','0004_data__add_hls_profile','2019-02-06 07:57:17.289957'),(222,'edxval','0005_videoimage','2019-02-06 07:57:17.492770'),(223,'edxval','0006_auto_20171009_0725','2019-02-06 07:57:17.716551'),(224,'edxval','0007_transcript_credentials_state','2019-02-06 07:57:17.845730'),(225,'edxval','0008_remove_subtitles','2019-02-06 07:57:17.992131'),(226,'edxval','0009_auto_20171127_0406','2019-02-06 07:57:18.060122'),(227,'edxval','0010_add_video_as_foreign_key','2019-02-06 07:57:18.365704'),(228,'edxval','0011_data__add_audio_mp3_profile','2019-02-06 07:57:18.730704'),(229,'email_marketing','0001_initial','2019-02-06 07:57:19.051984'),(230,'email_marketing','0002_auto_20160623_1656','2019-02-06 07:57:21.789475'),(231,'email_marketing','0003_auto_20160715_1145','2019-02-06 07:57:22.963260'),(232,'email_marketing','0004_emailmarketingconfiguration_welcome_email_send_delay','2019-02-06 07:57:23.293836'),(233,'email_marketing','0005_emailmarketingconfiguration_user_registration_cookie_timeout_delay','2019-02-06 07:57:23.617029'),(234,'email_marketing','0006_auto_20170711_0615','2019-02-06 07:57:24.245380'),(235,'email_marketing','0007_auto_20170809_0653','2019-02-06 07:57:24.897713'),(236,'email_marketing','0008_auto_20170809_0539','2019-02-06 07:57:25.325581'),(237,'email_marketing','0009_remove_emailmarketingconfiguration_sailthru_activation_template','2019-02-06 07:57:25.603626'),(238,'email_marketing','0010_auto_20180425_0800','2019-02-06 07:57:26.312049'),(239,'embargo','0001_initial','2019-02-06 07:57:28.072877'),(240,'embargo','0002_data__add_countries','2019-02-06 07:57:29.877570'),(241,'enterprise','0042_replace_sensitive_sso_username','2019-02-06 07:57:30.224348'),(242,'enterprise','0043_auto_20180507_0138','2019-02-06 07:57:30.838462'),(243,'enterprise','0044_reporting_config_multiple_types','2019-02-06 07:57:31.233674'),(244,'enterprise','0045_report_type_json','2019-02-06 07:57:31.322889'),(245,'enterprise','0046_remove_unique_constraints','2019-02-06 07:57:31.424455'),(246,'enterprise','0047_auto_20180517_0457','2019-02-06 07:57:31.785098'),(247,'enterprise','0048_enterprisecustomeruser_active','2019-02-06 07:57:31.904647'),(248,'enterprise','0049_auto_20180531_0321','2019-02-06 07:57:32.509863'),(249,'enterprise','0050_progress_v2','2019-02-06 07:57:33.253255'),(250,'enterprise','0051_add_enterprise_slug','2019-02-06 07:57:34.073175'),(251,'enterprise','0052_create_unique_slugs','2019-02-06 07:57:34.414601'),(252,'enterprise','0053_pendingenrollment_cohort_name','2019-02-06 07:57:34.520875'),(253,'enterprise','0053_auto_20180911_0811','2019-02-06 07:57:34.914654'),(254,'enterprise','0054_merge_20180914_1511','2019-02-06 07:57:34.944784'),(255,'enterprise','0055_auto_20181015_1112','2019-02-06 07:57:35.409450'),(256,'enterprise','0056_enterprisecustomerreportingconfiguration_pgp_encryption_key','2019-02-06 07:57:35.545845'),(257,'enterprise','0057_enterprisecustomerreportingconfiguration_enterprise_customer_catalogs','2019-02-06 07:57:35.960406'),(258,'enterprise','0058_auto_20181212_0145','2019-02-06 07:57:37.113916'),(259,'enterprise','0059_add_code_management_portal_config','2019-02-06 07:57:37.575928'),(260,'enterprise','0060_upgrade_django_simple_history','2019-02-06 07:57:38.213269'),(261,'student','0001_initial','2019-02-06 07:57:47.588358'),(262,'student','0002_auto_20151208_1034','2019-02-06 07:57:47.836707'),(263,'student','0003_auto_20160516_0938','2019-02-06 07:57:48.149932'),(264,'student','0004_auto_20160531_1422','2019-02-06 07:57:48.286460'),(265,'student','0005_auto_20160531_1653','2019-02-06 07:57:48.431860'),(266,'student','0006_logoutviewconfiguration','2019-02-06 07:57:48.974430'),(267,'student','0007_registrationcookieconfiguration','2019-02-06 07:57:49.147001'),(268,'student','0008_auto_20161117_1209','2019-02-06 07:57:49.263656'),(269,'student','0009_auto_20170111_0422','2019-02-06 07:57:49.377186'),(270,'student','0010_auto_20170207_0458','2019-02-06 07:57:49.407334'),(271,'student','0011_course_key_field_to_foreign_key','2019-02-06 07:57:50.975260'),(272,'student','0012_sociallink','2019-02-06 07:57:51.409953'),(273,'student','0013_delete_historical_enrollment_records','2019-02-06 07:57:52.968613'),(274,'entitlements','0001_initial','2019-02-06 07:57:53.425447'),(275,'entitlements','0002_auto_20171102_0719','2019-02-06 07:57:55.014484'),(276,'entitlements','0003_auto_20171205_1431','2019-02-06 07:57:57.282703'),(277,'entitlements','0004_auto_20171206_1729','2019-02-06 07:57:57.704486'),(278,'entitlements','0005_courseentitlementsupportdetail','2019-02-06 07:57:58.400522'),(279,'entitlements','0006_courseentitlementsupportdetail_action','2019-02-06 07:57:59.000339'),(280,'entitlements','0007_change_expiration_period_default','2019-02-06 07:57:59.217527'),(281,'entitlements','0008_auto_20180328_1107','2019-02-06 07:58:00.023003'),(282,'entitlements','0009_courseentitlement_refund_locked','2019-02-06 07:58:00.552995'),(283,'entitlements','0010_backfill_refund_lock','2019-02-06 07:58:01.471558'),(284,'experiments','0001_initial','2019-02-06 07:58:02.990331'),(285,'experiments','0002_auto_20170627_1402','2019-02-06 07:58:03.207899'),(286,'experiments','0003_auto_20170713_1148','2019-02-06 07:58:03.289623'),(287,'external_auth','0001_initial','2019-02-06 07:58:04.122332'),(288,'grades','0001_initial','2019-02-06 07:58:04.449795'),(289,'grades','0002_rename_last_edited_field','2019-02-06 07:58:04.542638'),(290,'grades','0003_coursepersistentgradesflag_persistentgradesenabledflag','2019-02-06 07:58:05.727274'),(291,'grades','0004_visibleblocks_course_id','2019-02-06 07:58:05.867193'),(292,'grades','0005_multiple_course_flags','2019-02-06 07:58:06.312646'),(293,'grades','0006_persistent_course_grades','2019-02-06 07:58:06.568446'),(294,'grades','0007_add_passed_timestamp_column','2019-02-06 07:58:07.247313'),(295,'grades','0008_persistentsubsectiongrade_first_attempted','2019-02-06 07:58:07.349076'),(296,'grades','0009_auto_20170111_1507','2019-02-06 07:58:07.498641'),(297,'grades','0010_auto_20170112_1156','2019-02-06 07:58:07.583662'),(298,'grades','0011_null_edited_time','2019-02-06 07:58:07.916494'),(299,'grades','0012_computegradessetting','2019-02-06 07:58:08.432066'),(300,'grades','0013_persistentsubsectiongradeoverride','2019-02-06 07:58:08.633723'),(301,'grades','0014_persistentsubsectiongradeoverridehistory','2019-02-06 07:58:09.160210'),(302,'instructor_task','0002_gradereportsetting','2019-02-06 07:58:09.580204'),(303,'waffle','0001_initial','2019-02-06 07:58:10.444295'),(304,'sap_success_factors','0001_initial','2019-02-06 07:58:12.042509'),(305,'sap_success_factors','0002_auto_20170224_1545','2019-02-06 07:58:13.979236'),(306,'sap_success_factors','0003_auto_20170317_1402','2019-02-06 07:58:14.701821'),(307,'sap_success_factors','0004_catalogtransmissionaudit_audit_summary','2019-02-06 07:58:14.797945'),(308,'sap_success_factors','0005_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 07:58:15.137352'),(309,'sap_success_factors','0006_sapsuccessfactors_use_enterprise_enrollment_page_waffle_flag','2019-02-06 07:58:15.692938'),(310,'sap_success_factors','0007_remove_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 07:58:16.090806'),(311,'sap_success_factors','0008_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 07:58:16.886204'),(312,'sap_success_factors','0009_sapsuccessfactors_remove_enterprise_enrollment_page_waffle_flag','2019-02-06 07:58:17.493133'),(313,'sap_success_factors','0010_move_audit_tables_to_base_integrated_channel','2019-02-06 07:58:18.256051'),(314,'integrated_channel','0001_initial','2019-02-06 07:58:18.434760'),(315,'integrated_channel','0002_delete_enterpriseintegratedchannel','2019-02-06 07:58:18.534852'),(316,'integrated_channel','0003_catalogtransmissionaudit_learnerdatatransmissionaudit','2019-02-06 07:58:18.697143'),(317,'integrated_channel','0004_catalogtransmissionaudit_channel','2019-02-06 07:58:18.821246'),(318,'integrated_channel','0005_auto_20180306_1251','2019-02-06 07:58:19.378821'),(319,'integrated_channel','0006_delete_catalogtransmissionaudit','2019-02-06 07:58:19.463872'),(320,'lms_xblock','0001_initial','2019-02-06 07:58:19.938021'),(321,'microsite_configuration','0001_initial','2019-02-06 07:58:24.417944'),(322,'microsite_configuration','0002_auto_20160202_0228','2019-02-06 07:58:24.704162'),(323,'microsite_configuration','0003_delete_historical_records','2019-02-06 07:58:27.217560'),(324,'milestones','0001_initial','2019-02-06 07:58:28.438298'),(325,'milestones','0002_data__seed_relationship_types','2019-02-06 07:58:29.074808'),(326,'milestones','0003_coursecontentmilestone_requirements','2019-02-06 07:58:29.198318'),(327,'milestones','0004_auto_20151221_1445','2019-02-06 07:58:29.608126'),(328,'mobile_api','0001_initial','2019-02-06 07:58:30.546212'),(329,'mobile_api','0002_auto_20160406_0904','2019-02-06 07:58:30.725452'),(330,'mobile_api','0003_ignore_mobile_available_flag','2019-02-06 07:58:31.637551'),(331,'notes','0001_initial','2019-02-06 07:58:32.158209'),(332,'oauth2','0002_auto_20160404_0813','2019-02-06 07:58:33.398358'),(333,'oauth2','0003_client_logout_uri','2019-02-06 07:58:33.785963'),(334,'oauth2','0004_add_index_on_grant_expires','2019-02-06 07:58:34.178788'),(335,'oauth2','0005_grant_nonce','2019-02-06 07:58:35.284863'),(336,'organizations','0001_initial','2019-02-06 07:58:35.646051'),(337,'organizations','0002_auto_20170117_1434','2019-02-06 07:58:35.750682'),(338,'organizations','0003_auto_20170221_1138','2019-02-06 07:58:35.925588'),(339,'organizations','0004_auto_20170413_2315','2019-02-06 07:58:36.060193'),(340,'organizations','0005_auto_20171116_0640','2019-02-06 07:58:36.145008'),(341,'organizations','0006_auto_20171207_0259','2019-02-06 07:58:36.257476'),(342,'oauth2_provider','0001_initial','2019-02-06 07:58:38.097999'),(343,'oauth_dispatch','0001_initial','2019-02-06 07:58:38.563660'),(344,'oauth_dispatch','0002_scopedapplication_scopedapplicationorganization','2019-02-06 07:58:40.054311'),(345,'oauth_dispatch','0003_application_data','2019-02-06 07:58:40.676680'),(346,'oauth_dispatch','0004_auto_20180626_1349','2019-02-06 07:58:43.112430'),(347,'oauth_dispatch','0005_applicationaccess_type','2019-02-06 07:58:43.714100'),(348,'oauth_dispatch','0006_drop_application_id_constraints','2019-02-06 07:58:44.030090'),(349,'oauth2_provider','0002_08_updates','2019-02-06 07:58:44.450850'),(350,'oauth2_provider','0003_auto_20160316_1503','2019-02-06 07:58:44.640899'),(351,'oauth2_provider','0004_auto_20160525_1623','2019-02-06 07:58:44.975564'),(352,'oauth2_provider','0005_auto_20170514_1141','2019-02-06 07:58:47.370031'),(353,'oauth2_provider','0006_auto_20171214_2232','2019-02-06 07:58:48.599294'),(354,'oauth_dispatch','0007_restore_application_id_constraints','2019-02-06 07:58:49.006205'),(355,'oauth_provider','0001_initial','2019-02-06 07:58:49.563238'),(356,'problem_builder','0001_initial','2019-02-06 07:58:49.794124'),(357,'problem_builder','0002_auto_20160121_1525','2019-02-06 07:58:50.200720'),(358,'problem_builder','0003_auto_20161124_0755','2019-02-06 07:58:50.413858'),(359,'problem_builder','0004_copy_course_ids','2019-02-06 07:58:51.128055'),(360,'problem_builder','0005_auto_20170112_1021','2019-02-06 07:58:51.340194'),(361,'problem_builder','0006_remove_deprecated_course_id','2019-02-06 07:58:51.564692'),(362,'programs','0001_initial','2019-02-06 07:58:51.747931'),(363,'programs','0002_programsapiconfig_cache_ttl','2019-02-06 07:58:51.898433'),(364,'programs','0003_auto_20151120_1613','2019-02-06 07:58:53.094465'),(365,'programs','0004_programsapiconfig_enable_certification','2019-02-06 07:58:53.288122'),(366,'programs','0005_programsapiconfig_max_retries','2019-02-06 07:58:53.445000'),(367,'programs','0006_programsapiconfig_xseries_ad_enabled','2019-02-06 07:58:53.602411'),(368,'programs','0007_programsapiconfig_program_listing_enabled','2019-02-06 07:58:53.755138'),(369,'programs','0008_programsapiconfig_program_details_enabled','2019-02-06 07:58:53.875763'),(370,'programs','0009_programsapiconfig_marketing_path','2019-02-06 07:58:54.018436'),(371,'programs','0010_auto_20170204_2332','2019-02-06 07:58:54.237222'),(372,'programs','0011_auto_20170301_1844','2019-02-06 07:58:55.604408'),(373,'programs','0012_auto_20170419_0018','2019-02-06 07:58:55.728622'),(374,'redirects','0001_initial','2019-02-06 07:58:56.618741'),(375,'rss_proxy','0001_initial','2019-02-06 07:58:56.722680'),(376,'sap_success_factors','0011_auto_20180104_0103','2019-02-06 07:59:01.328739'),(377,'sap_success_factors','0012_auto_20180109_0712','2019-02-06 07:59:01.778378'),(378,'sap_success_factors','0013_auto_20180306_1251','2019-02-06 07:59:02.285821'),(379,'sap_success_factors','0014_drop_historical_table','2019-02-06 07:59:02.903520'),(380,'sap_success_factors','0015_auto_20180510_1259','2019-02-06 07:59:03.734759'),(381,'sap_success_factors','0016_sapsuccessfactorsenterprisecustomerconfiguration_additional_locales','2019-02-06 07:59:03.878684'),(382,'sap_success_factors','0017_sapsuccessfactorsglobalconfiguration_search_student_api_path','2019-02-06 07:59:04.766539'),(383,'schedules','0001_initial','2019-02-06 07:59:05.179663'),(384,'schedules','0002_auto_20170816_1532','2019-02-06 07:59:05.397766'),(385,'schedules','0003_scheduleconfig','2019-02-06 07:59:05.977222'),(386,'schedules','0004_auto_20170922_1428','2019-02-06 07:59:06.791066'),(387,'schedules','0005_auto_20171010_1722','2019-02-06 07:59:07.631416'),(388,'schedules','0006_scheduleexperience','2019-02-06 07:59:08.189048'),(389,'schedules','0007_scheduleconfig_hold_back_ratio','2019-02-06 07:59:08.776239'),(390,'self_paced','0001_initial','2019-02-06 07:59:09.799050'),(391,'sessions','0001_initial','2019-02-06 07:59:09.921074'),(392,'shoppingcart','0001_initial','2019-02-06 07:59:21.053818'),(393,'shoppingcart','0002_auto_20151208_1034','2019-02-06 07:59:21.335220'),(394,'shoppingcart','0003_auto_20151217_0958','2019-02-06 07:59:21.599445'),(395,'shoppingcart','0004_change_meta_options','2019-02-06 07:59:21.823322'),(396,'site_configuration','0001_initial','2019-02-06 07:59:22.992881'),(397,'site_configuration','0002_auto_20160720_0231','2019-02-06 07:59:23.853074'),(398,'default','0001_initial','2019-02-06 07:59:25.015201'),(399,'social_auth','0001_initial','2019-02-06 07:59:25.046686'),(400,'default','0002_add_related_name','2019-02-06 07:59:25.500745'),(401,'social_auth','0002_add_related_name','2019-02-06 07:59:25.532177'),(402,'default','0003_alter_email_max_length','2019-02-06 07:59:25.652620'),(403,'social_auth','0003_alter_email_max_length','2019-02-06 07:59:25.690150'),(404,'default','0004_auto_20160423_0400','2019-02-06 07:59:26.074154'),(405,'social_auth','0004_auto_20160423_0400','2019-02-06 07:59:26.105575'),(406,'social_auth','0005_auto_20160727_2333','2019-02-06 07:59:26.241475'),(407,'social_django','0006_partial','2019-02-06 07:59:26.399875'),(408,'social_django','0007_code_timestamp','2019-02-06 07:59:26.566550'),(409,'social_django','0008_partial_timestamp','2019-02-06 07:59:26.712434'),(410,'splash','0001_initial','2019-02-06 07:59:27.288326'),(411,'static_replace','0001_initial','2019-02-06 07:59:27.851106'),(412,'static_replace','0002_assetexcludedextensionsconfig','2019-02-06 07:59:29.178463'),(413,'status','0001_initial','2019-02-06 07:59:30.834233'),(414,'status','0002_update_help_text','2019-02-06 07:59:31.259226'),(415,'student','0014_courseenrollmentallowed_user','2019-02-06 07:59:31.843553'),(416,'student','0015_manualenrollmentaudit_add_role','2019-02-06 07:59:32.339124'),(417,'student','0016_coursenrollment_course_on_delete_do_nothing','2019-02-06 07:59:33.019734'),(418,'student','0017_accountrecovery','2019-02-06 07:59:34.081866'),(419,'student','0018_remove_password_history','2019-02-06 07:59:35.360857'),(420,'student','0019_auto_20181221_0540','2019-02-06 07:59:36.450684'),(421,'submissions','0001_initial','2019-02-06 07:59:37.468217'),(422,'submissions','0002_auto_20151119_0913','2019-02-06 07:59:37.751719'),(423,'submissions','0003_submission_status','2019-02-06 07:59:37.951880'),(424,'submissions','0004_remove_django_extensions','2019-02-06 07:59:38.080449'),(425,'survey','0001_initial','2019-02-06 07:59:38.937112'),(426,'teams','0001_initial','2019-02-06 07:59:42.234272'),(427,'theming','0001_initial','2019-02-06 07:59:42.964122'),(428,'third_party_auth','0001_initial','2019-02-06 07:59:46.893944'),(429,'third_party_auth','0002_schema__provider_icon_image','2019-02-06 07:59:51.814091'),(430,'third_party_auth','0003_samlproviderconfig_debug_mode','2019-02-06 07:59:52.360263'),(431,'third_party_auth','0004_add_visible_field','2019-02-06 07:59:56.187303'),(432,'third_party_auth','0005_add_site_field','2019-02-06 08:00:00.726584'),(433,'third_party_auth','0006_samlproviderconfig_automatic_refresh_enabled','2019-02-06 08:00:01.267932'),(434,'third_party_auth','0007_auto_20170406_0912','2019-02-06 08:00:02.190874'),(435,'third_party_auth','0008_auto_20170413_1455','2019-02-06 08:00:03.658115'),(436,'third_party_auth','0009_auto_20170415_1144','2019-02-06 08:00:05.420674'),(437,'third_party_auth','0010_add_skip_hinted_login_dialog_field','2019-02-06 08:00:07.334260'),(438,'third_party_auth','0011_auto_20170616_0112','2019-02-06 08:00:07.841081'),(439,'third_party_auth','0012_auto_20170626_1135','2019-02-06 08:00:09.649831'),(440,'third_party_auth','0013_sync_learner_profile_data','2019-02-06 08:00:12.254172'),(441,'third_party_auth','0014_auto_20171222_1233','2019-02-06 08:00:13.935686'),(442,'third_party_auth','0015_samlproviderconfig_archived','2019-02-06 08:00:14.559179'),(443,'third_party_auth','0016_auto_20180130_0938','2019-02-06 08:00:15.656894'),(444,'third_party_auth','0017_remove_icon_class_image_secondary_fields','2019-02-06 08:00:17.597823'),(445,'third_party_auth','0018_auto_20180327_1631','2019-02-06 08:00:20.302724'),(446,'third_party_auth','0019_consolidate_slug','2019-02-06 08:00:23.246774'),(447,'third_party_auth','0020_cleanup_slug_fields','2019-02-06 08:00:25.498101'),(448,'third_party_auth','0021_sso_id_verification','2019-02-06 08:00:27.269685'),(449,'third_party_auth','0022_auto_20181012_0307','2019-02-06 08:00:30.475559'),(450,'thumbnail','0001_initial','2019-02-06 08:00:30.680886'),(451,'track','0001_initial','2019-02-06 08:00:30.998373'),(452,'user_api','0001_initial','2019-02-06 08:00:35.324701'),(453,'user_api','0002_retirementstate_userretirementstatus','2019-02-06 08:00:36.082707'),(454,'user_api','0003_userretirementrequest','2019-02-06 08:00:36.665229'),(455,'user_api','0004_userretirementpartnerreportingstatus','2019-02-06 08:00:37.317791'),(456,'user_authn','0001_data__add_login_service','2019-02-06 08:00:39.270679'),(457,'util','0001_initial','2019-02-06 08:00:39.822745'),(458,'util','0002_data__default_rate_limit_config','2019-02-06 08:00:40.606869'),(459,'verified_track_content','0002_verifiedtrackcohortedcourse_verified_cohort_name','2019-02-06 08:00:40.741152'),(460,'verified_track_content','0003_migrateverifiedtrackcohortssetting','2019-02-06 08:00:41.360407'),(461,'verify_student','0001_initial','2019-02-06 08:00:47.236180'),(462,'verify_student','0002_auto_20151124_1024','2019-02-06 08:00:47.481347'),(463,'verify_student','0003_auto_20151113_1443','2019-02-06 08:00:47.697474'),(464,'verify_student','0004_delete_historical_records','2019-02-06 08:00:47.928549'),(465,'verify_student','0005_remove_deprecated_models','2019-02-06 08:00:53.255639'),(466,'verify_student','0006_ssoverification','2019-02-06 08:00:53.608512'),(467,'verify_student','0007_idverificationaggregate','2019-02-06 08:00:54.126314'),(468,'verify_student','0008_populate_idverificationaggregate','2019-02-06 08:00:55.099295'),(469,'verify_student','0009_remove_id_verification_aggregate','2019-02-06 08:00:55.505989'),(470,'verify_student','0010_manualverification','2019-02-06 08:00:55.733258'),(471,'verify_student','0011_add_fields_to_sspv','2019-02-06 08:00:56.760072'),(472,'video_config','0001_initial','2019-02-06 08:00:57.094097'),(473,'video_config','0002_coursevideotranscriptenabledflag_videotranscriptenabledflag','2019-02-06 08:00:57.451972'),(474,'video_config','0003_transcriptmigrationsetting','2019-02-06 08:00:57.665251'),(475,'video_config','0004_transcriptmigrationsetting_command_run','2019-02-06 08:00:57.846477'),(476,'video_config','0005_auto_20180719_0752','2019-02-06 08:00:58.093978'),(477,'video_config','0006_videothumbnailetting_updatedcoursevideos','2019-02-06 08:00:58.479655'),(478,'video_config','0007_videothumbnailsetting_offset','2019-02-06 08:00:58.702464'),(479,'video_pipeline','0001_initial','2019-02-06 08:00:58.930134'),(480,'video_pipeline','0002_auto_20171114_0704','2019-02-06 08:00:59.248554'),(481,'video_pipeline','0003_coursevideouploadsenabledbydefault_videouploadsenabledbydefault','2019-02-06 08:00:59.639240'),(482,'waffle','0002_auto_20161201_0958','2019-02-06 08:00:59.770761'),(483,'waffle_utils','0001_initial','2019-02-06 08:01:00.120690'),(484,'wiki','0001_initial','2019-02-06 08:01:13.521825'),(485,'wiki','0002_remove_article_subscription','2019-02-06 08:01:13.635976'),(486,'wiki','0003_ip_address_conv','2019-02-06 08:01:15.191324'),(487,'wiki','0004_increase_slug_size','2019-02-06 08:01:15.438646'),(488,'wiki','0005_remove_attachments_and_images','2019-02-06 08:01:20.535437'),(489,'workflow','0001_initial','2019-02-06 08:01:20.955248'),(490,'workflow','0002_remove_django_extensions','2019-02-06 08:01:21.089005'),(491,'xapi','0001_initial','2019-02-06 08:01:21.762133'),(492,'xapi','0002_auto_20180726_0142','2019-02-06 08:01:22.140082'),(493,'xblock_django','0001_initial','2019-02-06 08:01:22.817601'),(494,'xblock_django','0002_auto_20160204_0809','2019-02-06 08:01:23.428800'),(495,'xblock_django','0003_add_new_config_models','2019-02-06 08:01:26.720065'),(496,'xblock_django','0004_delete_xblock_disable_config','2019-02-06 08:01:28.046351'),(497,'social_django','0002_add_related_name','2019-02-06 08:01:28.238120'),(498,'social_django','0003_alter_email_max_length','2019-02-06 08:01:28.295485'),(499,'social_django','0004_auto_20160423_0400','2019-02-06 08:01:28.369651'),(500,'social_django','0001_initial','2019-02-06 08:01:28.419547'),(501,'social_django','0005_auto_20160727_2333','2019-02-06 08:01:28.470149'),(502,'contentstore','0001_initial','2019-02-06 08:02:13.717472'),(503,'contentstore','0002_add_assets_page_flag','2019-02-06 08:02:14.894230'),(504,'contentstore','0003_remove_assets_page_flag','2019-02-06 08:02:15.936128'),(505,'course_creators','0001_initial','2019-02-06 08:02:16.677395'),(506,'tagging','0001_initial','2019-02-06 08:02:16.919416'),(507,'tagging','0002_auto_20170116_1541','2019-02-06 08:02:17.057789'),(508,'user_tasks','0001_initial','2019-02-06 08:02:18.095204'),(509,'user_tasks','0002_artifact_file_storage','2019-02-06 08:02:18.200132'),(510,'xblock_config','0001_initial','2019-02-06 08:02:18.497728'),(511,'xblock_config','0002_courseeditltifieldsenabledflag','2019-02-06 08:02:19.039966'),(512,'lti_provider','0001_initial','2019-02-20 13:01:39.285635'),(513,'lti_provider','0002_auto_20160325_0407','2019-02-20 13:01:39.369768'),(514,'lti_provider','0003_auto_20161118_1040','2019-02-20 13:01:39.445830'),(515,'content_type_gating','0005_auto_20190306_1547','2019-03-06 16:00:40.248896'),(516,'course_duration_limits','0005_auto_20190306_1546','2019-03-06 16:00:40.908922'),(517,'enterprise','0061_systemwideenterpriserole_systemwideenterpriseuserroleassignment','2019-03-08 15:47:17.741727'),(518,'enterprise','0062_add_system_wide_enterprise_roles','2019-03-08 15:47:17.809640'),(519,'content_type_gating','0006_auto_20190308_1447','2019-03-11 16:27:21.659554'),(520,'course_duration_limits','0006_auto_20190308_1447','2019-03-11 16:27:22.347994'),(521,'content_type_gating','0007_auto_20190311_1919','2019-03-12 16:11:14.076560'),(522,'course_duration_limits','0007_auto_20190311_1919','2019-03-12 16:11:17.332778'),(523,'announcements','0001_initial','2019-03-18 20:54:59.708245'),(524,'content_type_gating','0008_auto_20190313_1634','2019-03-18 20:55:00.145074'),(525,'course_duration_limits','0008_auto_20190313_1634','2019-03-18 20:55:00.800059'),(526,'enterprise','0063_systemwideenterpriserole_description','2019-03-21 18:40:50.646407'),(527,'enterprise','0064_enterprisefeaturerole_enterprisefeatureuserroleassignment','2019-03-28 19:29:40.049122'),(528,'enterprise','0065_add_enterprise_feature_roles','2019-03-28 19:29:40.122825'),(529,'enterprise','0066_add_system_wide_enterprise_operator_role','2019-03-28 19:29:40.190059'),(530,'student','0020_auto_20190227_2019','2019-04-01 21:47:10.285726'),(531,'certificates','0015_add_masters_choice','2019-04-05 14:56:54.180634'),(532,'enterprise','0067_add_role_based_access_control_switch','2019-04-08 20:44:56.835675'),(533,'program_enrollments','0001_initial','2019-04-10 20:25:28.810529'),(534,'program_enrollments','0002_historicalprogramcourseenrollment_programcourseenrollment','2019-04-18 16:07:31.718124'),(535,'third_party_auth','0023_auto_20190418_2033','2019-04-24 13:53:47.057323'),(536,'program_enrollments','0003_auto_20190424_1622','2019-04-24 16:34:31.400886'),(537,'courseware','0008_move_idde_to_edx_when','2019-04-25 14:14:01.833602'),(538,'edx_when','0001_initial','2019-04-25 14:14:04.077675'),(539,'edx_when','0002_auto_20190318_1736','2019-04-25 14:14:06.472260'),(540,'edx_when','0003_auto_20190402_1501','2019-04-25 14:14:08.565796'),(541,'edx_proctoring','0010_update_backend','2019-05-02 21:47:10.150692'),(542,'program_enrollments','0004_add_programcourseenrollment_relatedname','2019-05-02 21:47:10.839771'),(543,'student','0021_historicalcourseenrollment','2019-05-03 20:29:56.543955'),(544,'cornerstone','0001_initial','2019-05-29 09:32:41.107279'),(545,'cornerstone','0002_cornerstoneglobalconfiguration_subject_mapping','2019-05-29 09:32:41.540384'),(546,'third_party_auth','0024_fix_edit_disallowed','2019-05-29 14:34:07.293693'),(547,'discounts','0001_initial','2019-06-03 19:15:59.106385'),(548,'program_enrollments','0005_canceled_not_withdrawn','2019-06-03 19:15:59.936222'),(549,'entitlements','0011_historicalcourseentitlement','2019-06-04 17:56:15.038112'),(550,'organizations','0007_historicalorganization','2019-06-04 17:56:15.935805'),(551,'user_tasks','0003_url_max_length','2019-06-04 17:56:24.531329'),(552,'user_tasks','0004_url_textfield','2019-06-04 17:56:24.631710'),(553,'enterprise','0068_remove_role_based_access_control_switch','2019-06-05 10:59:25.727686'),(554,'grades','0015_historicalpersistentsubsectiongradeoverride','2019-06-10 16:42:15.294490'),(555,'bulk_grades','0001_initial','2019-06-12 14:00:05.595345'),(556,'super_csv','0001_initial','2019-06-12 14:00:05.668273'),(557,'super_csv','0002_csvoperation_user','2019-06-12 14:00:06.129086'),(558,'enterprise','0069_auto_20190613_0607','2019-06-13 20:29:34.416315'),(559,'course_modes','0012_historicalcoursemode','2019-06-20 14:16:40.384457'),(560,'student','0022_indexing_in_courseenrollment','2019-06-28 07:52:29.598606'),(561,'courseware','0009_auto_20190703_1955','2019-07-03 19:59:27.956010'),(562,'bulk_grades','0002_auto_20190703_1526','2019-07-09 16:23:49.075404'),(563,'course_overviews','0015_historicalcourseoverview','2019-07-09 16:23:49.552185'),(564,'courseware','0010_auto_20190709_1559','2019-07-09 16:23:49.959864'),(565,'grades','0016_auto_20190703_1446','2019-07-09 16:23:51.049448'),(566,'cornerstone','0003_auto_20190621_1000','2019-08-16 20:33:03.878476'),(567,'enterprise','0070_enterprise_catalog_query','2019-08-16 20:33:05.128301'),(568,'enterprise','0071_historicalpendingenrollment_historicalpendingenterprisecustomeruser','2019-08-16 20:33:06.381233'),(569,'instructor_task','0003_alter_task_input_field','2019-08-16 20:33:06.777708'),(570,'microsite_configuration','004_delete_all_tables','2019-08-16 20:33:08.216606'),(571,'sap_success_factors','0018_sapsuccessfactorsenterprisecustomerconfiguration_show_course_price','2019-08-16 20:33:08.320866'),(572,'super_csv','0003_csvoperation_original_filename','2019-08-16 20:33:08.729724'),(573,'system_wide_roles','0001_SystemWideRole_SystemWideRoleAssignment','2019-08-16 20:33:09.236280'),(574,'system_wide_roles','0002_add_system_wide_student_support_role','2019-08-16 20:33:10.100114'),(575,'contentstore','0004_remove_push_notification_configmodel_table','2019-08-16 20:33:16.971775'),(576,'xapi','0003_auto_20190807_1006','2019-08-23 11:39:26.089273'),(577,'program_enrollments','0006_add_the_correct_constraints','2019-08-23 18:08:47.891260'),(578,'video_config','0008_courseyoutubeblockedflag','2019-08-25 18:16:55.143257'),(579,'program_enrollments','0007_waiting_programcourseenrollment_constraint','2019-08-27 19:09:05.805301'),(580,'content_libraries','0001_initial','2019-08-30 19:27:59.312920'),(581,'courseware','0011_csm_id_bigint','2019-08-30 19:28:00.069282'),(582,'enterprise','0072_add_enterprise_report_config_feature_role','2019-08-30 19:28:00.572179'),(583,'enterprise','0073_enterprisecustomerreportingconfiguration_uuid','2019-08-30 19:28:01.681347'),(584,'enterprise','0074_auto_20190904_1143','2019-09-06 21:16:52.036849'),(585,'xapi','0004_auto_20190830_0710','2019-09-06 21:16:52.593883'),(586,'enterprise','0075_auto_20190916_1030','2019-09-16 21:24:18.290842'),(587,'course_overviews','0016_simulatecoursepublishconfig','2019-09-17 14:32:57.081562'),(588,'courseware','0012_adjust_fields','2019-09-19 19:47:08.473302'),(589,'enterprise','0076_auto_20190918_2037','2019-09-19 19:47:09.682209'),(590,'cornerstone','0004_cornerstoneglobalconfiguration_languages','2019-09-25 09:51:51.980971'),(591,'cornerstone','0005_auto_20190925_0730','2019-09-25 09:51:52.420065'),(592,'degreed','0007_auto_20190925_0730','2019-09-25 09:51:52.912089'),(593,'integrated_channel','0007_auto_20190925_0730','2019-09-25 09:51:52.965350'),(594,'sap_success_factors','0019_auto_20190925_0730','2019-09-25 09:51:53.387921'),(595,'course_overviews','0017_auto_20191002_0823','2019-10-03 17:35:24.874445'),(596,'courseware','0013_auto_20191001_1858','2019-10-03 17:35:25.469758'),(597,'edx_when','0004_datepolicy_rel_date','2019-10-03 17:35:25.561499'),(598,'edx_when','0005_auto_20190911_1056','2019-10-03 17:35:26.248583'),(599,'student','0023_bulkunenrollconfiguration','2019-10-08 08:54:34.630958'),(600,'program_enrollments','0008_add_ended_programenrollment_status','2019-10-15 16:54:18.793465'),(601,'enterprise','0077_auto_20191002_1529','2019-10-15 21:48:34.650220'),(602,'completion','0003_learning_context','2019-10-22 18:42:12.945705'),(603,'teams','0002_slug_field_ids','2019-10-22 18:42:13.905915'),(604,'entitlements','0012_allow_blank_order_number_values','2019-10-23 16:23:32.583686'),(605,'discounts','0002_auto_20191022_1720','2019-10-25 14:14:05.485328'),(606,'commerce','0008_auto_20191024_2048','2019-10-30 16:42:28.671238'),(607,'student','0024_fbeenrollmentexclusion','2019-10-31 16:16:17.991800'),(608,'student','0025_auto_20191101_1846','2019-11-05 14:23:09.546047'),(609,'cornerstone','0006_auto_20191001_0742','2019-11-15 09:41:31.515102'),(610,'degreed','0008_auto_20191001_0742','2019-11-15 09:41:31.985210'),(611,'enterprise','0078_auto_20191107_1536','2019-11-15 09:41:32.071798'),(612,'enterprise','0079_AddEnterpriseEnrollmentSource','2019-11-15 09:41:35.077452'),(613,'enterprise','0080_auto_20191113_1708','2019-11-15 09:41:35.165258'),(614,'sap_success_factors','0020_sapsuccessfactorsenterprisecustomerconfiguration_catalogs_to_transmit','2019-11-15 09:41:35.278200'),(615,'student','0026_allowedauthuser','2019-11-15 09:41:35.750216'),(616,'teams','0003_courseteam_organization_protected','2019-11-15 09:41:36.470845'),(617,'schedules','0008_add_new_start_date_field','2019-11-21 18:12:34.458532'),(618,'enterprise','0081_UpdateEnterpriseEnrollmentSource','2019-11-25 17:51:47.303851'),(619,'enterprise','0082_AddManagementEnterpriseEnrollmentSource','2019-12-03 20:57:24.426283'),(620,'edxval','0012_thirdpartytranscriptcredentialsstate_has_creds','2019-12-06 10:56:08.552448'),(621,'edxval','0013_thirdpartytranscriptcredentialsstate_copy_values','2019-12-13 13:13:20.308012'),(622,'edxval','0014_transcript_credentials_state_retype_exists','2019-12-13 13:13:20.408578'),(623,'programs','0013_customprogramsconfig','2019-12-13 13:13:21.067118'),(624,'verify_student','0012_sspverificationretryconfig','2019-12-13 13:13:21.515002'),(625,'assessment','0004_historicalsharedfileupload_sharedfileupload','2019-12-16 06:29:30.675880'),(626,'certificates','0016_historicalgeneratedcertificate','2019-12-17 14:29:56.935433'),(627,'entitlements','0013_historicalcourseentitlementsupportdetail','2019-12-17 14:29:57.436302'),(628,'credit','0005_creditrequirement_sort_value','2019-12-19 10:51:12.337166'),(629,'student','0027_courseenrollment_mode_callable_default','2019-12-26 15:35:57.040621'),(630,'enterprise','0083_enterprisecustomerreportingconfiguration_include_date','2019-12-26 21:47:14.728344'),(631,'schedules','0009_schedule_copy_column_values','2020-01-02 13:28:19.802979'),(632,'credit','0006_creditrequirement_alter_ordering','2020-01-03 18:18:36.334211'),(633,'credit','0007_creditrequirement_copy_values','2020-01-03 18:18:36.973921'),(634,'credit','0008_creditrequirement_remove_order','2020-01-08 11:38:24.657306'),(635,'grades','0017_delete_manual_psgoverride_table','2020-01-08 11:38:25.213640'),(636,'waffle','0003_update_strings_for_i18n','2020-01-08 14:05:29.720079'),(637,'student','0028_historicalmanualenrollmentaudit','2020-01-10 11:40:11.268574'),(638,'assessment','0005_add_filename_to_sharedupload','2020-01-13 10:35:07.847171'),(639,'course_overviews','0018_add_start_end_in_CourseOverview','2020-01-13 17:26:36.464326'),(640,'wiki','0006_auto_20200110_1003','2020-01-13 17:26:36.697919'),(641,'course_modes','0013_auto_20200115_2022','2020-01-15 20:27:50.992526'),(642,'entitlements','0014_auto_20200115_2022','2020-01-15 20:27:51.322976'),(643,'schedules','0010_remove_null_blank_from_schedules_date','2020-01-22 12:55:34.725873'),(644,'edxval','0015_remove_thirdpartytranscriptcredentialsstate_exists','2020-01-24 14:35:44.099846'),(645,'enterprise','0084_auto_20200120_1137','2020-01-24 14:35:44.172381'),(646,'enterprise','0085_enterprisecustomeruser_linked','2020-01-24 14:35:44.282887'),(647,'sap_success_factors','0021_sapsuccessfactorsenterprisecustomerconfiguration_show_total_hours','2020-01-27 10:53:31.872214'),(648,'course_overviews','0019_improve_courseoverviewtab','2020-01-28 16:51:30.714982'),(649,'enterprise','0086_auto_20200128_1726','2020-01-31 16:49:18.025706'),(650,'student','0029_add_data_researcher','2020-01-31 16:49:18.401525'),(651,'entitlements','0015_add_unique_together_constraint','2020-02-11 13:55:29.655054'),(652,'external_user_ids','0001_initial','2020-02-11 13:55:31.498884'),(653,'external_user_ids','0002_mb_coaching_20200210_1754','2020-02-11 13:55:31.894541'),(654,'sap_success_factors','0022_auto_20200206_1046','2020-02-11 13:55:32.101815'),(655,'track','0002_delete_trackinglog','2020-02-11 13:55:32.134542'),(656,'enterprise','0087_auto_20200206_1151','2020-02-18 09:55:42.697992'),(657,'site_configuration','0003_auto_20200217_1058','2020-02-18 09:55:42.825644'),(658,'student','0030_userprofile_phone_number','2020-02-20 14:48:47.685095'),(659,'course_date_signals','0001_initial','2020-02-21 16:45:43.955340'),(660,'oauth_dispatch','0008_applicationaccess_filters','2020-02-21 16:45:44.019075'),(661,'site_configuration','0004_add_site_values_field','2020-02-21 16:45:44.195027'),(662,'calendar_sync','0001_initial','2020-02-21 20:04:38.131685'),(663,'site_configuration','0005_copy_values_to_site_values','2020-02-24 18:47:53.200107'),(664,'external_user_ids','0003_auto_20200224_1836','2020-02-26 19:11:47.388528'),(665,'course_overviews','0020_courseoverviewtab_url_slug','2020-02-28 17:48:04.195272'),(666,'schedules','0011_auto_20200228_2018','2020-03-02 19:21:13.196282'),(667,'schedules','0012_auto_20200302_1914','2020-03-02 19:21:13.520829'),(668,'enterprise','0088_auto_20200224_1341','2020-03-03 20:05:46.920547'),(669,'experiments','0004_historicalexperimentkeyvalue','2020-03-03 20:05:47.277998'),(670,'program_enrollments','0009_update_course_enrollment_field_to_foreign_key','2020-03-03 20:05:47.685409'),(671,'site_configuration','0005_populate_siteconfig_history_site_values','2020-03-03 20:05:47.719133'),(672,'third_party_auth','0025_auto_20200303_1448','2020-03-03 20:05:48.252619'),(673,'oauth_dispatch','0009_delete_enable_scopes_waffle_switch','2020-03-04 16:01:48.080593'),(674,'schedules','0013_historicalschedule','2020-03-04 20:45:56.581945'),(675,'content_libraries','0002_group_permissions','2020-03-06 17:55:42.233448'),(676,'enterprise','0089_auto_20200305_0652','2020-03-06 17:55:42.297353'),(677,'site_configuration','0006_copy_values_to_site_values','2020-03-06 17:55:42.678035'),(678,'site_configuration','0007_remove_values_field','2020-03-06 17:55:42.788856'),(679,'schedules','0014_historicalschedule_drop_fk','2020-03-09 17:24:50.018834'),(680,'enterprise','0090_update_content_filter','2020-03-10 17:57:05.339287'),(681,'schedules','0015_schedules_start_nullable','2020-03-10 17:57:05.707643'),(682,'courseware','0014_fix_nan_value_for_global_speed','2020-03-11 13:49:13.615966'),(683,'enterprise','0091_add_sales_force_id_in_pendingenrollment','2020-03-12 10:54:44.467230'),(684,'enterprise','0092_auto_20200312_1650','2020-03-13 15:23:45.800175'),(685,'schedules','0016_remove_start_from_schedules','2020-03-13 15:23:45.883904'),(686,'schedules','0017_remove_start_from_historicalschedule','2020-03-13 15:23:45.976652'),(687,'schedules','0018_readd_historicalschedule_fks','2020-03-16 14:38:14.274410'),(688,'student','0031_auto_20200317_1122','2020-03-17 13:50:05.335676'),(689,'schedules','0019_auto_20200316_1935','2020-03-17 18:44:35.891013'),(690,'teams','0004_alter_defaults','2020-03-18 15:44:58.524624'),(691,'edxval','0016_add_transcript_credentials_model','2020-03-27 07:02:09.981900'),(692,'assessment','0006_TeamWorkflows','2020-03-30 19:21:36.208357'),(693,'edx_when','0006_drop_active_index','2020-03-30 19:21:36.251955'),(694,'program_enrollments','0010_add_courseaccessroleassignment','2020-03-30 19:21:36.855995'),(695,'workflow','0003_TeamWorkflows','2020-03-30 19:21:36.925096'),(696,'submissions','0005_CreateTeamModel','2020-04-01 20:57:39.372024'),(697,'third_party_auth','0026_auto_20200401_1932','2020-04-02 13:16:01.972784'),(698,'enterprise','0093_add_use_enterprise_catalog_flag','2020-04-08 18:22:44.709305'),(699,'enterprise','0094_add_use_enterprise_catalog_sample','2020-04-10 22:07:16.661282'),(700,'organizations','0001_squashed_0007_historicalorganization','2020-04-10 22:07:16.677543'),(701,'submissions','0001_squashed_0005_CreateTeamModel','2020-04-10 22:07:16.686207'); +INSERT INTO `django_migrations` VALUES (1,'contenttypes','0001_initial','2019-02-06 07:56:07.314317'),(2,'auth','0001_initial','2019-02-06 07:56:07.832368'),(3,'admin','0001_initial','2019-02-06 07:56:07.961256'),(4,'admin','0002_logentry_remove_auto_add','2019-02-06 07:56:08.013912'),(5,'sites','0001_initial','2019-02-06 07:56:08.072888'),(6,'contenttypes','0002_remove_content_type_name','2019-02-06 07:56:08.230528'),(7,'api_admin','0001_initial','2019-02-06 07:56:08.454101'),(8,'api_admin','0002_auto_20160325_1604','2019-02-06 07:56:08.533622'),(9,'api_admin','0003_auto_20160404_1618','2019-02-06 07:56:08.983603'),(10,'api_admin','0004_auto_20160412_1506','2019-02-06 07:56:09.311723'),(11,'api_admin','0005_auto_20160414_1232','2019-02-06 07:56:09.410291'),(12,'api_admin','0006_catalog','2019-02-06 07:56:09.439372'),(13,'api_admin','0007_delete_historical_api_records','2019-02-06 07:56:09.673117'),(14,'assessment','0001_initial','2019-02-06 07:56:11.477983'),(15,'assessment','0002_staffworkflow','2019-02-06 07:56:11.625937'),(16,'assessment','0003_expand_course_id','2019-02-06 07:56:11.815858'),(17,'auth','0002_alter_permission_name_max_length','2019-02-06 07:56:11.891156'),(18,'auth','0003_alter_user_email_max_length','2019-02-06 07:56:11.975525'),(19,'auth','0004_alter_user_username_opts','2019-02-06 07:56:12.013750'),(20,'auth','0005_alter_user_last_login_null','2019-02-06 07:56:12.096481'),(21,'auth','0006_require_contenttypes_0002','2019-02-06 07:56:12.108286'),(22,'auth','0007_alter_validators_add_error_messages','2019-02-06 07:56:12.164989'),(23,'auth','0008_alter_user_username_max_length','2019-02-06 07:56:12.240860'),(24,'instructor_task','0001_initial','2019-02-06 07:56:12.395820'),(25,'certificates','0001_initial','2019-02-06 07:56:13.480164'),(26,'certificates','0002_data__certificatehtmlviewconfiguration_data','2019-02-06 07:56:13.607503'),(27,'certificates','0003_data__default_modes','2019-02-06 07:56:13.751659'),(28,'certificates','0004_certificategenerationhistory','2019-02-06 07:56:13.904399'),(29,'certificates','0005_auto_20151208_0801','2019-02-06 07:56:13.986383'),(30,'certificates','0006_certificatetemplateasset_asset_slug','2019-02-06 07:56:14.058304'),(31,'certificates','0007_certificateinvalidation','2019-02-06 07:56:14.210453'),(32,'badges','0001_initial','2019-02-06 07:56:14.782804'),(33,'badges','0002_data__migrate_assertions','2019-02-06 07:56:15.175628'),(34,'badges','0003_schema__add_event_configuration','2019-02-06 07:56:15.324266'),(35,'block_structure','0001_config','2019-02-06 07:56:15.455000'),(36,'block_structure','0002_blockstructuremodel','2019-02-06 07:56:15.522120'),(37,'block_structure','0003_blockstructuremodel_storage','2019-02-06 07:56:15.564915'),(38,'block_structure','0004_blockstructuremodel_usagekeywithrun','2019-02-06 07:56:15.616240'),(39,'bookmarks','0001_initial','2019-02-06 07:56:16.017402'),(40,'branding','0001_initial','2019-02-06 07:56:16.267188'),(41,'course_modes','0001_initial','2019-02-06 07:56:16.438443'),(42,'course_modes','0002_coursemode_expiration_datetime_is_explicit','2019-02-06 07:56:16.519337'),(43,'course_modes','0003_auto_20151113_1443','2019-02-06 07:56:16.576659'),(44,'course_modes','0004_auto_20151113_1457','2019-02-06 07:56:16.732369'),(45,'course_modes','0005_auto_20151217_0958','2019-02-06 07:56:16.788036'),(46,'course_modes','0006_auto_20160208_1407','2019-02-06 07:56:16.883873'),(47,'course_modes','0007_coursemode_bulk_sku','2019-02-06 07:56:17.029222'),(48,'course_groups','0001_initial','2019-02-06 07:56:18.181254'),(49,'bulk_email','0001_initial','2019-02-06 07:56:18.660435'),(50,'bulk_email','0002_data__load_course_email_template','2019-02-06 07:56:18.937143'),(51,'bulk_email','0003_config_model_feature_flag','2019-02-06 07:56:19.093038'),(52,'bulk_email','0004_add_email_targets','2019-02-06 07:56:19.788595'),(53,'bulk_email','0005_move_target_data','2019-02-06 07:56:19.959402'),(54,'bulk_email','0006_course_mode_targets','2019-02-06 07:56:20.165336'),(55,'catalog','0001_initial','2019-02-06 07:56:20.308745'),(56,'catalog','0002_catalogintegration_username','2019-02-06 07:56:20.439737'),(57,'catalog','0003_catalogintegration_page_size','2019-02-06 07:56:20.584307'),(58,'catalog','0004_auto_20170616_0618','2019-02-06 07:56:20.692298'),(59,'catalog','0005_catalogintegration_long_term_cache_ttl','2019-02-06 07:56:20.821560'),(60,'django_comment_common','0001_initial','2019-02-06 07:56:21.271577'),(61,'django_comment_common','0002_forumsconfig','2019-02-06 07:56:21.463632'),(62,'verified_track_content','0001_initial','2019-02-06 07:56:21.537783'),(63,'course_overviews','0001_initial','2019-02-06 07:56:21.715657'),(64,'course_overviews','0002_add_course_catalog_fields','2019-02-06 07:56:21.984772'),(65,'course_overviews','0003_courseoverviewgeneratedhistory','2019-02-06 07:56:22.053252'),(66,'course_overviews','0004_courseoverview_org','2019-02-06 07:56:22.134954'),(67,'course_overviews','0005_delete_courseoverviewgeneratedhistory','2019-02-06 07:56:22.184071'),(68,'course_overviews','0006_courseoverviewimageset','2019-02-06 07:56:22.290455'),(69,'course_overviews','0007_courseoverviewimageconfig','2019-02-06 07:56:22.466348'),(70,'course_overviews','0008_remove_courseoverview_facebook_url','2019-02-06 07:56:22.484576'),(71,'course_overviews','0009_readd_facebook_url','2019-02-06 07:56:22.501725'),(72,'course_overviews','0010_auto_20160329_2317','2019-02-06 07:56:22.645825'),(73,'ccx','0001_initial','2019-02-06 07:56:23.183002'),(74,'ccx','0002_customcourseforedx_structure_json','2019-02-06 07:56:23.289052'),(75,'ccx','0003_add_master_course_staff_in_ccx','2019-02-06 07:56:23.840989'),(76,'ccx','0004_seed_forum_roles_in_ccx_courses','2019-02-06 07:56:23.988777'),(77,'ccx','0005_change_ccx_coach_to_staff','2019-02-06 07:56:24.160387'),(78,'ccx','0006_set_display_name_as_override','2019-02-06 07:56:24.337876'),(79,'ccxcon','0001_initial_ccxcon_model','2019-02-06 07:56:24.409092'),(80,'ccxcon','0002_auto_20160325_0407','2019-02-06 07:56:24.470172'),(81,'djcelery','0001_initial','2019-02-06 07:56:25.046777'),(82,'celery_utils','0001_initial','2019-02-06 07:56:25.165469'),(83,'celery_utils','0002_chordable_django_backend','2019-02-06 07:56:25.339734'),(84,'certificates','0008_schema__remove_badges','2019-02-06 07:56:25.535263'),(85,'certificates','0009_certificategenerationcoursesetting_language_self_generation','2019-02-06 07:56:25.851268'),(86,'certificates','0010_certificatetemplate_language','2019-02-06 07:56:25.927039'),(87,'certificates','0011_certificatetemplate_alter_unique','2019-02-06 07:56:26.154544'),(88,'certificates','0012_certificategenerationcoursesetting_include_hours_of_effort','2019-02-06 07:56:26.228554'),(89,'certificates','0013_remove_certificategenerationcoursesetting_enabled','2019-02-06 07:56:26.310926'),(90,'certificates','0014_change_eligible_certs_manager','2019-02-06 07:56:26.373051'),(91,'commerce','0001_data__add_ecommerce_service_user','2019-02-06 07:56:26.595906'),(92,'commerce','0002_commerceconfiguration','2019-02-06 07:56:26.698815'),(93,'commerce','0003_auto_20160329_0709','2019-02-06 07:56:26.761254'),(94,'commerce','0004_auto_20160531_0950','2019-02-06 07:56:27.150989'),(95,'commerce','0005_commerceconfiguration_enable_automatic_refund_approval','2019-02-06 07:56:27.241421'),(96,'commerce','0006_auto_20170424_1734','2019-02-06 07:56:27.316222'),(97,'commerce','0007_auto_20180313_0609','2019-02-06 07:56:27.466841'),(98,'completion','0001_initial','2019-02-06 07:56:27.696977'),(99,'completion','0002_auto_20180125_1510','2019-02-06 07:56:27.757853'),(100,'enterprise','0001_initial','2019-02-06 07:56:28.027244'),(101,'enterprise','0002_enterprisecustomerbrandingconfiguration','2019-02-06 07:56:28.117647'),(102,'enterprise','0003_auto_20161104_0937','2019-02-06 07:56:28.428631'),(103,'enterprise','0004_auto_20161114_0434','2019-02-06 07:56:28.594141'),(104,'enterprise','0005_pendingenterprisecustomeruser','2019-02-06 07:56:28.710577'),(105,'enterprise','0006_auto_20161121_0241','2019-02-06 07:56:28.775663'),(106,'enterprise','0007_auto_20161109_1511','2019-02-06 07:56:28.924039'),(107,'enterprise','0008_auto_20161124_2355','2019-02-06 07:56:29.200628'),(108,'enterprise','0009_auto_20161130_1651','2019-02-06 07:56:29.740933'),(109,'enterprise','0010_auto_20161222_1212','2019-02-06 07:56:29.889801'),(110,'enterprise','0011_enterprisecustomerentitlement_historicalenterprisecustomerentitlement','2019-02-06 07:56:30.134143'),(111,'enterprise','0012_auto_20170125_1033','2019-02-06 07:56:30.264122'),(112,'enterprise','0013_auto_20170125_1157','2019-02-06 07:56:30.893749'),(113,'enterprise','0014_enrollmentnotificationemailtemplate_historicalenrollmentnotificationemailtemplate','2019-02-06 07:56:31.215731'),(114,'enterprise','0015_auto_20170130_0003','2019-02-06 07:56:31.450278'),(115,'enterprise','0016_auto_20170405_0647','2019-02-06 07:56:32.231656'),(116,'enterprise','0017_auto_20170508_1341','2019-02-06 07:56:32.492394'),(117,'enterprise','0018_auto_20170511_1357','2019-02-06 07:56:32.686868'),(118,'enterprise','0019_auto_20170606_1853','2019-02-06 07:56:32.884924'),(119,'enterprise','0020_auto_20170624_2316','2019-02-06 07:56:33.722514'),(120,'enterprise','0021_auto_20170711_0712','2019-02-06 07:56:34.290994'),(121,'enterprise','0022_auto_20170720_1543','2019-02-06 07:56:34.459932'),(122,'enterprise','0023_audit_data_reporting_flag','2019-02-06 07:56:34.693710'),(123,'enterprise','0024_enterprisecustomercatalog_historicalenterprisecustomercatalog','2019-02-06 07:56:34.991211'),(124,'enterprise','0025_auto_20170828_1412','2019-02-06 07:56:35.555899'),(125,'enterprise','0026_make_require_account_level_consent_nullable','2019-02-06 07:56:35.765541'),(126,'enterprise','0027_remove_account_level_consent','2019-02-06 07:56:36.799493'),(127,'enterprise','0028_link_enterprise_to_enrollment_template','2019-02-06 07:56:37.434413'),(128,'enterprise','0029_auto_20170925_1909','2019-02-06 07:56:37.650440'),(129,'enterprise','0030_auto_20171005_1600','2019-02-06 07:56:38.219936'),(130,'enterprise','0031_auto_20171012_1249','2019-02-06 07:56:38.438979'),(131,'enterprise','0032_reporting_model','2019-02-06 07:56:38.594362'),(132,'enterprise','0033_add_history_change_reason_field','2019-02-06 07:56:39.182772'),(133,'enterprise','0034_auto_20171023_0727','2019-02-06 07:56:39.321896'),(134,'enterprise','0035_auto_20171212_1129','2019-02-06 07:56:39.517158'),(135,'enterprise','0036_sftp_reporting_support','2019-02-06 07:56:39.958256'),(136,'enterprise','0037_auto_20180110_0450','2019-02-06 07:56:40.144689'),(137,'enterprise','0038_auto_20180122_1427','2019-02-06 07:56:40.326004'),(138,'enterprise','0039_auto_20180129_1034','2019-02-06 07:56:40.539093'),(139,'enterprise','0040_auto_20180129_1428','2019-02-06 07:56:40.854288'),(140,'enterprise','0041_auto_20180212_1507','2019-02-06 07:56:41.037158'),(141,'consent','0001_initial','2019-02-06 07:56:41.608778'),(142,'consent','0002_migrate_to_new_data_sharing_consent','2019-02-06 07:56:42.267785'),(143,'consent','0003_historicaldatasharingconsent_history_change_reason','2019-02-06 07:56:42.405847'),(144,'consent','0004_datasharingconsenttextoverrides','2019-02-06 07:56:42.584250'),(145,'sites','0002_alter_domain_unique','2019-02-06 07:56:42.663878'),(146,'course_overviews','0011_courseoverview_marketing_url','2019-02-06 07:56:42.745921'),(147,'course_overviews','0012_courseoverview_eligible_for_financial_aid','2019-02-06 07:56:42.834692'),(148,'course_overviews','0013_courseoverview_language','2019-02-06 07:56:42.913480'),(149,'course_overviews','0014_courseoverview_certificate_available_date','2019-02-06 07:56:42.991669'),(150,'content_type_gating','0001_initial','2019-02-06 07:56:43.235932'),(151,'content_type_gating','0002_auto_20181119_0959','2019-02-06 07:56:43.426345'),(152,'content_type_gating','0003_auto_20181128_1407','2019-02-06 07:56:43.580657'),(153,'content_type_gating','0004_auto_20181128_1521','2019-02-06 07:56:43.695613'),(154,'contentserver','0001_initial','2019-02-06 07:56:43.851239'),(155,'contentserver','0002_cdnuseragentsconfig','2019-02-06 07:56:44.018561'),(156,'cors_csrf','0001_initial','2019-02-06 07:56:44.181287'),(157,'course_action_state','0001_initial','2019-02-06 07:56:44.503331'),(158,'course_duration_limits','0001_initial','2019-02-06 07:56:44.746279'),(159,'course_duration_limits','0002_auto_20181119_0959','2019-02-06 07:56:44.877465'),(160,'course_duration_limits','0003_auto_20181128_1407','2019-02-06 07:56:45.039785'),(161,'course_duration_limits','0004_auto_20181128_1521','2019-02-06 07:56:45.182919'),(162,'course_goals','0001_initial','2019-02-06 07:56:45.519690'),(163,'course_goals','0002_auto_20171010_1129','2019-02-06 07:56:45.644315'),(164,'course_groups','0002_change_inline_default_cohort_value','2019-02-06 07:56:45.709570'),(165,'course_groups','0003_auto_20170609_1455','2019-02-06 07:56:45.983496'),(166,'course_modes','0008_course_key_field_to_foreign_key','2019-02-06 07:56:46.593883'),(167,'course_modes','0009_suggested_prices_to_charfield','2019-02-06 07:56:46.661433'),(168,'course_modes','0010_archived_suggested_prices_to_charfield','2019-02-06 07:56:46.723034'),(169,'course_modes','0011_change_regex_for_comma_separated_ints','2019-02-06 07:56:46.829468'),(170,'courseware','0001_initial','2019-02-06 07:56:49.952932'),(171,'courseware','0002_coursedynamicupgradedeadlineconfiguration_dynamicupgradedeadlineconfiguration','2019-02-06 07:56:50.721374'),(172,'courseware','0003_auto_20170825_0935','2019-02-06 07:56:50.903279'),(173,'courseware','0004_auto_20171010_1639','2019-02-06 07:56:51.166884'),(174,'courseware','0005_orgdynamicupgradedeadlineconfiguration','2019-02-06 07:56:51.597870'),(175,'courseware','0006_remove_module_id_index','2019-02-06 07:56:51.781895'),(176,'courseware','0007_remove_done_index','2019-02-06 07:56:51.968472'),(177,'coursewarehistoryextended','0001_initial','2019-02-06 07:56:52.632278'),(178,'coursewarehistoryextended','0002_force_studentmodule_index','2019-02-06 07:56:52.709752'),(179,'crawlers','0001_initial','2019-02-06 07:56:53.074661'),(180,'crawlers','0002_auto_20170419_0018','2019-02-06 07:56:53.203552'),(181,'credentials','0001_initial','2019-02-06 07:56:53.404087'),(182,'credentials','0002_auto_20160325_0631','2019-02-06 07:56:53.531754'),(183,'credentials','0003_auto_20170525_1109','2019-02-06 07:56:53.709376'),(184,'credentials','0004_notifycredentialsconfig','2019-02-06 07:56:53.854337'),(185,'credit','0001_initial','2019-02-06 07:56:55.324738'),(186,'credit','0002_creditconfig','2019-02-06 07:56:55.478476'),(187,'credit','0003_auto_20160511_2227','2019-02-06 07:56:55.552916'),(188,'credit','0004_delete_historical_credit_records','2019-02-06 07:56:56.180340'),(189,'dark_lang','0001_initial','2019-02-06 07:56:56.341474'),(190,'dark_lang','0002_data__enable_on_install','2019-02-06 07:56:56.783194'),(191,'dark_lang','0003_auto_20180425_0359','2019-02-06 07:56:57.055067'),(192,'database_fixups','0001_initial','2019-02-06 07:56:57.627927'),(193,'degreed','0001_initial','2019-02-06 07:56:58.969941'),(194,'degreed','0002_auto_20180104_0103','2019-02-06 07:56:59.471941'),(195,'degreed','0003_auto_20180109_0712','2019-02-06 07:56:59.731040'),(196,'degreed','0004_auto_20180306_1251','2019-02-06 07:56:59.997860'),(197,'degreed','0005_auto_20180807_1302','2019-02-06 07:57:02.069830'),(198,'degreed','0006_upgrade_django_simple_history','2019-02-06 07:57:02.273708'),(199,'django_comment_common','0003_enable_forums','2019-02-06 07:57:02.626514'),(200,'django_comment_common','0004_auto_20161117_1209','2019-02-06 07:57:02.820104'),(201,'django_comment_common','0005_coursediscussionsettings','2019-02-06 07:57:02.896624'),(202,'django_comment_common','0006_coursediscussionsettings_discussions_id_map','2019-02-06 07:57:02.998038'),(203,'django_comment_common','0007_discussionsidmapping','2019-02-06 07:57:03.083783'),(204,'django_comment_common','0008_role_user_index','2019-02-06 07:57:03.168933'),(205,'django_notify','0001_initial','2019-02-06 07:57:04.348365'),(206,'django_openid_auth','0001_initial','2019-02-06 07:57:04.778823'),(207,'oauth2','0001_initial','2019-02-06 07:57:06.639640'),(208,'edx_oauth2_provider','0001_initial','2019-02-06 07:57:06.912829'),(209,'edx_proctoring','0001_initial','2019-02-06 07:57:11.833284'),(210,'edx_proctoring','0002_proctoredexamstudentattempt_is_status_acknowledged','2019-02-06 07:57:12.158509'),(211,'edx_proctoring','0003_auto_20160101_0525','2019-02-06 07:57:12.624375'),(212,'edx_proctoring','0004_auto_20160201_0523','2019-02-06 07:57:13.412490'),(213,'edx_proctoring','0005_proctoredexam_hide_after_due','2019-02-06 07:57:13.542482'),(214,'edx_proctoring','0006_allowed_time_limit_mins','2019-02-06 07:57:13.995842'),(215,'edx_proctoring','0007_proctoredexam_backend','2019-02-06 07:57:14.113562'),(216,'edx_proctoring','0008_auto_20181116_1551','2019-02-06 07:57:14.705891'),(217,'edx_proctoring','0009_proctoredexamreviewpolicy_remove_rules','2019-02-06 07:57:15.116276'),(218,'edxval','0001_initial','2019-02-06 07:57:15.863533'),(219,'edxval','0002_data__default_profiles','2019-02-06 07:57:16.818661'),(220,'edxval','0003_coursevideo_is_hidden','2019-02-06 07:57:16.918246'),(221,'edxval','0004_data__add_hls_profile','2019-02-06 07:57:17.289957'),(222,'edxval','0005_videoimage','2019-02-06 07:57:17.492770'),(223,'edxval','0006_auto_20171009_0725','2019-02-06 07:57:17.716551'),(224,'edxval','0007_transcript_credentials_state','2019-02-06 07:57:17.845730'),(225,'edxval','0008_remove_subtitles','2019-02-06 07:57:17.992131'),(226,'edxval','0009_auto_20171127_0406','2019-02-06 07:57:18.060122'),(227,'edxval','0010_add_video_as_foreign_key','2019-02-06 07:57:18.365704'),(228,'edxval','0011_data__add_audio_mp3_profile','2019-02-06 07:57:18.730704'),(229,'email_marketing','0001_initial','2019-02-06 07:57:19.051984'),(230,'email_marketing','0002_auto_20160623_1656','2019-02-06 07:57:21.789475'),(231,'email_marketing','0003_auto_20160715_1145','2019-02-06 07:57:22.963260'),(232,'email_marketing','0004_emailmarketingconfiguration_welcome_email_send_delay','2019-02-06 07:57:23.293836'),(233,'email_marketing','0005_emailmarketingconfiguration_user_registration_cookie_timeout_delay','2019-02-06 07:57:23.617029'),(234,'email_marketing','0006_auto_20170711_0615','2019-02-06 07:57:24.245380'),(235,'email_marketing','0007_auto_20170809_0653','2019-02-06 07:57:24.897713'),(236,'email_marketing','0008_auto_20170809_0539','2019-02-06 07:57:25.325581'),(237,'email_marketing','0009_remove_emailmarketingconfiguration_sailthru_activation_template','2019-02-06 07:57:25.603626'),(238,'email_marketing','0010_auto_20180425_0800','2019-02-06 07:57:26.312049'),(239,'embargo','0001_initial','2019-02-06 07:57:28.072877'),(240,'embargo','0002_data__add_countries','2019-02-06 07:57:29.877570'),(241,'enterprise','0042_replace_sensitive_sso_username','2019-02-06 07:57:30.224348'),(242,'enterprise','0043_auto_20180507_0138','2019-02-06 07:57:30.838462'),(243,'enterprise','0044_reporting_config_multiple_types','2019-02-06 07:57:31.233674'),(244,'enterprise','0045_report_type_json','2019-02-06 07:57:31.322889'),(245,'enterprise','0046_remove_unique_constraints','2019-02-06 07:57:31.424455'),(246,'enterprise','0047_auto_20180517_0457','2019-02-06 07:57:31.785098'),(247,'enterprise','0048_enterprisecustomeruser_active','2019-02-06 07:57:31.904647'),(248,'enterprise','0049_auto_20180531_0321','2019-02-06 07:57:32.509863'),(249,'enterprise','0050_progress_v2','2019-02-06 07:57:33.253255'),(250,'enterprise','0051_add_enterprise_slug','2019-02-06 07:57:34.073175'),(251,'enterprise','0052_create_unique_slugs','2019-02-06 07:57:34.414601'),(252,'enterprise','0053_pendingenrollment_cohort_name','2019-02-06 07:57:34.520875'),(253,'enterprise','0053_auto_20180911_0811','2019-02-06 07:57:34.914654'),(254,'enterprise','0054_merge_20180914_1511','2019-02-06 07:57:34.944784'),(255,'enterprise','0055_auto_20181015_1112','2019-02-06 07:57:35.409450'),(256,'enterprise','0056_enterprisecustomerreportingconfiguration_pgp_encryption_key','2019-02-06 07:57:35.545845'),(257,'enterprise','0057_enterprisecustomerreportingconfiguration_enterprise_customer_catalogs','2019-02-06 07:57:35.960406'),(258,'enterprise','0058_auto_20181212_0145','2019-02-06 07:57:37.113916'),(259,'enterprise','0059_add_code_management_portal_config','2019-02-06 07:57:37.575928'),(260,'enterprise','0060_upgrade_django_simple_history','2019-02-06 07:57:38.213269'),(261,'student','0001_initial','2019-02-06 07:57:47.588358'),(262,'student','0002_auto_20151208_1034','2019-02-06 07:57:47.836707'),(263,'student','0003_auto_20160516_0938','2019-02-06 07:57:48.149932'),(264,'student','0004_auto_20160531_1422','2019-02-06 07:57:48.286460'),(265,'student','0005_auto_20160531_1653','2019-02-06 07:57:48.431860'),(266,'student','0006_logoutviewconfiguration','2019-02-06 07:57:48.974430'),(267,'student','0007_registrationcookieconfiguration','2019-02-06 07:57:49.147001'),(268,'student','0008_auto_20161117_1209','2019-02-06 07:57:49.263656'),(269,'student','0009_auto_20170111_0422','2019-02-06 07:57:49.377186'),(270,'student','0010_auto_20170207_0458','2019-02-06 07:57:49.407334'),(271,'student','0011_course_key_field_to_foreign_key','2019-02-06 07:57:50.975260'),(272,'student','0012_sociallink','2019-02-06 07:57:51.409953'),(273,'student','0013_delete_historical_enrollment_records','2019-02-06 07:57:52.968613'),(274,'entitlements','0001_initial','2019-02-06 07:57:53.425447'),(275,'entitlements','0002_auto_20171102_0719','2019-02-06 07:57:55.014484'),(276,'entitlements','0003_auto_20171205_1431','2019-02-06 07:57:57.282703'),(277,'entitlements','0004_auto_20171206_1729','2019-02-06 07:57:57.704486'),(278,'entitlements','0005_courseentitlementsupportdetail','2019-02-06 07:57:58.400522'),(279,'entitlements','0006_courseentitlementsupportdetail_action','2019-02-06 07:57:59.000339'),(280,'entitlements','0007_change_expiration_period_default','2019-02-06 07:57:59.217527'),(281,'entitlements','0008_auto_20180328_1107','2019-02-06 07:58:00.023003'),(282,'entitlements','0009_courseentitlement_refund_locked','2019-02-06 07:58:00.552995'),(283,'entitlements','0010_backfill_refund_lock','2019-02-06 07:58:01.471558'),(284,'experiments','0001_initial','2019-02-06 07:58:02.990331'),(285,'experiments','0002_auto_20170627_1402','2019-02-06 07:58:03.207899'),(286,'experiments','0003_auto_20170713_1148','2019-02-06 07:58:03.289623'),(287,'external_auth','0001_initial','2019-02-06 07:58:04.122332'),(288,'grades','0001_initial','2019-02-06 07:58:04.449795'),(289,'grades','0002_rename_last_edited_field','2019-02-06 07:58:04.542638'),(290,'grades','0003_coursepersistentgradesflag_persistentgradesenabledflag','2019-02-06 07:58:05.727274'),(291,'grades','0004_visibleblocks_course_id','2019-02-06 07:58:05.867193'),(292,'grades','0005_multiple_course_flags','2019-02-06 07:58:06.312646'),(293,'grades','0006_persistent_course_grades','2019-02-06 07:58:06.568446'),(294,'grades','0007_add_passed_timestamp_column','2019-02-06 07:58:07.247313'),(295,'grades','0008_persistentsubsectiongrade_first_attempted','2019-02-06 07:58:07.349076'),(296,'grades','0009_auto_20170111_1507','2019-02-06 07:58:07.498641'),(297,'grades','0010_auto_20170112_1156','2019-02-06 07:58:07.583662'),(298,'grades','0011_null_edited_time','2019-02-06 07:58:07.916494'),(299,'grades','0012_computegradessetting','2019-02-06 07:58:08.432066'),(300,'grades','0013_persistentsubsectiongradeoverride','2019-02-06 07:58:08.633723'),(301,'grades','0014_persistentsubsectiongradeoverridehistory','2019-02-06 07:58:09.160210'),(302,'instructor_task','0002_gradereportsetting','2019-02-06 07:58:09.580204'),(303,'waffle','0001_initial','2019-02-06 07:58:10.444295'),(304,'sap_success_factors','0001_initial','2019-02-06 07:58:12.042509'),(305,'sap_success_factors','0002_auto_20170224_1545','2019-02-06 07:58:13.979236'),(306,'sap_success_factors','0003_auto_20170317_1402','2019-02-06 07:58:14.701821'),(307,'sap_success_factors','0004_catalogtransmissionaudit_audit_summary','2019-02-06 07:58:14.797945'),(308,'sap_success_factors','0005_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 07:58:15.137352'),(309,'sap_success_factors','0006_sapsuccessfactors_use_enterprise_enrollment_page_waffle_flag','2019-02-06 07:58:15.692938'),(310,'sap_success_factors','0007_remove_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 07:58:16.090806'),(311,'sap_success_factors','0008_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 07:58:16.886204'),(312,'sap_success_factors','0009_sapsuccessfactors_remove_enterprise_enrollment_page_waffle_flag','2019-02-06 07:58:17.493133'),(313,'sap_success_factors','0010_move_audit_tables_to_base_integrated_channel','2019-02-06 07:58:18.256051'),(314,'integrated_channel','0001_initial','2019-02-06 07:58:18.434760'),(315,'integrated_channel','0002_delete_enterpriseintegratedchannel','2019-02-06 07:58:18.534852'),(316,'integrated_channel','0003_catalogtransmissionaudit_learnerdatatransmissionaudit','2019-02-06 07:58:18.697143'),(317,'integrated_channel','0004_catalogtransmissionaudit_channel','2019-02-06 07:58:18.821246'),(318,'integrated_channel','0005_auto_20180306_1251','2019-02-06 07:58:19.378821'),(319,'integrated_channel','0006_delete_catalogtransmissionaudit','2019-02-06 07:58:19.463872'),(320,'lms_xblock','0001_initial','2019-02-06 07:58:19.938021'),(321,'microsite_configuration','0001_initial','2019-02-06 07:58:24.417944'),(322,'microsite_configuration','0002_auto_20160202_0228','2019-02-06 07:58:24.704162'),(323,'microsite_configuration','0003_delete_historical_records','2019-02-06 07:58:27.217560'),(324,'milestones','0001_initial','2019-02-06 07:58:28.438298'),(325,'milestones','0002_data__seed_relationship_types','2019-02-06 07:58:29.074808'),(326,'milestones','0003_coursecontentmilestone_requirements','2019-02-06 07:58:29.198318'),(327,'milestones','0004_auto_20151221_1445','2019-02-06 07:58:29.608126'),(328,'mobile_api','0001_initial','2019-02-06 07:58:30.546212'),(329,'mobile_api','0002_auto_20160406_0904','2019-02-06 07:58:30.725452'),(330,'mobile_api','0003_ignore_mobile_available_flag','2019-02-06 07:58:31.637551'),(331,'notes','0001_initial','2019-02-06 07:58:32.158209'),(332,'oauth2','0002_auto_20160404_0813','2019-02-06 07:58:33.398358'),(333,'oauth2','0003_client_logout_uri','2019-02-06 07:58:33.785963'),(334,'oauth2','0004_add_index_on_grant_expires','2019-02-06 07:58:34.178788'),(335,'oauth2','0005_grant_nonce','2019-02-06 07:58:35.284863'),(336,'organizations','0001_initial','2019-02-06 07:58:35.646051'),(337,'organizations','0002_auto_20170117_1434','2019-02-06 07:58:35.750682'),(338,'organizations','0003_auto_20170221_1138','2019-02-06 07:58:35.925588'),(339,'organizations','0004_auto_20170413_2315','2019-02-06 07:58:36.060193'),(340,'organizations','0005_auto_20171116_0640','2019-02-06 07:58:36.145008'),(341,'organizations','0006_auto_20171207_0259','2019-02-06 07:58:36.257476'),(342,'oauth2_provider','0001_initial','2019-02-06 07:58:38.097999'),(343,'oauth_dispatch','0001_initial','2019-02-06 07:58:38.563660'),(344,'oauth_dispatch','0002_scopedapplication_scopedapplicationorganization','2019-02-06 07:58:40.054311'),(345,'oauth_dispatch','0003_application_data','2019-02-06 07:58:40.676680'),(346,'oauth_dispatch','0004_auto_20180626_1349','2019-02-06 07:58:43.112430'),(347,'oauth_dispatch','0005_applicationaccess_type','2019-02-06 07:58:43.714100'),(348,'oauth_dispatch','0006_drop_application_id_constraints','2019-02-06 07:58:44.030090'),(349,'oauth2_provider','0002_08_updates','2019-02-06 07:58:44.450850'),(350,'oauth2_provider','0003_auto_20160316_1503','2019-02-06 07:58:44.640899'),(351,'oauth2_provider','0004_auto_20160525_1623','2019-02-06 07:58:44.975564'),(352,'oauth2_provider','0005_auto_20170514_1141','2019-02-06 07:58:47.370031'),(353,'oauth2_provider','0006_auto_20171214_2232','2019-02-06 07:58:48.599294'),(354,'oauth_dispatch','0007_restore_application_id_constraints','2019-02-06 07:58:49.006205'),(355,'oauth_provider','0001_initial','2019-02-06 07:58:49.563238'),(356,'problem_builder','0001_initial','2019-02-06 07:58:49.794124'),(357,'problem_builder','0002_auto_20160121_1525','2019-02-06 07:58:50.200720'),(358,'problem_builder','0003_auto_20161124_0755','2019-02-06 07:58:50.413858'),(359,'problem_builder','0004_copy_course_ids','2019-02-06 07:58:51.128055'),(360,'problem_builder','0005_auto_20170112_1021','2019-02-06 07:58:51.340194'),(361,'problem_builder','0006_remove_deprecated_course_id','2019-02-06 07:58:51.564692'),(362,'programs','0001_initial','2019-02-06 07:58:51.747931'),(363,'programs','0002_programsapiconfig_cache_ttl','2019-02-06 07:58:51.898433'),(364,'programs','0003_auto_20151120_1613','2019-02-06 07:58:53.094465'),(365,'programs','0004_programsapiconfig_enable_certification','2019-02-06 07:58:53.288122'),(366,'programs','0005_programsapiconfig_max_retries','2019-02-06 07:58:53.445000'),(367,'programs','0006_programsapiconfig_xseries_ad_enabled','2019-02-06 07:58:53.602411'),(368,'programs','0007_programsapiconfig_program_listing_enabled','2019-02-06 07:58:53.755138'),(369,'programs','0008_programsapiconfig_program_details_enabled','2019-02-06 07:58:53.875763'),(370,'programs','0009_programsapiconfig_marketing_path','2019-02-06 07:58:54.018436'),(371,'programs','0010_auto_20170204_2332','2019-02-06 07:58:54.237222'),(372,'programs','0011_auto_20170301_1844','2019-02-06 07:58:55.604408'),(373,'programs','0012_auto_20170419_0018','2019-02-06 07:58:55.728622'),(374,'redirects','0001_initial','2019-02-06 07:58:56.618741'),(375,'rss_proxy','0001_initial','2019-02-06 07:58:56.722680'),(376,'sap_success_factors','0011_auto_20180104_0103','2019-02-06 07:59:01.328739'),(377,'sap_success_factors','0012_auto_20180109_0712','2019-02-06 07:59:01.778378'),(378,'sap_success_factors','0013_auto_20180306_1251','2019-02-06 07:59:02.285821'),(379,'sap_success_factors','0014_drop_historical_table','2019-02-06 07:59:02.903520'),(380,'sap_success_factors','0015_auto_20180510_1259','2019-02-06 07:59:03.734759'),(381,'sap_success_factors','0016_sapsuccessfactorsenterprisecustomerconfiguration_additional_locales','2019-02-06 07:59:03.878684'),(382,'sap_success_factors','0017_sapsuccessfactorsglobalconfiguration_search_student_api_path','2019-02-06 07:59:04.766539'),(383,'schedules','0001_initial','2019-02-06 07:59:05.179663'),(384,'schedules','0002_auto_20170816_1532','2019-02-06 07:59:05.397766'),(385,'schedules','0003_scheduleconfig','2019-02-06 07:59:05.977222'),(386,'schedules','0004_auto_20170922_1428','2019-02-06 07:59:06.791066'),(387,'schedules','0005_auto_20171010_1722','2019-02-06 07:59:07.631416'),(388,'schedules','0006_scheduleexperience','2019-02-06 07:59:08.189048'),(389,'schedules','0007_scheduleconfig_hold_back_ratio','2019-02-06 07:59:08.776239'),(390,'self_paced','0001_initial','2019-02-06 07:59:09.799050'),(391,'sessions','0001_initial','2019-02-06 07:59:09.921074'),(392,'shoppingcart','0001_initial','2019-02-06 07:59:21.053818'),(393,'shoppingcart','0002_auto_20151208_1034','2019-02-06 07:59:21.335220'),(394,'shoppingcart','0003_auto_20151217_0958','2019-02-06 07:59:21.599445'),(395,'shoppingcart','0004_change_meta_options','2019-02-06 07:59:21.823322'),(396,'site_configuration','0001_initial','2019-02-06 07:59:22.992881'),(397,'site_configuration','0002_auto_20160720_0231','2019-02-06 07:59:23.853074'),(398,'default','0001_initial','2019-02-06 07:59:25.015201'),(399,'social_auth','0001_initial','2019-02-06 07:59:25.046686'),(400,'default','0002_add_related_name','2019-02-06 07:59:25.500745'),(401,'social_auth','0002_add_related_name','2019-02-06 07:59:25.532177'),(402,'default','0003_alter_email_max_length','2019-02-06 07:59:25.652620'),(403,'social_auth','0003_alter_email_max_length','2019-02-06 07:59:25.690150'),(404,'default','0004_auto_20160423_0400','2019-02-06 07:59:26.074154'),(405,'social_auth','0004_auto_20160423_0400','2019-02-06 07:59:26.105575'),(406,'social_auth','0005_auto_20160727_2333','2019-02-06 07:59:26.241475'),(407,'social_django','0006_partial','2019-02-06 07:59:26.399875'),(408,'social_django','0007_code_timestamp','2019-02-06 07:59:26.566550'),(409,'social_django','0008_partial_timestamp','2019-02-06 07:59:26.712434'),(410,'splash','0001_initial','2019-02-06 07:59:27.288326'),(411,'static_replace','0001_initial','2019-02-06 07:59:27.851106'),(412,'static_replace','0002_assetexcludedextensionsconfig','2019-02-06 07:59:29.178463'),(413,'status','0001_initial','2019-02-06 07:59:30.834233'),(414,'status','0002_update_help_text','2019-02-06 07:59:31.259226'),(415,'student','0014_courseenrollmentallowed_user','2019-02-06 07:59:31.843553'),(416,'student','0015_manualenrollmentaudit_add_role','2019-02-06 07:59:32.339124'),(417,'student','0016_coursenrollment_course_on_delete_do_nothing','2019-02-06 07:59:33.019734'),(418,'student','0017_accountrecovery','2019-02-06 07:59:34.081866'),(419,'student','0018_remove_password_history','2019-02-06 07:59:35.360857'),(420,'student','0019_auto_20181221_0540','2019-02-06 07:59:36.450684'),(421,'submissions','0001_initial','2019-02-06 07:59:37.468217'),(422,'submissions','0002_auto_20151119_0913','2019-02-06 07:59:37.751719'),(423,'submissions','0003_submission_status','2019-02-06 07:59:37.951880'),(424,'submissions','0004_remove_django_extensions','2019-02-06 07:59:38.080449'),(425,'survey','0001_initial','2019-02-06 07:59:38.937112'),(426,'teams','0001_initial','2019-02-06 07:59:42.234272'),(427,'theming','0001_initial','2019-02-06 07:59:42.964122'),(428,'third_party_auth','0001_initial','2019-02-06 07:59:46.893944'),(429,'third_party_auth','0002_schema__provider_icon_image','2019-02-06 07:59:51.814091'),(430,'third_party_auth','0003_samlproviderconfig_debug_mode','2019-02-06 07:59:52.360263'),(431,'third_party_auth','0004_add_visible_field','2019-02-06 07:59:56.187303'),(432,'third_party_auth','0005_add_site_field','2019-02-06 08:00:00.726584'),(433,'third_party_auth','0006_samlproviderconfig_automatic_refresh_enabled','2019-02-06 08:00:01.267932'),(434,'third_party_auth','0007_auto_20170406_0912','2019-02-06 08:00:02.190874'),(435,'third_party_auth','0008_auto_20170413_1455','2019-02-06 08:00:03.658115'),(436,'third_party_auth','0009_auto_20170415_1144','2019-02-06 08:00:05.420674'),(437,'third_party_auth','0010_add_skip_hinted_login_dialog_field','2019-02-06 08:00:07.334260'),(438,'third_party_auth','0011_auto_20170616_0112','2019-02-06 08:00:07.841081'),(439,'third_party_auth','0012_auto_20170626_1135','2019-02-06 08:00:09.649831'),(440,'third_party_auth','0013_sync_learner_profile_data','2019-02-06 08:00:12.254172'),(441,'third_party_auth','0014_auto_20171222_1233','2019-02-06 08:00:13.935686'),(442,'third_party_auth','0015_samlproviderconfig_archived','2019-02-06 08:00:14.559179'),(443,'third_party_auth','0016_auto_20180130_0938','2019-02-06 08:00:15.656894'),(444,'third_party_auth','0017_remove_icon_class_image_secondary_fields','2019-02-06 08:00:17.597823'),(445,'third_party_auth','0018_auto_20180327_1631','2019-02-06 08:00:20.302724'),(446,'third_party_auth','0019_consolidate_slug','2019-02-06 08:00:23.246774'),(447,'third_party_auth','0020_cleanup_slug_fields','2019-02-06 08:00:25.498101'),(448,'third_party_auth','0021_sso_id_verification','2019-02-06 08:00:27.269685'),(449,'third_party_auth','0022_auto_20181012_0307','2019-02-06 08:00:30.475559'),(450,'thumbnail','0001_initial','2019-02-06 08:00:30.680886'),(451,'track','0001_initial','2019-02-06 08:00:30.998373'),(452,'user_api','0001_initial','2019-02-06 08:00:35.324701'),(453,'user_api','0002_retirementstate_userretirementstatus','2019-02-06 08:00:36.082707'),(454,'user_api','0003_userretirementrequest','2019-02-06 08:00:36.665229'),(455,'user_api','0004_userretirementpartnerreportingstatus','2019-02-06 08:00:37.317791'),(456,'user_authn','0001_data__add_login_service','2019-02-06 08:00:39.270679'),(457,'util','0001_initial','2019-02-06 08:00:39.822745'),(458,'util','0002_data__default_rate_limit_config','2019-02-06 08:00:40.606869'),(459,'verified_track_content','0002_verifiedtrackcohortedcourse_verified_cohort_name','2019-02-06 08:00:40.741152'),(460,'verified_track_content','0003_migrateverifiedtrackcohortssetting','2019-02-06 08:00:41.360407'),(461,'verify_student','0001_initial','2019-02-06 08:00:47.236180'),(462,'verify_student','0002_auto_20151124_1024','2019-02-06 08:00:47.481347'),(463,'verify_student','0003_auto_20151113_1443','2019-02-06 08:00:47.697474'),(464,'verify_student','0004_delete_historical_records','2019-02-06 08:00:47.928549'),(465,'verify_student','0005_remove_deprecated_models','2019-02-06 08:00:53.255639'),(466,'verify_student','0006_ssoverification','2019-02-06 08:00:53.608512'),(467,'verify_student','0007_idverificationaggregate','2019-02-06 08:00:54.126314'),(468,'verify_student','0008_populate_idverificationaggregate','2019-02-06 08:00:55.099295'),(469,'verify_student','0009_remove_id_verification_aggregate','2019-02-06 08:00:55.505989'),(470,'verify_student','0010_manualverification','2019-02-06 08:00:55.733258'),(471,'verify_student','0011_add_fields_to_sspv','2019-02-06 08:00:56.760072'),(472,'video_config','0001_initial','2019-02-06 08:00:57.094097'),(473,'video_config','0002_coursevideotranscriptenabledflag_videotranscriptenabledflag','2019-02-06 08:00:57.451972'),(474,'video_config','0003_transcriptmigrationsetting','2019-02-06 08:00:57.665251'),(475,'video_config','0004_transcriptmigrationsetting_command_run','2019-02-06 08:00:57.846477'),(476,'video_config','0005_auto_20180719_0752','2019-02-06 08:00:58.093978'),(477,'video_config','0006_videothumbnailetting_updatedcoursevideos','2019-02-06 08:00:58.479655'),(478,'video_config','0007_videothumbnailsetting_offset','2019-02-06 08:00:58.702464'),(479,'video_pipeline','0001_initial','2019-02-06 08:00:58.930134'),(480,'video_pipeline','0002_auto_20171114_0704','2019-02-06 08:00:59.248554'),(481,'video_pipeline','0003_coursevideouploadsenabledbydefault_videouploadsenabledbydefault','2019-02-06 08:00:59.639240'),(482,'waffle','0002_auto_20161201_0958','2019-02-06 08:00:59.770761'),(483,'waffle_utils','0001_initial','2019-02-06 08:01:00.120690'),(484,'wiki','0001_initial','2019-02-06 08:01:13.521825'),(485,'wiki','0002_remove_article_subscription','2019-02-06 08:01:13.635976'),(486,'wiki','0003_ip_address_conv','2019-02-06 08:01:15.191324'),(487,'wiki','0004_increase_slug_size','2019-02-06 08:01:15.438646'),(488,'wiki','0005_remove_attachments_and_images','2019-02-06 08:01:20.535437'),(489,'workflow','0001_initial','2019-02-06 08:01:20.955248'),(490,'workflow','0002_remove_django_extensions','2019-02-06 08:01:21.089005'),(491,'xapi','0001_initial','2019-02-06 08:01:21.762133'),(492,'xapi','0002_auto_20180726_0142','2019-02-06 08:01:22.140082'),(493,'xblock_django','0001_initial','2019-02-06 08:01:22.817601'),(494,'xblock_django','0002_auto_20160204_0809','2019-02-06 08:01:23.428800'),(495,'xblock_django','0003_add_new_config_models','2019-02-06 08:01:26.720065'),(496,'xblock_django','0004_delete_xblock_disable_config','2019-02-06 08:01:28.046351'),(497,'social_django','0002_add_related_name','2019-02-06 08:01:28.238120'),(498,'social_django','0003_alter_email_max_length','2019-02-06 08:01:28.295485'),(499,'social_django','0004_auto_20160423_0400','2019-02-06 08:01:28.369651'),(500,'social_django','0001_initial','2019-02-06 08:01:28.419547'),(501,'social_django','0005_auto_20160727_2333','2019-02-06 08:01:28.470149'),(502,'contentstore','0001_initial','2019-02-06 08:02:13.717472'),(503,'contentstore','0002_add_assets_page_flag','2019-02-06 08:02:14.894230'),(504,'contentstore','0003_remove_assets_page_flag','2019-02-06 08:02:15.936128'),(505,'course_creators','0001_initial','2019-02-06 08:02:16.677395'),(506,'tagging','0001_initial','2019-02-06 08:02:16.919416'),(507,'tagging','0002_auto_20170116_1541','2019-02-06 08:02:17.057789'),(508,'user_tasks','0001_initial','2019-02-06 08:02:18.095204'),(509,'user_tasks','0002_artifact_file_storage','2019-02-06 08:02:18.200132'),(510,'xblock_config','0001_initial','2019-02-06 08:02:18.497728'),(511,'xblock_config','0002_courseeditltifieldsenabledflag','2019-02-06 08:02:19.039966'),(512,'lti_provider','0001_initial','2019-02-20 13:01:39.285635'),(513,'lti_provider','0002_auto_20160325_0407','2019-02-20 13:01:39.369768'),(514,'lti_provider','0003_auto_20161118_1040','2019-02-20 13:01:39.445830'),(515,'content_type_gating','0005_auto_20190306_1547','2019-03-06 16:00:40.248896'),(516,'course_duration_limits','0005_auto_20190306_1546','2019-03-06 16:00:40.908922'),(517,'enterprise','0061_systemwideenterpriserole_systemwideenterpriseuserroleassignment','2019-03-08 15:47:17.741727'),(518,'enterprise','0062_add_system_wide_enterprise_roles','2019-03-08 15:47:17.809640'),(519,'content_type_gating','0006_auto_20190308_1447','2019-03-11 16:27:21.659554'),(520,'course_duration_limits','0006_auto_20190308_1447','2019-03-11 16:27:22.347994'),(521,'content_type_gating','0007_auto_20190311_1919','2019-03-12 16:11:14.076560'),(522,'course_duration_limits','0007_auto_20190311_1919','2019-03-12 16:11:17.332778'),(523,'announcements','0001_initial','2019-03-18 20:54:59.708245'),(524,'content_type_gating','0008_auto_20190313_1634','2019-03-18 20:55:00.145074'),(525,'course_duration_limits','0008_auto_20190313_1634','2019-03-18 20:55:00.800059'),(526,'enterprise','0063_systemwideenterpriserole_description','2019-03-21 18:40:50.646407'),(527,'enterprise','0064_enterprisefeaturerole_enterprisefeatureuserroleassignment','2019-03-28 19:29:40.049122'),(528,'enterprise','0065_add_enterprise_feature_roles','2019-03-28 19:29:40.122825'),(529,'enterprise','0066_add_system_wide_enterprise_operator_role','2019-03-28 19:29:40.190059'),(530,'student','0020_auto_20190227_2019','2019-04-01 21:47:10.285726'),(531,'certificates','0015_add_masters_choice','2019-04-05 14:56:54.180634'),(532,'enterprise','0067_add_role_based_access_control_switch','2019-04-08 20:44:56.835675'),(533,'program_enrollments','0001_initial','2019-04-10 20:25:28.810529'),(534,'program_enrollments','0002_historicalprogramcourseenrollment_programcourseenrollment','2019-04-18 16:07:31.718124'),(535,'third_party_auth','0023_auto_20190418_2033','2019-04-24 13:53:47.057323'),(536,'program_enrollments','0003_auto_20190424_1622','2019-04-24 16:34:31.400886'),(537,'courseware','0008_move_idde_to_edx_when','2019-04-25 14:14:01.833602'),(538,'edx_when','0001_initial','2019-04-25 14:14:04.077675'),(539,'edx_when','0002_auto_20190318_1736','2019-04-25 14:14:06.472260'),(540,'edx_when','0003_auto_20190402_1501','2019-04-25 14:14:08.565796'),(541,'edx_proctoring','0010_update_backend','2019-05-02 21:47:10.150692'),(542,'program_enrollments','0004_add_programcourseenrollment_relatedname','2019-05-02 21:47:10.839771'),(543,'student','0021_historicalcourseenrollment','2019-05-03 20:29:56.543955'),(544,'cornerstone','0001_initial','2019-05-29 09:32:41.107279'),(545,'cornerstone','0002_cornerstoneglobalconfiguration_subject_mapping','2019-05-29 09:32:41.540384'),(546,'third_party_auth','0024_fix_edit_disallowed','2019-05-29 14:34:07.293693'),(547,'discounts','0001_initial','2019-06-03 19:15:59.106385'),(548,'program_enrollments','0005_canceled_not_withdrawn','2019-06-03 19:15:59.936222'),(549,'entitlements','0011_historicalcourseentitlement','2019-06-04 17:56:15.038112'),(550,'organizations','0007_historicalorganization','2019-06-04 17:56:15.935805'),(551,'user_tasks','0003_url_max_length','2019-06-04 17:56:24.531329'),(552,'user_tasks','0004_url_textfield','2019-06-04 17:56:24.631710'),(553,'enterprise','0068_remove_role_based_access_control_switch','2019-06-05 10:59:25.727686'),(554,'grades','0015_historicalpersistentsubsectiongradeoverride','2019-06-10 16:42:15.294490'),(555,'bulk_grades','0001_initial','2019-06-12 14:00:05.595345'),(556,'super_csv','0001_initial','2019-06-12 14:00:05.668273'),(557,'super_csv','0002_csvoperation_user','2019-06-12 14:00:06.129086'),(558,'enterprise','0069_auto_20190613_0607','2019-06-13 20:29:34.416315'),(559,'course_modes','0012_historicalcoursemode','2019-06-20 14:16:40.384457'),(560,'student','0022_indexing_in_courseenrollment','2019-06-28 07:52:29.598606'),(561,'courseware','0009_auto_20190703_1955','2019-07-03 19:59:27.956010'),(562,'bulk_grades','0002_auto_20190703_1526','2019-07-09 16:23:49.075404'),(563,'course_overviews','0015_historicalcourseoverview','2019-07-09 16:23:49.552185'),(564,'courseware','0010_auto_20190709_1559','2019-07-09 16:23:49.959864'),(565,'grades','0016_auto_20190703_1446','2019-07-09 16:23:51.049448'),(566,'cornerstone','0003_auto_20190621_1000','2019-08-16 20:33:03.878476'),(567,'enterprise','0070_enterprise_catalog_query','2019-08-16 20:33:05.128301'),(568,'enterprise','0071_historicalpendingenrollment_historicalpendingenterprisecustomeruser','2019-08-16 20:33:06.381233'),(569,'instructor_task','0003_alter_task_input_field','2019-08-16 20:33:06.777708'),(570,'microsite_configuration','004_delete_all_tables','2019-08-16 20:33:08.216606'),(571,'sap_success_factors','0018_sapsuccessfactorsenterprisecustomerconfiguration_show_course_price','2019-08-16 20:33:08.320866'),(572,'super_csv','0003_csvoperation_original_filename','2019-08-16 20:33:08.729724'),(573,'system_wide_roles','0001_SystemWideRole_SystemWideRoleAssignment','2019-08-16 20:33:09.236280'),(574,'system_wide_roles','0002_add_system_wide_student_support_role','2019-08-16 20:33:10.100114'),(575,'contentstore','0004_remove_push_notification_configmodel_table','2019-08-16 20:33:16.971775'),(576,'xapi','0003_auto_20190807_1006','2019-08-23 11:39:26.089273'),(577,'program_enrollments','0006_add_the_correct_constraints','2019-08-23 18:08:47.891260'),(578,'video_config','0008_courseyoutubeblockedflag','2019-08-25 18:16:55.143257'),(579,'program_enrollments','0007_waiting_programcourseenrollment_constraint','2019-08-27 19:09:05.805301'),(580,'content_libraries','0001_initial','2019-08-30 19:27:59.312920'),(581,'courseware','0011_csm_id_bigint','2019-08-30 19:28:00.069282'),(582,'enterprise','0072_add_enterprise_report_config_feature_role','2019-08-30 19:28:00.572179'),(583,'enterprise','0073_enterprisecustomerreportingconfiguration_uuid','2019-08-30 19:28:01.681347'),(584,'enterprise','0074_auto_20190904_1143','2019-09-06 21:16:52.036849'),(585,'xapi','0004_auto_20190830_0710','2019-09-06 21:16:52.593883'),(586,'enterprise','0075_auto_20190916_1030','2019-09-16 21:24:18.290842'),(587,'course_overviews','0016_simulatecoursepublishconfig','2019-09-17 14:32:57.081562'),(588,'courseware','0012_adjust_fields','2019-09-19 19:47:08.473302'),(589,'enterprise','0076_auto_20190918_2037','2019-09-19 19:47:09.682209'),(590,'cornerstone','0004_cornerstoneglobalconfiguration_languages','2019-09-25 09:51:51.980971'),(591,'cornerstone','0005_auto_20190925_0730','2019-09-25 09:51:52.420065'),(592,'degreed','0007_auto_20190925_0730','2019-09-25 09:51:52.912089'),(593,'integrated_channel','0007_auto_20190925_0730','2019-09-25 09:51:52.965350'),(594,'sap_success_factors','0019_auto_20190925_0730','2019-09-25 09:51:53.387921'),(595,'course_overviews','0017_auto_20191002_0823','2019-10-03 17:35:24.874445'),(596,'courseware','0013_auto_20191001_1858','2019-10-03 17:35:25.469758'),(597,'edx_when','0004_datepolicy_rel_date','2019-10-03 17:35:25.561499'),(598,'edx_when','0005_auto_20190911_1056','2019-10-03 17:35:26.248583'),(599,'student','0023_bulkunenrollconfiguration','2019-10-08 08:54:34.630958'),(600,'program_enrollments','0008_add_ended_programenrollment_status','2019-10-15 16:54:18.793465'),(601,'enterprise','0077_auto_20191002_1529','2019-10-15 21:48:34.650220'),(602,'completion','0003_learning_context','2019-10-22 18:42:12.945705'),(603,'teams','0002_slug_field_ids','2019-10-22 18:42:13.905915'),(604,'entitlements','0012_allow_blank_order_number_values','2019-10-23 16:23:32.583686'),(605,'discounts','0002_auto_20191022_1720','2019-10-25 14:14:05.485328'),(606,'commerce','0008_auto_20191024_2048','2019-10-30 16:42:28.671238'),(607,'student','0024_fbeenrollmentexclusion','2019-10-31 16:16:17.991800'),(608,'student','0025_auto_20191101_1846','2019-11-05 14:23:09.546047'),(609,'cornerstone','0006_auto_20191001_0742','2019-11-15 09:41:31.515102'),(610,'degreed','0008_auto_20191001_0742','2019-11-15 09:41:31.985210'),(611,'enterprise','0078_auto_20191107_1536','2019-11-15 09:41:32.071798'),(612,'enterprise','0079_AddEnterpriseEnrollmentSource','2019-11-15 09:41:35.077452'),(613,'enterprise','0080_auto_20191113_1708','2019-11-15 09:41:35.165258'),(614,'sap_success_factors','0020_sapsuccessfactorsenterprisecustomerconfiguration_catalogs_to_transmit','2019-11-15 09:41:35.278200'),(615,'student','0026_allowedauthuser','2019-11-15 09:41:35.750216'),(616,'teams','0003_courseteam_organization_protected','2019-11-15 09:41:36.470845'),(617,'schedules','0008_add_new_start_date_field','2019-11-21 18:12:34.458532'),(618,'enterprise','0081_UpdateEnterpriseEnrollmentSource','2019-11-25 17:51:47.303851'),(619,'enterprise','0082_AddManagementEnterpriseEnrollmentSource','2019-12-03 20:57:24.426283'),(620,'edxval','0012_thirdpartytranscriptcredentialsstate_has_creds','2019-12-06 10:56:08.552448'),(621,'edxval','0013_thirdpartytranscriptcredentialsstate_copy_values','2019-12-13 13:13:20.308012'),(622,'edxval','0014_transcript_credentials_state_retype_exists','2019-12-13 13:13:20.408578'),(623,'programs','0013_customprogramsconfig','2019-12-13 13:13:21.067118'),(624,'verify_student','0012_sspverificationretryconfig','2019-12-13 13:13:21.515002'),(625,'assessment','0004_historicalsharedfileupload_sharedfileupload','2019-12-16 06:29:30.675880'),(626,'certificates','0016_historicalgeneratedcertificate','2019-12-17 14:29:56.935433'),(627,'entitlements','0013_historicalcourseentitlementsupportdetail','2019-12-17 14:29:57.436302'),(628,'credit','0005_creditrequirement_sort_value','2019-12-19 10:51:12.337166'),(629,'student','0027_courseenrollment_mode_callable_default','2019-12-26 15:35:57.040621'),(630,'enterprise','0083_enterprisecustomerreportingconfiguration_include_date','2019-12-26 21:47:14.728344'),(631,'schedules','0009_schedule_copy_column_values','2020-01-02 13:28:19.802979'),(632,'credit','0006_creditrequirement_alter_ordering','2020-01-03 18:18:36.334211'),(633,'credit','0007_creditrequirement_copy_values','2020-01-03 18:18:36.973921'),(634,'credit','0008_creditrequirement_remove_order','2020-01-08 11:38:24.657306'),(635,'grades','0017_delete_manual_psgoverride_table','2020-01-08 11:38:25.213640'),(636,'waffle','0003_update_strings_for_i18n','2020-01-08 14:05:29.720079'),(637,'student','0028_historicalmanualenrollmentaudit','2020-01-10 11:40:11.268574'),(638,'assessment','0005_add_filename_to_sharedupload','2020-01-13 10:35:07.847171'),(639,'course_overviews','0018_add_start_end_in_CourseOverview','2020-01-13 17:26:36.464326'),(640,'wiki','0006_auto_20200110_1003','2020-01-13 17:26:36.697919'),(641,'course_modes','0013_auto_20200115_2022','2020-01-15 20:27:50.992526'),(642,'entitlements','0014_auto_20200115_2022','2020-01-15 20:27:51.322976'),(643,'schedules','0010_remove_null_blank_from_schedules_date','2020-01-22 12:55:34.725873'),(644,'edxval','0015_remove_thirdpartytranscriptcredentialsstate_exists','2020-01-24 14:35:44.099846'),(645,'enterprise','0084_auto_20200120_1137','2020-01-24 14:35:44.172381'),(646,'enterprise','0085_enterprisecustomeruser_linked','2020-01-24 14:35:44.282887'),(647,'sap_success_factors','0021_sapsuccessfactorsenterprisecustomerconfiguration_show_total_hours','2020-01-27 10:53:31.872214'),(648,'course_overviews','0019_improve_courseoverviewtab','2020-01-28 16:51:30.714982'),(649,'enterprise','0086_auto_20200128_1726','2020-01-31 16:49:18.025706'),(650,'student','0029_add_data_researcher','2020-01-31 16:49:18.401525'),(651,'entitlements','0015_add_unique_together_constraint','2020-02-11 13:55:29.655054'),(652,'external_user_ids','0001_initial','2020-02-11 13:55:31.498884'),(653,'external_user_ids','0002_mb_coaching_20200210_1754','2020-02-11 13:55:31.894541'),(654,'sap_success_factors','0022_auto_20200206_1046','2020-02-11 13:55:32.101815'),(655,'track','0002_delete_trackinglog','2020-02-11 13:55:32.134542'),(656,'enterprise','0087_auto_20200206_1151','2020-02-18 09:55:42.697992'),(657,'site_configuration','0003_auto_20200217_1058','2020-02-18 09:55:42.825644'),(658,'student','0030_userprofile_phone_number','2020-02-20 14:48:47.685095'),(659,'course_date_signals','0001_initial','2020-02-21 16:45:43.955340'),(660,'oauth_dispatch','0008_applicationaccess_filters','2020-02-21 16:45:44.019075'),(661,'site_configuration','0004_add_site_values_field','2020-02-21 16:45:44.195027'),(662,'calendar_sync','0001_initial','2020-02-21 20:04:38.131685'),(663,'site_configuration','0005_copy_values_to_site_values','2020-02-24 18:47:53.200107'),(664,'external_user_ids','0003_auto_20200224_1836','2020-02-26 19:11:47.388528'),(665,'course_overviews','0020_courseoverviewtab_url_slug','2020-02-28 17:48:04.195272'),(666,'schedules','0011_auto_20200228_2018','2020-03-02 19:21:13.196282'),(667,'schedules','0012_auto_20200302_1914','2020-03-02 19:21:13.520829'),(668,'enterprise','0088_auto_20200224_1341','2020-03-03 20:05:46.920547'),(669,'experiments','0004_historicalexperimentkeyvalue','2020-03-03 20:05:47.277998'),(670,'program_enrollments','0009_update_course_enrollment_field_to_foreign_key','2020-03-03 20:05:47.685409'),(671,'site_configuration','0005_populate_siteconfig_history_site_values','2020-03-03 20:05:47.719133'),(672,'third_party_auth','0025_auto_20200303_1448','2020-03-03 20:05:48.252619'),(673,'oauth_dispatch','0009_delete_enable_scopes_waffle_switch','2020-03-04 16:01:48.080593'),(674,'schedules','0013_historicalschedule','2020-03-04 20:45:56.581945'),(675,'content_libraries','0002_group_permissions','2020-03-06 17:55:42.233448'),(676,'enterprise','0089_auto_20200305_0652','2020-03-06 17:55:42.297353'),(677,'site_configuration','0006_copy_values_to_site_values','2020-03-06 17:55:42.678035'),(678,'site_configuration','0007_remove_values_field','2020-03-06 17:55:42.788856'),(679,'schedules','0014_historicalschedule_drop_fk','2020-03-09 17:24:50.018834'),(680,'enterprise','0090_update_content_filter','2020-03-10 17:57:05.339287'),(681,'schedules','0015_schedules_start_nullable','2020-03-10 17:57:05.707643'),(682,'courseware','0014_fix_nan_value_for_global_speed','2020-03-11 13:49:13.615966'),(683,'enterprise','0091_add_sales_force_id_in_pendingenrollment','2020-03-12 10:54:44.467230'),(684,'enterprise','0092_auto_20200312_1650','2020-03-13 15:23:45.800175'),(685,'schedules','0016_remove_start_from_schedules','2020-03-13 15:23:45.883904'),(686,'schedules','0017_remove_start_from_historicalschedule','2020-03-13 15:23:45.976652'),(687,'schedules','0018_readd_historicalschedule_fks','2020-03-16 14:38:14.274410'),(688,'student','0031_auto_20200317_1122','2020-03-17 13:50:05.335676'),(689,'schedules','0019_auto_20200316_1935','2020-03-17 18:44:35.891013'),(690,'teams','0004_alter_defaults','2020-03-18 15:44:58.524624'),(691,'edxval','0016_add_transcript_credentials_model','2020-03-27 07:02:09.981900'),(692,'assessment','0006_TeamWorkflows','2020-03-30 19:21:36.208357'),(693,'edx_when','0006_drop_active_index','2020-03-30 19:21:36.251955'),(694,'program_enrollments','0010_add_courseaccessroleassignment','2020-03-30 19:21:36.855995'),(695,'workflow','0003_TeamWorkflows','2020-03-30 19:21:36.925096'),(696,'submissions','0005_CreateTeamModel','2020-04-01 20:57:39.372024'),(697,'third_party_auth','0026_auto_20200401_1932','2020-04-02 13:16:01.972784'),(698,'enterprise','0093_add_use_enterprise_catalog_flag','2020-04-08 18:22:44.709305'),(699,'enterprise','0094_add_use_enterprise_catalog_sample','2020-04-10 22:07:16.661282'),(700,'organizations','0001_squashed_0007_historicalorganization','2020-04-10 22:07:16.677543'),(701,'submissions','0001_squashed_0005_CreateTeamModel','2020-04-10 22:07:16.686207'),(702,'admin','0003_logentry_add_action_flag_choices','2020-04-23 18:11:46.942946'),(703,'auth','0009_alter_user_last_name_max_length','2020-04-23 18:11:47.230497'),(704,'auth','0010_alter_group_name_max_length','2020-04-23 18:11:47.298692'),(705,'auth','0011_update_proxy_permissions','2020-04-23 18:11:47.664132'),(706,'edx_when','0007_meta_tweaks','2020-04-23 18:11:47.691758'),(707,'oauth2_provider','0002_auto_20190406_1805','2020-04-23 18:11:47.818878'),(708,'student','0032_removed_logout_view_configuration','2020-04-23 18:11:48.393044'),(709,'student','0001_squashed_0031_auto_20200317_1122','2020-04-23 18:11:48.408997'),(710,'edxval','0001_squashed_0016_add_transcript_credentials_model','2020-04-23 18:11:48.416824'),(711,'enterprise','0001_squashed_0092_auto_20200312_1650','2020-04-23 18:11:48.424495'),(712,'third_party_auth','0001_squashed_0026_auto_20200401_1932','2020-04-23 18:11:48.432006'),(713,'integrated_channel','0001_squashed_0007_auto_20190925_0730','2020-04-24 16:47:34.188700'),(714,'sap_success_factors','0001_squashed_0022_auto_20200206_1046','2020-04-24 16:47:34.229718'),(715,'course_overviews','0021_courseoverviewtab_link','2020-05-04 10:59:26.420098'),(716,'course_overviews','0022_courseoverviewtab_is_hidden','2020-05-04 10:59:26.485523'),(717,'edxval','0002_add_error_description_field','2020-05-04 10:59:26.540249'),(718,'external_user_ids','0004_add_lti_type','2020-05-04 10:59:26.921830'),(719,'enterprise','0095_auto_20200507_1138','2020-05-08 20:20:32.807231'),(720,'enterprise','0096_enterprise_catalog_admin_role','2020-05-13 22:12:12.358228'),(721,'student','0033_userprofile_state','2020-05-13 22:12:12.631121'),(722,'edxval','0003_delete_transcriptcredentials','2020-05-27 10:59:38.022407'),(723,'learning_sequences','0001_initial','2020-06-04 06:05:36.384464'),(724,'video_pipeline','0004_vempipelineintegration','2020-06-04 06:05:36.976657'),(725,'social_django','0009_auto_20191118_0520','2020-06-19 00:00:47.256847'),(726,'social_django','0010_uid_db_index','2020-06-19 00:00:47.498169'),(727,'student','0034_courseenrollmentcelebration','2020-06-19 00:00:48.071380'),(728,'enterprise','0097_auto_20200619_1130','2020-06-19 19:05:07.673699'),(729,'grades','0018_add_waffle_flag_defaults','2020-06-23 18:17:18.366253'),(730,'contentstore','0005_add_enable_checklists_quality_waffle_flag','2020-06-23 18:17:25.592864'); /*!40000 ALTER TABLE `django_migrations` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; diff --git a/common/test/db_cache/bok_choy_migrations_data_student_module_history.sql b/common/test/db_cache/bok_choy_migrations_data_student_module_history.sql index 1056dbad59591e17bee50d2c2c48f1965fe511af..74b197fe06659b7ed493832019bd8edc0926d459 100644 --- a/common/test/db_cache/bok_choy_migrations_data_student_module_history.sql +++ b/common/test/db_cache/bok_choy_migrations_data_student_module_history.sql @@ -12,7 +12,7 @@ LOCK TABLES `django_migrations` WRITE; /*!40000 ALTER TABLE `django_migrations` DISABLE KEYS */; -INSERT INTO `django_migrations` VALUES (1,'contenttypes','0001_initial','2019-02-06 08:03:27.973279'),(2,'auth','0001_initial','2019-02-06 08:03:28.047577'),(3,'admin','0001_initial','2019-02-06 08:03:28.084214'),(4,'admin','0002_logentry_remove_auto_add','2019-02-06 08:03:28.117004'),(5,'sites','0001_initial','2019-02-06 08:03:28.138797'),(6,'contenttypes','0002_remove_content_type_name','2019-02-06 08:03:28.216567'),(7,'api_admin','0001_initial','2019-02-06 08:03:28.285457'),(8,'api_admin','0002_auto_20160325_1604','2019-02-06 08:03:28.307547'),(9,'api_admin','0003_auto_20160404_1618','2019-02-06 08:03:28.500622'),(10,'api_admin','0004_auto_20160412_1506','2019-02-06 08:03:28.633954'),(11,'api_admin','0005_auto_20160414_1232','2019-02-06 08:03:28.673633'),(12,'api_admin','0006_catalog','2019-02-06 08:03:28.696279'),(13,'api_admin','0007_delete_historical_api_records','2019-02-06 08:03:28.816693'),(14,'assessment','0001_initial','2019-02-06 08:03:29.290939'),(15,'assessment','0002_staffworkflow','2019-02-06 08:03:29.313966'),(16,'assessment','0003_expand_course_id','2019-02-06 08:03:29.378298'),(17,'auth','0002_alter_permission_name_max_length','2019-02-06 08:03:29.412172'),(18,'auth','0003_alter_user_email_max_length','2019-02-06 08:03:29.449614'),(19,'auth','0004_alter_user_username_opts','2019-02-06 08:03:29.489793'),(20,'auth','0005_alter_user_last_login_null','2019-02-06 08:03:29.529832'),(21,'auth','0006_require_contenttypes_0002','2019-02-06 08:03:29.535701'),(22,'auth','0007_alter_validators_add_error_messages','2019-02-06 08:03:29.572495'),(23,'auth','0008_alter_user_username_max_length','2019-02-06 08:03:29.606716'),(24,'instructor_task','0001_initial','2019-02-06 08:03:29.648070'),(25,'certificates','0001_initial','2019-02-06 08:03:30.038510'),(26,'certificates','0002_data__certificatehtmlviewconfiguration_data','2019-02-06 08:03:30.060258'),(27,'certificates','0003_data__default_modes','2019-02-06 08:03:30.081042'),(28,'certificates','0004_certificategenerationhistory','2019-02-06 08:03:30.138110'),(29,'certificates','0005_auto_20151208_0801','2019-02-06 08:03:30.188489'),(30,'certificates','0006_certificatetemplateasset_asset_slug','2019-02-06 08:03:30.217197'),(31,'certificates','0007_certificateinvalidation','2019-02-06 08:03:30.269518'),(32,'badges','0001_initial','2019-02-06 08:03:30.415373'),(33,'badges','0002_data__migrate_assertions','2019-02-06 08:03:30.438183'),(34,'badges','0003_schema__add_event_configuration','2019-02-06 08:03:30.731342'),(35,'block_structure','0001_config','2019-02-06 08:03:30.788599'),(36,'block_structure','0002_blockstructuremodel','2019-02-06 08:03:30.816557'),(37,'block_structure','0003_blockstructuremodel_storage','2019-02-06 08:03:30.846376'),(38,'block_structure','0004_blockstructuremodel_usagekeywithrun','2019-02-06 08:03:30.880450'),(39,'bookmarks','0001_initial','2019-02-06 08:03:31.054199'),(40,'branding','0001_initial','2019-02-06 08:03:31.166611'),(41,'course_modes','0001_initial','2019-02-06 08:03:31.243105'),(42,'course_modes','0002_coursemode_expiration_datetime_is_explicit','2019-02-06 08:03:31.269180'),(43,'course_modes','0003_auto_20151113_1443','2019-02-06 08:03:31.298423'),(44,'course_modes','0004_auto_20151113_1457','2019-02-06 08:03:31.371839'),(45,'course_modes','0005_auto_20151217_0958','2019-02-06 08:03:31.410727'),(46,'course_modes','0006_auto_20160208_1407','2019-02-06 08:03:31.485161'),(47,'course_modes','0007_coursemode_bulk_sku','2019-02-06 08:03:31.516196'),(48,'course_groups','0001_initial','2019-02-06 08:03:32.021134'),(49,'bulk_email','0001_initial','2019-02-06 08:03:32.263160'),(50,'bulk_email','0002_data__load_course_email_template','2019-02-06 08:03:32.285972'),(51,'bulk_email','0003_config_model_feature_flag','2019-02-06 08:03:32.366594'),(52,'bulk_email','0004_add_email_targets','2019-02-06 08:03:32.873567'),(53,'bulk_email','0005_move_target_data','2019-02-06 08:03:32.900737'),(54,'bulk_email','0006_course_mode_targets','2019-02-06 08:03:33.043008'),(55,'catalog','0001_initial','2019-02-06 08:03:33.155594'),(56,'catalog','0002_catalogintegration_username','2019-02-06 08:03:33.250400'),(57,'catalog','0003_catalogintegration_page_size','2019-02-06 08:03:33.342320'),(58,'catalog','0004_auto_20170616_0618','2019-02-06 08:03:33.440389'),(59,'catalog','0005_catalogintegration_long_term_cache_ttl','2019-02-06 08:03:33.567527'),(60,'django_comment_common','0001_initial','2019-02-06 08:03:33.854539'),(61,'django_comment_common','0002_forumsconfig','2019-02-06 08:03:33.972708'),(62,'verified_track_content','0001_initial','2019-02-06 08:03:33.998702'),(63,'course_overviews','0001_initial','2019-02-06 08:03:34.057460'),(64,'course_overviews','0002_add_course_catalog_fields','2019-02-06 08:03:34.224588'),(65,'course_overviews','0003_courseoverviewgeneratedhistory','2019-02-06 08:03:34.285061'),(66,'course_overviews','0004_courseoverview_org','2019-02-06 08:03:34.361105'),(67,'course_overviews','0005_delete_courseoverviewgeneratedhistory','2019-02-06 08:03:34.421372'),(68,'course_overviews','0006_courseoverviewimageset','2019-02-06 08:03:34.487776'),(69,'course_overviews','0007_courseoverviewimageconfig','2019-02-06 08:03:34.633259'),(70,'course_overviews','0008_remove_courseoverview_facebook_url','2019-02-06 08:03:34.646695'),(71,'course_overviews','0009_readd_facebook_url','2019-02-06 08:03:34.725856'),(72,'course_overviews','0010_auto_20160329_2317','2019-02-06 08:03:34.825796'),(73,'ccx','0001_initial','2019-02-06 08:03:35.149281'),(74,'ccx','0002_customcourseforedx_structure_json','2019-02-06 08:03:35.213941'),(75,'ccx','0003_add_master_course_staff_in_ccx','2019-02-06 08:03:35.275108'),(76,'ccx','0004_seed_forum_roles_in_ccx_courses','2019-02-06 08:03:35.320321'),(77,'ccx','0005_change_ccx_coach_to_staff','2019-02-06 08:03:35.350700'),(78,'ccx','0006_set_display_name_as_override','2019-02-06 08:03:35.391529'),(79,'ccxcon','0001_initial_ccxcon_model','2019-02-06 08:03:35.425585'),(80,'ccxcon','0002_auto_20160325_0407','2019-02-06 08:03:35.481080'),(81,'djcelery','0001_initial','2019-02-06 08:03:36.180254'),(82,'celery_utils','0001_initial','2019-02-06 08:03:36.284503'),(83,'celery_utils','0002_chordable_django_backend','2019-02-06 08:03:36.366801'),(84,'certificates','0008_schema__remove_badges','2019-02-06 08:03:36.556119'),(85,'certificates','0009_certificategenerationcoursesetting_language_self_generation','2019-02-06 08:03:36.773167'),(86,'certificates','0010_certificatetemplate_language','2019-02-06 08:03:36.815500'),(87,'certificates','0011_certificatetemplate_alter_unique','2019-02-06 08:03:36.919819'),(88,'certificates','0012_certificategenerationcoursesetting_include_hours_of_effort','2019-02-06 08:03:36.957024'),(89,'certificates','0013_remove_certificategenerationcoursesetting_enabled','2019-02-06 08:03:37.024718'),(90,'certificates','0014_change_eligible_certs_manager','2019-02-06 08:03:37.104973'),(91,'commerce','0001_data__add_ecommerce_service_user','2019-02-06 08:03:37.147354'),(92,'commerce','0002_commerceconfiguration','2019-02-06 08:03:37.232132'),(93,'commerce','0003_auto_20160329_0709','2019-02-06 08:03:37.297795'),(94,'commerce','0004_auto_20160531_0950','2019-02-06 08:03:37.417586'),(95,'commerce','0005_commerceconfiguration_enable_automatic_refund_approval','2019-02-06 08:03:37.504233'),(96,'commerce','0006_auto_20170424_1734','2019-02-06 08:03:37.578243'),(97,'commerce','0007_auto_20180313_0609','2019-02-06 08:03:37.688751'),(98,'completion','0001_initial','2019-02-06 08:03:37.847750'),(99,'completion','0002_auto_20180125_1510','2019-02-06 08:03:37.917588'),(100,'enterprise','0001_initial','2019-02-06 08:03:38.090862'),(101,'enterprise','0002_enterprisecustomerbrandingconfiguration','2019-02-06 08:03:38.142785'),(102,'enterprise','0003_auto_20161104_0937','2019-02-06 08:03:38.362358'),(103,'enterprise','0004_auto_20161114_0434','2019-02-06 08:03:38.484589'),(104,'enterprise','0005_pendingenterprisecustomeruser','2019-02-06 08:03:38.565074'),(105,'enterprise','0006_auto_20161121_0241','2019-02-06 08:03:38.604288'),(106,'enterprise','0007_auto_20161109_1511','2019-02-06 08:03:38.706534'),(107,'enterprise','0008_auto_20161124_2355','2019-02-06 08:03:38.935742'),(108,'enterprise','0009_auto_20161130_1651','2019-02-06 08:03:39.582739'),(109,'enterprise','0010_auto_20161222_1212','2019-02-06 08:03:39.710110'),(110,'enterprise','0011_enterprisecustomerentitlement_historicalenterprisecustomerentitlement','2019-02-06 08:03:39.820222'),(111,'enterprise','0012_auto_20170125_1033','2019-02-06 08:03:39.921636'),(112,'enterprise','0013_auto_20170125_1157','2019-02-06 08:03:40.091299'),(113,'enterprise','0014_enrollmentnotificationemailtemplate_historicalenrollmentnotificationemailtemplate','2019-02-06 08:03:40.226864'),(114,'enterprise','0015_auto_20170130_0003','2019-02-06 08:03:40.375822'),(115,'enterprise','0016_auto_20170405_0647','2019-02-06 08:03:41.108702'),(116,'enterprise','0017_auto_20170508_1341','2019-02-06 08:03:41.558782'),(117,'enterprise','0018_auto_20170511_1357','2019-02-06 08:03:41.671248'),(118,'enterprise','0019_auto_20170606_1853','2019-02-06 08:03:41.795407'),(119,'enterprise','0020_auto_20170624_2316','2019-02-06 08:03:42.114378'),(120,'enterprise','0021_auto_20170711_0712','2019-02-06 08:03:42.443741'),(121,'enterprise','0022_auto_20170720_1543','2019-02-06 08:03:42.555544'),(122,'enterprise','0023_audit_data_reporting_flag','2019-02-06 08:03:42.667708'),(123,'enterprise','0024_enterprisecustomercatalog_historicalenterprisecustomercatalog','2019-02-06 08:03:42.823862'),(124,'enterprise','0025_auto_20170828_1412','2019-02-06 08:03:43.148897'),(125,'enterprise','0026_make_require_account_level_consent_nullable','2019-02-06 08:03:43.564302'),(126,'enterprise','0027_remove_account_level_consent','2019-02-06 08:03:44.095360'),(127,'enterprise','0028_link_enterprise_to_enrollment_template','2019-02-06 08:03:44.318418'),(128,'enterprise','0029_auto_20170925_1909','2019-02-06 08:03:44.398129'),(129,'enterprise','0030_auto_20171005_1600','2019-02-06 08:03:44.553947'),(130,'enterprise','0031_auto_20171012_1249','2019-02-06 08:03:44.725906'),(131,'enterprise','0032_reporting_model','2019-02-06 08:03:44.840167'),(132,'enterprise','0033_add_history_change_reason_field','2019-02-06 08:03:45.245971'),(133,'enterprise','0034_auto_20171023_0727','2019-02-06 08:03:45.385659'),(134,'enterprise','0035_auto_20171212_1129','2019-02-06 08:03:45.513332'),(135,'enterprise','0036_sftp_reporting_support','2019-02-06 08:03:46.086601'),(136,'enterprise','0037_auto_20180110_0450','2019-02-06 08:03:46.208354'),(137,'enterprise','0038_auto_20180122_1427','2019-02-06 08:03:46.303546'),(138,'enterprise','0039_auto_20180129_1034','2019-02-06 08:03:46.415988'),(139,'enterprise','0040_auto_20180129_1428','2019-02-06 08:03:46.564661'),(140,'enterprise','0041_auto_20180212_1507','2019-02-06 08:03:46.626003'),(141,'consent','0001_initial','2019-02-06 08:03:46.846549'),(142,'consent','0002_migrate_to_new_data_sharing_consent','2019-02-06 08:03:46.875083'),(143,'consent','0003_historicaldatasharingconsent_history_change_reason','2019-02-06 08:03:46.965702'),(144,'consent','0004_datasharingconsenttextoverrides','2019-02-06 08:03:47.065885'),(145,'sites','0002_alter_domain_unique','2019-02-06 08:03:47.113519'),(146,'course_overviews','0011_courseoverview_marketing_url','2019-02-06 08:03:47.173117'),(147,'course_overviews','0012_courseoverview_eligible_for_financial_aid','2019-02-06 08:03:47.251335'),(148,'course_overviews','0013_courseoverview_language','2019-02-06 08:03:47.323251'),(149,'course_overviews','0014_courseoverview_certificate_available_date','2019-02-06 08:03:47.375112'),(150,'content_type_gating','0001_initial','2019-02-06 08:03:47.504223'),(151,'content_type_gating','0002_auto_20181119_0959','2019-02-06 08:03:47.696167'),(152,'content_type_gating','0003_auto_20181128_1407','2019-02-06 08:03:47.802689'),(153,'content_type_gating','0004_auto_20181128_1521','2019-02-06 08:03:47.899743'),(154,'contentserver','0001_initial','2019-02-06 08:03:48.012402'),(155,'contentserver','0002_cdnuseragentsconfig','2019-02-06 08:03:48.115897'),(156,'cors_csrf','0001_initial','2019-02-06 08:03:48.228961'),(157,'course_action_state','0001_initial','2019-02-06 08:03:48.432637'),(158,'course_duration_limits','0001_initial','2019-02-06 08:03:48.561335'),(159,'course_duration_limits','0002_auto_20181119_0959','2019-02-06 08:03:49.033726'),(160,'course_duration_limits','0003_auto_20181128_1407','2019-02-06 08:03:49.154788'),(161,'course_duration_limits','0004_auto_20181128_1521','2019-02-06 08:03:49.286782'),(162,'course_goals','0001_initial','2019-02-06 08:03:49.504320'),(163,'course_goals','0002_auto_20171010_1129','2019-02-06 08:03:49.596345'),(164,'course_groups','0002_change_inline_default_cohort_value','2019-02-06 08:03:49.642049'),(165,'course_groups','0003_auto_20170609_1455','2019-02-06 08:03:50.080016'),(166,'course_modes','0008_course_key_field_to_foreign_key','2019-02-06 08:03:50.526973'),(167,'course_modes','0009_suggested_prices_to_charfield','2019-02-06 08:03:50.584282'),(168,'course_modes','0010_archived_suggested_prices_to_charfield','2019-02-06 08:03:50.629980'),(169,'course_modes','0011_change_regex_for_comma_separated_ints','2019-02-06 08:03:50.727914'),(170,'courseware','0001_initial','2019-02-06 08:03:53.237177'),(171,'courseware','0002_coursedynamicupgradedeadlineconfiguration_dynamicupgradedeadlineconfiguration','2019-02-06 08:03:53.619502'),(172,'courseware','0003_auto_20170825_0935','2019-02-06 08:03:53.747454'),(173,'courseware','0004_auto_20171010_1639','2019-02-06 08:03:53.895768'),(174,'courseware','0005_orgdynamicupgradedeadlineconfiguration','2019-02-06 08:03:54.230018'),(175,'courseware','0006_remove_module_id_index','2019-02-06 08:03:54.435353'),(176,'courseware','0007_remove_done_index','2019-02-06 08:03:55.012607'),(177,'coursewarehistoryextended','0001_initial','2019-02-06 08:03:55.303411'),(178,'coursewarehistoryextended','0002_force_studentmodule_index','2019-02-06 08:03:55.370079'),(179,'crawlers','0001_initial','2019-02-06 08:03:55.442696'),(180,'crawlers','0002_auto_20170419_0018','2019-02-06 08:03:55.510303'),(181,'credentials','0001_initial','2019-02-06 08:03:55.578783'),(182,'credentials','0002_auto_20160325_0631','2019-02-06 08:03:55.640533'),(183,'credentials','0003_auto_20170525_1109','2019-02-06 08:03:55.760811'),(184,'credentials','0004_notifycredentialsconfig','2019-02-06 08:03:55.827343'),(185,'credit','0001_initial','2019-02-06 08:03:56.379666'),(186,'credit','0002_creditconfig','2019-02-06 08:03:56.456288'),(187,'credit','0003_auto_20160511_2227','2019-02-06 08:03:56.510076'),(188,'credit','0004_delete_historical_credit_records','2019-02-06 08:03:56.908755'),(189,'dark_lang','0001_initial','2019-02-06 08:03:56.974435'),(190,'dark_lang','0002_data__enable_on_install','2019-02-06 08:03:57.008178'),(191,'dark_lang','0003_auto_20180425_0359','2019-02-06 08:03:57.123998'),(192,'database_fixups','0001_initial','2019-02-06 08:03:57.156768'),(193,'degreed','0001_initial','2019-02-06 08:03:58.035952'),(194,'degreed','0002_auto_20180104_0103','2019-02-06 08:03:58.408761'),(195,'degreed','0003_auto_20180109_0712','2019-02-06 08:03:58.616044'),(196,'degreed','0004_auto_20180306_1251','2019-02-06 08:03:58.814623'),(197,'degreed','0005_auto_20180807_1302','2019-02-06 08:04:00.635482'),(198,'degreed','0006_upgrade_django_simple_history','2019-02-06 08:04:00.815237'),(199,'django_comment_common','0003_enable_forums','2019-02-06 08:04:00.851878'),(200,'django_comment_common','0004_auto_20161117_1209','2019-02-06 08:04:01.011618'),(201,'django_comment_common','0005_coursediscussionsettings','2019-02-06 08:04:01.048387'),(202,'django_comment_common','0006_coursediscussionsettings_discussions_id_map','2019-02-06 08:04:01.092669'),(203,'django_comment_common','0007_discussionsidmapping','2019-02-06 08:04:01.135336'),(204,'django_comment_common','0008_role_user_index','2019-02-06 08:04:01.166345'),(205,'django_notify','0001_initial','2019-02-06 08:04:01.899046'),(206,'django_openid_auth','0001_initial','2019-02-06 08:04:02.148673'),(207,'oauth2','0001_initial','2019-02-06 08:04:03.447522'),(208,'edx_oauth2_provider','0001_initial','2019-02-06 08:04:03.637123'),(209,'edx_proctoring','0001_initial','2019-02-06 08:04:06.249264'),(210,'edx_proctoring','0002_proctoredexamstudentattempt_is_status_acknowledged','2019-02-06 08:04:06.453204'),(211,'edx_proctoring','0003_auto_20160101_0525','2019-02-06 08:04:06.849450'),(212,'edx_proctoring','0004_auto_20160201_0523','2019-02-06 08:04:07.035676'),(213,'edx_proctoring','0005_proctoredexam_hide_after_due','2019-02-06 08:04:07.119540'),(214,'edx_proctoring','0006_allowed_time_limit_mins','2019-02-06 08:04:07.870116'),(215,'edx_proctoring','0007_proctoredexam_backend','2019-02-06 08:04:07.931188'),(216,'edx_proctoring','0008_auto_20181116_1551','2019-02-06 08:04:08.424205'),(217,'edx_proctoring','0009_proctoredexamreviewpolicy_remove_rules','2019-02-06 08:04:08.762512'),(218,'edxval','0001_initial','2019-02-06 08:04:09.122448'),(219,'edxval','0002_data__default_profiles','2019-02-06 08:04:09.157306'),(220,'edxval','0003_coursevideo_is_hidden','2019-02-06 08:04:09.208230'),(221,'edxval','0004_data__add_hls_profile','2019-02-06 08:04:09.249124'),(222,'edxval','0005_videoimage','2019-02-06 08:04:09.314101'),(223,'edxval','0006_auto_20171009_0725','2019-02-06 08:04:09.422431'),(224,'edxval','0007_transcript_credentials_state','2019-02-06 08:04:09.502957'),(225,'edxval','0008_remove_subtitles','2019-02-06 08:04:09.597483'),(226,'edxval','0009_auto_20171127_0406','2019-02-06 08:04:09.650707'),(227,'edxval','0010_add_video_as_foreign_key','2019-02-06 08:04:09.853179'),(228,'edxval','0011_data__add_audio_mp3_profile','2019-02-06 08:04:09.888952'),(229,'email_marketing','0001_initial','2019-02-06 08:04:10.490362'),(230,'email_marketing','0002_auto_20160623_1656','2019-02-06 08:04:12.322113'),(231,'email_marketing','0003_auto_20160715_1145','2019-02-06 08:04:13.625016'),(232,'email_marketing','0004_emailmarketingconfiguration_welcome_email_send_delay','2019-02-06 08:04:13.804721'),(233,'email_marketing','0005_emailmarketingconfiguration_user_registration_cookie_timeout_delay','2019-02-06 08:04:13.987226'),(234,'email_marketing','0006_auto_20170711_0615','2019-02-06 08:04:14.175392'),(235,'email_marketing','0007_auto_20170809_0653','2019-02-06 08:04:14.743333'),(236,'email_marketing','0008_auto_20170809_0539','2019-02-06 08:04:14.781400'),(237,'email_marketing','0009_remove_emailmarketingconfiguration_sailthru_activation_template','2019-02-06 08:04:15.000262'),(238,'email_marketing','0010_auto_20180425_0800','2019-02-06 08:04:15.577846'),(239,'embargo','0001_initial','2019-02-06 08:04:16.853715'),(240,'embargo','0002_data__add_countries','2019-02-06 08:04:16.895352'),(241,'enterprise','0042_replace_sensitive_sso_username','2019-02-06 08:04:17.169747'),(242,'enterprise','0043_auto_20180507_0138','2019-02-06 08:04:17.765765'),(243,'enterprise','0044_reporting_config_multiple_types','2019-02-06 08:04:18.048084'),(244,'enterprise','0045_report_type_json','2019-02-06 08:04:18.121655'),(245,'enterprise','0046_remove_unique_constraints','2019-02-06 08:04:18.194060'),(246,'enterprise','0047_auto_20180517_0457','2019-02-06 08:04:18.519446'),(247,'enterprise','0048_enterprisecustomeruser_active','2019-02-06 08:04:18.962011'),(248,'enterprise','0049_auto_20180531_0321','2019-02-06 08:04:20.082033'),(249,'enterprise','0050_progress_v2','2019-02-06 08:04:20.186103'),(250,'enterprise','0051_add_enterprise_slug','2019-02-06 08:04:20.652158'),(251,'enterprise','0052_create_unique_slugs','2019-02-06 08:04:21.259457'),(252,'enterprise','0053_pendingenrollment_cohort_name','2019-02-06 08:04:21.457833'),(253,'enterprise','0053_auto_20180911_0811','2019-02-06 08:04:22.130573'),(254,'enterprise','0054_merge_20180914_1511','2019-02-06 08:04:22.143011'),(255,'enterprise','0055_auto_20181015_1112','2019-02-06 08:04:22.603605'),(256,'enterprise','0056_enterprisecustomerreportingconfiguration_pgp_encryption_key','2019-02-06 08:04:22.718871'),(257,'enterprise','0057_enterprisecustomerreportingconfiguration_enterprise_customer_catalogs','2019-02-06 08:04:23.004578'),(258,'enterprise','0058_auto_20181212_0145','2019-02-06 08:04:23.860134'),(259,'enterprise','0059_add_code_management_portal_config','2019-02-06 08:04:24.184355'),(260,'enterprise','0060_upgrade_django_simple_history','2019-02-06 08:04:24.698860'),(261,'student','0001_initial','2019-02-06 08:04:31.285410'),(262,'student','0002_auto_20151208_1034','2019-02-06 08:04:31.449034'),(263,'student','0003_auto_20160516_0938','2019-02-06 08:04:31.626628'),(264,'student','0004_auto_20160531_1422','2019-02-06 08:04:31.724604'),(265,'student','0005_auto_20160531_1653','2019-02-06 08:04:32.170241'),(266,'student','0006_logoutviewconfiguration','2019-02-06 08:04:32.266892'),(267,'student','0007_registrationcookieconfiguration','2019-02-06 08:04:32.366689'),(268,'student','0008_auto_20161117_1209','2019-02-06 08:04:32.463972'),(269,'student','0009_auto_20170111_0422','2019-02-06 08:04:32.558706'),(270,'student','0010_auto_20170207_0458','2019-02-06 08:04:32.564759'),(271,'student','0011_course_key_field_to_foreign_key','2019-02-06 08:04:34.027590'),(272,'student','0012_sociallink','2019-02-06 08:04:34.353842'),(273,'student','0013_delete_historical_enrollment_records','2019-02-06 08:04:35.810292'),(274,'entitlements','0001_initial','2019-02-06 08:04:36.165929'),(275,'entitlements','0002_auto_20171102_0719','2019-02-06 08:04:38.257565'),(276,'entitlements','0003_auto_20171205_1431','2019-02-06 08:04:40.470342'),(277,'entitlements','0004_auto_20171206_1729','2019-02-06 08:04:40.982538'),(278,'entitlements','0005_courseentitlementsupportdetail','2019-02-06 08:04:41.539847'),(279,'entitlements','0006_courseentitlementsupportdetail_action','2019-02-06 08:04:41.979223'),(280,'entitlements','0007_change_expiration_period_default','2019-02-06 08:04:42.159096'),(281,'entitlements','0008_auto_20180328_1107','2019-02-06 08:04:42.683695'),(282,'entitlements','0009_courseentitlement_refund_locked','2019-02-06 08:04:43.025841'),(283,'entitlements','0010_backfill_refund_lock','2019-02-06 08:04:43.067438'),(284,'experiments','0001_initial','2019-02-06 08:04:44.694218'),(285,'experiments','0002_auto_20170627_1402','2019-02-06 08:04:44.793494'),(286,'experiments','0003_auto_20170713_1148','2019-02-06 08:04:44.853420'),(287,'external_auth','0001_initial','2019-02-06 08:04:45.445694'),(288,'grades','0001_initial','2019-02-06 08:04:45.632121'),(289,'grades','0002_rename_last_edited_field','2019-02-06 08:04:45.699684'),(290,'grades','0003_coursepersistentgradesflag_persistentgradesenabledflag','2019-02-06 08:04:46.457202'),(291,'grades','0004_visibleblocks_course_id','2019-02-06 08:04:46.531908'),(292,'grades','0005_multiple_course_flags','2019-02-06 08:04:46.849592'),(293,'grades','0006_persistent_course_grades','2019-02-06 08:04:46.952796'),(294,'grades','0007_add_passed_timestamp_column','2019-02-06 08:04:47.066573'),(295,'grades','0008_persistentsubsectiongrade_first_attempted','2019-02-06 08:04:47.138816'),(296,'grades','0009_auto_20170111_1507','2019-02-06 08:04:47.259581'),(297,'grades','0010_auto_20170112_1156','2019-02-06 08:04:47.344906'),(298,'grades','0011_null_edited_time','2019-02-06 08:04:47.527358'),(299,'grades','0012_computegradessetting','2019-02-06 08:04:48.367572'),(300,'grades','0013_persistentsubsectiongradeoverride','2019-02-06 08:04:48.436380'),(301,'grades','0014_persistentsubsectiongradeoverridehistory','2019-02-06 08:04:48.767621'),(302,'instructor_task','0002_gradereportsetting','2019-02-06 08:04:49.116174'),(303,'waffle','0001_initial','2019-02-06 08:04:49.522307'),(304,'sap_success_factors','0001_initial','2019-02-06 08:04:50.784688'),(305,'sap_success_factors','0002_auto_20170224_1545','2019-02-06 08:04:52.503372'),(306,'sap_success_factors','0003_auto_20170317_1402','2019-02-06 08:04:53.057896'),(307,'sap_success_factors','0004_catalogtransmissionaudit_audit_summary','2019-02-06 08:04:53.112654'),(308,'sap_success_factors','0005_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 08:04:53.414309'),(309,'sap_success_factors','0006_sapsuccessfactors_use_enterprise_enrollment_page_waffle_flag','2019-02-06 08:04:53.467401'),(310,'sap_success_factors','0007_remove_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 08:04:53.753419'),(311,'sap_success_factors','0008_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 08:04:54.072310'),(312,'sap_success_factors','0009_sapsuccessfactors_remove_enterprise_enrollment_page_waffle_flag','2019-02-06 08:04:54.115078'),(313,'sap_success_factors','0010_move_audit_tables_to_base_integrated_channel','2019-02-06 08:04:54.280162'),(314,'integrated_channel','0001_initial','2019-02-06 08:04:54.374204'),(315,'integrated_channel','0002_delete_enterpriseintegratedchannel','2019-02-06 08:04:54.413351'),(316,'integrated_channel','0003_catalogtransmissionaudit_learnerdatatransmissionaudit','2019-02-06 08:04:54.514947'),(317,'integrated_channel','0004_catalogtransmissionaudit_channel','2019-02-06 08:04:54.566483'),(318,'integrated_channel','0005_auto_20180306_1251','2019-02-06 08:04:55.508336'),(319,'integrated_channel','0006_delete_catalogtransmissionaudit','2019-02-06 08:04:55.564564'),(320,'lms_xblock','0001_initial','2019-02-06 08:04:55.920260'),(321,'microsite_configuration','0001_initial','2019-02-06 08:04:59.149839'),(322,'microsite_configuration','0002_auto_20160202_0228','2019-02-06 08:04:59.263415'),(323,'microsite_configuration','0003_delete_historical_records','2019-02-06 08:05:00.613558'),(324,'milestones','0001_initial','2019-02-06 08:05:01.624456'),(325,'milestones','0002_data__seed_relationship_types','2019-02-06 08:05:01.663935'),(326,'milestones','0003_coursecontentmilestone_requirements','2019-02-06 08:05:01.731497'),(327,'milestones','0004_auto_20151221_1445','2019-02-06 08:05:01.953395'),(328,'mobile_api','0001_initial','2019-02-06 08:05:02.276280'),(329,'mobile_api','0002_auto_20160406_0904','2019-02-06 08:05:02.375950'),(330,'mobile_api','0003_ignore_mobile_available_flag','2019-02-06 08:05:02.955623'),(331,'notes','0001_initial','2019-02-06 08:05:03.284134'),(332,'oauth2','0002_auto_20160404_0813','2019-02-06 08:05:04.320559'),(333,'oauth2','0003_client_logout_uri','2019-02-06 08:05:05.028463'),(334,'oauth2','0004_add_index_on_grant_expires','2019-02-06 08:05:05.320810'),(335,'oauth2','0005_grant_nonce','2019-02-06 08:05:05.628866'),(336,'organizations','0001_initial','2019-02-06 08:05:05.786592'),(337,'organizations','0002_auto_20170117_1434','2019-02-06 08:05:05.850615'),(338,'organizations','0003_auto_20170221_1138','2019-02-06 08:05:05.970702'),(339,'organizations','0004_auto_20170413_2315','2019-02-06 08:05:06.085590'),(340,'organizations','0005_auto_20171116_0640','2019-02-06 08:05:06.148448'),(341,'organizations','0006_auto_20171207_0259','2019-02-06 08:05:06.215454'),(342,'oauth2_provider','0001_initial','2019-02-06 08:05:07.961621'),(343,'oauth_dispatch','0001_initial','2019-02-06 08:05:08.350586'),(344,'oauth_dispatch','0002_scopedapplication_scopedapplicationorganization','2019-02-06 08:05:09.132604'),(345,'oauth_dispatch','0003_application_data','2019-02-06 08:05:09.196710'),(346,'oauth_dispatch','0004_auto_20180626_1349','2019-02-06 08:05:11.499019'),(347,'oauth_dispatch','0005_applicationaccess_type','2019-02-06 08:05:11.606808'),(348,'oauth_dispatch','0006_drop_application_id_constraints','2019-02-06 08:05:11.875498'),(349,'oauth2_provider','0002_08_updates','2019-02-06 08:05:12.127180'),(350,'oauth2_provider','0003_auto_20160316_1503','2019-02-06 08:05:12.219934'),(351,'oauth2_provider','0004_auto_20160525_1623','2019-02-06 08:05:12.448186'),(352,'oauth2_provider','0005_auto_20170514_1141','2019-02-06 08:05:13.676168'),(353,'oauth2_provider','0006_auto_20171214_2232','2019-02-06 08:05:14.539094'),(354,'oauth_dispatch','0007_restore_application_id_constraints','2019-02-06 08:05:14.834346'),(355,'oauth_provider','0001_initial','2019-02-06 08:05:15.171734'),(356,'problem_builder','0001_initial','2019-02-06 08:05:15.299615'),(357,'problem_builder','0002_auto_20160121_1525','2019-02-06 08:05:15.503283'),(358,'problem_builder','0003_auto_20161124_0755','2019-02-06 08:05:15.621050'),(359,'problem_builder','0004_copy_course_ids','2019-02-06 08:05:15.672698'),(360,'problem_builder','0005_auto_20170112_1021','2019-02-06 08:05:15.822489'),(361,'problem_builder','0006_remove_deprecated_course_id','2019-02-06 08:05:15.937076'),(362,'programs','0001_initial','2019-02-06 08:05:16.056792'),(363,'programs','0002_programsapiconfig_cache_ttl','2019-02-06 08:05:16.160203'),(364,'programs','0003_auto_20151120_1613','2019-02-06 08:05:16.532675'),(365,'programs','0004_programsapiconfig_enable_certification','2019-02-06 08:05:17.329411'),(366,'programs','0005_programsapiconfig_max_retries','2019-02-06 08:05:17.560011'),(367,'programs','0006_programsapiconfig_xseries_ad_enabled','2019-02-06 08:05:17.710363'),(368,'programs','0007_programsapiconfig_program_listing_enabled','2019-02-06 08:05:17.830224'),(369,'programs','0008_programsapiconfig_program_details_enabled','2019-02-06 08:05:17.950796'),(370,'programs','0009_programsapiconfig_marketing_path','2019-02-06 08:05:18.079013'),(371,'programs','0010_auto_20170204_2332','2019-02-06 08:05:18.382249'),(372,'programs','0011_auto_20170301_1844','2019-02-06 08:05:19.698119'),(373,'programs','0012_auto_20170419_0018','2019-02-06 08:05:19.800404'),(374,'redirects','0001_initial','2019-02-06 08:05:20.155019'),(375,'rss_proxy','0001_initial','2019-02-06 08:05:20.204027'),(376,'sap_success_factors','0011_auto_20180104_0103','2019-02-06 08:05:24.276543'),(377,'sap_success_factors','0012_auto_20180109_0712','2019-02-06 08:05:24.679152'),(378,'sap_success_factors','0013_auto_20180306_1251','2019-02-06 08:05:25.083064'),(379,'sap_success_factors','0014_drop_historical_table','2019-02-06 08:05:25.129347'),(380,'sap_success_factors','0015_auto_20180510_1259','2019-02-06 08:05:25.860155'),(381,'sap_success_factors','0016_sapsuccessfactorsenterprisecustomerconfiguration_additional_locales','2019-02-06 08:05:25.960191'),(382,'sap_success_factors','0017_sapsuccessfactorsglobalconfiguration_search_student_api_path','2019-02-06 08:05:26.285693'),(383,'schedules','0001_initial','2019-02-06 08:05:26.690791'),(384,'schedules','0002_auto_20170816_1532','2019-02-06 08:05:27.302276'),(385,'schedules','0003_scheduleconfig','2019-02-06 08:05:27.646134'),(386,'schedules','0004_auto_20170922_1428','2019-02-06 08:05:28.252876'),(387,'schedules','0005_auto_20171010_1722','2019-02-06 08:05:28.881956'),(388,'schedules','0006_scheduleexperience','2019-02-06 08:05:29.251797'),(389,'schedules','0007_scheduleconfig_hold_back_ratio','2019-02-06 08:05:29.617048'),(390,'self_paced','0001_initial','2019-02-06 08:05:30.027241'),(391,'sessions','0001_initial','2019-02-06 08:05:30.078048'),(392,'shoppingcart','0001_initial','2019-02-06 08:05:38.998266'),(393,'shoppingcart','0002_auto_20151208_1034','2019-02-06 08:05:39.154428'),(394,'shoppingcart','0003_auto_20151217_0958','2019-02-06 08:05:39.312762'),(395,'shoppingcart','0004_change_meta_options','2019-02-06 08:05:39.468307'),(396,'site_configuration','0001_initial','2019-02-06 08:05:40.221457'),(397,'site_configuration','0002_auto_20160720_0231','2019-02-06 08:05:40.436234'),(398,'default','0001_initial','2019-02-06 08:05:41.857778'),(399,'social_auth','0001_initial','2019-02-06 08:05:41.863663'),(400,'default','0002_add_related_name','2019-02-06 08:05:42.234168'),(401,'social_auth','0002_add_related_name','2019-02-06 08:05:42.241171'),(402,'default','0003_alter_email_max_length','2019-02-06 08:05:42.308536'),(403,'social_auth','0003_alter_email_max_length','2019-02-06 08:05:42.316793'),(404,'default','0004_auto_20160423_0400','2019-02-06 08:05:42.679083'),(405,'social_auth','0004_auto_20160423_0400','2019-02-06 08:05:42.685800'),(406,'social_auth','0005_auto_20160727_2333','2019-02-06 08:05:42.757758'),(407,'social_django','0006_partial','2019-02-06 08:05:42.816147'),(408,'social_django','0007_code_timestamp','2019-02-06 08:05:42.883285'),(409,'social_django','0008_partial_timestamp','2019-02-06 08:05:42.957758'),(410,'splash','0001_initial','2019-02-06 08:05:43.433414'),(411,'static_replace','0001_initial','2019-02-06 08:05:44.140144'),(412,'static_replace','0002_assetexcludedextensionsconfig','2019-02-06 08:05:46.566804'),(413,'status','0001_initial','2019-02-06 08:05:47.436513'),(414,'status','0002_update_help_text','2019-02-06 08:05:47.800113'),(415,'student','0014_courseenrollmentallowed_user','2019-02-06 08:05:48.264692'),(416,'student','0015_manualenrollmentaudit_add_role','2019-02-06 08:05:48.712619'),(417,'student','0016_coursenrollment_course_on_delete_do_nothing','2019-02-06 08:05:49.240041'),(418,'student','0017_accountrecovery','2019-02-06 08:05:49.748236'),(419,'student','0018_remove_password_history','2019-02-06 08:05:50.694342'),(420,'student','0019_auto_20181221_0540','2019-02-06 08:05:51.482317'),(421,'submissions','0001_initial','2019-02-06 08:05:51.980676'),(422,'submissions','0002_auto_20151119_0913','2019-02-06 08:05:52.129788'),(423,'submissions','0003_submission_status','2019-02-06 08:05:52.207556'),(424,'submissions','0004_remove_django_extensions','2019-02-06 08:05:52.285295'),(425,'survey','0001_initial','2019-02-06 08:05:53.028225'),(426,'teams','0001_initial','2019-02-06 08:05:56.392431'),(427,'theming','0001_initial','2019-02-06 08:05:57.128347'),(428,'third_party_auth','0001_initial','2019-02-06 08:06:00.383669'),(429,'third_party_auth','0002_schema__provider_icon_image','2019-02-06 08:06:04.313456'),(430,'third_party_auth','0003_samlproviderconfig_debug_mode','2019-02-06 08:06:04.721469'),(431,'third_party_auth','0004_add_visible_field','2019-02-06 08:06:08.188893'),(432,'third_party_auth','0005_add_site_field','2019-02-06 08:06:11.231121'),(433,'third_party_auth','0006_samlproviderconfig_automatic_refresh_enabled','2019-02-06 08:06:11.638402'),(434,'third_party_auth','0007_auto_20170406_0912','2019-02-06 08:06:12.463541'),(435,'third_party_auth','0008_auto_20170413_1455','2019-02-06 08:06:13.699789'),(436,'third_party_auth','0009_auto_20170415_1144','2019-02-06 08:06:15.877426'),(437,'third_party_auth','0010_add_skip_hinted_login_dialog_field','2019-02-06 08:06:17.252327'),(438,'third_party_auth','0011_auto_20170616_0112','2019-02-06 08:06:17.697662'),(439,'third_party_auth','0012_auto_20170626_1135','2019-02-06 08:06:19.014914'),(440,'third_party_auth','0013_sync_learner_profile_data','2019-02-06 08:06:21.184194'),(441,'third_party_auth','0014_auto_20171222_1233','2019-02-06 08:06:22.500576'),(442,'third_party_auth','0015_samlproviderconfig_archived','2019-02-06 08:06:22.910782'),(443,'third_party_auth','0016_auto_20180130_0938','2019-02-06 08:06:23.768574'),(444,'third_party_auth','0017_remove_icon_class_image_secondary_fields','2019-02-06 08:06:25.677996'),(445,'third_party_auth','0018_auto_20180327_1631','2019-02-06 08:06:26.945645'),(446,'third_party_auth','0019_consolidate_slug','2019-02-06 08:06:28.225165'),(447,'third_party_auth','0020_cleanup_slug_fields','2019-02-06 08:06:29.071340'),(448,'third_party_auth','0021_sso_id_verification','2019-02-06 08:06:30.920266'),(449,'third_party_auth','0022_auto_20181012_0307','2019-02-06 08:06:33.001900'),(450,'thumbnail','0001_initial','2019-02-06 08:06:33.058625'),(451,'track','0001_initial','2019-02-06 08:06:33.135878'),(452,'user_api','0001_initial','2019-02-06 08:06:36.568433'),(453,'user_api','0002_retirementstate_userretirementstatus','2019-02-06 08:06:37.067536'),(454,'user_api','0003_userretirementrequest','2019-02-06 08:06:37.538805'),(455,'user_api','0004_userretirementpartnerreportingstatus','2019-02-06 08:06:38.846620'),(456,'user_authn','0001_data__add_login_service','2019-02-06 08:06:38.924862'),(457,'util','0001_initial','2019-02-06 08:06:39.401783'),(458,'util','0002_data__default_rate_limit_config','2019-02-06 08:06:39.459887'),(459,'verified_track_content','0002_verifiedtrackcohortedcourse_verified_cohort_name','2019-02-06 08:06:39.538104'),(460,'verified_track_content','0003_migrateverifiedtrackcohortssetting','2019-02-06 08:06:40.048232'),(461,'verify_student','0001_initial','2019-02-06 08:06:45.357816'),(462,'verify_student','0002_auto_20151124_1024','2019-02-06 08:06:45.516943'),(463,'verify_student','0003_auto_20151113_1443','2019-02-06 08:06:45.673513'),(464,'verify_student','0004_delete_historical_records','2019-02-06 08:06:45.835049'),(465,'verify_student','0005_remove_deprecated_models','2019-02-06 08:06:49.679210'),(466,'verify_student','0006_ssoverification','2019-02-06 08:06:49.790644'),(467,'verify_student','0007_idverificationaggregate','2019-02-06 08:06:49.891841'),(468,'verify_student','0008_populate_idverificationaggregate','2019-02-06 08:06:49.947020'),(469,'verify_student','0009_remove_id_verification_aggregate','2019-02-06 08:06:50.183257'),(470,'verify_student','0010_manualverification','2019-02-06 08:06:50.284386'),(471,'verify_student','0011_add_fields_to_sspv','2019-02-06 08:06:50.459982'),(472,'video_config','0001_initial','2019-02-06 08:06:50.654393'),(473,'video_config','0002_coursevideotranscriptenabledflag_videotranscriptenabledflag','2019-02-06 08:06:50.846809'),(474,'video_config','0003_transcriptmigrationsetting','2019-02-06 08:06:50.952242'),(475,'video_config','0004_transcriptmigrationsetting_command_run','2019-02-06 08:06:51.053615'),(476,'video_config','0005_auto_20180719_0752','2019-02-06 08:06:51.770192'),(477,'video_config','0006_videothumbnailetting_updatedcoursevideos','2019-02-06 08:06:51.998431'),(478,'video_config','0007_videothumbnailsetting_offset','2019-02-06 08:06:52.104225'),(479,'video_pipeline','0001_initial','2019-02-06 08:06:52.217246'),(480,'video_pipeline','0002_auto_20171114_0704','2019-02-06 08:06:52.423437'),(481,'video_pipeline','0003_coursevideouploadsenabledbydefault_videouploadsenabledbydefault','2019-02-06 08:06:52.652384'),(482,'waffle','0002_auto_20161201_0958','2019-02-06 08:06:52.731546'),(483,'waffle_utils','0001_initial','2019-02-06 08:06:52.859204'),(484,'wiki','0001_initial','2019-02-06 08:07:04.002394'),(485,'wiki','0002_remove_article_subscription','2019-02-06 08:07:04.852782'),(486,'wiki','0003_ip_address_conv','2019-02-06 08:07:06.546138'),(487,'wiki','0004_increase_slug_size','2019-02-06 08:07:06.749915'),(488,'wiki','0005_remove_attachments_and_images','2019-02-06 08:07:10.711449'),(489,'workflow','0001_initial','2019-02-06 08:07:10.929774'),(490,'workflow','0002_remove_django_extensions','2019-02-06 08:07:11.016177'),(491,'xapi','0001_initial','2019-02-06 08:07:11.530173'),(492,'xapi','0002_auto_20180726_0142','2019-02-06 08:07:11.853838'),(493,'xblock_django','0001_initial','2019-02-06 08:07:12.421573'),(494,'xblock_django','0002_auto_20160204_0809','2019-02-06 08:07:12.884088'),(495,'xblock_django','0003_add_new_config_models','2019-02-06 08:07:15.322827'),(496,'xblock_django','0004_delete_xblock_disable_config','2019-02-06 08:07:15.939861'),(497,'social_django','0002_add_related_name','2019-02-06 08:07:15.955501'),(498,'social_django','0003_alter_email_max_length','2019-02-06 08:07:15.960905'),(499,'social_django','0004_auto_20160423_0400','2019-02-06 08:07:15.967703'),(500,'social_django','0001_initial','2019-02-06 08:07:15.972077'),(501,'social_django','0005_auto_20160727_2333','2019-02-06 08:07:15.978019'),(502,'contentstore','0001_initial','2019-02-06 08:07:47.027361'),(503,'contentstore','0002_add_assets_page_flag','2019-02-06 08:07:48.064450'),(504,'contentstore','0003_remove_assets_page_flag','2019-02-06 08:07:48.989553'),(505,'course_creators','0001_initial','2019-02-06 08:07:49.658930'),(506,'tagging','0001_initial','2019-02-06 08:07:49.791763'),(507,'tagging','0002_auto_20170116_1541','2019-02-06 08:07:49.890533'),(508,'user_tasks','0001_initial','2019-02-06 08:07:50.803460'),(509,'user_tasks','0002_artifact_file_storage','2019-02-06 08:07:50.865286'),(510,'xblock_config','0001_initial','2019-02-06 08:07:51.079346'),(511,'xblock_config','0002_courseeditltifieldsenabledflag','2019-02-06 08:07:51.540299'),(512,'lti_provider','0001_initial','2019-02-20 13:02:12.609875'),(513,'lti_provider','0002_auto_20160325_0407','2019-02-20 13:02:12.673092'),(514,'lti_provider','0003_auto_20161118_1040','2019-02-20 13:02:12.735420'),(515,'content_type_gating','0005_auto_20190306_1547','2019-03-06 16:01:10.563542'),(516,'course_duration_limits','0005_auto_20190306_1546','2019-03-06 16:01:11.211966'),(517,'enterprise','0061_systemwideenterpriserole_systemwideenterpriseuserroleassignment','2019-03-08 15:47:46.856657'),(518,'enterprise','0062_add_system_wide_enterprise_roles','2019-03-08 15:47:46.906778'),(519,'content_type_gating','0006_auto_20190308_1447','2019-03-11 16:27:52.135257'),(520,'course_duration_limits','0006_auto_20190308_1447','2019-03-11 16:27:52.779284'),(521,'content_type_gating','0007_auto_20190311_1919','2019-03-12 16:11:54.043782'),(522,'course_duration_limits','0007_auto_20190311_1919','2019-03-12 16:11:56.790492'),(523,'announcements','0001_initial','2019-03-18 20:55:30.988286'),(524,'content_type_gating','0008_auto_20190313_1634','2019-03-18 20:55:31.415131'),(525,'course_duration_limits','0008_auto_20190313_1634','2019-03-18 20:55:32.064734'),(526,'enterprise','0063_systemwideenterpriserole_description','2019-03-21 18:42:16.699719'),(527,'enterprise','0064_enterprisefeaturerole_enterprisefeatureuserroleassignment','2019-03-28 19:30:12.392842'),(528,'enterprise','0065_add_enterprise_feature_roles','2019-03-28 19:30:12.443188'),(529,'enterprise','0066_add_system_wide_enterprise_operator_role','2019-03-28 19:30:12.488801'),(530,'student','0020_auto_20190227_2019','2019-04-01 21:47:42.163913'),(531,'certificates','0015_add_masters_choice','2019-04-05 14:57:27.206603'),(532,'enterprise','0067_add_role_based_access_control_switch','2019-04-08 20:45:27.538157'),(533,'program_enrollments','0001_initial','2019-04-10 20:26:00.692153'),(534,'program_enrollments','0002_historicalprogramcourseenrollment_programcourseenrollment','2019-04-18 16:08:03.137722'),(535,'third_party_auth','0023_auto_20190418_2033','2019-04-24 13:54:18.834044'),(536,'program_enrollments','0003_auto_20190424_1622','2019-04-24 16:35:05.844296'),(537,'courseware','0008_move_idde_to_edx_when','2019-04-25 14:14:41.176920'),(538,'edx_when','0001_initial','2019-04-25 14:14:42.645389'),(539,'edx_when','0002_auto_20190318_1736','2019-04-25 14:14:44.336320'),(540,'edx_when','0003_auto_20190402_1501','2019-04-25 14:14:46.294533'),(541,'edx_proctoring','0010_update_backend','2019-05-02 21:47:41.213808'),(542,'program_enrollments','0004_add_programcourseenrollment_relatedname','2019-05-02 21:47:41.764379'),(543,'student','0021_historicalcourseenrollment','2019-05-03 20:30:26.687544'),(544,'cornerstone','0001_initial','2019-05-29 09:33:13.719793'),(545,'cornerstone','0002_cornerstoneglobalconfiguration_subject_mapping','2019-05-29 09:33:14.111664'),(546,'third_party_auth','0024_fix_edit_disallowed','2019-05-29 14:34:39.226961'),(547,'discounts','0001_initial','2019-06-03 19:16:30.854700'),(548,'program_enrollments','0005_canceled_not_withdrawn','2019-06-03 19:16:31.705259'),(549,'entitlements','0011_historicalcourseentitlement','2019-06-04 17:56:44.090401'),(550,'organizations','0007_historicalorganization','2019-06-04 17:56:44.882744'),(551,'user_tasks','0003_url_max_length','2019-06-04 17:56:52.649984'),(552,'user_tasks','0004_url_textfield','2019-06-04 17:56:52.708857'),(553,'enterprise','0068_remove_role_based_access_control_switch','2019-06-05 10:59:54.361142'),(554,'grades','0015_historicalpersistentsubsectiongradeoverride','2019-06-10 16:42:35.419978'),(555,'bulk_grades','0001_initial','2019-06-12 14:00:26.847460'),(556,'super_csv','0001_initial','2019-06-12 14:00:26.879762'),(557,'super_csv','0002_csvoperation_user','2019-06-12 14:00:27.257652'),(558,'enterprise','0069_auto_20190613_0607','2019-06-13 20:29:54.231876'),(559,'course_modes','0012_historicalcoursemode','2019-06-20 14:17:00.883900'),(560,'student','0022_indexing_in_courseenrollment','2019-06-28 07:52:49.937484'),(561,'courseware','0009_auto_20190703_1955','2019-07-03 19:59:48.322976'),(562,'bulk_grades','0002_auto_20190703_1526','2019-07-09 16:24:12.489841'),(563,'course_overviews','0015_historicalcourseoverview','2019-07-09 16:24:12.865655'),(564,'courseware','0010_auto_20190709_1559','2019-07-09 16:24:13.249043'),(565,'grades','0016_auto_20190703_1446','2019-07-09 16:24:14.162438'),(566,'cornerstone','0003_auto_20190621_1000','2019-08-16 20:33:30.643210'),(567,'enterprise','0070_enterprise_catalog_query','2019-08-16 20:33:31.677056'),(568,'enterprise','0071_historicalpendingenrollment_historicalpendingenterprisecustomeruser','2019-08-16 20:33:32.745997'),(569,'instructor_task','0003_alter_task_input_field','2019-08-16 20:33:33.017938'),(570,'microsite_configuration','004_delete_all_tables','2019-08-16 20:33:34.256853'),(571,'sap_success_factors','0018_sapsuccessfactorsenterprisecustomerconfiguration_show_course_price','2019-08-16 20:33:34.327113'),(572,'super_csv','0003_csvoperation_original_filename','2019-08-16 20:33:34.600410'),(573,'system_wide_roles','0001_SystemWideRole_SystemWideRoleAssignment','2019-08-16 20:33:34.993423'),(574,'system_wide_roles','0002_add_system_wide_student_support_role','2019-08-16 20:33:35.022596'),(575,'contentstore','0004_remove_push_notification_configmodel_table','2019-08-16 20:33:41.465727'),(576,'xapi','0003_auto_20190807_1006','2019-08-23 11:39:48.729878'),(577,'program_enrollments','0006_add_the_correct_constraints','2019-08-23 18:09:09.268961'),(578,'video_config','0008_courseyoutubeblockedflag','2019-08-25 18:17:15.983779'),(579,'program_enrollments','0007_waiting_programcourseenrollment_constraint','2019-08-27 19:09:27.680607'),(580,'content_libraries','0001_initial','2019-08-30 19:28:25.635235'),(581,'courseware','0011_csm_id_bigint','2019-08-30 19:28:26.395259'),(582,'enterprise','0072_add_enterprise_report_config_feature_role','2019-08-30 19:28:26.428135'),(583,'enterprise','0073_enterprisecustomerreportingconfiguration_uuid','2019-08-30 19:28:26.610136'),(584,'enterprise','0074_auto_20190904_1143','2019-09-06 21:17:13.932220'),(585,'xapi','0004_auto_20190830_0710','2019-09-06 21:17:14.456308'),(586,'enterprise','0075_auto_20190916_1030','2019-09-16 21:24:40.846129'),(587,'course_overviews','0016_simulatecoursepublishconfig','2019-09-17 14:33:18.318209'),(588,'courseware','0012_adjust_fields','2019-09-19 19:47:32.265973'),(589,'enterprise','0076_auto_20190918_2037','2019-09-19 19:47:33.356916'),(590,'cornerstone','0004_cornerstoneglobalconfiguration_languages','2019-09-25 09:52:14.183189'),(591,'cornerstone','0005_auto_20190925_0730','2019-09-25 09:52:14.554260'),(592,'degreed','0007_auto_20190925_0730','2019-09-25 09:52:14.965290'),(593,'integrated_channel','0007_auto_20190925_0730','2019-09-25 09:52:15.001578'),(594,'sap_success_factors','0019_auto_20190925_0730','2019-09-25 09:52:15.372786'),(595,'course_overviews','0017_auto_20191002_0823','2019-10-03 17:35:47.108732'),(596,'courseware','0013_auto_20191001_1858','2019-10-03 17:35:47.675913'),(597,'edx_when','0004_datepolicy_rel_date','2019-10-03 17:35:47.714137'),(598,'edx_when','0005_auto_20190911_1056','2019-10-03 17:35:48.352268'),(599,'student','0023_bulkunenrollconfiguration','2019-10-08 08:54:55.531674'),(600,'program_enrollments','0008_add_ended_programenrollment_status','2019-10-15 16:54:40.812546'),(601,'enterprise','0077_auto_20191002_1529','2019-10-15 21:48:57.015096'),(602,'completion','0003_learning_context','2019-10-22 18:42:37.071520'),(603,'teams','0002_slug_field_ids','2019-10-22 18:42:37.978486'),(604,'entitlements','0012_allow_blank_order_number_values','2019-10-23 16:23:53.619696'),(605,'discounts','0002_auto_20191022_1720','2019-10-25 14:14:29.317857'),(606,'commerce','0008_auto_20191024_2048','2019-10-30 16:42:49.876338'),(607,'student','0024_fbeenrollmentexclusion','2019-10-31 16:16:38.116056'),(608,'student','0025_auto_20191101_1846','2019-11-05 14:23:29.298316'),(609,'cornerstone','0006_auto_20191001_0742','2019-11-15 09:41:58.615907'),(610,'degreed','0008_auto_20191001_0742','2019-11-15 09:41:59.004037'),(611,'enterprise','0078_auto_20191107_1536','2019-11-15 09:41:59.081745'),(612,'enterprise','0079_AddEnterpriseEnrollmentSource','2019-11-15 09:42:01.297444'),(613,'enterprise','0080_auto_20191113_1708','2019-11-15 09:42:01.373867'),(614,'sap_success_factors','0020_sapsuccessfactorsenterprisecustomerconfiguration_catalogs_to_transmit','2019-11-15 09:42:01.448662'),(615,'student','0026_allowedauthuser','2019-11-15 09:42:01.867741'),(616,'teams','0003_courseteam_organization_protected','2019-11-15 09:42:02.160822'),(617,'schedules','0008_add_new_start_date_field','2019-11-21 18:12:54.950500'),(618,'enterprise','0081_UpdateEnterpriseEnrollmentSource','2019-11-25 17:52:07.779142'),(619,'enterprise','0082_AddManagementEnterpriseEnrollmentSource','2019-12-03 20:57:44.528593'),(620,'edxval','0012_thirdpartytranscriptcredentialsstate_has_creds','2019-12-06 10:56:28.616253'),(621,'edxval','0013_thirdpartytranscriptcredentialsstate_copy_values','2019-12-13 13:13:43.103802'),(622,'edxval','0014_transcript_credentials_state_retype_exists','2019-12-13 13:13:43.146474'),(623,'programs','0013_customprogramsconfig','2019-12-13 13:13:43.769272'),(624,'verify_student','0012_sspverificationretryconfig','2019-12-13 13:13:44.172148'),(625,'assessment','0004_historicalsharedfileupload_sharedfileupload','2019-12-16 06:29:51.457888'),(626,'certificates','0016_historicalgeneratedcertificate','2019-12-17 14:30:19.195816'),(627,'entitlements','0013_historicalcourseentitlementsupportdetail','2019-12-17 14:30:19.608404'),(628,'credit','0005_creditrequirement_sort_value','2019-12-19 10:51:33.510519'),(629,'student','0027_courseenrollment_mode_callable_default','2019-12-26 15:36:18.942310'),(630,'enterprise','0083_enterprisecustomerreportingconfiguration_include_date','2019-12-26 21:47:36.992960'),(631,'schedules','0009_schedule_copy_column_values','2020-01-02 13:28:40.924356'),(632,'credit','0006_creditrequirement_alter_ordering','2020-01-03 18:18:59.132478'),(633,'credit','0007_creditrequirement_copy_values','2020-01-03 18:18:59.153966'),(634,'credit','0008_creditrequirement_remove_order','2020-01-08 11:38:46.464661'),(635,'grades','0017_delete_manual_psgoverride_table','2020-01-08 11:38:46.979886'),(636,'waffle','0003_update_strings_for_i18n','2020-01-08 14:05:56.793699'),(637,'student','0028_historicalmanualenrollmentaudit','2020-01-10 11:40:33.721153'),(638,'assessment','0005_add_filename_to_sharedupload','2020-01-13 10:35:30.849694'),(639,'course_overviews','0018_add_start_end_in_CourseOverview','2020-01-13 17:26:59.381741'),(640,'wiki','0006_auto_20200110_1003','2020-01-13 17:26:59.580772'),(641,'course_modes','0013_auto_20200115_2022','2020-01-15 20:28:11.826240'),(642,'entitlements','0014_auto_20200115_2022','2020-01-15 20:28:12.121824'),(643,'schedules','0010_remove_null_blank_from_schedules_date','2020-01-22 12:55:55.562069'),(644,'edxval','0015_remove_thirdpartytranscriptcredentialsstate_exists','2020-01-24 14:36:05.625239'),(645,'enterprise','0084_auto_20200120_1137','2020-01-24 14:36:05.682781'),(646,'enterprise','0085_enterprisecustomeruser_linked','2020-01-24 14:36:05.737471'),(647,'sap_success_factors','0021_sapsuccessfactorsenterprisecustomerconfiguration_show_total_hours','2020-01-27 10:53:54.883903'),(648,'course_overviews','0019_improve_courseoverviewtab','2020-01-28 16:51:53.392851'),(649,'enterprise','0086_auto_20200128_1726','2020-01-31 16:49:40.116068'),(650,'student','0029_add_data_researcher','2020-01-31 16:49:40.134245'),(651,'entitlements','0015_add_unique_together_constraint','2020-02-11 13:55:54.821099'),(652,'external_user_ids','0001_initial','2020-02-11 13:55:56.286689'),(653,'external_user_ids','0002_mb_coaching_20200210_1754','2020-02-11 13:55:56.302455'),(654,'sap_success_factors','0022_auto_20200206_1046','2020-02-11 13:55:56.431451'),(655,'track','0002_delete_trackinglog','2020-02-11 13:55:56.448287'),(656,'enterprise','0087_auto_20200206_1151','2020-02-18 09:56:05.261459'),(657,'site_configuration','0003_auto_20200217_1058','2020-02-18 09:56:05.382056'),(658,'student','0030_userprofile_phone_number','2020-02-20 14:49:09.679286'),(659,'course_date_signals','0001_initial','2020-02-21 16:46:07.245424'),(660,'oauth_dispatch','0008_applicationaccess_filters','2020-02-21 16:46:07.279347'),(661,'site_configuration','0004_add_site_values_field','2020-02-21 16:46:07.400523'),(662,'calendar_sync','0001_initial','2020-02-21 20:05:00.723064'),(663,'site_configuration','0005_copy_values_to_site_values','2020-02-24 18:48:13.968250'),(664,'external_user_ids','0003_auto_20200224_1836','2020-02-26 19:12:10.225163'),(665,'course_overviews','0020_courseoverviewtab_url_slug','2020-02-28 17:48:26.402935'),(666,'schedules','0011_auto_20200228_2018','2020-03-02 19:21:35.447856'),(667,'schedules','0012_auto_20200302_1914','2020-03-02 19:21:35.760107'),(668,'enterprise','0088_auto_20200224_1341','2020-03-03 20:06:11.193549'),(669,'experiments','0004_historicalexperimentkeyvalue','2020-03-03 20:06:11.472740'),(670,'program_enrollments','0009_update_course_enrollment_field_to_foreign_key','2020-03-03 20:06:11.793880'),(671,'site_configuration','0005_populate_siteconfig_history_site_values','2020-03-03 20:06:11.809759'),(672,'third_party_auth','0025_auto_20200303_1448','2020-03-03 20:06:12.334364'),(673,'oauth_dispatch','0009_delete_enable_scopes_waffle_switch','2020-03-04 16:02:10.087753'),(674,'schedules','0013_historicalschedule','2020-03-04 20:46:18.382627'),(675,'content_libraries','0002_group_permissions','2020-03-06 17:56:06.253916'),(676,'enterprise','0089_auto_20200305_0652','2020-03-06 17:56:06.313096'),(677,'site_configuration','0006_copy_values_to_site_values','2020-03-06 17:56:06.328937'),(678,'site_configuration','0007_remove_values_field','2020-03-06 17:56:06.393334'),(679,'schedules','0014_historicalschedule_drop_fk','2020-03-09 17:25:11.320964'),(680,'enterprise','0090_update_content_filter','2020-03-10 17:57:28.234120'),(681,'schedules','0015_schedules_start_nullable','2020-03-10 17:57:28.512287'),(682,'courseware','0014_fix_nan_value_for_global_speed','2020-03-11 13:49:34.540416'),(683,'enterprise','0091_add_sales_force_id_in_pendingenrollment','2020-03-12 10:55:06.528703'),(684,'enterprise','0092_auto_20200312_1650','2020-03-13 15:24:08.871983'),(685,'schedules','0016_remove_start_from_schedules','2020-03-13 15:24:08.919319'),(686,'schedules','0017_remove_start_from_historicalschedule','2020-03-13 15:24:08.961171'),(687,'schedules','0018_readd_historicalschedule_fks','2020-03-16 14:38:37.163574'),(688,'student','0031_auto_20200317_1122','2020-03-17 13:50:29.328406'),(689,'schedules','0019_auto_20200316_1935','2020-03-17 18:44:58.495941'),(690,'teams','0004_alter_defaults','2020-03-18 15:45:23.207866'),(691,'edxval','0016_add_transcript_credentials_model','2020-03-27 07:02:32.020569'),(692,'assessment','0006_TeamWorkflows','2020-03-30 19:21:59.600633'),(693,'edx_when','0006_drop_active_index','2020-03-30 19:21:59.632637'),(694,'program_enrollments','0010_add_courseaccessroleassignment','2020-03-30 19:22:00.189635'),(695,'workflow','0003_TeamWorkflows','2020-03-30 19:22:00.217685'),(696,'submissions','0005_CreateTeamModel','2020-04-01 20:58:02.569032'),(697,'third_party_auth','0026_auto_20200401_1932','2020-04-02 13:16:24.403863'),(698,'enterprise','0093_add_use_enterprise_catalog_flag','2020-04-08 18:23:05.688441'),(699,'enterprise','0094_add_use_enterprise_catalog_sample','2020-04-10 22:07:38.597967'),(700,'submissions','0001_squashed_0005_CreateTeamModel','2020-04-10 22:07:38.604906'),(701,'organizations','0001_squashed_0007_historicalorganization','2020-04-10 22:07:38.607140'); +INSERT INTO `django_migrations` VALUES (1,'contenttypes','0001_initial','2019-02-06 08:03:27.973279'),(2,'auth','0001_initial','2019-02-06 08:03:28.047577'),(3,'admin','0001_initial','2019-02-06 08:03:28.084214'),(4,'admin','0002_logentry_remove_auto_add','2019-02-06 08:03:28.117004'),(5,'sites','0001_initial','2019-02-06 08:03:28.138797'),(6,'contenttypes','0002_remove_content_type_name','2019-02-06 08:03:28.216567'),(7,'api_admin','0001_initial','2019-02-06 08:03:28.285457'),(8,'api_admin','0002_auto_20160325_1604','2019-02-06 08:03:28.307547'),(9,'api_admin','0003_auto_20160404_1618','2019-02-06 08:03:28.500622'),(10,'api_admin','0004_auto_20160412_1506','2019-02-06 08:03:28.633954'),(11,'api_admin','0005_auto_20160414_1232','2019-02-06 08:03:28.673633'),(12,'api_admin','0006_catalog','2019-02-06 08:03:28.696279'),(13,'api_admin','0007_delete_historical_api_records','2019-02-06 08:03:28.816693'),(14,'assessment','0001_initial','2019-02-06 08:03:29.290939'),(15,'assessment','0002_staffworkflow','2019-02-06 08:03:29.313966'),(16,'assessment','0003_expand_course_id','2019-02-06 08:03:29.378298'),(17,'auth','0002_alter_permission_name_max_length','2019-02-06 08:03:29.412172'),(18,'auth','0003_alter_user_email_max_length','2019-02-06 08:03:29.449614'),(19,'auth','0004_alter_user_username_opts','2019-02-06 08:03:29.489793'),(20,'auth','0005_alter_user_last_login_null','2019-02-06 08:03:29.529832'),(21,'auth','0006_require_contenttypes_0002','2019-02-06 08:03:29.535701'),(22,'auth','0007_alter_validators_add_error_messages','2019-02-06 08:03:29.572495'),(23,'auth','0008_alter_user_username_max_length','2019-02-06 08:03:29.606716'),(24,'instructor_task','0001_initial','2019-02-06 08:03:29.648070'),(25,'certificates','0001_initial','2019-02-06 08:03:30.038510'),(26,'certificates','0002_data__certificatehtmlviewconfiguration_data','2019-02-06 08:03:30.060258'),(27,'certificates','0003_data__default_modes','2019-02-06 08:03:30.081042'),(28,'certificates','0004_certificategenerationhistory','2019-02-06 08:03:30.138110'),(29,'certificates','0005_auto_20151208_0801','2019-02-06 08:03:30.188489'),(30,'certificates','0006_certificatetemplateasset_asset_slug','2019-02-06 08:03:30.217197'),(31,'certificates','0007_certificateinvalidation','2019-02-06 08:03:30.269518'),(32,'badges','0001_initial','2019-02-06 08:03:30.415373'),(33,'badges','0002_data__migrate_assertions','2019-02-06 08:03:30.438183'),(34,'badges','0003_schema__add_event_configuration','2019-02-06 08:03:30.731342'),(35,'block_structure','0001_config','2019-02-06 08:03:30.788599'),(36,'block_structure','0002_blockstructuremodel','2019-02-06 08:03:30.816557'),(37,'block_structure','0003_blockstructuremodel_storage','2019-02-06 08:03:30.846376'),(38,'block_structure','0004_blockstructuremodel_usagekeywithrun','2019-02-06 08:03:30.880450'),(39,'bookmarks','0001_initial','2019-02-06 08:03:31.054199'),(40,'branding','0001_initial','2019-02-06 08:03:31.166611'),(41,'course_modes','0001_initial','2019-02-06 08:03:31.243105'),(42,'course_modes','0002_coursemode_expiration_datetime_is_explicit','2019-02-06 08:03:31.269180'),(43,'course_modes','0003_auto_20151113_1443','2019-02-06 08:03:31.298423'),(44,'course_modes','0004_auto_20151113_1457','2019-02-06 08:03:31.371839'),(45,'course_modes','0005_auto_20151217_0958','2019-02-06 08:03:31.410727'),(46,'course_modes','0006_auto_20160208_1407','2019-02-06 08:03:31.485161'),(47,'course_modes','0007_coursemode_bulk_sku','2019-02-06 08:03:31.516196'),(48,'course_groups','0001_initial','2019-02-06 08:03:32.021134'),(49,'bulk_email','0001_initial','2019-02-06 08:03:32.263160'),(50,'bulk_email','0002_data__load_course_email_template','2019-02-06 08:03:32.285972'),(51,'bulk_email','0003_config_model_feature_flag','2019-02-06 08:03:32.366594'),(52,'bulk_email','0004_add_email_targets','2019-02-06 08:03:32.873567'),(53,'bulk_email','0005_move_target_data','2019-02-06 08:03:32.900737'),(54,'bulk_email','0006_course_mode_targets','2019-02-06 08:03:33.043008'),(55,'catalog','0001_initial','2019-02-06 08:03:33.155594'),(56,'catalog','0002_catalogintegration_username','2019-02-06 08:03:33.250400'),(57,'catalog','0003_catalogintegration_page_size','2019-02-06 08:03:33.342320'),(58,'catalog','0004_auto_20170616_0618','2019-02-06 08:03:33.440389'),(59,'catalog','0005_catalogintegration_long_term_cache_ttl','2019-02-06 08:03:33.567527'),(60,'django_comment_common','0001_initial','2019-02-06 08:03:33.854539'),(61,'django_comment_common','0002_forumsconfig','2019-02-06 08:03:33.972708'),(62,'verified_track_content','0001_initial','2019-02-06 08:03:33.998702'),(63,'course_overviews','0001_initial','2019-02-06 08:03:34.057460'),(64,'course_overviews','0002_add_course_catalog_fields','2019-02-06 08:03:34.224588'),(65,'course_overviews','0003_courseoverviewgeneratedhistory','2019-02-06 08:03:34.285061'),(66,'course_overviews','0004_courseoverview_org','2019-02-06 08:03:34.361105'),(67,'course_overviews','0005_delete_courseoverviewgeneratedhistory','2019-02-06 08:03:34.421372'),(68,'course_overviews','0006_courseoverviewimageset','2019-02-06 08:03:34.487776'),(69,'course_overviews','0007_courseoverviewimageconfig','2019-02-06 08:03:34.633259'),(70,'course_overviews','0008_remove_courseoverview_facebook_url','2019-02-06 08:03:34.646695'),(71,'course_overviews','0009_readd_facebook_url','2019-02-06 08:03:34.725856'),(72,'course_overviews','0010_auto_20160329_2317','2019-02-06 08:03:34.825796'),(73,'ccx','0001_initial','2019-02-06 08:03:35.149281'),(74,'ccx','0002_customcourseforedx_structure_json','2019-02-06 08:03:35.213941'),(75,'ccx','0003_add_master_course_staff_in_ccx','2019-02-06 08:03:35.275108'),(76,'ccx','0004_seed_forum_roles_in_ccx_courses','2019-02-06 08:03:35.320321'),(77,'ccx','0005_change_ccx_coach_to_staff','2019-02-06 08:03:35.350700'),(78,'ccx','0006_set_display_name_as_override','2019-02-06 08:03:35.391529'),(79,'ccxcon','0001_initial_ccxcon_model','2019-02-06 08:03:35.425585'),(80,'ccxcon','0002_auto_20160325_0407','2019-02-06 08:03:35.481080'),(81,'djcelery','0001_initial','2019-02-06 08:03:36.180254'),(82,'celery_utils','0001_initial','2019-02-06 08:03:36.284503'),(83,'celery_utils','0002_chordable_django_backend','2019-02-06 08:03:36.366801'),(84,'certificates','0008_schema__remove_badges','2019-02-06 08:03:36.556119'),(85,'certificates','0009_certificategenerationcoursesetting_language_self_generation','2019-02-06 08:03:36.773167'),(86,'certificates','0010_certificatetemplate_language','2019-02-06 08:03:36.815500'),(87,'certificates','0011_certificatetemplate_alter_unique','2019-02-06 08:03:36.919819'),(88,'certificates','0012_certificategenerationcoursesetting_include_hours_of_effort','2019-02-06 08:03:36.957024'),(89,'certificates','0013_remove_certificategenerationcoursesetting_enabled','2019-02-06 08:03:37.024718'),(90,'certificates','0014_change_eligible_certs_manager','2019-02-06 08:03:37.104973'),(91,'commerce','0001_data__add_ecommerce_service_user','2019-02-06 08:03:37.147354'),(92,'commerce','0002_commerceconfiguration','2019-02-06 08:03:37.232132'),(93,'commerce','0003_auto_20160329_0709','2019-02-06 08:03:37.297795'),(94,'commerce','0004_auto_20160531_0950','2019-02-06 08:03:37.417586'),(95,'commerce','0005_commerceconfiguration_enable_automatic_refund_approval','2019-02-06 08:03:37.504233'),(96,'commerce','0006_auto_20170424_1734','2019-02-06 08:03:37.578243'),(97,'commerce','0007_auto_20180313_0609','2019-02-06 08:03:37.688751'),(98,'completion','0001_initial','2019-02-06 08:03:37.847750'),(99,'completion','0002_auto_20180125_1510','2019-02-06 08:03:37.917588'),(100,'enterprise','0001_initial','2019-02-06 08:03:38.090862'),(101,'enterprise','0002_enterprisecustomerbrandingconfiguration','2019-02-06 08:03:38.142785'),(102,'enterprise','0003_auto_20161104_0937','2019-02-06 08:03:38.362358'),(103,'enterprise','0004_auto_20161114_0434','2019-02-06 08:03:38.484589'),(104,'enterprise','0005_pendingenterprisecustomeruser','2019-02-06 08:03:38.565074'),(105,'enterprise','0006_auto_20161121_0241','2019-02-06 08:03:38.604288'),(106,'enterprise','0007_auto_20161109_1511','2019-02-06 08:03:38.706534'),(107,'enterprise','0008_auto_20161124_2355','2019-02-06 08:03:38.935742'),(108,'enterprise','0009_auto_20161130_1651','2019-02-06 08:03:39.582739'),(109,'enterprise','0010_auto_20161222_1212','2019-02-06 08:03:39.710110'),(110,'enterprise','0011_enterprisecustomerentitlement_historicalenterprisecustomerentitlement','2019-02-06 08:03:39.820222'),(111,'enterprise','0012_auto_20170125_1033','2019-02-06 08:03:39.921636'),(112,'enterprise','0013_auto_20170125_1157','2019-02-06 08:03:40.091299'),(113,'enterprise','0014_enrollmentnotificationemailtemplate_historicalenrollmentnotificationemailtemplate','2019-02-06 08:03:40.226864'),(114,'enterprise','0015_auto_20170130_0003','2019-02-06 08:03:40.375822'),(115,'enterprise','0016_auto_20170405_0647','2019-02-06 08:03:41.108702'),(116,'enterprise','0017_auto_20170508_1341','2019-02-06 08:03:41.558782'),(117,'enterprise','0018_auto_20170511_1357','2019-02-06 08:03:41.671248'),(118,'enterprise','0019_auto_20170606_1853','2019-02-06 08:03:41.795407'),(119,'enterprise','0020_auto_20170624_2316','2019-02-06 08:03:42.114378'),(120,'enterprise','0021_auto_20170711_0712','2019-02-06 08:03:42.443741'),(121,'enterprise','0022_auto_20170720_1543','2019-02-06 08:03:42.555544'),(122,'enterprise','0023_audit_data_reporting_flag','2019-02-06 08:03:42.667708'),(123,'enterprise','0024_enterprisecustomercatalog_historicalenterprisecustomercatalog','2019-02-06 08:03:42.823862'),(124,'enterprise','0025_auto_20170828_1412','2019-02-06 08:03:43.148897'),(125,'enterprise','0026_make_require_account_level_consent_nullable','2019-02-06 08:03:43.564302'),(126,'enterprise','0027_remove_account_level_consent','2019-02-06 08:03:44.095360'),(127,'enterprise','0028_link_enterprise_to_enrollment_template','2019-02-06 08:03:44.318418'),(128,'enterprise','0029_auto_20170925_1909','2019-02-06 08:03:44.398129'),(129,'enterprise','0030_auto_20171005_1600','2019-02-06 08:03:44.553947'),(130,'enterprise','0031_auto_20171012_1249','2019-02-06 08:03:44.725906'),(131,'enterprise','0032_reporting_model','2019-02-06 08:03:44.840167'),(132,'enterprise','0033_add_history_change_reason_field','2019-02-06 08:03:45.245971'),(133,'enterprise','0034_auto_20171023_0727','2019-02-06 08:03:45.385659'),(134,'enterprise','0035_auto_20171212_1129','2019-02-06 08:03:45.513332'),(135,'enterprise','0036_sftp_reporting_support','2019-02-06 08:03:46.086601'),(136,'enterprise','0037_auto_20180110_0450','2019-02-06 08:03:46.208354'),(137,'enterprise','0038_auto_20180122_1427','2019-02-06 08:03:46.303546'),(138,'enterprise','0039_auto_20180129_1034','2019-02-06 08:03:46.415988'),(139,'enterprise','0040_auto_20180129_1428','2019-02-06 08:03:46.564661'),(140,'enterprise','0041_auto_20180212_1507','2019-02-06 08:03:46.626003'),(141,'consent','0001_initial','2019-02-06 08:03:46.846549'),(142,'consent','0002_migrate_to_new_data_sharing_consent','2019-02-06 08:03:46.875083'),(143,'consent','0003_historicaldatasharingconsent_history_change_reason','2019-02-06 08:03:46.965702'),(144,'consent','0004_datasharingconsenttextoverrides','2019-02-06 08:03:47.065885'),(145,'sites','0002_alter_domain_unique','2019-02-06 08:03:47.113519'),(146,'course_overviews','0011_courseoverview_marketing_url','2019-02-06 08:03:47.173117'),(147,'course_overviews','0012_courseoverview_eligible_for_financial_aid','2019-02-06 08:03:47.251335'),(148,'course_overviews','0013_courseoverview_language','2019-02-06 08:03:47.323251'),(149,'course_overviews','0014_courseoverview_certificate_available_date','2019-02-06 08:03:47.375112'),(150,'content_type_gating','0001_initial','2019-02-06 08:03:47.504223'),(151,'content_type_gating','0002_auto_20181119_0959','2019-02-06 08:03:47.696167'),(152,'content_type_gating','0003_auto_20181128_1407','2019-02-06 08:03:47.802689'),(153,'content_type_gating','0004_auto_20181128_1521','2019-02-06 08:03:47.899743'),(154,'contentserver','0001_initial','2019-02-06 08:03:48.012402'),(155,'contentserver','0002_cdnuseragentsconfig','2019-02-06 08:03:48.115897'),(156,'cors_csrf','0001_initial','2019-02-06 08:03:48.228961'),(157,'course_action_state','0001_initial','2019-02-06 08:03:48.432637'),(158,'course_duration_limits','0001_initial','2019-02-06 08:03:48.561335'),(159,'course_duration_limits','0002_auto_20181119_0959','2019-02-06 08:03:49.033726'),(160,'course_duration_limits','0003_auto_20181128_1407','2019-02-06 08:03:49.154788'),(161,'course_duration_limits','0004_auto_20181128_1521','2019-02-06 08:03:49.286782'),(162,'course_goals','0001_initial','2019-02-06 08:03:49.504320'),(163,'course_goals','0002_auto_20171010_1129','2019-02-06 08:03:49.596345'),(164,'course_groups','0002_change_inline_default_cohort_value','2019-02-06 08:03:49.642049'),(165,'course_groups','0003_auto_20170609_1455','2019-02-06 08:03:50.080016'),(166,'course_modes','0008_course_key_field_to_foreign_key','2019-02-06 08:03:50.526973'),(167,'course_modes','0009_suggested_prices_to_charfield','2019-02-06 08:03:50.584282'),(168,'course_modes','0010_archived_suggested_prices_to_charfield','2019-02-06 08:03:50.629980'),(169,'course_modes','0011_change_regex_for_comma_separated_ints','2019-02-06 08:03:50.727914'),(170,'courseware','0001_initial','2019-02-06 08:03:53.237177'),(171,'courseware','0002_coursedynamicupgradedeadlineconfiguration_dynamicupgradedeadlineconfiguration','2019-02-06 08:03:53.619502'),(172,'courseware','0003_auto_20170825_0935','2019-02-06 08:03:53.747454'),(173,'courseware','0004_auto_20171010_1639','2019-02-06 08:03:53.895768'),(174,'courseware','0005_orgdynamicupgradedeadlineconfiguration','2019-02-06 08:03:54.230018'),(175,'courseware','0006_remove_module_id_index','2019-02-06 08:03:54.435353'),(176,'courseware','0007_remove_done_index','2019-02-06 08:03:55.012607'),(177,'coursewarehistoryextended','0001_initial','2019-02-06 08:03:55.303411'),(178,'coursewarehistoryextended','0002_force_studentmodule_index','2019-02-06 08:03:55.370079'),(179,'crawlers','0001_initial','2019-02-06 08:03:55.442696'),(180,'crawlers','0002_auto_20170419_0018','2019-02-06 08:03:55.510303'),(181,'credentials','0001_initial','2019-02-06 08:03:55.578783'),(182,'credentials','0002_auto_20160325_0631','2019-02-06 08:03:55.640533'),(183,'credentials','0003_auto_20170525_1109','2019-02-06 08:03:55.760811'),(184,'credentials','0004_notifycredentialsconfig','2019-02-06 08:03:55.827343'),(185,'credit','0001_initial','2019-02-06 08:03:56.379666'),(186,'credit','0002_creditconfig','2019-02-06 08:03:56.456288'),(187,'credit','0003_auto_20160511_2227','2019-02-06 08:03:56.510076'),(188,'credit','0004_delete_historical_credit_records','2019-02-06 08:03:56.908755'),(189,'dark_lang','0001_initial','2019-02-06 08:03:56.974435'),(190,'dark_lang','0002_data__enable_on_install','2019-02-06 08:03:57.008178'),(191,'dark_lang','0003_auto_20180425_0359','2019-02-06 08:03:57.123998'),(192,'database_fixups','0001_initial','2019-02-06 08:03:57.156768'),(193,'degreed','0001_initial','2019-02-06 08:03:58.035952'),(194,'degreed','0002_auto_20180104_0103','2019-02-06 08:03:58.408761'),(195,'degreed','0003_auto_20180109_0712','2019-02-06 08:03:58.616044'),(196,'degreed','0004_auto_20180306_1251','2019-02-06 08:03:58.814623'),(197,'degreed','0005_auto_20180807_1302','2019-02-06 08:04:00.635482'),(198,'degreed','0006_upgrade_django_simple_history','2019-02-06 08:04:00.815237'),(199,'django_comment_common','0003_enable_forums','2019-02-06 08:04:00.851878'),(200,'django_comment_common','0004_auto_20161117_1209','2019-02-06 08:04:01.011618'),(201,'django_comment_common','0005_coursediscussionsettings','2019-02-06 08:04:01.048387'),(202,'django_comment_common','0006_coursediscussionsettings_discussions_id_map','2019-02-06 08:04:01.092669'),(203,'django_comment_common','0007_discussionsidmapping','2019-02-06 08:04:01.135336'),(204,'django_comment_common','0008_role_user_index','2019-02-06 08:04:01.166345'),(205,'django_notify','0001_initial','2019-02-06 08:04:01.899046'),(206,'django_openid_auth','0001_initial','2019-02-06 08:04:02.148673'),(207,'oauth2','0001_initial','2019-02-06 08:04:03.447522'),(208,'edx_oauth2_provider','0001_initial','2019-02-06 08:04:03.637123'),(209,'edx_proctoring','0001_initial','2019-02-06 08:04:06.249264'),(210,'edx_proctoring','0002_proctoredexamstudentattempt_is_status_acknowledged','2019-02-06 08:04:06.453204'),(211,'edx_proctoring','0003_auto_20160101_0525','2019-02-06 08:04:06.849450'),(212,'edx_proctoring','0004_auto_20160201_0523','2019-02-06 08:04:07.035676'),(213,'edx_proctoring','0005_proctoredexam_hide_after_due','2019-02-06 08:04:07.119540'),(214,'edx_proctoring','0006_allowed_time_limit_mins','2019-02-06 08:04:07.870116'),(215,'edx_proctoring','0007_proctoredexam_backend','2019-02-06 08:04:07.931188'),(216,'edx_proctoring','0008_auto_20181116_1551','2019-02-06 08:04:08.424205'),(217,'edx_proctoring','0009_proctoredexamreviewpolicy_remove_rules','2019-02-06 08:04:08.762512'),(218,'edxval','0001_initial','2019-02-06 08:04:09.122448'),(219,'edxval','0002_data__default_profiles','2019-02-06 08:04:09.157306'),(220,'edxval','0003_coursevideo_is_hidden','2019-02-06 08:04:09.208230'),(221,'edxval','0004_data__add_hls_profile','2019-02-06 08:04:09.249124'),(222,'edxval','0005_videoimage','2019-02-06 08:04:09.314101'),(223,'edxval','0006_auto_20171009_0725','2019-02-06 08:04:09.422431'),(224,'edxval','0007_transcript_credentials_state','2019-02-06 08:04:09.502957'),(225,'edxval','0008_remove_subtitles','2019-02-06 08:04:09.597483'),(226,'edxval','0009_auto_20171127_0406','2019-02-06 08:04:09.650707'),(227,'edxval','0010_add_video_as_foreign_key','2019-02-06 08:04:09.853179'),(228,'edxval','0011_data__add_audio_mp3_profile','2019-02-06 08:04:09.888952'),(229,'email_marketing','0001_initial','2019-02-06 08:04:10.490362'),(230,'email_marketing','0002_auto_20160623_1656','2019-02-06 08:04:12.322113'),(231,'email_marketing','0003_auto_20160715_1145','2019-02-06 08:04:13.625016'),(232,'email_marketing','0004_emailmarketingconfiguration_welcome_email_send_delay','2019-02-06 08:04:13.804721'),(233,'email_marketing','0005_emailmarketingconfiguration_user_registration_cookie_timeout_delay','2019-02-06 08:04:13.987226'),(234,'email_marketing','0006_auto_20170711_0615','2019-02-06 08:04:14.175392'),(235,'email_marketing','0007_auto_20170809_0653','2019-02-06 08:04:14.743333'),(236,'email_marketing','0008_auto_20170809_0539','2019-02-06 08:04:14.781400'),(237,'email_marketing','0009_remove_emailmarketingconfiguration_sailthru_activation_template','2019-02-06 08:04:15.000262'),(238,'email_marketing','0010_auto_20180425_0800','2019-02-06 08:04:15.577846'),(239,'embargo','0001_initial','2019-02-06 08:04:16.853715'),(240,'embargo','0002_data__add_countries','2019-02-06 08:04:16.895352'),(241,'enterprise','0042_replace_sensitive_sso_username','2019-02-06 08:04:17.169747'),(242,'enterprise','0043_auto_20180507_0138','2019-02-06 08:04:17.765765'),(243,'enterprise','0044_reporting_config_multiple_types','2019-02-06 08:04:18.048084'),(244,'enterprise','0045_report_type_json','2019-02-06 08:04:18.121655'),(245,'enterprise','0046_remove_unique_constraints','2019-02-06 08:04:18.194060'),(246,'enterprise','0047_auto_20180517_0457','2019-02-06 08:04:18.519446'),(247,'enterprise','0048_enterprisecustomeruser_active','2019-02-06 08:04:18.962011'),(248,'enterprise','0049_auto_20180531_0321','2019-02-06 08:04:20.082033'),(249,'enterprise','0050_progress_v2','2019-02-06 08:04:20.186103'),(250,'enterprise','0051_add_enterprise_slug','2019-02-06 08:04:20.652158'),(251,'enterprise','0052_create_unique_slugs','2019-02-06 08:04:21.259457'),(252,'enterprise','0053_pendingenrollment_cohort_name','2019-02-06 08:04:21.457833'),(253,'enterprise','0053_auto_20180911_0811','2019-02-06 08:04:22.130573'),(254,'enterprise','0054_merge_20180914_1511','2019-02-06 08:04:22.143011'),(255,'enterprise','0055_auto_20181015_1112','2019-02-06 08:04:22.603605'),(256,'enterprise','0056_enterprisecustomerreportingconfiguration_pgp_encryption_key','2019-02-06 08:04:22.718871'),(257,'enterprise','0057_enterprisecustomerreportingconfiguration_enterprise_customer_catalogs','2019-02-06 08:04:23.004578'),(258,'enterprise','0058_auto_20181212_0145','2019-02-06 08:04:23.860134'),(259,'enterprise','0059_add_code_management_portal_config','2019-02-06 08:04:24.184355'),(260,'enterprise','0060_upgrade_django_simple_history','2019-02-06 08:04:24.698860'),(261,'student','0001_initial','2019-02-06 08:04:31.285410'),(262,'student','0002_auto_20151208_1034','2019-02-06 08:04:31.449034'),(263,'student','0003_auto_20160516_0938','2019-02-06 08:04:31.626628'),(264,'student','0004_auto_20160531_1422','2019-02-06 08:04:31.724604'),(265,'student','0005_auto_20160531_1653','2019-02-06 08:04:32.170241'),(266,'student','0006_logoutviewconfiguration','2019-02-06 08:04:32.266892'),(267,'student','0007_registrationcookieconfiguration','2019-02-06 08:04:32.366689'),(268,'student','0008_auto_20161117_1209','2019-02-06 08:04:32.463972'),(269,'student','0009_auto_20170111_0422','2019-02-06 08:04:32.558706'),(270,'student','0010_auto_20170207_0458','2019-02-06 08:04:32.564759'),(271,'student','0011_course_key_field_to_foreign_key','2019-02-06 08:04:34.027590'),(272,'student','0012_sociallink','2019-02-06 08:04:34.353842'),(273,'student','0013_delete_historical_enrollment_records','2019-02-06 08:04:35.810292'),(274,'entitlements','0001_initial','2019-02-06 08:04:36.165929'),(275,'entitlements','0002_auto_20171102_0719','2019-02-06 08:04:38.257565'),(276,'entitlements','0003_auto_20171205_1431','2019-02-06 08:04:40.470342'),(277,'entitlements','0004_auto_20171206_1729','2019-02-06 08:04:40.982538'),(278,'entitlements','0005_courseentitlementsupportdetail','2019-02-06 08:04:41.539847'),(279,'entitlements','0006_courseentitlementsupportdetail_action','2019-02-06 08:04:41.979223'),(280,'entitlements','0007_change_expiration_period_default','2019-02-06 08:04:42.159096'),(281,'entitlements','0008_auto_20180328_1107','2019-02-06 08:04:42.683695'),(282,'entitlements','0009_courseentitlement_refund_locked','2019-02-06 08:04:43.025841'),(283,'entitlements','0010_backfill_refund_lock','2019-02-06 08:04:43.067438'),(284,'experiments','0001_initial','2019-02-06 08:04:44.694218'),(285,'experiments','0002_auto_20170627_1402','2019-02-06 08:04:44.793494'),(286,'experiments','0003_auto_20170713_1148','2019-02-06 08:04:44.853420'),(287,'external_auth','0001_initial','2019-02-06 08:04:45.445694'),(288,'grades','0001_initial','2019-02-06 08:04:45.632121'),(289,'grades','0002_rename_last_edited_field','2019-02-06 08:04:45.699684'),(290,'grades','0003_coursepersistentgradesflag_persistentgradesenabledflag','2019-02-06 08:04:46.457202'),(291,'grades','0004_visibleblocks_course_id','2019-02-06 08:04:46.531908'),(292,'grades','0005_multiple_course_flags','2019-02-06 08:04:46.849592'),(293,'grades','0006_persistent_course_grades','2019-02-06 08:04:46.952796'),(294,'grades','0007_add_passed_timestamp_column','2019-02-06 08:04:47.066573'),(295,'grades','0008_persistentsubsectiongrade_first_attempted','2019-02-06 08:04:47.138816'),(296,'grades','0009_auto_20170111_1507','2019-02-06 08:04:47.259581'),(297,'grades','0010_auto_20170112_1156','2019-02-06 08:04:47.344906'),(298,'grades','0011_null_edited_time','2019-02-06 08:04:47.527358'),(299,'grades','0012_computegradessetting','2019-02-06 08:04:48.367572'),(300,'grades','0013_persistentsubsectiongradeoverride','2019-02-06 08:04:48.436380'),(301,'grades','0014_persistentsubsectiongradeoverridehistory','2019-02-06 08:04:48.767621'),(302,'instructor_task','0002_gradereportsetting','2019-02-06 08:04:49.116174'),(303,'waffle','0001_initial','2019-02-06 08:04:49.522307'),(304,'sap_success_factors','0001_initial','2019-02-06 08:04:50.784688'),(305,'sap_success_factors','0002_auto_20170224_1545','2019-02-06 08:04:52.503372'),(306,'sap_success_factors','0003_auto_20170317_1402','2019-02-06 08:04:53.057896'),(307,'sap_success_factors','0004_catalogtransmissionaudit_audit_summary','2019-02-06 08:04:53.112654'),(308,'sap_success_factors','0005_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 08:04:53.414309'),(309,'sap_success_factors','0006_sapsuccessfactors_use_enterprise_enrollment_page_waffle_flag','2019-02-06 08:04:53.467401'),(310,'sap_success_factors','0007_remove_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 08:04:53.753419'),(311,'sap_success_factors','0008_historicalsapsuccessfactorsenterprisecustomerconfiguration_history_change_reason','2019-02-06 08:04:54.072310'),(312,'sap_success_factors','0009_sapsuccessfactors_remove_enterprise_enrollment_page_waffle_flag','2019-02-06 08:04:54.115078'),(313,'sap_success_factors','0010_move_audit_tables_to_base_integrated_channel','2019-02-06 08:04:54.280162'),(314,'integrated_channel','0001_initial','2019-02-06 08:04:54.374204'),(315,'integrated_channel','0002_delete_enterpriseintegratedchannel','2019-02-06 08:04:54.413351'),(316,'integrated_channel','0003_catalogtransmissionaudit_learnerdatatransmissionaudit','2019-02-06 08:04:54.514947'),(317,'integrated_channel','0004_catalogtransmissionaudit_channel','2019-02-06 08:04:54.566483'),(318,'integrated_channel','0005_auto_20180306_1251','2019-02-06 08:04:55.508336'),(319,'integrated_channel','0006_delete_catalogtransmissionaudit','2019-02-06 08:04:55.564564'),(320,'lms_xblock','0001_initial','2019-02-06 08:04:55.920260'),(321,'microsite_configuration','0001_initial','2019-02-06 08:04:59.149839'),(322,'microsite_configuration','0002_auto_20160202_0228','2019-02-06 08:04:59.263415'),(323,'microsite_configuration','0003_delete_historical_records','2019-02-06 08:05:00.613558'),(324,'milestones','0001_initial','2019-02-06 08:05:01.624456'),(325,'milestones','0002_data__seed_relationship_types','2019-02-06 08:05:01.663935'),(326,'milestones','0003_coursecontentmilestone_requirements','2019-02-06 08:05:01.731497'),(327,'milestones','0004_auto_20151221_1445','2019-02-06 08:05:01.953395'),(328,'mobile_api','0001_initial','2019-02-06 08:05:02.276280'),(329,'mobile_api','0002_auto_20160406_0904','2019-02-06 08:05:02.375950'),(330,'mobile_api','0003_ignore_mobile_available_flag','2019-02-06 08:05:02.955623'),(331,'notes','0001_initial','2019-02-06 08:05:03.284134'),(332,'oauth2','0002_auto_20160404_0813','2019-02-06 08:05:04.320559'),(333,'oauth2','0003_client_logout_uri','2019-02-06 08:05:05.028463'),(334,'oauth2','0004_add_index_on_grant_expires','2019-02-06 08:05:05.320810'),(335,'oauth2','0005_grant_nonce','2019-02-06 08:05:05.628866'),(336,'organizations','0001_initial','2019-02-06 08:05:05.786592'),(337,'organizations','0002_auto_20170117_1434','2019-02-06 08:05:05.850615'),(338,'organizations','0003_auto_20170221_1138','2019-02-06 08:05:05.970702'),(339,'organizations','0004_auto_20170413_2315','2019-02-06 08:05:06.085590'),(340,'organizations','0005_auto_20171116_0640','2019-02-06 08:05:06.148448'),(341,'organizations','0006_auto_20171207_0259','2019-02-06 08:05:06.215454'),(342,'oauth2_provider','0001_initial','2019-02-06 08:05:07.961621'),(343,'oauth_dispatch','0001_initial','2019-02-06 08:05:08.350586'),(344,'oauth_dispatch','0002_scopedapplication_scopedapplicationorganization','2019-02-06 08:05:09.132604'),(345,'oauth_dispatch','0003_application_data','2019-02-06 08:05:09.196710'),(346,'oauth_dispatch','0004_auto_20180626_1349','2019-02-06 08:05:11.499019'),(347,'oauth_dispatch','0005_applicationaccess_type','2019-02-06 08:05:11.606808'),(348,'oauth_dispatch','0006_drop_application_id_constraints','2019-02-06 08:05:11.875498'),(349,'oauth2_provider','0002_08_updates','2019-02-06 08:05:12.127180'),(350,'oauth2_provider','0003_auto_20160316_1503','2019-02-06 08:05:12.219934'),(351,'oauth2_provider','0004_auto_20160525_1623','2019-02-06 08:05:12.448186'),(352,'oauth2_provider','0005_auto_20170514_1141','2019-02-06 08:05:13.676168'),(353,'oauth2_provider','0006_auto_20171214_2232','2019-02-06 08:05:14.539094'),(354,'oauth_dispatch','0007_restore_application_id_constraints','2019-02-06 08:05:14.834346'),(355,'oauth_provider','0001_initial','2019-02-06 08:05:15.171734'),(356,'problem_builder','0001_initial','2019-02-06 08:05:15.299615'),(357,'problem_builder','0002_auto_20160121_1525','2019-02-06 08:05:15.503283'),(358,'problem_builder','0003_auto_20161124_0755','2019-02-06 08:05:15.621050'),(359,'problem_builder','0004_copy_course_ids','2019-02-06 08:05:15.672698'),(360,'problem_builder','0005_auto_20170112_1021','2019-02-06 08:05:15.822489'),(361,'problem_builder','0006_remove_deprecated_course_id','2019-02-06 08:05:15.937076'),(362,'programs','0001_initial','2019-02-06 08:05:16.056792'),(363,'programs','0002_programsapiconfig_cache_ttl','2019-02-06 08:05:16.160203'),(364,'programs','0003_auto_20151120_1613','2019-02-06 08:05:16.532675'),(365,'programs','0004_programsapiconfig_enable_certification','2019-02-06 08:05:17.329411'),(366,'programs','0005_programsapiconfig_max_retries','2019-02-06 08:05:17.560011'),(367,'programs','0006_programsapiconfig_xseries_ad_enabled','2019-02-06 08:05:17.710363'),(368,'programs','0007_programsapiconfig_program_listing_enabled','2019-02-06 08:05:17.830224'),(369,'programs','0008_programsapiconfig_program_details_enabled','2019-02-06 08:05:17.950796'),(370,'programs','0009_programsapiconfig_marketing_path','2019-02-06 08:05:18.079013'),(371,'programs','0010_auto_20170204_2332','2019-02-06 08:05:18.382249'),(372,'programs','0011_auto_20170301_1844','2019-02-06 08:05:19.698119'),(373,'programs','0012_auto_20170419_0018','2019-02-06 08:05:19.800404'),(374,'redirects','0001_initial','2019-02-06 08:05:20.155019'),(375,'rss_proxy','0001_initial','2019-02-06 08:05:20.204027'),(376,'sap_success_factors','0011_auto_20180104_0103','2019-02-06 08:05:24.276543'),(377,'sap_success_factors','0012_auto_20180109_0712','2019-02-06 08:05:24.679152'),(378,'sap_success_factors','0013_auto_20180306_1251','2019-02-06 08:05:25.083064'),(379,'sap_success_factors','0014_drop_historical_table','2019-02-06 08:05:25.129347'),(380,'sap_success_factors','0015_auto_20180510_1259','2019-02-06 08:05:25.860155'),(381,'sap_success_factors','0016_sapsuccessfactorsenterprisecustomerconfiguration_additional_locales','2019-02-06 08:05:25.960191'),(382,'sap_success_factors','0017_sapsuccessfactorsglobalconfiguration_search_student_api_path','2019-02-06 08:05:26.285693'),(383,'schedules','0001_initial','2019-02-06 08:05:26.690791'),(384,'schedules','0002_auto_20170816_1532','2019-02-06 08:05:27.302276'),(385,'schedules','0003_scheduleconfig','2019-02-06 08:05:27.646134'),(386,'schedules','0004_auto_20170922_1428','2019-02-06 08:05:28.252876'),(387,'schedules','0005_auto_20171010_1722','2019-02-06 08:05:28.881956'),(388,'schedules','0006_scheduleexperience','2019-02-06 08:05:29.251797'),(389,'schedules','0007_scheduleconfig_hold_back_ratio','2019-02-06 08:05:29.617048'),(390,'self_paced','0001_initial','2019-02-06 08:05:30.027241'),(391,'sessions','0001_initial','2019-02-06 08:05:30.078048'),(392,'shoppingcart','0001_initial','2019-02-06 08:05:38.998266'),(393,'shoppingcart','0002_auto_20151208_1034','2019-02-06 08:05:39.154428'),(394,'shoppingcart','0003_auto_20151217_0958','2019-02-06 08:05:39.312762'),(395,'shoppingcart','0004_change_meta_options','2019-02-06 08:05:39.468307'),(396,'site_configuration','0001_initial','2019-02-06 08:05:40.221457'),(397,'site_configuration','0002_auto_20160720_0231','2019-02-06 08:05:40.436234'),(398,'default','0001_initial','2019-02-06 08:05:41.857778'),(399,'social_auth','0001_initial','2019-02-06 08:05:41.863663'),(400,'default','0002_add_related_name','2019-02-06 08:05:42.234168'),(401,'social_auth','0002_add_related_name','2019-02-06 08:05:42.241171'),(402,'default','0003_alter_email_max_length','2019-02-06 08:05:42.308536'),(403,'social_auth','0003_alter_email_max_length','2019-02-06 08:05:42.316793'),(404,'default','0004_auto_20160423_0400','2019-02-06 08:05:42.679083'),(405,'social_auth','0004_auto_20160423_0400','2019-02-06 08:05:42.685800'),(406,'social_auth','0005_auto_20160727_2333','2019-02-06 08:05:42.757758'),(407,'social_django','0006_partial','2019-02-06 08:05:42.816147'),(408,'social_django','0007_code_timestamp','2019-02-06 08:05:42.883285'),(409,'social_django','0008_partial_timestamp','2019-02-06 08:05:42.957758'),(410,'splash','0001_initial','2019-02-06 08:05:43.433414'),(411,'static_replace','0001_initial','2019-02-06 08:05:44.140144'),(412,'static_replace','0002_assetexcludedextensionsconfig','2019-02-06 08:05:46.566804'),(413,'status','0001_initial','2019-02-06 08:05:47.436513'),(414,'status','0002_update_help_text','2019-02-06 08:05:47.800113'),(415,'student','0014_courseenrollmentallowed_user','2019-02-06 08:05:48.264692'),(416,'student','0015_manualenrollmentaudit_add_role','2019-02-06 08:05:48.712619'),(417,'student','0016_coursenrollment_course_on_delete_do_nothing','2019-02-06 08:05:49.240041'),(418,'student','0017_accountrecovery','2019-02-06 08:05:49.748236'),(419,'student','0018_remove_password_history','2019-02-06 08:05:50.694342'),(420,'student','0019_auto_20181221_0540','2019-02-06 08:05:51.482317'),(421,'submissions','0001_initial','2019-02-06 08:05:51.980676'),(422,'submissions','0002_auto_20151119_0913','2019-02-06 08:05:52.129788'),(423,'submissions','0003_submission_status','2019-02-06 08:05:52.207556'),(424,'submissions','0004_remove_django_extensions','2019-02-06 08:05:52.285295'),(425,'survey','0001_initial','2019-02-06 08:05:53.028225'),(426,'teams','0001_initial','2019-02-06 08:05:56.392431'),(427,'theming','0001_initial','2019-02-06 08:05:57.128347'),(428,'third_party_auth','0001_initial','2019-02-06 08:06:00.383669'),(429,'third_party_auth','0002_schema__provider_icon_image','2019-02-06 08:06:04.313456'),(430,'third_party_auth','0003_samlproviderconfig_debug_mode','2019-02-06 08:06:04.721469'),(431,'third_party_auth','0004_add_visible_field','2019-02-06 08:06:08.188893'),(432,'third_party_auth','0005_add_site_field','2019-02-06 08:06:11.231121'),(433,'third_party_auth','0006_samlproviderconfig_automatic_refresh_enabled','2019-02-06 08:06:11.638402'),(434,'third_party_auth','0007_auto_20170406_0912','2019-02-06 08:06:12.463541'),(435,'third_party_auth','0008_auto_20170413_1455','2019-02-06 08:06:13.699789'),(436,'third_party_auth','0009_auto_20170415_1144','2019-02-06 08:06:15.877426'),(437,'third_party_auth','0010_add_skip_hinted_login_dialog_field','2019-02-06 08:06:17.252327'),(438,'third_party_auth','0011_auto_20170616_0112','2019-02-06 08:06:17.697662'),(439,'third_party_auth','0012_auto_20170626_1135','2019-02-06 08:06:19.014914'),(440,'third_party_auth','0013_sync_learner_profile_data','2019-02-06 08:06:21.184194'),(441,'third_party_auth','0014_auto_20171222_1233','2019-02-06 08:06:22.500576'),(442,'third_party_auth','0015_samlproviderconfig_archived','2019-02-06 08:06:22.910782'),(443,'third_party_auth','0016_auto_20180130_0938','2019-02-06 08:06:23.768574'),(444,'third_party_auth','0017_remove_icon_class_image_secondary_fields','2019-02-06 08:06:25.677996'),(445,'third_party_auth','0018_auto_20180327_1631','2019-02-06 08:06:26.945645'),(446,'third_party_auth','0019_consolidate_slug','2019-02-06 08:06:28.225165'),(447,'third_party_auth','0020_cleanup_slug_fields','2019-02-06 08:06:29.071340'),(448,'third_party_auth','0021_sso_id_verification','2019-02-06 08:06:30.920266'),(449,'third_party_auth','0022_auto_20181012_0307','2019-02-06 08:06:33.001900'),(450,'thumbnail','0001_initial','2019-02-06 08:06:33.058625'),(451,'track','0001_initial','2019-02-06 08:06:33.135878'),(452,'user_api','0001_initial','2019-02-06 08:06:36.568433'),(453,'user_api','0002_retirementstate_userretirementstatus','2019-02-06 08:06:37.067536'),(454,'user_api','0003_userretirementrequest','2019-02-06 08:06:37.538805'),(455,'user_api','0004_userretirementpartnerreportingstatus','2019-02-06 08:06:38.846620'),(456,'user_authn','0001_data__add_login_service','2019-02-06 08:06:38.924862'),(457,'util','0001_initial','2019-02-06 08:06:39.401783'),(458,'util','0002_data__default_rate_limit_config','2019-02-06 08:06:39.459887'),(459,'verified_track_content','0002_verifiedtrackcohortedcourse_verified_cohort_name','2019-02-06 08:06:39.538104'),(460,'verified_track_content','0003_migrateverifiedtrackcohortssetting','2019-02-06 08:06:40.048232'),(461,'verify_student','0001_initial','2019-02-06 08:06:45.357816'),(462,'verify_student','0002_auto_20151124_1024','2019-02-06 08:06:45.516943'),(463,'verify_student','0003_auto_20151113_1443','2019-02-06 08:06:45.673513'),(464,'verify_student','0004_delete_historical_records','2019-02-06 08:06:45.835049'),(465,'verify_student','0005_remove_deprecated_models','2019-02-06 08:06:49.679210'),(466,'verify_student','0006_ssoverification','2019-02-06 08:06:49.790644'),(467,'verify_student','0007_idverificationaggregate','2019-02-06 08:06:49.891841'),(468,'verify_student','0008_populate_idverificationaggregate','2019-02-06 08:06:49.947020'),(469,'verify_student','0009_remove_id_verification_aggregate','2019-02-06 08:06:50.183257'),(470,'verify_student','0010_manualverification','2019-02-06 08:06:50.284386'),(471,'verify_student','0011_add_fields_to_sspv','2019-02-06 08:06:50.459982'),(472,'video_config','0001_initial','2019-02-06 08:06:50.654393'),(473,'video_config','0002_coursevideotranscriptenabledflag_videotranscriptenabledflag','2019-02-06 08:06:50.846809'),(474,'video_config','0003_transcriptmigrationsetting','2019-02-06 08:06:50.952242'),(475,'video_config','0004_transcriptmigrationsetting_command_run','2019-02-06 08:06:51.053615'),(476,'video_config','0005_auto_20180719_0752','2019-02-06 08:06:51.770192'),(477,'video_config','0006_videothumbnailetting_updatedcoursevideos','2019-02-06 08:06:51.998431'),(478,'video_config','0007_videothumbnailsetting_offset','2019-02-06 08:06:52.104225'),(479,'video_pipeline','0001_initial','2019-02-06 08:06:52.217246'),(480,'video_pipeline','0002_auto_20171114_0704','2019-02-06 08:06:52.423437'),(481,'video_pipeline','0003_coursevideouploadsenabledbydefault_videouploadsenabledbydefault','2019-02-06 08:06:52.652384'),(482,'waffle','0002_auto_20161201_0958','2019-02-06 08:06:52.731546'),(483,'waffle_utils','0001_initial','2019-02-06 08:06:52.859204'),(484,'wiki','0001_initial','2019-02-06 08:07:04.002394'),(485,'wiki','0002_remove_article_subscription','2019-02-06 08:07:04.852782'),(486,'wiki','0003_ip_address_conv','2019-02-06 08:07:06.546138'),(487,'wiki','0004_increase_slug_size','2019-02-06 08:07:06.749915'),(488,'wiki','0005_remove_attachments_and_images','2019-02-06 08:07:10.711449'),(489,'workflow','0001_initial','2019-02-06 08:07:10.929774'),(490,'workflow','0002_remove_django_extensions','2019-02-06 08:07:11.016177'),(491,'xapi','0001_initial','2019-02-06 08:07:11.530173'),(492,'xapi','0002_auto_20180726_0142','2019-02-06 08:07:11.853838'),(493,'xblock_django','0001_initial','2019-02-06 08:07:12.421573'),(494,'xblock_django','0002_auto_20160204_0809','2019-02-06 08:07:12.884088'),(495,'xblock_django','0003_add_new_config_models','2019-02-06 08:07:15.322827'),(496,'xblock_django','0004_delete_xblock_disable_config','2019-02-06 08:07:15.939861'),(497,'social_django','0002_add_related_name','2019-02-06 08:07:15.955501'),(498,'social_django','0003_alter_email_max_length','2019-02-06 08:07:15.960905'),(499,'social_django','0004_auto_20160423_0400','2019-02-06 08:07:15.967703'),(500,'social_django','0001_initial','2019-02-06 08:07:15.972077'),(501,'social_django','0005_auto_20160727_2333','2019-02-06 08:07:15.978019'),(502,'contentstore','0001_initial','2019-02-06 08:07:47.027361'),(503,'contentstore','0002_add_assets_page_flag','2019-02-06 08:07:48.064450'),(504,'contentstore','0003_remove_assets_page_flag','2019-02-06 08:07:48.989553'),(505,'course_creators','0001_initial','2019-02-06 08:07:49.658930'),(506,'tagging','0001_initial','2019-02-06 08:07:49.791763'),(507,'tagging','0002_auto_20170116_1541','2019-02-06 08:07:49.890533'),(508,'user_tasks','0001_initial','2019-02-06 08:07:50.803460'),(509,'user_tasks','0002_artifact_file_storage','2019-02-06 08:07:50.865286'),(510,'xblock_config','0001_initial','2019-02-06 08:07:51.079346'),(511,'xblock_config','0002_courseeditltifieldsenabledflag','2019-02-06 08:07:51.540299'),(512,'lti_provider','0001_initial','2019-02-20 13:02:12.609875'),(513,'lti_provider','0002_auto_20160325_0407','2019-02-20 13:02:12.673092'),(514,'lti_provider','0003_auto_20161118_1040','2019-02-20 13:02:12.735420'),(515,'content_type_gating','0005_auto_20190306_1547','2019-03-06 16:01:10.563542'),(516,'course_duration_limits','0005_auto_20190306_1546','2019-03-06 16:01:11.211966'),(517,'enterprise','0061_systemwideenterpriserole_systemwideenterpriseuserroleassignment','2019-03-08 15:47:46.856657'),(518,'enterprise','0062_add_system_wide_enterprise_roles','2019-03-08 15:47:46.906778'),(519,'content_type_gating','0006_auto_20190308_1447','2019-03-11 16:27:52.135257'),(520,'course_duration_limits','0006_auto_20190308_1447','2019-03-11 16:27:52.779284'),(521,'content_type_gating','0007_auto_20190311_1919','2019-03-12 16:11:54.043782'),(522,'course_duration_limits','0007_auto_20190311_1919','2019-03-12 16:11:56.790492'),(523,'announcements','0001_initial','2019-03-18 20:55:30.988286'),(524,'content_type_gating','0008_auto_20190313_1634','2019-03-18 20:55:31.415131'),(525,'course_duration_limits','0008_auto_20190313_1634','2019-03-18 20:55:32.064734'),(526,'enterprise','0063_systemwideenterpriserole_description','2019-03-21 18:42:16.699719'),(527,'enterprise','0064_enterprisefeaturerole_enterprisefeatureuserroleassignment','2019-03-28 19:30:12.392842'),(528,'enterprise','0065_add_enterprise_feature_roles','2019-03-28 19:30:12.443188'),(529,'enterprise','0066_add_system_wide_enterprise_operator_role','2019-03-28 19:30:12.488801'),(530,'student','0020_auto_20190227_2019','2019-04-01 21:47:42.163913'),(531,'certificates','0015_add_masters_choice','2019-04-05 14:57:27.206603'),(532,'enterprise','0067_add_role_based_access_control_switch','2019-04-08 20:45:27.538157'),(533,'program_enrollments','0001_initial','2019-04-10 20:26:00.692153'),(534,'program_enrollments','0002_historicalprogramcourseenrollment_programcourseenrollment','2019-04-18 16:08:03.137722'),(535,'third_party_auth','0023_auto_20190418_2033','2019-04-24 13:54:18.834044'),(536,'program_enrollments','0003_auto_20190424_1622','2019-04-24 16:35:05.844296'),(537,'courseware','0008_move_idde_to_edx_when','2019-04-25 14:14:41.176920'),(538,'edx_when','0001_initial','2019-04-25 14:14:42.645389'),(539,'edx_when','0002_auto_20190318_1736','2019-04-25 14:14:44.336320'),(540,'edx_when','0003_auto_20190402_1501','2019-04-25 14:14:46.294533'),(541,'edx_proctoring','0010_update_backend','2019-05-02 21:47:41.213808'),(542,'program_enrollments','0004_add_programcourseenrollment_relatedname','2019-05-02 21:47:41.764379'),(543,'student','0021_historicalcourseenrollment','2019-05-03 20:30:26.687544'),(544,'cornerstone','0001_initial','2019-05-29 09:33:13.719793'),(545,'cornerstone','0002_cornerstoneglobalconfiguration_subject_mapping','2019-05-29 09:33:14.111664'),(546,'third_party_auth','0024_fix_edit_disallowed','2019-05-29 14:34:39.226961'),(547,'discounts','0001_initial','2019-06-03 19:16:30.854700'),(548,'program_enrollments','0005_canceled_not_withdrawn','2019-06-03 19:16:31.705259'),(549,'entitlements','0011_historicalcourseentitlement','2019-06-04 17:56:44.090401'),(550,'organizations','0007_historicalorganization','2019-06-04 17:56:44.882744'),(551,'user_tasks','0003_url_max_length','2019-06-04 17:56:52.649984'),(552,'user_tasks','0004_url_textfield','2019-06-04 17:56:52.708857'),(553,'enterprise','0068_remove_role_based_access_control_switch','2019-06-05 10:59:54.361142'),(554,'grades','0015_historicalpersistentsubsectiongradeoverride','2019-06-10 16:42:35.419978'),(555,'bulk_grades','0001_initial','2019-06-12 14:00:26.847460'),(556,'super_csv','0001_initial','2019-06-12 14:00:26.879762'),(557,'super_csv','0002_csvoperation_user','2019-06-12 14:00:27.257652'),(558,'enterprise','0069_auto_20190613_0607','2019-06-13 20:29:54.231876'),(559,'course_modes','0012_historicalcoursemode','2019-06-20 14:17:00.883900'),(560,'student','0022_indexing_in_courseenrollment','2019-06-28 07:52:49.937484'),(561,'courseware','0009_auto_20190703_1955','2019-07-03 19:59:48.322976'),(562,'bulk_grades','0002_auto_20190703_1526','2019-07-09 16:24:12.489841'),(563,'course_overviews','0015_historicalcourseoverview','2019-07-09 16:24:12.865655'),(564,'courseware','0010_auto_20190709_1559','2019-07-09 16:24:13.249043'),(565,'grades','0016_auto_20190703_1446','2019-07-09 16:24:14.162438'),(566,'cornerstone','0003_auto_20190621_1000','2019-08-16 20:33:30.643210'),(567,'enterprise','0070_enterprise_catalog_query','2019-08-16 20:33:31.677056'),(568,'enterprise','0071_historicalpendingenrollment_historicalpendingenterprisecustomeruser','2019-08-16 20:33:32.745997'),(569,'instructor_task','0003_alter_task_input_field','2019-08-16 20:33:33.017938'),(570,'microsite_configuration','004_delete_all_tables','2019-08-16 20:33:34.256853'),(571,'sap_success_factors','0018_sapsuccessfactorsenterprisecustomerconfiguration_show_course_price','2019-08-16 20:33:34.327113'),(572,'super_csv','0003_csvoperation_original_filename','2019-08-16 20:33:34.600410'),(573,'system_wide_roles','0001_SystemWideRole_SystemWideRoleAssignment','2019-08-16 20:33:34.993423'),(574,'system_wide_roles','0002_add_system_wide_student_support_role','2019-08-16 20:33:35.022596'),(575,'contentstore','0004_remove_push_notification_configmodel_table','2019-08-16 20:33:41.465727'),(576,'xapi','0003_auto_20190807_1006','2019-08-23 11:39:48.729878'),(577,'program_enrollments','0006_add_the_correct_constraints','2019-08-23 18:09:09.268961'),(578,'video_config','0008_courseyoutubeblockedflag','2019-08-25 18:17:15.983779'),(579,'program_enrollments','0007_waiting_programcourseenrollment_constraint','2019-08-27 19:09:27.680607'),(580,'content_libraries','0001_initial','2019-08-30 19:28:25.635235'),(581,'courseware','0011_csm_id_bigint','2019-08-30 19:28:26.395259'),(582,'enterprise','0072_add_enterprise_report_config_feature_role','2019-08-30 19:28:26.428135'),(583,'enterprise','0073_enterprisecustomerreportingconfiguration_uuid','2019-08-30 19:28:26.610136'),(584,'enterprise','0074_auto_20190904_1143','2019-09-06 21:17:13.932220'),(585,'xapi','0004_auto_20190830_0710','2019-09-06 21:17:14.456308'),(586,'enterprise','0075_auto_20190916_1030','2019-09-16 21:24:40.846129'),(587,'course_overviews','0016_simulatecoursepublishconfig','2019-09-17 14:33:18.318209'),(588,'courseware','0012_adjust_fields','2019-09-19 19:47:32.265973'),(589,'enterprise','0076_auto_20190918_2037','2019-09-19 19:47:33.356916'),(590,'cornerstone','0004_cornerstoneglobalconfiguration_languages','2019-09-25 09:52:14.183189'),(591,'cornerstone','0005_auto_20190925_0730','2019-09-25 09:52:14.554260'),(592,'degreed','0007_auto_20190925_0730','2019-09-25 09:52:14.965290'),(593,'integrated_channel','0007_auto_20190925_0730','2019-09-25 09:52:15.001578'),(594,'sap_success_factors','0019_auto_20190925_0730','2019-09-25 09:52:15.372786'),(595,'course_overviews','0017_auto_20191002_0823','2019-10-03 17:35:47.108732'),(596,'courseware','0013_auto_20191001_1858','2019-10-03 17:35:47.675913'),(597,'edx_when','0004_datepolicy_rel_date','2019-10-03 17:35:47.714137'),(598,'edx_when','0005_auto_20190911_1056','2019-10-03 17:35:48.352268'),(599,'student','0023_bulkunenrollconfiguration','2019-10-08 08:54:55.531674'),(600,'program_enrollments','0008_add_ended_programenrollment_status','2019-10-15 16:54:40.812546'),(601,'enterprise','0077_auto_20191002_1529','2019-10-15 21:48:57.015096'),(602,'completion','0003_learning_context','2019-10-22 18:42:37.071520'),(603,'teams','0002_slug_field_ids','2019-10-22 18:42:37.978486'),(604,'entitlements','0012_allow_blank_order_number_values','2019-10-23 16:23:53.619696'),(605,'discounts','0002_auto_20191022_1720','2019-10-25 14:14:29.317857'),(606,'commerce','0008_auto_20191024_2048','2019-10-30 16:42:49.876338'),(607,'student','0024_fbeenrollmentexclusion','2019-10-31 16:16:38.116056'),(608,'student','0025_auto_20191101_1846','2019-11-05 14:23:29.298316'),(609,'cornerstone','0006_auto_20191001_0742','2019-11-15 09:41:58.615907'),(610,'degreed','0008_auto_20191001_0742','2019-11-15 09:41:59.004037'),(611,'enterprise','0078_auto_20191107_1536','2019-11-15 09:41:59.081745'),(612,'enterprise','0079_AddEnterpriseEnrollmentSource','2019-11-15 09:42:01.297444'),(613,'enterprise','0080_auto_20191113_1708','2019-11-15 09:42:01.373867'),(614,'sap_success_factors','0020_sapsuccessfactorsenterprisecustomerconfiguration_catalogs_to_transmit','2019-11-15 09:42:01.448662'),(615,'student','0026_allowedauthuser','2019-11-15 09:42:01.867741'),(616,'teams','0003_courseteam_organization_protected','2019-11-15 09:42:02.160822'),(617,'schedules','0008_add_new_start_date_field','2019-11-21 18:12:54.950500'),(618,'enterprise','0081_UpdateEnterpriseEnrollmentSource','2019-11-25 17:52:07.779142'),(619,'enterprise','0082_AddManagementEnterpriseEnrollmentSource','2019-12-03 20:57:44.528593'),(620,'edxval','0012_thirdpartytranscriptcredentialsstate_has_creds','2019-12-06 10:56:28.616253'),(621,'edxval','0013_thirdpartytranscriptcredentialsstate_copy_values','2019-12-13 13:13:43.103802'),(622,'edxval','0014_transcript_credentials_state_retype_exists','2019-12-13 13:13:43.146474'),(623,'programs','0013_customprogramsconfig','2019-12-13 13:13:43.769272'),(624,'verify_student','0012_sspverificationretryconfig','2019-12-13 13:13:44.172148'),(625,'assessment','0004_historicalsharedfileupload_sharedfileupload','2019-12-16 06:29:51.457888'),(626,'certificates','0016_historicalgeneratedcertificate','2019-12-17 14:30:19.195816'),(627,'entitlements','0013_historicalcourseentitlementsupportdetail','2019-12-17 14:30:19.608404'),(628,'credit','0005_creditrequirement_sort_value','2019-12-19 10:51:33.510519'),(629,'student','0027_courseenrollment_mode_callable_default','2019-12-26 15:36:18.942310'),(630,'enterprise','0083_enterprisecustomerreportingconfiguration_include_date','2019-12-26 21:47:36.992960'),(631,'schedules','0009_schedule_copy_column_values','2020-01-02 13:28:40.924356'),(632,'credit','0006_creditrequirement_alter_ordering','2020-01-03 18:18:59.132478'),(633,'credit','0007_creditrequirement_copy_values','2020-01-03 18:18:59.153966'),(634,'credit','0008_creditrequirement_remove_order','2020-01-08 11:38:46.464661'),(635,'grades','0017_delete_manual_psgoverride_table','2020-01-08 11:38:46.979886'),(636,'waffle','0003_update_strings_for_i18n','2020-01-08 14:05:56.793699'),(637,'student','0028_historicalmanualenrollmentaudit','2020-01-10 11:40:33.721153'),(638,'assessment','0005_add_filename_to_sharedupload','2020-01-13 10:35:30.849694'),(639,'course_overviews','0018_add_start_end_in_CourseOverview','2020-01-13 17:26:59.381741'),(640,'wiki','0006_auto_20200110_1003','2020-01-13 17:26:59.580772'),(641,'course_modes','0013_auto_20200115_2022','2020-01-15 20:28:11.826240'),(642,'entitlements','0014_auto_20200115_2022','2020-01-15 20:28:12.121824'),(643,'schedules','0010_remove_null_blank_from_schedules_date','2020-01-22 12:55:55.562069'),(644,'edxval','0015_remove_thirdpartytranscriptcredentialsstate_exists','2020-01-24 14:36:05.625239'),(645,'enterprise','0084_auto_20200120_1137','2020-01-24 14:36:05.682781'),(646,'enterprise','0085_enterprisecustomeruser_linked','2020-01-24 14:36:05.737471'),(647,'sap_success_factors','0021_sapsuccessfactorsenterprisecustomerconfiguration_show_total_hours','2020-01-27 10:53:54.883903'),(648,'course_overviews','0019_improve_courseoverviewtab','2020-01-28 16:51:53.392851'),(649,'enterprise','0086_auto_20200128_1726','2020-01-31 16:49:40.116068'),(650,'student','0029_add_data_researcher','2020-01-31 16:49:40.134245'),(651,'entitlements','0015_add_unique_together_constraint','2020-02-11 13:55:54.821099'),(652,'external_user_ids','0001_initial','2020-02-11 13:55:56.286689'),(653,'external_user_ids','0002_mb_coaching_20200210_1754','2020-02-11 13:55:56.302455'),(654,'sap_success_factors','0022_auto_20200206_1046','2020-02-11 13:55:56.431451'),(655,'track','0002_delete_trackinglog','2020-02-11 13:55:56.448287'),(656,'enterprise','0087_auto_20200206_1151','2020-02-18 09:56:05.261459'),(657,'site_configuration','0003_auto_20200217_1058','2020-02-18 09:56:05.382056'),(658,'student','0030_userprofile_phone_number','2020-02-20 14:49:09.679286'),(659,'course_date_signals','0001_initial','2020-02-21 16:46:07.245424'),(660,'oauth_dispatch','0008_applicationaccess_filters','2020-02-21 16:46:07.279347'),(661,'site_configuration','0004_add_site_values_field','2020-02-21 16:46:07.400523'),(662,'calendar_sync','0001_initial','2020-02-21 20:05:00.723064'),(663,'site_configuration','0005_copy_values_to_site_values','2020-02-24 18:48:13.968250'),(664,'external_user_ids','0003_auto_20200224_1836','2020-02-26 19:12:10.225163'),(665,'course_overviews','0020_courseoverviewtab_url_slug','2020-02-28 17:48:26.402935'),(666,'schedules','0011_auto_20200228_2018','2020-03-02 19:21:35.447856'),(667,'schedules','0012_auto_20200302_1914','2020-03-02 19:21:35.760107'),(668,'enterprise','0088_auto_20200224_1341','2020-03-03 20:06:11.193549'),(669,'experiments','0004_historicalexperimentkeyvalue','2020-03-03 20:06:11.472740'),(670,'program_enrollments','0009_update_course_enrollment_field_to_foreign_key','2020-03-03 20:06:11.793880'),(671,'site_configuration','0005_populate_siteconfig_history_site_values','2020-03-03 20:06:11.809759'),(672,'third_party_auth','0025_auto_20200303_1448','2020-03-03 20:06:12.334364'),(673,'oauth_dispatch','0009_delete_enable_scopes_waffle_switch','2020-03-04 16:02:10.087753'),(674,'schedules','0013_historicalschedule','2020-03-04 20:46:18.382627'),(675,'content_libraries','0002_group_permissions','2020-03-06 17:56:06.253916'),(676,'enterprise','0089_auto_20200305_0652','2020-03-06 17:56:06.313096'),(677,'site_configuration','0006_copy_values_to_site_values','2020-03-06 17:56:06.328937'),(678,'site_configuration','0007_remove_values_field','2020-03-06 17:56:06.393334'),(679,'schedules','0014_historicalschedule_drop_fk','2020-03-09 17:25:11.320964'),(680,'enterprise','0090_update_content_filter','2020-03-10 17:57:28.234120'),(681,'schedules','0015_schedules_start_nullable','2020-03-10 17:57:28.512287'),(682,'courseware','0014_fix_nan_value_for_global_speed','2020-03-11 13:49:34.540416'),(683,'enterprise','0091_add_sales_force_id_in_pendingenrollment','2020-03-12 10:55:06.528703'),(684,'enterprise','0092_auto_20200312_1650','2020-03-13 15:24:08.871983'),(685,'schedules','0016_remove_start_from_schedules','2020-03-13 15:24:08.919319'),(686,'schedules','0017_remove_start_from_historicalschedule','2020-03-13 15:24:08.961171'),(687,'schedules','0018_readd_historicalschedule_fks','2020-03-16 14:38:37.163574'),(688,'student','0031_auto_20200317_1122','2020-03-17 13:50:29.328406'),(689,'schedules','0019_auto_20200316_1935','2020-03-17 18:44:58.495941'),(690,'teams','0004_alter_defaults','2020-03-18 15:45:23.207866'),(691,'edxval','0016_add_transcript_credentials_model','2020-03-27 07:02:32.020569'),(692,'assessment','0006_TeamWorkflows','2020-03-30 19:21:59.600633'),(693,'edx_when','0006_drop_active_index','2020-03-30 19:21:59.632637'),(694,'program_enrollments','0010_add_courseaccessroleassignment','2020-03-30 19:22:00.189635'),(695,'workflow','0003_TeamWorkflows','2020-03-30 19:22:00.217685'),(696,'submissions','0005_CreateTeamModel','2020-04-01 20:58:02.569032'),(697,'third_party_auth','0026_auto_20200401_1932','2020-04-02 13:16:24.403863'),(698,'enterprise','0093_add_use_enterprise_catalog_flag','2020-04-08 18:23:05.688441'),(699,'enterprise','0094_add_use_enterprise_catalog_sample','2020-04-10 22:07:38.597967'),(700,'submissions','0001_squashed_0005_CreateTeamModel','2020-04-10 22:07:38.604906'),(701,'organizations','0001_squashed_0007_historicalorganization','2020-04-10 22:07:38.607140'),(702,'admin','0003_logentry_add_action_flag_choices','2020-04-23 18:12:12.574100'),(703,'auth','0009_alter_user_last_name_max_length','2020-04-23 18:12:12.796012'),(704,'auth','0010_alter_group_name_max_length','2020-04-23 18:12:12.828059'),(705,'auth','0011_update_proxy_permissions','2020-04-23 18:12:12.844008'),(706,'edx_when','0007_meta_tweaks','2020-04-23 18:12:12.867316'),(707,'oauth2_provider','0002_auto_20190406_1805','2020-04-23 18:12:12.934409'),(708,'student','0032_removed_logout_view_configuration','2020-04-23 18:12:13.224802'),(709,'third_party_auth','0001_squashed_0026_auto_20200401_1932','2020-04-23 18:12:13.228610'),(710,'student','0001_squashed_0031_auto_20200317_1122','2020-04-23 18:12:13.230794'),(711,'enterprise','0001_squashed_0092_auto_20200312_1650','2020-04-23 18:12:13.231901'),(712,'edxval','0001_squashed_0016_add_transcript_credentials_model','2020-04-23 18:12:13.233806'),(713,'integrated_channel','0001_squashed_0007_auto_20190925_0730','2020-04-24 16:47:58.386734'),(714,'sap_success_factors','0001_squashed_0022_auto_20200206_1046','2020-04-24 16:47:58.389680'),(715,'course_overviews','0021_courseoverviewtab_link','2020-05-04 10:59:50.657693'),(716,'course_overviews','0022_courseoverviewtab_is_hidden','2020-05-04 10:59:50.698025'),(717,'edxval','0002_add_error_description_field','2020-05-04 10:59:50.726121'),(718,'external_user_ids','0004_add_lti_type','2020-05-04 10:59:50.742411'),(719,'enterprise','0095_auto_20200507_1138','2020-05-08 20:20:57.110248'),(720,'enterprise','0096_enterprise_catalog_admin_role','2020-05-13 22:12:35.726151'),(721,'student','0033_userprofile_state','2020-05-13 22:12:35.951058'),(722,'edxval','0003_delete_transcriptcredentials','2020-05-27 11:00:00.899989'),(723,'learning_sequences','0001_initial','2020-06-04 06:06:00.367312'),(724,'video_pipeline','0004_vempipelineintegration','2020-06-04 06:06:00.662081'),(725,'social_django','0009_auto_20191118_0520','2020-06-19 00:01:12.172817'),(726,'social_django','0010_uid_db_index','2020-06-19 00:01:12.397908'),(727,'student','0034_courseenrollmentcelebration','2020-06-19 00:01:12.953638'),(728,'enterprise','0097_auto_20200619_1130','2020-06-19 19:05:31.695995'),(729,'grades','0018_add_waffle_flag_defaults','2020-06-23 18:17:40.133076'),(730,'contentstore','0005_add_enable_checklists_quality_waffle_flag','2020-06-23 18:17:46.707561'); /*!40000 ALTER TABLE `django_migrations` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; diff --git a/common/test/db_cache/bok_choy_schema_default.sql b/common/test/db_cache/bok_choy_schema_default.sql index 6a720d0a3e00b0db835b05b9b13d8807ff3bd618..8ab0a613f2d646ab9a83d30f6db43f8339c8ddf0 100644 --- a/common/test/db_cache/bok_choy_schema_default.sql +++ b/common/test/db_cache/bok_choy_schema_default.sql @@ -401,7 +401,7 @@ DROP TABLE IF EXISTS `auth_group`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `auth_group` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(80) NOT NULL, + `name` varchar(150) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; @@ -431,7 +431,7 @@ CREATE TABLE `auth_permission` ( PRIMARY KEY (`id`), UNIQUE KEY `auth_permission_content_type_id_codename_01ab375a_uniq` (`content_type_id`,`codename`), CONSTRAINT `auth_permission_content_type_id_2f476e4b_fk_django_co` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=2444 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=2868 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `auth_registration`; /*!40101 SET @saved_cs_client = @@character_set_client */; @@ -456,7 +456,7 @@ CREATE TABLE `auth_user` ( `is_superuser` tinyint(1) NOT NULL, `username` varchar(150) NOT NULL, `first_name` varchar(30) NOT NULL, - `last_name` varchar(30) NOT NULL, + `last_name` varchar(150) NOT NULL, `email` varchar(254) NOT NULL, `is_staff` tinyint(1) NOT NULL, `is_active` tinyint(1) NOT NULL, @@ -516,6 +516,7 @@ CREATE TABLE `auth_userprofile` ( `profile_image_uploaded_at` datetime(6) DEFAULT NULL, `user_id` int(11) NOT NULL, `phone_number` varchar(50) DEFAULT NULL, + `state` varchar(2) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `user_id` (`user_id`), KEY `auth_userprofile_name_50909f10` (`name`), @@ -1907,6 +1908,8 @@ CREATE TABLE `course_overviews_courseoverviewtab` ( `name` longtext, `type` varchar(50) DEFAULT NULL, `url_slug` longtext, + `link` longtext, + `is_hidden` tinyint(1) NOT NULL, PRIMARY KEY (`id`), KEY `course_overviews_cou_course_overview_id_71fa6321_fk_course_ov` (`course_overview_id`), CONSTRAINT `course_overviews_cou_course_overview_id_71fa6321_fk_course_ov` FOREIGN KEY (`course_overview_id`) REFERENCES `course_overviews_courseoverview` (`id`) @@ -2618,7 +2621,7 @@ CREATE TABLE `django_content_type` ( `model` varchar(100) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `django_content_type_app_label_model_76bd3d3b_uniq` (`app_label`,`model`) -) ENGINE=InnoDB AUTO_INCREMENT=812 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=818 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `django_migrations`; /*!40101 SET @saved_cs_client = @@character_set_client */; @@ -2629,7 +2632,7 @@ CREATE TABLE `django_migrations` ( `name` varchar(255) NOT NULL, `applied` datetime(6) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=702 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=731 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `django_openid_auth_association`; /*!40101 SET @saved_cs_client = @@character_set_client */; @@ -2918,21 +2921,6 @@ CREATE TABLE `edxval_thirdpartytranscriptcredentialsstate` ( UNIQUE KEY `edxval_thirdpartytranscr_org_provider_188f7ddf_uniq` (`org`,`provider`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -DROP TABLE IF EXISTS `edxval_transcriptcredentials`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `edxval_transcriptcredentials` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `created` datetime(6) NOT NULL, - `modified` datetime(6) NOT NULL, - `org` varchar(50) NOT NULL, - `provider` varchar(50) NOT NULL, - `api_key` longblob NOT NULL, - `api_secret` longblob NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `edxval_transcriptcredentials_org_provider_7c5dbd2d_uniq` (`org`,`provider`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `edxval_transcriptpreference`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -2961,6 +2949,7 @@ CREATE TABLE `edxval_video` ( `client_video_id` varchar(255) NOT NULL, `duration` double NOT NULL, `status` varchar(255) NOT NULL, + `error_description` longtext, PRIMARY KEY (`id`), UNIQUE KEY `edx_video_id` (`edx_video_id`), KEY `edxval_video_client_video_id_2b668312` (`client_video_id`), @@ -3195,6 +3184,7 @@ CREATE TABLE `enterprise_enterprisecustomer` ( `enable_portal_reporting_config_screen` tinyint(1) NOT NULL, `contact_email` varchar(254) DEFAULT NULL, `enable_portal_subscription_management_screen` tinyint(1) NOT NULL, + `enable_slug_login` tinyint(1) NOT NULL, PRIMARY KEY (`uuid`), UNIQUE KEY `enterprise_enterprisecustomer_slug_80411f46_uniq` (`slug`), KEY `enterprise_enterprisecustomer_site_id_947ed084_fk_django_site_id` (`site_id`), @@ -3447,6 +3437,7 @@ CREATE TABLE `enterprise_historicalenterprisecustomer` ( `enable_portal_reporting_config_screen` tinyint(1) NOT NULL, `contact_email` varchar(254) DEFAULT NULL, `enable_portal_subscription_management_screen` tinyint(1) NOT NULL, + `enable_slug_login` tinyint(1) NOT NULL, PRIMARY KEY (`history_id`), KEY `enterprise_historica_history_user_id_bbd9b0d6_fk_auth_user` (`history_user_id`), KEY `enterprise_historicalenterprisecustomer_uuid_75c3528e` (`uuid`), @@ -3578,7 +3569,7 @@ CREATE TABLE `enterprise_systemwideenterpriserole` ( `description` longtext, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) -) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `enterprise_systemwideenterpriseuserroleassignment`; /*!40101 SET @saved_cs_client = @@character_set_client */; @@ -3826,7 +3817,7 @@ CREATE TABLE `external_user_ids_externalidtype` ( `description` longtext NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `external_user_ids_historicalexternalid`; /*!40101 SET @saved_cs_client = @@character_set_client */; @@ -4101,6 +4092,78 @@ CREATE TABLE `integrated_channel_learnerdatatransmissionaudit` ( KEY `integrated_channel_learnerd_enterprise_course_enrollmen_c2e6c2e0` (`enterprise_course_enrollment_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `learning_sequences_coursesection`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `learning_sequences_coursesection` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `ordering` int(10) unsigned NOT NULL, + `usage_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `title` varchar(1000) NOT NULL, + `hide_from_toc` tinyint(1) NOT NULL, + `visible_to_staff_only` tinyint(1) NOT NULL, + `created` datetime(6) NOT NULL, + `modified` datetime(6) NOT NULL, + `learning_context_id` bigint(20) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `learning_sequences_cours_learning_context_id_usag_9348bc89_uniq` (`learning_context_id`,`usage_key`), + KEY `learning_sequences_course_learning_context_id_order_46e992d3_idx` (`learning_context_id`,`ordering`), + CONSTRAINT `learning_sequences_c_learning_context_id_bf86e237_fk_learning_` FOREIGN KEY (`learning_context_id`) REFERENCES `learning_sequences_learningcontext` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `learning_sequences_coursesectionsequence`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `learning_sequences_coursesectionsequence` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `ordering` int(10) unsigned NOT NULL, + `hide_from_toc` tinyint(1) NOT NULL, + `visible_to_staff_only` tinyint(1) NOT NULL, + `created` datetime(6) NOT NULL, + `modified` datetime(6) NOT NULL, + `learning_context_id` bigint(20) NOT NULL, + `section_id` bigint(20) NOT NULL, + `sequence_id` bigint(20) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `learning_sequences_cours_learning_context_id_orde_ad7604bd_uniq` (`learning_context_id`,`ordering`), + KEY `learning_sequences_c_section_id_646c2074_fk_learning_` (`section_id`), + KEY `learning_sequences_c_sequence_id_e6a12a64_fk_learning_` (`sequence_id`), + CONSTRAINT `learning_sequences_c_learning_context_id_25d18335_fk_learning_` FOREIGN KEY (`learning_context_id`) REFERENCES `learning_sequences_learningcontext` (`id`), + CONSTRAINT `learning_sequences_c_section_id_646c2074_fk_learning_` FOREIGN KEY (`section_id`) REFERENCES `learning_sequences_coursesection` (`id`), + CONSTRAINT `learning_sequences_c_sequence_id_e6a12a64_fk_learning_` FOREIGN KEY (`sequence_id`) REFERENCES `learning_sequences_learningsequence` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `learning_sequences_learningcontext`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `learning_sequences_learningcontext` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `context_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `title` varchar(255) NOT NULL, + `published_at` datetime(6) NOT NULL, + `published_version` varchar(255) NOT NULL, + `created` datetime(6) NOT NULL, + `modified` datetime(6) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `context_key` (`context_key`), + KEY `learning_se_publish_62319b_idx` (`published_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `learning_sequences_learningsequence`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `learning_sequences_learningsequence` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `learning_context_id` bigint(20) NOT NULL, + `usage_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, + `title` varchar(1000) NOT NULL, + `created` datetime(6) NOT NULL, + `modified` datetime(6) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `learning_sequences_learn_learning_context_id_usag_6a13230f_uniq` (`learning_context_id`,`usage_key`), + CONSTRAINT `learning_sequences_l_learning_context_id_25f3e4ab_fk_learning_` FOREIGN KEY (`learning_context_id`) REFERENCES `learning_sequences_learningcontext` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `lms_xblock_xblockasidesconfig`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -4518,6 +4581,8 @@ CREATE TABLE `oauth2_provider_grant` ( `user_id` int(11) NOT NULL, `created` datetime(6) NOT NULL, `updated` datetime(6) NOT NULL, + `code_challenge` varchar(128) NOT NULL, + `code_challenge_method` varchar(10) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `oauth2_provider_grant_code_49ab4ddf_uniq` (`code`), KEY `oauth2_provider_grant_application_id_81923564_fk` (`application_id`), @@ -5741,9 +5806,12 @@ CREATE TABLE `social_auth_usersocialauth` ( `uid` varchar(255) NOT NULL, `extra_data` longtext NOT NULL, `user_id` int(11) NOT NULL, + `created` datetime(6) NOT NULL, + `modified` datetime(6) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `social_auth_usersocialauth_provider_uid_e6b5e668_uniq` (`provider`,`uid`), KEY `social_auth_usersocialauth_user_id_17d28448_fk_auth_user_id` (`user_id`), + KEY `social_auth_usersocialauth_uid_796e51dc` (`uid`), CONSTRAINT `social_auth_usersocialauth_user_id_17d28448_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; @@ -5971,6 +6039,20 @@ CREATE TABLE `student_courseenrollmentattribute` ( CONSTRAINT `student_courseenroll_enrollment_id_b2173db0_fk_student_c` FOREIGN KEY (`enrollment_id`) REFERENCES `student_courseenrollment` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `student_courseenrollmentcelebration`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `student_courseenrollmentcelebration` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `created` datetime(6) NOT NULL, + `modified` datetime(6) NOT NULL, + `celebrate_first_section` tinyint(1) NOT NULL, + `enrollment_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `enrollment_id` (`enrollment_id`), + CONSTRAINT `student_courseenroll_enrollment_id_c697e4ce_fk_student_c` FOREIGN KEY (`enrollment_id`) REFERENCES `student_courseenrollment` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `student_dashboardconfiguration`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -6096,19 +6178,6 @@ CREATE TABLE `student_loginfailures` ( CONSTRAINT `student_loginfailures_user_id_50d85202_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -DROP TABLE IF EXISTS `student_logoutviewconfiguration`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `student_logoutviewconfiguration` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `change_date` datetime(6) NOT NULL, - `enabled` tinyint(1) NOT NULL, - `changed_by_id` int(11) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `student_logoutviewco_changed_by_id_a787d3e7_fk_auth_user` (`changed_by_id`), - CONSTRAINT `student_logoutviewco_changed_by_id_a787d3e7_fk_auth_user` FOREIGN KEY (`changed_by_id`) REFERENCES `auth_user` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `student_manualenrollmentaudit`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -7212,6 +7281,22 @@ CREATE TABLE `video_pipeline_coursevideouploadsenabledbydefault` ( CONSTRAINT `video_pipeline_cours_changed_by_id_84ec1a58_fk_auth_user` FOREIGN KEY (`changed_by_id`) REFERENCES `auth_user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `video_pipeline_vempipelineintegration`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `video_pipeline_vempipelineintegration` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `change_date` datetime(6) NOT NULL, + `enabled` tinyint(1) NOT NULL, + `client_name` varchar(100) NOT NULL, + `api_url` varchar(200) NOT NULL, + `service_username` varchar(100) NOT NULL, + `changed_by_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `video_pipeline_vempi_changed_by_id_cadc1895_fk_auth_user` (`changed_by_id`), + CONSTRAINT `video_pipeline_vempi_changed_by_id_cadc1895_fk_auth_user` FOREIGN KEY (`changed_by_id`) REFERENCES `auth_user` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `video_pipeline_videopipelineintegration`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -7262,7 +7347,7 @@ CREATE TABLE `waffle_flag` ( PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`), KEY `waffle_flag_created_4a6e8cef` (`created`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `waffle_flag_groups`; /*!40101 SET @saved_cs_client = @@character_set_client */; diff --git a/common/test/db_cache/bok_choy_schema_student_module_history.sql b/common/test/db_cache/bok_choy_schema_student_module_history.sql index 6f807e790fd744d9bf15788b0050f53ef4a0402b..cc12bbbda91e867afc87e2f28b97a6618eb29d6d 100644 --- a/common/test/db_cache/bok_choy_schema_student_module_history.sql +++ b/common/test/db_cache/bok_choy_schema_student_module_history.sql @@ -36,7 +36,7 @@ CREATE TABLE `django_migrations` ( `name` varchar(255) NOT NULL, `applied` datetime(6) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=702 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=731 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; diff --git a/common/test/test-theme/lms/templates/static_templates/embargo.html b/common/test/test-theme/lms/templates/static_templates/embargo.html index 284824fa20a3e047f7e96f5e018984395a2138a7..b7006b011139f110caad16eb5b119d8553c2f4e5 100644 --- a/common/test/test-theme/lms/templates/static_templates/embargo.html +++ b/common/test/test-theme/lms/templates/static_templates/embargo.html @@ -12,12 +12,12 @@ from openedx.core.djangolib.markup import HTML, Text <section class="outside-app"> <p> ${Text(_("Our system indicates that you are trying to access this {platform_name} " - "course from a country or region currently subject to U.S. economic and trade sanctions." - "Unfortunately, because {platform_name} is required to comply with export controls," + "course from a country or region currently subject to U.S. economic and trade sanctions. " + "Unfortunately, because {platform_name} is required to comply with export controls, " "we cannot allow you to access this course at this time." - )).format( + )).format( platform_name=Text(settings.PLATFORM_NAME), - )} + )} </p> </section> </main> diff --git a/conf/locale/babel_underscore.cfg b/conf/locale/babel_underscore.cfg index 0769f65f28f1f6e34d3de0275b26d89f7337a90c..9f75e777b18e05e695b0a480cb3dc46ec2ff0f09 100644 --- a/conf/locale/babel_underscore.cfg +++ b/conf/locale/babel_underscore.cfg @@ -3,4 +3,4 @@ input_encoding = utf-8 [extractors] -underscore = django_babel_underscore:extract +underscore = enmerkar_underscore:extract diff --git a/conf/locale/ca/LC_MESSAGES/django.mo b/conf/locale/ca/LC_MESSAGES/django.mo index 6f9b294034df65423c4996152d67f1ca3486214b..c372ab9e034d82b8ba1c3dad781363d25a3a35fa 100644 Binary files a/conf/locale/ca/LC_MESSAGES/django.mo and b/conf/locale/ca/LC_MESSAGES/django.mo differ diff --git a/conf/locale/ca/LC_MESSAGES/django.po b/conf/locale/ca/LC_MESSAGES/django.po index 92925c59418dae618f0cd6dd7ed48b36dedee88b..15d841abb3667fdf7bdbeeacde4e52c10ba821a3 100644 --- a/conf/locale/ca/LC_MESSAGES/django.po +++ b/conf/locale/ca/LC_MESSAGES/django.po @@ -64,7 +64,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed <waheed@edx.org>, 2019\n" "Language-Team: Catalan (https://www.transifex.com/open-edx/teams/6205/ca/)\n" @@ -73,7 +73,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -98,8 +98,8 @@ msgstr "Exà men d'entrada" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "Unitat" @@ -400,13 +400,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "Ja existeix un compte amb el nom d'usuari públic '{username}'." +msgid "An account with the Email '{email}' already exists." +msgstr "Ja existeix un compte amb l'email '{email}'." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "Ja existeix un compte amb l'email '{email}'." +msgid "An account with the Public Username '{username}' already exists." +msgstr "Ja existeix un compte amb el nom d'usuari públic '{username}'." #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2021,7 +2021,7 @@ msgstr "" msgid "Never" msgstr "" -#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/capa_base.py lms/templates/courseware/dates.html msgid "Past Due" msgstr "" @@ -2192,9 +2192,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -3834,7 +3834,7 @@ msgstr "" msgid "Enrollment Track Groups" msgstr "Grups de seguiment d'inscripció" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "" @@ -4411,17 +4411,17 @@ msgstr "" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "Tancar" @@ -5302,50 +5302,6 @@ msgid "" "this request, please visit the link(s) below." msgstr "" -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "" @@ -5406,10 +5362,22 @@ msgstr "" msgid "You do not have access to this course on a mobile device" msgstr "" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "Actualitza a verificat" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -6036,9 +6004,8 @@ msgid "Good" msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html @@ -6046,6 +6013,11 @@ msgstr "" msgid "View discussion" msgstr "" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6172,8 +6144,8 @@ msgstr "" msgid "Student" msgstr "Estudiant" -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "Personal" @@ -6289,29 +6261,6 @@ msgstr "" msgid "Could not find problem with this location." msgstr "" -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "" - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "" @@ -6342,9 +6291,8 @@ msgstr "" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "Nom d'usuari" @@ -6449,52 +6397,6 @@ msgstr "" msgid "The file must contain a 'username' column, an 'email' column, or both." msgstr "" -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "Codi de cupó" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "Identificador del Curs" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "Descripció" - -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "Data de caducitat" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -6515,14 +6417,6 @@ msgstr "" msgid "proctored exam results" msgstr "" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -6735,63 +6629,6 @@ msgid "" " try again." msgstr "" -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "Si us plau, introdueix la data en aquest format ex: mes/dia/any" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "" @@ -6898,29 +6735,6 @@ msgstr "" msgid "Incomplete" msgstr "" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "" - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7315,8 +7129,8 @@ msgstr "" #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Programes" @@ -7490,9 +7304,11 @@ msgid "{mode_name} for course {course}" msgstr "" #: lms/djangoapps/shoppingcart/models.py +#, python-brace-format msgid "" -"You can unenroll in the course and receive a full refund for 14 days after " -"the course start date. " +"To receive a refund you may unenroll from the course on your edX Dashboard " +"({dashboard_url}) up to 14 days after your payment or 14 days after your " +"course starts (up to six months after your payment).\n" msgstr "" #: lms/djangoapps/shoppingcart/models.py @@ -7505,15 +7321,14 @@ msgstr "" #: lms/djangoapps/shoppingcart/models.py msgid "" "You can unenroll in the course and receive a full refund for 2 days after " -"the course start date. " +"the course start date.\n" msgstr "" #: lms/djangoapps/shoppingcart/models.py #, python-brace-format msgid "" -"{refund_reminder_msg}To receive your refund, contact {billing_email}. Please" -" include your order number in your email. Please do NOT include your credit " -"card information." +"{refund_reminder_msg}For help unenrolling, Please see How do I unenroll from" +" a course? ({how_to_unenroll_link}) in our edX HelpCenter." msgstr "" #: lms/djangoapps/shoppingcart/models.py @@ -7930,6 +7745,15 @@ msgstr "" msgid "Currency" msgstr "Moneda" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "Descripció" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "" @@ -8072,14 +7896,6 @@ msgstr "" msgid "View and regenerate certificates." msgstr "" -#: lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "Reemborsament manual" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "" - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -8156,42 +7972,8 @@ msgstr "" msgid "User Disabled Successfully" msgstr "" -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "Correu electrònic" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "ID del curs" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" msgstr "" #: lms/djangoapps/teams/models.py @@ -8239,13 +8021,17 @@ msgid "The supplied course_id {course_id} is not valid." msgstr "" #: lms/djangoapps/teams/views.py -msgid "You are already in a team in this course." +msgid "topic_id is required" msgstr "" #: lms/djangoapps/teams/views.py msgid "You can't create a team in an instructor managed topic." msgstr "" +#: lms/djangoapps/teams/views.py +msgid "You are already in a team in this teamset." +msgstr "" + #: lms/djangoapps/teams/views.py msgid "teamset_id and team_id are mutually exclusive options." msgstr "" @@ -8802,8 +8588,8 @@ msgid "Allow" msgstr "" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "Error" @@ -9196,8 +8982,8 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "Adjunts" @@ -9235,11 +9021,10 @@ msgstr "" "a actualitzacions d'aquests articles, cosa que pot ser bo o dolent." #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -9645,6 +9430,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -10016,6 +9805,10 @@ msgstr "" msgid "Schedule start < course start" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "Identificador del Curs" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "Tots" @@ -10024,6 +9817,15 @@ msgstr "Tots" msgid "Experience" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "ID del curs" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -10224,6 +10026,7 @@ msgid "" msgstr "" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "" @@ -10447,7 +10250,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -10474,8 +10276,8 @@ msgid "Success" msgstr "Éxit" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "Accions" @@ -10637,6 +10439,14 @@ msgstr "" "Hi ha hagut un error rebent la teva informació de registre. Si us plau, " "envia'ns un email." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -10653,17 +10463,17 @@ msgstr "Massa errors per entrar. Prova-ho de nou més tard." #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" -"As {allowed_domain} user, You must login with your {allowed_domain} " -"{link_start}{provider} account{link_end}." +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"As {allowed_domain} user, You must login with your {allowed_domain} " +"{link_start}{provider} account{link_end}." msgstr "" #. Translators: These instructions appear on the login form, immediately @@ -10681,6 +10491,12 @@ msgstr "" msgid "Create Account" msgstr "" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -10693,6 +10509,11 @@ msgid "" "password." msgstr "" +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "" @@ -10712,11 +10533,6 @@ msgid "" "created. {bold_start}{email}{bold_end} is now your primary login email." msgstr "" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "" @@ -10935,6 +10751,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "" @@ -10953,6 +10781,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "" @@ -11658,8 +11490,8 @@ msgstr "Curs exportat correctament a repositori git" msgid "Vertical" msgstr "Vertical" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "Secció" @@ -11938,6 +11770,18 @@ msgstr "Transcripció en curs" msgid "Transcript Ready" msgstr "Transcripció preparada" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "Es requereix un fitxer d'imatge." @@ -12089,8 +11933,8 @@ msgstr "Contingut" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "Configuració" @@ -12138,14 +11982,14 @@ msgstr "Número del curs:" msgid "Course Run:" msgstr "Curs d'execució:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "Cursos" @@ -12169,8 +12013,9 @@ msgstr "Instructors" msgid "Requirements" msgstr "Requisits" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "Detalls" @@ -12224,15 +12069,15 @@ msgstr "" msgid "Choose Language" msgstr "Escolliu Idioma" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "Compte" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -12304,8 +12149,8 @@ msgstr "Menudusuari" msgid "Usermenu dropdown" msgstr "Menudusuari deplegable" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "Tanqueu sessió" @@ -12475,8 +12320,8 @@ msgstr "Comença: {date}" msgid "View all Courses" msgstr "Veure tots els cursos" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "Panell" @@ -12495,8 +12340,8 @@ msgstr "Encara no esteu inscrit en cap curs." #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "Exploreu cursos" @@ -12514,7 +12359,7 @@ msgstr "Errors de cà rrega del curs" msgid "Search Your Courses" msgstr "Busqueu els vostres cursos" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "Neteja la cerca" @@ -12539,7 +12384,7 @@ msgstr "Rebeu correus electrònics del curs" msgid "Save Settings" msgstr "Deseu configuració" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -12549,9 +12394,87 @@ msgstr "Deseu configuració" msgid "Unenroll" msgstr "Anul·lar la sessió" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "Mostra una unitat a Studio" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -12585,7 +12508,7 @@ msgstr "Ja existeix un compte amb la nova adreça de correu electrònic." msgid "You should Register before trying to access the Unit" msgstr "Heu de registrar-vos abans de provar d'accedir a la Unitat" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "Inscriure's" @@ -12695,7 +12618,7 @@ msgstr "" " {line_break} Si heu completat aquesta tasca, la vostre nota està disponible" " a la {link_start} pà gina de progrés {link_end}." -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "Cerca un curs" @@ -12843,23 +12766,16 @@ msgstr "(torneu a carregar la pà gina per actualitzar)" msgid "working" msgstr "treballant" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "S'ha produït un error en els servidors {platform_name}" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html -#: lms/templates/courseware/error-message.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"Ho sentim, aquest mòdul no està disponible temporalment. El nostre personal " -"està treballant per solucionar-ho el més aviat possible. Envieu-nos un " -"correu electrònic a {tech_support_email} per informar qualsevol problema o " -"temps d'inactivitat." #: lms/templates/module-error.html msgid "Raw data:" @@ -12898,7 +12814,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "Ara veieu el curs com {i_start} {user_name} {i_end}." #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -12965,16 +12889,6 @@ msgstr "Correu electrònic" msgid "Return To %s" msgstr "Torna a %s" -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "Torneu a subscriure's amb èxit!" @@ -13027,7 +12941,7 @@ msgstr "" msgid "Sequence" msgstr "Seqüència" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -13158,18 +13072,18 @@ msgstr "Puntuació (només per a l'anul·lació)" msgid "Reset Learner's Attempts to Zero" msgstr "Restablir els intents d'aprenentatge de Zero" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "Suprimeix l'estat de l'estudiant" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "Rescore Submission de l'alumne" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "Rescore només si la puntuació es millora" @@ -13207,7 +13121,7 @@ msgstr "{course_number} Llibre de text" msgid "Textbook Navigation" msgstr "Navegació en el llibre de text" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "Pà gina" @@ -13320,9 +13234,9 @@ msgstr "Pà gina {current_page} de {total_pages}" msgid "Recent git load activity for {course_id}" msgstr "Activitat recent de cà rrega de git per {course_id}" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -13381,7 +13295,7 @@ msgstr "" " {dashboard_link_start} tornar al tauler {link_end}. Si no volieu fer això, " "{undo_link_start} podeu tornar a subscriure {link_end}." -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "Panell per a:" @@ -13389,8 +13303,8 @@ msgstr "Panell per a:" msgid "More options" msgstr "Més opcions" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "Més opcions" @@ -14923,37 +14837,6 @@ msgstr "" msgid "About edX Certificates" msgstr "Sobre els certificats edX" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "Comanda cancel·lada" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"S'ha cancel·lat la transacció. Si creieu que s'ha produït un error, " -"contacteu amb {email}." - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "Error a la transacció" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "S'estan carregant dades de comanda ..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "Espereu mentre recuperem els detalls de la vostra comanda." - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -15177,28 +15060,25 @@ msgstr "{section_format} deu {{date}}" msgid "This content is graded" msgstr "Aquest contingut està classificat" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "Hi ha hagut un error. Siusplau, intenta-ho més tard." - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "Hi ha hagut un error. Siusplau, intenta-ho més tard." + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "Està s inscrit en aquest curs" #: lms/templates/courseware/course_about.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: lms/templates/shoppingcart/registration_code_receipt.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "View Course" msgstr "Veure curs" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "El curs està ple" @@ -15211,10 +15091,6 @@ msgstr "La inscripció en aquest curs és només per invitació" msgid "Enrollment is Closed" msgstr "La inscripció està tancada" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "Inscriviu-vos ara" @@ -15340,6 +15216,13 @@ msgstr "Utilitats del curs" msgid "Courseware" msgstr "Cursos informatius" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "Cerca del curs" @@ -15372,7 +15255,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -15380,8 +15263,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" +msgstr "" + +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -15436,8 +15322,9 @@ msgid "Welcome to {course_title}!" msgstr "Benvingut a {course_title}." #: lms/templates/courseware/info.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "Resume Course" msgstr "Resum del curs" @@ -16076,10 +15963,8 @@ msgstr "Heu enviat la vostra informació de verificació." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" -"Veureu un missatge al tauler quan el procés de verificació estigui complet " -"(generalment en 1-2 dies)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -16089,10 +15974,8 @@ msgstr "La vostra verificació actual caducarà aviat!" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" -"Heu enviat la vostra informació de verificació. Veureu un missatge al tauler" -" quan el procés de verificació estigui complet (generalment en 1-2 dies)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -16835,151 +16718,6 @@ msgstr "" "els propers dies per confirmar si la verificació ha estat correcta. També " "podeu consultar l'estat del procés de verificació al tauler." -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "Grà cies per comprar inscripcions a {course_name}." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"S'ha adjuntat una factura per {currency_symbol} {total_price}. El pagament " -"es demana a la recepció. Podeu trobar informació sobre mètodes de pagament a" -" la factura." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -"S'adjunta un fitxer .csv que enumera els vostres codis d'inscripció. Podeu " -"utilitzar la plantilla de correu electrònic següent per distribuir els codis" -" d'inscripció als vostres estudiants. Cada estudiant ha d'utilitzar un codi " -"d'inscripció independent." - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"Grà cies,\n" -"L'equip {platform_name}" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "Benvolgut [[Nom]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"Hem proporcionat un codi de matrÃcula de curs a {course_name}. Per " -"inscriure's al curs, feu clic al següent enllaç:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "Enllaç HTML des del fitxer CSV adjunt" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"Després d'inscriure's, podeu veure el curs al tauler de l'alumne. Podeu " -"veure els materials del curs després de la data d'inici del curs." - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"Atentament,\n" -"[[La teva signatura]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "FACTURA" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "Data: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "Factura No: {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "Termes: deguts a la recepció" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "Data de venciment: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "Factura a:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "Número de referència del client: {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "Saldo degut: {currency_symbol} {sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "Curs: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"Preu: {currency_symbol} {course_price} Quantitat: {quantity} " -"Subtotal: {currency_symbol} {sub_total} Descompte: {currency_symbol} " -"{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "Total: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "Instruccions de pagament" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"Si no rebem el pagament, les matrÃcules que utilitzen aquests codis es " -"cancel·laran i els alumnes no podran accedir als materials del curs. Totes " -"les compres són finals. Per obtenir més informació, consulteu la polÃtica de" -" cancel·lació {site_name}." - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "Per a preguntes de pagament, contacteu amb {contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -17184,8 +16922,8 @@ msgstr "Sol·liciteu Assistència Financera" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} Pà gina d'inici" @@ -17208,19 +16946,11 @@ msgstr "Descobreix Nou" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "Sysadmin" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "Carret de compra" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "Enllaços complementaris" @@ -17257,6 +16987,12 @@ msgstr "Afegiu el codi de cupó" msgid "Enter information about the coupon code below." msgstr "Introduïu informació sobre el codi de cupó a continuació." +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "Codi de cupó" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "Percentatge de descompte" @@ -17882,6 +17618,11 @@ msgstr "Descarregueu els codis de cupó" msgid "Coupon Codes" msgstr "Codis de cupons" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "Data de caducitat" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "Cupó (%)" @@ -19295,6 +19036,10 @@ msgstr "Organització de compres" msgid "Purchase order number (if any)" msgstr "Número de comanda de compra (si n'hi ha)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "Correu electrònic" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "email@example.com" @@ -19612,6 +19357,10 @@ msgstr[0] "" msgstr[1] "" "{course_names} s'han eliminat perquè el perÃode d'inscripció s'ha tancat." +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "Carret de compra" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "Portada de la imatge" @@ -19700,12 +19449,8 @@ msgstr "Confirmació" #: lms/templates/static_templates/404.html msgid "" "The page that you were looking for was not found. Go back to the " -"{link_start}homepage{link_end} or let us know about any pages that may have " -"been moved at {email}." +"{link_start}homepage{link_end} ." msgstr "" -"No s'ha trobat la pà gina que cercà veu. Torneu a la {link_start} pà gina " -"d'inici {link_end} o informeu-nos-ne de les pà gines que s'hagin mogut a " -"{email}." #: lms/templates/static_templates/about.html #: lms/templates/static_templates/blog.html @@ -19761,23 +19506,15 @@ msgstr "Actualment els servidors {platform_name} estan baixats" #: lms/templates/static_templates/server-overloaded.html msgid "" "Our staff is currently working to get the site back up as soon as possible. " -"Please email us at {tech_support_email} to report any problems or downtime." msgstr "" -"Actualment, el nostre equip està treballant perquè la còpia del lloc sigui " -"tan aviat com sigui possible. Envieu-nos un correu electrònic a " -"{tech_support_email} per informar qualsevol problema o temps d'inactivitat." #: lms/templates/static_templates/server-error.html msgid "There has been a 500 error on the {platform_name} servers" msgstr "Hi ha hagut un error 500 en els servidors {platform_name}" #: lms/templates/static_templates/server-error.html -msgid "" -"Please wait a few seconds and then reload the page. If the problem persists," -" please email us at {email}." +msgid "Please wait a few seconds and then reload the page." msgstr "" -"Espereu uns segons i torneu a carregar la pà gina. Si el problema persisteix," -" envieu-nos un correu electrònic a {email}." #: lms/templates/static_templates/server-overloaded.html msgid "Currently the {platform_name} servers are overloaded" @@ -19845,46 +19582,6 @@ msgstr "Atenció als estudiants: administrar l'usuari" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "Sobre el reembossament d'aquest ordre:" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "Indentificador de comanda:" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "Inscripció:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "inscrit" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "sense inscripcions" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "Cost:" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "Estat de l'element del certificat:" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "Estat de la comanda:" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "Temps complert:" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "Temps de sol·licitud de reemborsament:" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "Enquesta d'usuaris" @@ -20040,11 +19737,8 @@ msgstr "Verificació d'identitat" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" -"Ja heu enviat la vostra informació de verificació. Veureu un missatge al " -"tauler quan el procés de verificació estigui complet (generalment en 1-2 " -"dies)." #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -20275,6 +19969,10 @@ msgstr "Última actualització" msgid "Get started on what's next: " msgstr "" +#: openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html +msgid "Show More" +msgstr "" + #: openedx/features/course_search/templates/course_search/course-search-fragment.html msgid "Search Results" msgstr "Resultats de la cerca" @@ -20654,8 +20352,8 @@ msgid "Already registered?" msgstr "Ja registrat?" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "Iniciar Sessió" @@ -20775,12 +20473,8 @@ msgid "The page that you were looking for was not found." msgstr "No s'ha trobat la pà gina que estaves buscant." #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" -"Vagi enrere a la {homepage} o informa'ns de qualsevol pà gina que hagi estat " -"moguda a {email}." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -20806,11 +20500,6 @@ msgstr "" "Hem pres nota de l'error i el nostre personal hi està treballant per " "solucionar-lo el més aviat possible." -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "" -"Si el problema persisteix, si us plau envia'ns un correu a {email_link}." - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "PolÃtica d'accessibilitat d'estudi" @@ -21513,14 +21202,8 @@ msgstr "La pà gina que heu sol·licitat no es pot trobar" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" -"Ho sentim. No hem pogut trobar la pà gina {studio_name} que cerqueu. Podeu " -"tornar al tauler {studio_name} i torneu-ho a provar. Si encara teniu " -"problemes per accedir a les coses, no dubteu a {link_start} contactar " -"{studio_name} suport {link_end} per obtenir més ajuda." #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -21530,15 +21213,8 @@ msgstr "El servidor ha detectat un error" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" -"Ho sentim. Hi va haver un problema amb el servidor mentre intentava " -"processar la vostra última sol · licitud. Podeu tornar al tauler " -"{studio_name} o tornar a provar aquesta sol·licitud. Si encara teniu " -"problemes per accedir a les coses, no dubteu a {link_start} contactar " -"{studio_name} suport {link_end} per obtenir més ajuda." #: cms/templates/error.html msgid "Back to dashboard" @@ -24947,8 +24623,8 @@ msgstr "%(file)s ha estat canviat a la revisió #%(revision)d" msgid "%(file)s has been saved." msgstr "%(file)s ha estat guardat." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "Imatges" @@ -25159,8 +24835,8 @@ msgstr "Esborra la llista de notificacions" msgid "Search..." msgstr "Cerca..." -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "Registra't" diff --git a/conf/locale/de_DE/LC_MESSAGES/django.mo b/conf/locale/de_DE/LC_MESSAGES/django.mo index 2fd7293587f2f5a9c3f82031fbc17f294b8411ff..5b15405d1867260be6b43c37f20dbc02de25be5b 100644 Binary files a/conf/locale/de_DE/LC_MESSAGES/django.mo and b/conf/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/conf/locale/de_DE/LC_MESSAGES/django.po b/conf/locale/de_DE/LC_MESSAGES/django.po index 40226abf7dfa022c88384896aff92f38d6fab2f9..1c74cf881be887432193ad5e35d3a915ffb7a284 100644 --- a/conf/locale/de_DE/LC_MESSAGES/django.po +++ b/conf/locale/de_DE/LC_MESSAGES/django.po @@ -31,7 +31,7 @@ # Ron Lucke <ronlucke@googlemail.com>, 2014 # Ron Lucke <ronlucke@googlemail.com>, 2014 # Sabrina Lischke <sabrina.lischke@freenet.de>, 2016 -# Sebastian W. Ertl <inactive+ertls@transifex.com>, 2014 +# a5385abb81e0b3494a2690bd43e8f1ee_e81de6f <eef66273b8f1f4085117ecd62ea59dbc_229028>, 2014 # Shan <shanmathuran.sritharan@paluno.uni-due.de>, 2013 # Shan <shanmathuran.sritharan@paluno.uni-due.de>, 2013-2014 # Simon D. <hardys972@googlemail.com>, 2014 @@ -78,7 +78,7 @@ # Alexander Gropmann <alexander.gropmann@charite.de>, 2018 # Alexander L. <alexander.lohberg@ufo-style.de>, 2013-2014 # Alexander L. <alexander.lohberg@ufo-style.de>, 2016-2017 -# berit.braun, 2014 +# 9309a68e5ef70fb98095fd18e848e998_2d7fe4e, 2014 # Bert Krohn <bert.krohn@tum.de>, 2018 # derMarc <dasunuebliche@email.de>, 2014 # Donna Kl <donna@polarstern-education.com>, 2019 @@ -98,7 +98,7 @@ # mrolappe <m_rolappe@gmx.net>, 2014 # pongratz <pongratz@tum.de>, 2014 # pongratz <pongratz@tum.de>, 2014 -# v4rp1ng <inactive+v4rp1ng@transifex.com>, 2014 +# a44cc3e9393feb16b9a6b297471280a5_cf4574c <542714ce952f7f0fa8b5f6591bf1451e_216225>, 2014 # Ron Lucke <ronlucke@googlemail.com>, 2014 # Ron Lucke <ronlucke@googlemail.com>, 2014 # Kiel <segner-svea@web.de>, 2014 @@ -120,7 +120,7 @@ # Alexander Gropmann <alexander.gropmann@charite.de>, 2018 # Alexander L. <alexander.lohberg@ufo-style.de>, 2014 # Alexander L. <alexander.lohberg@ufo-style.de>, 2016-2017 -# dabang <inactive+dabang@transifex.com>, 2014 +# 2b2d35a2693e2be4fb9cc6718ad20b07_8542ebf <37324aa543125a600265fedaa47d04f3_158329>, 2014 # Bert Krohn <bert.krohn@tum.de>, 2018 # Donna Kl <donna@polarstern-education.com>, 2019 # Donna Kl <donna@polarstern-education.com>, 2019 @@ -172,7 +172,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Stefania Trabucchi <stefania.trabucchi@abstract-technology.de>, 2019\n" "Language-Team: German (Germany) (https://www.transifex.com/open-edx/teams/6205/de_DE/)\n" @@ -181,7 +181,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -206,8 +206,8 @@ msgstr "Eingangsprüfung" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "Lerneinheit" @@ -540,6 +540,11 @@ msgstr "Die E-Mail hat keinen {domain_name} Domainnamen." msgid "User with this email doesn't exist in system." msgstr "Benutzer mit dieser E-Mail existiert nicht im System." +#: common/djangoapps/student/helpers.py +#, python-brace-format +msgid "An account with the Email '{email}' already exists." +msgstr "Es existiert bereits ein Konto mit dieser E-Mail-Adresse '{email}'." + #: common/djangoapps/student/helpers.py #, python-brace-format msgid "An account with the Public Username '{username}' already exists." @@ -547,11 +552,6 @@ msgstr "" "Es existiert bereits ein Konto mit dem öffentlichem Benutzernamen " "'{username}'." -#: common/djangoapps/student/helpers.py -#, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "Es existiert bereits ein Konto mit dieser E-Mail-Adresse '{email}'." - #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" msgstr "Gruppe entfernt: \"{}\"" @@ -2526,9 +2526,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -4566,12 +4566,12 @@ msgstr "" "Antworteinreichungen für Problemmodule im Bewertungsalgorithmus der " "Aufnahmeprüfung berücksichtigt." -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "Einschreibemodus Gruppen" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "Partition zur Segmentierung von Benutzern durch den Einschreibemodus" @@ -5275,17 +5275,17 @@ msgstr "Benutzerkonto freischalten" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "Schließen" @@ -6303,57 +6303,6 @@ msgstr "" " diese Anfrage zu bearbeiten, besuchen Sie bitte den/die untenstehenden " "Link(s)." -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "Rechnung" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "Zahlung fehlgeschlagen" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "" -"Es gab ein Problem mit Ihrer Transaktion. Ihnen wurde nichts berechnet. " - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" -"Vergewissern Sie sich, dass Ihre Angaben korrekt sind, oder versuchen Sie es" -" erneut mit einer anderen Karte oder einer anderen Zahlungsart." - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" -"Ein Systemfehler trat während der Bearbeitung Ihrer Zahlung auf. Es wurde " -"Ihnen nichts berechnet. " - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "Bitte warten Sie einige Minuten und versuchen es erneut. " - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "Für Hilfe, kontaktieren Sie bitte {payment_support_link}." - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "Bei der Rechnungserstellung ist ein Fehler aufgetreten." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"Wenn ein gekaufter Kurs nicht in 'Meine Kurse' aufgelistet wird, " -"kontaktieren Sie {payment_support_link}." - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "Erhalten Sie ein Zertifikat" @@ -6416,11 +6365,23 @@ msgstr "Sie haben keinen Zugang zu diesem Kurs. " msgid "You do not have access to this course on a mobile device" msgstr "Sie haben keinen Zugang zu diesem Kurs von einem mobilen Gerät." +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "Upgrade auf Verifiziert" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "Aufgabe" @@ -7130,16 +7091,20 @@ msgid "Good" msgstr "Gut" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" -msgstr "%(comment_username)s hat geantwortet auf <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" +msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt msgid "View discussion" msgstr "Diskussion betrachten" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "%(comment_username)s hat geantwortet auf <b>%(thread_title)s</b>:" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -7294,8 +7259,8 @@ msgid "Student" msgstr "Teilnehmer" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "Mitarbeiter" @@ -7426,31 +7391,6 @@ msgstr "Fehlerreporte" msgid "Could not find problem with this location." msgstr "Konte keine Fragestellung mit diesem Pfad finden. " -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "Rechnung mit der Nummer '{num}' existiert nicht." - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "" -"Der mit dieser Rechnung verbundene Verkauf wurde bereits für ungültig " -"erklärt." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "Rechnungsnummer {0} ungültig." - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "Diese Rechnung ist bereits aktiv." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "Die Registrierungscodes für die Rechnung {0} wurden wieder aktiviert." - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "Kurs-ID" @@ -7481,9 +7421,8 @@ msgstr "Benutzer-ID" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "Nutzername" @@ -7607,54 +7546,6 @@ msgstr "" "Die Datei muss eine Spalte \"Benutzername\", eine Spalte \"E-Mail\" oder " "beides enthalten." -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "Gutschein-Code" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "Kurs ID" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% Rabatt" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "Beschreibung" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "Ablaufdatum" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "Ist Aktiv" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "Eingelöster Code-Betrag" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "Gesamtzahl der rabattierten Einschreibungsplätze" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "Gesamter rabattierter Betrag" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -7675,16 +7566,6 @@ msgstr "Umfrage" msgid "proctored exam results" msgstr "Ergebnisse der beaufsichtigten Prüfung" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "Der Betrag konnte nicht als Dezimalzahl ausgewertet werden." - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" -"Es ist nicht möglich, Einlösungscodes zu generieren, aufgrund einer " -"fehlerhaften Konfiguration des Kurses." - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -7938,66 +7819,6 @@ msgstr "" "überprüfen Sie Benutzernamen/E-Mail des Teilnehmers und den ausgewählten " "Kurs auf Richtigkeit und versuchen Sie es erneut." -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "Gutschein-ID ist nicht gegeben" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "Gutschein mit Gutschein-ID ({coupon_id}) existiert nicht" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "Gutschein mit Gutschein-ID ({coupon_id}) ist bereits inaktiv" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "Gutschein mit Gutschein-ID ({coupon_id}) erfolgreich aktualisiert" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" -"Den Code ({code}) den du versucht hast festzulegen, ist bereits als ein " -"Registrierungscode in Benutzung" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "Bitte gib einen Ganzzahlwert für die Gutscheinermäßigung ein" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "" -"Bitte gib einen Gutscheinermäßigungswert der kleiner oder gleich 100 ist ein" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "Bitte geben Sie Datumsangaben im folgenden Format ein Monat/Tag/Jahr" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "Gutschein mit Gutschein-ID ({code}) erfolgreich hinzugefügt" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "Gutschein mit Gutschein-ID ({code}) existiert bereits für diesen Kurs" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "Gutschein-ID nicht gefunden" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "Gutschein mit Gutschein-ID ({coupon_id}) erfolgreich aktualisiert" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "Dozent" @@ -8109,33 +7930,6 @@ msgstr "Abgeschlossen" msgid "Incomplete" msgstr "Unvollständig" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "" -"Der Einschreibungscode ({code}) für den Kurs {course_name} konnte nicht " -"gefunden werden." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "" -"Dieser Einschreibungsscode wurde storniert. Es kann nicht mehr verwendet " -"werden." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "Dieser Einschreibungscode wurde als unbenutzt markiert." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "Der Einschreibungscode wurde wiederhergestellt." - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "Die Einlösung erfolgt nicht gegen den Registrierungscode ({code})." - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -8549,8 +8343,8 @@ msgstr "(von {total})" #: lms/djangoapps/learner_dashboard/programs.py #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Programme" @@ -8761,12 +8555,12 @@ msgid "{mode_name} for course {course}" msgstr "{mode_name} für Kurs {course}" #: lms/djangoapps/shoppingcart/models.py +#, python-brace-format msgid "" -"You can unenroll in the course and receive a full refund for 14 days after " -"the course start date. " +"To receive a refund you may unenroll from the course on your edX Dashboard " +"({dashboard_url}) up to 14 days after your payment or 14 days after your " +"course starts (up to six months after your payment).\n" msgstr "" -"Sie können sich aus dem Kurs ausschreiben und erhalten eine volle " -"Rückerstattung für 14 Tage nach Kursbeginn. " #: lms/djangoapps/shoppingcart/models.py #, python-brace-format @@ -8780,21 +8574,15 @@ msgstr "" #: lms/djangoapps/shoppingcart/models.py msgid "" "You can unenroll in the course and receive a full refund for 2 days after " -"the course start date. " +"the course start date.\n" msgstr "" -"Sie können sich aus dem Kurs ausschreiben und erhalten eine volle " -"Rückerstattung für 2 Tage nach Kursbeginn. " #: lms/djangoapps/shoppingcart/models.py #, python-brace-format msgid "" -"{refund_reminder_msg}To receive your refund, contact {billing_email}. Please" -" include your order number in your email. Please do NOT include your credit " -"card information." +"{refund_reminder_msg}For help unenrolling, Please see How do I unenroll from" +" a course? ({how_to_unenroll_link}) in our edX HelpCenter." msgstr "" -"{refund_reminder_msg}Um Ihre Rückerstattung zu erhalten, wenden Sie sich " -"bitte an {billing_email}. Bitte geben Sie Ihre Bestellnummer in Ihrer E-Mail" -" an. Bitte geben Sie Ihre Kreditkartendaten NICHT an." #: lms/djangoapps/shoppingcart/models.py #, python-brace-format @@ -9330,6 +9118,15 @@ msgstr "Gesamtpreis" msgid "Currency" msgstr "Währung" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "Beschreibung" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "Kommentare" @@ -9477,14 +9274,6 @@ msgstr "Sie haben nicht die Erlaubnis, diese Seite anzusehen." msgid "View and regenerate certificates." msgstr "Zertifikate anzeigen und neu erstellen " -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "Händische Rückerstattung" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "Verfolgen Sie Rückerstattungen, die direkt über CyberSource erfolgen." - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -9564,45 +9353,9 @@ msgstr "Benutzer erfolgreich aktiviert" msgid "User Disabled Successfully" msgstr "Benutzer erfolgreich deaktiviert" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "E-Mail-Adresse" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "Kurs-ID" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "Nutzer nicht gefunden" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" msgstr "" -"Kurs {course_id} hat den Rückerstattungszeitraum noch nicht überschritten." - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "Keine Bestellung für {user} des Kurs {course_id} gefunden" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "{user} aus {course_id} entfernt" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "Rückerstattung in Höhe von {cost} für Bestellnummer {order_id}" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -9650,14 +9403,18 @@ msgid "The supplied course_id {course_id} is not valid." msgstr "Die angegebene Kurs-ID {course_id} ist nicht gültig." #: lms/djangoapps/teams/views.py -msgid "You are already in a team in this course." -msgstr "Sie sind bereits in dem Team des Kurses." +msgid "topic_id is required" +msgstr "" #: lms/djangoapps/teams/views.py msgid "You can't create a team in an instructor managed topic." msgstr "" "Sie können kein Team in einem vom Dozenten verwalteten Thema erstellen." +#: lms/djangoapps/teams/views.py +msgid "You are already in a team in this teamset." +msgstr "" + #: lms/djangoapps/teams/views.py msgid "teamset_id and team_id are mutually exclusive options." msgstr "teamset_id und team_id sind sich gegenseitig ausschließende Optionen." @@ -10298,8 +10055,8 @@ msgid "Allow" msgstr "Erlauben" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "Fehler" @@ -10710,8 +10467,8 @@ msgstr "" "für Hilfe." #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "Anhänge" @@ -10750,11 +10507,10 @@ msgstr "" "Artikel, was gut oder schlecht sein kann." #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -11209,6 +10965,10 @@ msgstr "" "Die Konfiguration darf nicht auf mehr als einer Ebene gleichzeitig " "festgelegt werden." +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "Verwalte Benutzer und Autoren Inhalt" @@ -11643,6 +11403,10 @@ msgstr "Bekannter Fehlerfall" msgid "Schedule start < course start" msgstr "Schedule start < Starten" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "Kurs ID" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "Alles" @@ -11651,6 +11415,15 @@ msgstr "Alles" msgid "Experience" msgstr "Erfahrung" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "Kurs-ID" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -12155,7 +11928,6 @@ msgstr "" "entfernen, lassen Sie dieses Feld leer." #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -12184,8 +11956,8 @@ msgid "Success" msgstr "Operation Erfolgreich" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "Aktionen" @@ -12380,6 +12152,14 @@ msgstr "" "Es ist ein Fehler beim Empfangen deiner Anmeldeinformationen aufgetreten. " "Bitte sende uns eine E-Mail." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -12399,6 +12179,15 @@ msgstr "" "Zu viele fehlgeschlagene Anmeldeversuche. Bitte versuche es später noch " "einmal." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -12408,15 +12197,6 @@ msgstr "" "Als {allowed_domain} Benutzer, müssen Sie sich mit Ihrem {allowed_domain} " "{link_start}{provider} Konto anmelden{link_end}." -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "username@domain.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -12434,6 +12214,12 @@ msgstr "" msgid "Create Account" msgstr "Konto erstellen" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "username@domain.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -12450,6 +12236,13 @@ msgstr "" "Mit dem Nutzerkonto das zu dieser E-Mail-Adresse gehört können Sie das " "Passwort nicht zurücksetzen." +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" +"Ihre vorherige Anfrage ist in Bearbeitung, bitte versuchen Sie es in wenigen" +" Augenblicken erneut." + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "Zurücksetzen des Passworts nicht erfolgreich" @@ -12473,13 +12266,6 @@ msgstr "" "{html_start}Passworterstellung abgeschlossen{html_end}Ihr Passwort wurde " "erstellt. {bold_start}{email}{bold_end} ist nun Ihre primäre Anmelde E-Mail." -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" -"Ihre vorherige Anfrage ist in Bearbeitung, bitte versuchen Sie es in wenigen" -" Augenblicken erneut." - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es noch einmal." @@ -12730,6 +12516,18 @@ msgstr "" "Benutzername erstellt für die Video Pipeline Integration, z.B. " "veda_service_user." +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "Aufdrücken" @@ -12750,6 +12548,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "Dieser Inhalt ist nur für eingeschriebene Nutzer sichtbar." +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "Dieser Wert ist ungültig." @@ -13545,8 +13347,8 @@ msgid "Vertical" msgstr "Senkrecht" #: cms/djangoapps/contentstore/views/helpers.py -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "Abschnitt" @@ -13834,6 +13636,18 @@ msgstr "Transkript wird verarbeitet" msgid "Transcript Ready" msgstr "Transkript ist fertig" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "Ein Bild ist hier erforderlich." @@ -13989,8 +13803,8 @@ msgstr "Inhalt" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "Einstellungen" @@ -14038,14 +13852,14 @@ msgstr "Kursnummer:" msgid "Course Run:" msgstr "Kurslaufzeit:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "Meine Kurse" @@ -14069,8 +13883,9 @@ msgstr "Dozenten" msgid "Requirements" msgstr "Vorraussetzungen" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "Details" @@ -14126,15 +13941,15 @@ msgstr "" msgid "Choose Language" msgstr "Sprache wählen" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "Benutzerkonto" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -14207,8 +14022,8 @@ msgstr "Nutzermenü" msgid "Usermenu dropdown" msgstr "Dropdown Nutzermenü" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "Abmelden" @@ -14378,8 +14193,8 @@ msgstr "Beginn: {date}" msgid "View all Courses" msgstr "Alle Kurse anzeigen" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "Meine Kurse" @@ -14398,8 +14213,8 @@ msgstr "Sie sind noch in keinem Kurs eingeschrieben." #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "Kursübersicht" @@ -14417,7 +14232,7 @@ msgstr "Kursladefehler" msgid "Search Your Courses" msgstr "Nach Kursen suchen" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "Suche löschen" @@ -14442,7 +14257,7 @@ msgstr "Kurs-E-Mails erhalten" msgid "Save Settings" msgstr "Einstellungen speichern" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -14452,9 +14267,87 @@ msgstr "Einstellungen speichern" msgid "Unenroll" msgstr "Ausschreiben" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "Lerneinheit im Studio betrachten" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -14488,7 +14381,7 @@ msgstr "Es existiert bereits ein Konto mit dieser E-Mail-Adresse" msgid "You should Register before trying to access the Unit" msgstr "Sie sollten sich registrieren bevor sie auf diese Einheit zugreifen." -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "Einschreiben" @@ -14596,7 +14489,7 @@ msgstr "" "verfügbar.{line_break}Wenn Sie diese Aufgabe abgeschlossen haben, ist Ihre " "Bewertung auf der {link_start}Fortschrittsseite{link_end} verfügbar." -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "Suche nach einem Kurs" @@ -14744,23 +14637,16 @@ msgstr "(aktualisieren Sie die Seite)" msgid "working" msgstr "in Arbeit" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "Es gab einen Fehler auf den {platform_name} Servern" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html -#: lms/templates/courseware/error-message.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"Es tut uns leid, dieses Modul steht momentan nicht zur Verfügung. Unsere " -"Mitarbeiter arbeiten daran, das Problem so schnell wie möglich zu beheben. " -"Bitte schreiben Sie eine E-Mail an {tech_support_email}, um Probleme und " -"Ausfallzeiten zu benennen." #: lms/templates/module-error.html msgid "Raw data:" @@ -14799,8 +14685,16 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "Sie sehen den Kurs aus der Sicht von {i_start}{user_name}{i_end}." #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" -msgstr "Sehen Sie sich diese Einheit in der neuen Erfahrung an" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" +msgstr "" #: lms/templates/problem.html msgid "You have used {num_used} of {num_total} attempt" @@ -14867,18 +14761,6 @@ msgstr "E-Mail" msgid "Return To %s" msgstr "Zurück zu %s" -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" -"Es sieht so aus, als hätten Sie einige wichtige Fristen verpasst. Setzen Sie" -" Ihre Fristen zurück und legen Sie noch heute los." - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "Meine Fristen zurücksetzen" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "Benachrichtigungen aktiviert!" @@ -14932,7 +14814,7 @@ msgstr "Nächster" msgid "Sequence" msgstr "Ablauf" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "Beendet" @@ -15064,18 +14946,18 @@ msgstr "Punktzahl (nur zur Ãœberschreibung)" msgid "Reset Learner's Attempts to Zero" msgstr "Teilnehmerversuche auf Null zurücksetzen" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "Teilnehmerfortschritt löschen" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "Teilnehmereinreichung neu bewerten" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "Neubewertung nur, falls sich dardurch die Benotung verbessert" @@ -15113,7 +14995,7 @@ msgstr "{course_number} Lehrbuch" msgid "Textbook Navigation" msgstr "Lehrbuch Navigation" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "Seite" @@ -15227,9 +15109,9 @@ msgstr "Seite {current_page} von {total_pages}" msgid "Recent git load activity for {course_id}" msgstr "Letzte git-Ladeaktivität für {course_id}" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -15289,7 +15171,7 @@ msgstr "" "Ãœbersicht{link_end} zurückkehren. Wenn Sie dies nicht wollten, können Sie " "diese {undo_link_start} erneut abonnieren{link_end}." -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "Ãœbersicht für Meine Kurse:" @@ -15297,8 +15179,8 @@ msgstr "Ãœbersicht für Meine Kurse:" msgid "More options" msgstr "Weitere Optionen" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "Weitere Optionen" @@ -16873,40 +16755,6 @@ msgstr "" msgid "About edX Certificates" msgstr "Ãœber edX Zertifikate" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "Bezahlung abgebrochen " - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"Ihre Transaktion wurde abgebrochen. Wenn Sie das Gefühl haben, ein Fehler " -"ist aufgetreten, kontaktieren Sie {email}." - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "Fehler an der Kasse" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" -"Bei Ihrer Zahlung ist ein Fehler aufgetreten. {b_start}Es wurde Ihnen nichts" -" berechnet.{b_end} Bitte versuchen Sie, Ihre Zahlung erneut einzureichen. " -"Wenn dieses Problem weiterhin besteht, wenden Sie sich an {email}." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "Bestelldaten werden geladen..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "Bitte warten Sie. Bestellungsinformationen werden abgerufen." - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -17148,31 +16996,28 @@ msgstr "{section_format} Fälligkeit {{date}}" msgid "This content is graded" msgstr "Dieser Inhalt ist benotet" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "" -"Ein Fehler ist aufgetreten. Bitte versuchen Sie es später noch einmal." - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" "Es ist ein Fehler aufgetreten. Bitte stellen Sie sicher, dass Sie für die " "Einschreibung eingeloggt sind." +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "" +"Ein Fehler ist aufgetreten. Bitte versuchen Sie es später noch einmal." + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "Sie sind in diesem Kurs eingeschrieben" #: lms/templates/courseware/course_about.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: lms/templates/shoppingcart/registration_code_receipt.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "View Course" msgstr "Anzeigen" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "Dieser Kurs ist in Ihrem {start_cart_link}Warenkorb{end_cart_link}." - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "Kurs ist voll" @@ -17185,12 +17030,6 @@ msgstr "Einschreibung zu diesem Kurs erfolgt nur auf Einladung" msgid "Enrollment is Closed" msgstr "Einschreibung ist geschlossen" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" -"Hinzufügen von {course_name} zum Warenkorb {start_span}({price} " -"USD){end_span}" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "Jetzt einschreiben" @@ -17321,6 +17160,13 @@ msgstr "Kurswerkzeuge" msgid "Courseware" msgstr "Kursinhalte" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "Kurssuche" @@ -17353,19 +17199,20 @@ msgid "Important Dates" msgstr "Wichtige Termine" #: lms/templates/courseware/dates.html -msgid "Due Today" -msgstr "Heute fällig" +msgid "Today" +msgstr "" #: lms/templates/courseware/dates.html msgid "Verified Only" msgstr "Nur verifiziert" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" +msgstr "" + +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" -"{a_start}Aktualisieren Sie{a_end}{space}auf ein verifiziertes Zertifikat, um" -" vollen Zugriff zu erhalten." #: lms/templates/courseware/gradebook.html msgid "Gradebook" @@ -17419,8 +17266,9 @@ msgid "Welcome to {course_title}!" msgstr "Willkommen bei {course_title}!" #: lms/templates/courseware/info.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "Resume Course" msgstr "Kurs fortsetzen" @@ -18074,11 +17922,8 @@ msgstr "Sie haben Ihre Verifizierungsinformationen eingereicht." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" -"Sie werden eine Nachricht auf Ihrem Dashboard sehen, wenn der " -"Verifizierungsprozess abgeschlossen ist (normalerweise innerhalb von 1-2 " -"Tagen)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -18088,11 +17933,8 @@ msgstr "Ihre aktuelle Verifikation wird bald ablaufen!" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" -"Sie haben Ihre Reverifizierung eingereicht. Sie werden eine Nachricht auf " -"Ihrer Ãœbersichtsseite sehen, sobald der Prozess abgeschlossen ist und Ihre " -"Identität verifiziert wurde (normalerweise innerhalb von 1-2 Tagen)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -18863,150 +18705,6 @@ msgstr "" " bestätigen, ob Ihre Verifikation erfolgreich war, und überprüfen Sie den " "Status des Verifikationsprozesses auf Ihrer 'Meine Kurse' Ãœbersicht." -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "Vielen Dank für den Kauf von Plätzen im Kurs {course_name}." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"Die Rechnung für {currency_symbol}{total_price} ist angehängt. Die Bezahlung" -" ist quittiert. Sie finden die Bezahlinformationen in der Rechnung." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -"Eine .csv-Datei, die Ihre Einschreibecodes auflistet, ist angehängt. Sie " -"können die untenstehende E-Mail-Vorlage verwenden, um Einschreibecodes an " -"IhreTeilnehmer zu verteilen. Jeder Teilnehmer muss einen separaten " -"Einschreibecode verwenden." - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"Danke,\n" -"Das {platform_name} Team" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "Sehr geehrter [[Name]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"Wir haben einen Zugangscode für den Kurs {course_name} erstellt. Um sich nun" -" dort einschreiben zu können, klicken Sie bitte auf den folgenden Link:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "HTML-Link der angehängten CSV-Datei" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"Nachdem Sie sich eingeschrieben haben, wird der Kurs in der Teilnehmer-Seite" -" \"Meine Kurse\" aufgelistet. Sie können die Kursmaterialien nach dem " -"Startdatum einsehen." - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"Hochachtungsvoll,\n" -"[[Deine Unterschrift ]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "RECHNUNG" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "Datum: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "Rechnungsnr.: {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "Bedingungen: Fällig nach Erhalt " - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "Fälligkeitsdatum: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "Rechnung an:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "Kundenreferenz Nummer: {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "Offener Restbetrag: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "Kurs: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"Preis: {currency_symbol}{course_price} Menge: {quantity} " -"Summe: {currency_symbol}{sub_total} Rabatt: {currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "Summe: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "Zahlungsanweisungen" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"Wenn wir keine Zahlung erhalten, werden die Anmeldungen von Lernenden, die " -"diese Codes verwenden, storniert und die Lernenden können nicht auf " -"Kursmaterialien zugreifen. Alle Käufe sind endgültig. Weitere Informationen " -"finden Sie in der Stornierungsrichtlinie {site_name}." - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "Bei Fragen bezüglich der Bezahlung, kontaktieren Sie {contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -19219,8 +18917,8 @@ msgstr "Für finanzielle Unterstützung bewerben" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} Startseite" @@ -19244,19 +18942,11 @@ msgstr "Kursübersicht" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "Systemadministrator" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "Warenkorb" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "Zusätzliche Links" @@ -19293,6 +18983,12 @@ msgstr "Gutschein-Code hinzufügen" msgid "Enter information about the coupon code below." msgstr "Geben Sie Informationen zu diesem Gutschein-Code unten ein. " +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "Gutschein-Code" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "Ermäßigung in Prozent" @@ -19929,6 +19625,11 @@ msgstr "Gutschein-Codes herunterladen" msgid "Coupon Codes" msgstr "Gutschein Codes" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "Ablaufdatum" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "Gutschein (%)" @@ -21377,6 +21078,10 @@ msgstr "Einkaufende Organisation" msgid "Purchase order number (if any)" msgstr "Bestellnummer (wenn vorhanden)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "E-Mail-Adresse" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "email@example.com" @@ -21702,6 +21407,10 @@ msgstr[0] "" msgstr[1] "" "{course_names} Wurden entfernt, da die Frist zur Anmeldung abgelaufen ist." +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "Warenkorb" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "Titelbild" @@ -21792,12 +21501,8 @@ msgstr "Bestätigung" #: lms/templates/static_templates/404.html msgid "" "The page that you were looking for was not found. Go back to the " -"{link_start}homepage{link_end} or let us know about any pages that may have " -"been moved at {email}." +"{link_start}homepage{link_end} ." msgstr "" -"Die Seite nach der Sie suchen wurde nicht gefunden. Gehen Sie zurück zur " -"{link_start}Startseite{link_end} oder benachrichtigen Sie uns über alle " -"Seiten, die umgezogen sein könnten, unter {email}." #: lms/templates/static_templates/about.html #: lms/templates/static_templates/blog.html @@ -21851,23 +21556,15 @@ msgstr "Die {platform_name} Server stehen augenblicklich nicht zu Verfügung." #: lms/templates/static_templates/server-overloaded.html msgid "" "Our staff is currently working to get the site back up as soon as possible. " -"Please email us at {tech_support_email} to report any problems or downtime." msgstr "" -"Unsere Mitarbeiter sind gerade dabei die Seite so schnell wie möglich wieder" -" zum Laufen zu bringen. Bitte senden Sie uns eine E-Mail an " -"{tech_support_email}, um Probleme oder Ausfallzeiten zu benennen." #: lms/templates/static_templates/server-error.html msgid "There has been a 500 error on the {platform_name} servers" msgstr "Es gab einen Fehler 500 auf den {platform_name}-Servern" #: lms/templates/static_templates/server-error.html -msgid "" -"Please wait a few seconds and then reload the page. If the problem persists," -" please email us at {email}." +msgid "Please wait a few seconds and then reload the page." msgstr "" -"Bitte warten Sie einen Moment und laden Sie dann die Seite neu. Sollte das " -"Problem weiterhin bestehen kontaktieren Sie uns bitte unter {email}." #: lms/templates/static_templates/server-overloaded.html msgid "Currently the {platform_name} servers are overloaded" @@ -21937,46 +21634,6 @@ msgstr "Teilnehmersupport: Benutzer verwalten" msgid "Program Enrollments Inspector" msgstr "Inspektor für Programmeinschreibungen" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "Details Rückerstattung dieser Bestellung:" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "Bestellnummer:" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "Einschreibung:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "eingeschrieben" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "entfernt" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "Kosten:" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "Status Zertifkat:" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "Status Bestellung:" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "Benötigte Zeit:" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "Zeit der Rückerstattungsanfrage:" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "Benutzerbefragung" @@ -22131,12 +21788,8 @@ msgstr "Identitäts-Verifikation" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" -"Sie haben Ihre Verikationsinformationen bereits übermittelt. Sie werden eine" -" Meldung auf Ihrer 'Meine Kurse' Ãœbersicht sehen, wenn der " -"Verifikationsprozess abgeschlossen ist (normalerweise innerhalb von 1-2 " -"Tagen)." #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -22366,6 +22019,10 @@ msgstr "Letztes Update" msgid "Get started on what's next: " msgstr "Beginnen Sie mit den nächsten Schritten:" +#: openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html +msgid "Show More" +msgstr "" + #: openedx/features/course_search/templates/course_search/course-search-fragment.html msgid "Search Results" msgstr "Suchergebnisse" @@ -22755,8 +22412,8 @@ msgid "Already registered?" msgstr "Bereits registriert?" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "Anmelden" @@ -22879,12 +22536,8 @@ msgid "The page that you were looking for was not found." msgstr "Die aufgerufene Seite wurde leider nicht gefunden" #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" -"Gehen Sie zurück zur Seite {homepage} oder teilen Sie uns Seiten, die " -"wahrscheinlich verschoben sind, unter {email} mit." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -22911,12 +22564,6 @@ msgstr "" "Wir haben diesen Fehler registriert und unsere Mitarbeiter arbeiten daran, " "diesen Fehler so schnell wie möglich zu beheben." -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "" -"Wenn das Problem weiter besteht, schicken Sie uns bitte eine E-Mail unter " -"{email_link}" - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "Zugangsrichtlinien für Studio" @@ -23627,15 +23274,8 @@ msgstr "Die angefragte Seite kann nicht gefunden werden" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." -msgstr "" -"Es tut uns leid. Wir konnten die Seite {studio_name}, die Sie suchen, nicht " -"finden. Sie sollten zur {studio_name} Ãœbersicht zurückkehren und es noch " -"einmal versuchen. Wenn Sie immer noch Probleme mit dem Zugriff haben, wenden" -" Sie sich bitte für weitere Hilfe an {link_start}den {studio_name} " -"Support{link_end}." +" may want to return to the {studio_name} Dashboard and try again." +msgstr "" #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -23645,15 +23285,8 @@ msgstr "Beim Server trat ein Fehler auf" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" -"Es tut uns leid. Es gab ein Problem mit dem Server beim Versuch, Ihre letzte" -" Anfrage zu bearbeiten. Sie können zur {studio_name} Ãœbersicht zurückkehren " -"oder diese Anfrage erneut versuchen. Wenn Sie immer noch Probleme mit dem " -"Zugriff haben, wenden Sie sich bitte für weitere Hilfe an {link_start}den " -"{studio_name} Support{link_end}." #: cms/templates/error.html msgid "Back to dashboard" @@ -27102,8 +26735,8 @@ msgstr "%(file)s wurde auf Revision #%(revision)d abgeändert" msgid "%(file)s has been saved." msgstr "%(file)s wurde gesichert." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "Bilder" @@ -27317,8 +26950,8 @@ msgstr "Liste der Benachrichtigungen bereinigen" msgid "Search..." msgstr "Suche..." -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "Registrieren" diff --git a/conf/locale/de_DE/LC_MESSAGES/djangojs.mo b/conf/locale/de_DE/LC_MESSAGES/djangojs.mo index 656e036ce8b35c6af860be6452dd86a0ebd02cf6..e8388c7421a55cf6275165a37246f2b7aaa95060 100644 Binary files a/conf/locale/de_DE/LC_MESSAGES/djangojs.mo and b/conf/locale/de_DE/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/de_DE/LC_MESSAGES/djangojs.po b/conf/locale/de_DE/LC_MESSAGES/djangojs.po index d2babd32d604af8e6a95d6b9bf7ba50438037316..60337a703accbf23320e6f008aaf58e1125bb7a9 100644 --- a/conf/locale/de_DE/LC_MESSAGES/djangojs.po +++ b/conf/locale/de_DE/LC_MESSAGES/djangojs.po @@ -12,9 +12,9 @@ # Alexander L. <alexander.lohberg@ufo-style.de>, 2013-2014 # Alexander L. <alexander.lohberg@ufo-style.de>, 2016-2017 # andreas.frey <andreas.frey@liip.ch>, 2014 -# dabang <inactive+dabang@transifex.com>, 2014 +# 2b2d35a2693e2be4fb9cc6718ad20b07_8542ebf <37324aa543125a600265fedaa47d04f3_158329>, 2014 # c377c1a4a254197c7969440fac89353f, 2014 -# berit.braun, 2014 +# 9309a68e5ef70fb98095fd18e848e998_2d7fe4e, 2014 # Bert Krohn <bert.krohn@tum.de>, 2017 # Christian Layr <Christian.Layr@unisg.ch>, 2015 # Donna Kl <donna@polarstern-education.com>, 2019 @@ -129,16 +129,16 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" -"PO-Revision-Date: 2020-01-06 08:48+0000\n" -"Last-Translator: Stefania Trabucchi <stefania.trabucchi@abstract-technology.de>\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" +"Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: German (Germany) (http://www.transifex.com/open-edx/edx-platform/language/de_DE/)\n" "Language: de_DE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -159,21 +159,6 @@ msgstr "Speichert" #: cms/static/js/views/manage_users_and_roles.js #: cms/static/js/views/show_textbook.js #: lms/djangoapps/teams/static/teams/js/views/instructor_tools.js -#: cms/templates/js/certificate-details.underscore -#: cms/templates/js/certificate-editor.underscore -#: cms/templates/js/content-group-editor.underscore -#: cms/templates/js/course-instructor-details.underscore -#: cms/templates/js/course-outline.underscore -#: cms/templates/js/course-settings-learning-fields.underscore -#: cms/templates/js/course_grade_policy.underscore -#: cms/templates/js/course_info_update.underscore -#: cms/templates/js/group-configuration-details.underscore -#: cms/templates/js/group-configuration-editor.underscore -#: cms/templates/js/partition-group-details.underscore -#: cms/templates/js/show-textbook.underscore -#: cms/templates/js/signatory-editor.underscore -#: cms/templates/js/video-transcripts.underscore -#: cms/templates/js/xblock-outline.underscore msgid "Delete" msgstr "Löschen" @@ -202,6 +187,7 @@ msgstr "Löschen" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -224,6 +210,7 @@ msgstr "Hochladen" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -253,6 +240,7 @@ msgstr "Datei auswählen" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "OK" @@ -846,7 +834,6 @@ msgstr "Lösche Tabelle" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Beschreibung" @@ -881,18 +868,9 @@ msgstr "Dokumenteneigenschaften" msgid "Edit HTML" msgstr "Bearbeite HTML" -#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-# #. Translators: this is a message from the raw HTML editor displayed in the #. browser when a user needs to edit HTML #: common/lib/xmodule/xmodule/js/src/html/edit.js -#: cms/templates/js/certificate-details.underscore -#: cms/templates/js/course_info_handouts.underscore -#: cms/templates/js/course_info_update.underscore -#: cms/templates/js/group-configuration-details.underscore -#: cms/templates/js/partition-group-details.underscore -#: cms/templates/js/show-textbook.underscore -#: cms/templates/js/signatory-details.underscore -#: cms/templates/js/xblock-string-field-editor.underscore msgid "Edit" msgstr "Bearbeiten" @@ -1295,6 +1273,7 @@ msgstr "Neues Fenster" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Weiter" @@ -1638,12 +1617,9 @@ msgstr "" "Die URL, die du eingegeben hast scheint ein externer Link zu sein. Möchtest " "du das benötigte Prefix http:// hinzufügen?" -#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-# #. Translators: this is a message from the raw HTML editor displayed in the #. browser when a user needs to edit HTML #: common/lib/xmodule/xmodule/js/src/html/edit.js -#: cms/templates/js/course-instructor-details.underscore -#: cms/templates/js/signatory-details.underscore msgid "Title" msgstr "Titel, Namenszusatz" @@ -2614,23 +2590,32 @@ msgid "Other" msgstr "Anderer Abschluss" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" -msgstr "Wie können wir Ihnen helfen, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Details" msgstr "Details" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" -"Je mehr Sie uns von Ihrem Anliegen berichten, desto genauer und schneller " -"können wir Ihnen helfen!" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Absenden" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "Wie können wir Ihnen helfen, {username}?" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." @@ -2639,11 +2624,8 @@ msgstr "" "helfen können." #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" -"Wenn Sie keinen Zugang zu Ihrem Account haben, kontaktieren Sie uns via " -"E-Mail {email}." #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "" @@ -2655,12 +2637,24 @@ msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "Select a subject for your support request." -msgstr "Wählen Sie ein Thema für Ihre Supportanfrage aus." +msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "Enter some details for your support request." msgstr "Geben Sie bitte genaue Details in Ihrer Support Anfrage an." +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2684,10 +2678,9 @@ msgstr "Gehe zur Startseite der {platform} " #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" -"Vielen Dank für Ihre Anfrage! Wir werden Sie innerhalb von 24 Stunden " -"kontaktieren." #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx msgid "Cancel upload" @@ -2878,6 +2871,10 @@ msgstr "{span_start} {team_name} {span_end} ansehen" msgid "An error occurred. Try again." msgstr "Ein Fehler ist aufgetreten. Bitte versuchen Sie es noch einmal." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Dieses Team verlassen?" @@ -3432,6 +3429,7 @@ msgid "There has been an error processing your survey." msgstr "Es ist ein Fehler beim verarbeiten der Umfrage aufgetreten." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -5608,6 +5606,14 @@ msgstr "Alles erweitern" msgid "Collapse All" msgstr "Alles verbergen" +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show More" +msgstr "Mehr zeigen" + +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show Less" +msgstr "Weniger zeigen" + #: openedx/features/course_search/static/course_search/js/views/search_results_view.js msgid "{total_results} result" msgid_plural "{total_results} results" @@ -5762,6 +5768,10 @@ msgstr "Ja, erlaube das Editieren von aktiven Zertifikaten" msgid "certificate" msgstr "Zertifikat" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Richten Sie sich Ihr Zertifikat ein" @@ -5773,8 +5783,8 @@ msgid "You have not created any certificates yet." msgstr "Du hast bislang keine Zertifikate erhalten." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "Lösche \"<%= signatoryName %>\" von der Liste der Unterzeichner?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -6101,11 +6111,9 @@ msgstr "Alle Kapitel benötigen einen Namen und Inhalte" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" -"Nur <%= fileTypes %> Dateien können hochgeladen werden. Bitte wählen Sie " -"eine Datei mit der Dateiendung <%= fileExtensions %> zum hochladen aus." #: cms/static/js/models/uploads.js #: lms/templates/student_account/hinted_login.underscore @@ -6291,8 +6299,8 @@ msgid "{selectedProvider} credentials saved" msgstr "{selectedProvider} Anmeldeinformationen gespeichert" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" -msgstr "Neues PDf unter “<%= name %>†hochgeladen" +msgid "Upload a new PDF to “<%- name %>â€" +msgstr "" #: cms/static/js/views/edit_chapter.js msgid "Please select a PDF file to upload." @@ -6917,18 +6925,14 @@ msgstr "Wir bitten um Entschuldigung, ein Fehler ist aufgetreten" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" -"Die Gesamtlänge der Felder Organisation, Kursnummer und Kursablauf darf " -"nicht mehr als <%=limit%> Zeichen betragen." #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" -"Die Gesamtlänge der Codefelder Organisation und Bibliothek darf nicht mehr " -"als <%=limit%> Zeichen betragen." #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -7297,13 +7301,13 @@ msgid "Unscheduled" msgstr "Nicht terminiert" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Datum" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Zurück" @@ -7352,6 +7356,310 @@ msgstr "Suche löschen" msgid "Search" msgstr "Suchen" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Absenden" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "Alle Beiträge" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "Forum Home" @@ -7411,10 +7719,6 @@ msgstr "" "Aktivieren Sie diese Box und Sie erhalten einmal am Tag eine Zusammenfassung" " von neuen, ungelesenen Aktivitäten zu Beiträgen, denen Sie folgen. " -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "Alle Beiträge" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "Nutzername od. E-Mail" @@ -7654,6 +7958,10 @@ msgstr "Hast Du Probleme ein Team zum Beitreten zu finden?" msgid "Join Team" msgstr "Trete Team bei" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "Team Details" @@ -7741,105 +8049,6 @@ msgstr "Untereinheit %(subsectionDisplayName)s entfernen" msgid "Remove unit %(unitName)s" msgstr "%(unitName)s Lerneinheit entfernen" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" -"Sie müssen noch die Website %(display_name)s besuchen, um den Credit-Prozess" -" abzuschließen." - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"Um den Credit-Prozess abzuschließen, %(display_name)s müssen die Lernenden " -"von %(platform_name)s einen Kreditantrag stellen." - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Credit bekommen" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" -"Viele Dank %(full_name)s! Wir haben Ihre Zahlung für %(course_name)s " -"erhalten." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"Bitte drucken Sie diese Seite für Ihre Unterlagen aus, sie dient als Ihre " -"Quittung. Sie erhalten außerdem eine E-Mail mit den gleichen Informationen." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "Bestellnummer" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Summe" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Gesamt" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Bitte beachten Sie" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "Gekreuzte Einzelteile wurden erstattet." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Rechnung an" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Keine Quittung verfügbar" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Zu \"Meine Kurse\"" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" -"Wenn Sie Ihre Identität jetzt nicht verifizieren, können Sie Ihren Kurs " -"trotzdem über 'Meine Kurse' erkunden. Sie erhalten von {platformName} " -"regelmäßig Erinnerungen, um Ihre Identität zu überprüfen." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "Wollen Sie ihre Identität später bestätigen?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Verifiziere Jetzt" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Markiere Prüfung als vollständig" @@ -7866,14 +8075,6 @@ msgstr "" "Um Credits für Probleme zu erhalten, müssen Sie für jedes Problem \"Senden\"" " auswählen, bevor Sie \"Meine Prüfung beenden\" wählen." -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show More" -msgstr "Mehr zeigen" - -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show Less" -msgstr "Weniger zeigen" - #: lms/templates/courseware/proctored-exam-status.underscore msgid "Exam timer and end exam button" msgstr "Zeitschaltuhr und Taste zum Beenden der Prüfung" @@ -7981,10 +8182,8 @@ msgstr "Ãœber Sie" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" -"Die folgende Information ist bereits in Ihrem {platform} Profil. Wir haben " -"dies hier eingefügt." #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -8015,6 +8214,10 @@ msgstr "" "{course_name} gestellt haben! Sie können mit einer Antwort in 2-4 Werktagen " "rechnen." +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Zu \"Meine Kurse\"" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "Sammelausnahmen" @@ -8388,14 +8591,6 @@ msgstr "Sie können die Sitzung nicht mehr ändern." msgid "You can change sessions until {expiration_date}." msgstr "Sie können Sitzungen bis zum {expiration_date} ändern." -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "Finale Auswertung" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "für {courseName}" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "Archivierte Kurse anzeigen" @@ -8624,8 +8819,28 @@ msgid "An error occurred. Please reload the page." msgstr "Ein Fehler ist aufgetreten. Bitte lade die Seite erneut." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" -msgstr "Brauchen Sie Hilfe beim anmelden?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" +msgstr "" #: lms/templates/student_account/hinted_login.underscore #: lms/templates/student_account/login.underscore @@ -8844,33 +9059,22 @@ msgid "What You Need for Verification" msgstr "Was du zur Verifizierung benötigst" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Webcam" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" -"Sie benötigen ein Computer oder Handy mit integrierter Webcam. Wenn Sie eine" -" Anfrage über Ihren Browser bekommen, stellen Sie sicher, dass der Zugriff " -"auf die Kamera aktiviert ist." #: lms/templates/verify_student/face_photo_step.underscore msgid "Photo Identification" msgstr "Fotoidentifikation" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"Sie benötigen einen Führerschein, Reisepass oder einen anderen staatlich " -"ausgestellten Lichtbildausweis mit Ihrem Namen und Foto." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8897,19 +9101,11 @@ msgstr "Dein Gesicht ist gut beleuchtet." msgid "Your entire face fits inside the frame." msgstr "Dein ganzes Gesicht passt in den Rahmen." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "" -"Das Foto von deinem Gesicht muss mit dem Foto in deinem Identitätsnachweis " -"übereinstimmen" - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" -"Um das aktuelle Foto zu verwenden, wählen Sie die Kamerataste {icon}. Um ein" -" weiteres Foto aufzunehmen, wählen Sie die Wiederholungs-Taste {icon}." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8925,16 +9121,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Wieso braucht %(platformName)s mein Foto?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"Als teil unsere Ãœberprüfung Prozess brauchen wir ein Foto von ihr Gesicht " -"und ein Bildausweis mit amtlichen Licht. Unser Autorisierungsdienst " -"bestätigt ihre Identität durch das vergleichen von beide Fotos." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8945,18 +9135,12 @@ msgstr "Was macht %(platformName)s mit dieses Foto?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"Wir verwenden die höchste Sicherheit zur Verfügung um das Foto zu " -"verschlüsseln und senden es an unsere Autorisierungsdienst für Kritik. Ihre " -"Fotos und Daten sind nicht gespeichert und auch nicht sichtbar auf " -"%(platformName)s nach das Ãœberprüfung Prozess." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -9029,22 +9213,14 @@ msgid "Take a Photo of Your ID" msgstr "Nehmen Sie ein Foto von ihr Ausweis" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"Benutzen Sie ihre webcam um ein Foto von ihr Ausweis zu nehmen. Wir werden " -"dieses Foto mit das Foto von ihr Gesicht und der Name auf ihr Konto " -"vergleichen." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Sie brauchen ein Ausweis mit ihr Name und Foto. Akzeptierte " -"Identitätsnachweise sind Führerscheine, Reisepässe oder andere Bildausweise " -"mit amtlichen Licht." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -9073,6 +9249,13 @@ msgstr "" "Nutzen Sie den Wiederholungsknopf, wenn Sie unzufrieden mit Ihrer Aufnahme " "sind." +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -9135,6 +9318,29 @@ msgstr "" "Dürfen wir das von dir gemachte Foto mit dem aus deinem Identitätsnachweis " "vergleichen?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"Als teil unsere Ãœberprüfung Prozess brauchen wir ein Foto von ihr Gesicht " +"und ein Bildausweis mit amtlichen Licht. Unser Autorisierungsdienst " +"bestätigt ihre Identität durch das vergleichen von beide Fotos." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"Wir verwenden die höchste Sicherheit zur Verfügung um das Foto zu " +"verschlüsseln und senden es an unsere Autorisierungsdienst für Kritik. Ihre " +"Fotos und Daten sind nicht gespeichert und auch nicht sichtbar auf " +"%(platformName)s nach das Ãœberprüfung Prozess." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -9170,6 +9376,13 @@ msgstr "" "Ein Führerschein, Reisepass, oder ein anderes Bildausweis mit amtliches " "Licht" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Webcam" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -9273,6 +9486,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "Ãœberprüfen Sie Ihre E-Mail auf eine Aktivierungsnachricht." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Gesamt" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "Professionelles Zertifikat für {courseName}" @@ -9319,6 +9537,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "Dankeschön! Wir haben Ihre Zahlung für {courseName} bekommen" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"Bitte drucken Sie diese Seite für Ihre Unterlagen aus, sie dient als Ihre " +"Quittung. Sie erhalten außerdem eine E-Mail mit den gleichen Informationen." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "Bestellnummer" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Summe" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Bitte beachten Sie" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "Gekreuzte Einzelteile wurden erstattet." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Rechnung an" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Keine Quittung verfügbar" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "Als nächstes: Bestätigen Sie ihre Identität" @@ -9354,6 +9604,10 @@ msgstr "" "Kurs erkunden von Ihrem Armaturenbrett. Sie werden regelmäßigen Erinnerungen" " von %(platformName)s erhalten um Ihre Identität zu überprüfen." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "Wollen Sie ihre Identität später bestätigen?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "Verifikation Ihrer Identität in Bearbeitung" @@ -9362,14 +9616,9 @@ msgstr "Verifikation Ihrer Identität in Bearbeitung" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"Wir haben Ihre Informationen erhalten und verifizieren Ihre Identität. Sie " -"werden eine Meldung auf Ihrer 'Meine Kurse' Ãœbersicht sehen, wenn der " -"Verifikationsprozess abgeschlossen ist (normalerweise innerhalb von 1-2 " -"Tagen). In der Zwischenzeit können Sie noch auf alle verfügbaren Kursinhalte" -" zugreifen." #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -9405,10 +9654,6 @@ msgstr "Fotovoraussetzungen:" msgid "Does the photo of you show your whole face?" msgstr "Zeiget das Foto ihr vollständiges Gesicht?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "Passt das Foto zu das Foto auf ihr Ausweis?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "Ist ihr Name auf ihr Ausweis lesbar?" @@ -10950,6 +11195,21 @@ msgstr "Als spezielle Prüfung einstellen" msgid "Exam Types" msgstr "Prüfungsarten" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Terminiert" @@ -11158,14 +11418,14 @@ msgstr "" msgid "Read more" msgstr "Mehr erfahren" -#: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" -msgstr "Transkripte anzeigen ({totalTranscripts})" - #: cms/templates/js/video-transcripts.underscore msgid "No transcript uploaded." msgstr "Kein Transkript hochgeladen." +#: cms/templates/js/video-transcripts.underscore +msgid "Show transcripts ({totalTranscripts})" +msgstr "Transkripte anzeigen ({totalTranscripts})" + #: cms/templates/js/xblock-access-editor.underscore msgid "Set Access" msgstr "Zugriff festlegen" diff --git a/conf/locale/en/LC_MESSAGES/django.po b/conf/locale/en/LC_MESSAGES/django.po index 5a6759e2eff7bcab28c8186c8fa3e4843311ef8e..a42c20f957da55b0a5ff589a0a734de518b19a46 100644 --- a/conf/locale/en/LC_MESSAGES/django.po +++ b/conf/locale/en/LC_MESSAGES/django.po @@ -38,8 +38,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:53+0000\n" -"PO-Revision-Date: 2020-04-12 20:53:38.526475\n" +"POT-Creation-Date: 2020-06-21 20:50+0000\n" +"PO-Revision-Date: 2020-06-21 20:50:24.457974\n" "Last-Translator: \n" "Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n" "Language: en\n" @@ -47,7 +47,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (0.1a) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -72,8 +72,8 @@ msgstr "" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "" @@ -384,12 +384,12 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." +msgid "An account with the Email '{email}' already exists." msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." +msgid "An account with the Public Username '{username}' already exists." msgstr "" #: common/djangoapps/student/management/commands/manage_group.py @@ -1997,7 +1997,7 @@ msgstr "" msgid "Never" msgstr "" -#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/capa_base.py lms/templates/courseware/dates.html msgid "Past Due" msgstr "" @@ -2168,9 +2168,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -3809,12 +3809,12 @@ msgid "" " considered in the Entrance Exam scoring/gating algorithm." msgstr "" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "" @@ -4395,17 +4395,17 @@ msgstr "" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "" @@ -5282,50 +5282,6 @@ msgid "" "this request, please visit the link(s) below." msgstr "" -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "" @@ -5388,11 +5344,23 @@ msgstr "" msgid "You do not have access to this course on a mobile device" msgstr "" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -5412,6 +5380,11 @@ msgstr "" msgid "in {relative} - {absolute}" msgstr "" +#: lms/djangoapps/courseware/date_summary.py +#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py +msgid "Enrollment Date" +msgstr "" + #: lms/djangoapps/courseware/date_summary.py msgid "Course Starts" msgstr "" @@ -6024,9 +5997,8 @@ msgid "Good" msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html @@ -6034,6 +6006,11 @@ msgstr "" msgid "View discussion" msgstr "" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6161,8 +6138,8 @@ msgid "Student" msgstr "" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "" @@ -6278,29 +6255,6 @@ msgstr "" msgid "Could not find problem with this location." msgstr "" -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "" - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "" @@ -6331,9 +6285,8 @@ msgstr "" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "" @@ -6453,54 +6406,6 @@ msgstr "" msgid "The file must contain a 'username' column, an 'email' column, or both." msgstr "" -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -6521,14 +6426,6 @@ msgstr "" msgid "proctored exam results" msgstr "" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -6741,63 +6638,6 @@ msgid "" " try again." msgstr "" -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "" @@ -6906,29 +6746,6 @@ msgstr "" msgid "Incomplete" msgstr "" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "" - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7123,10 +6940,6 @@ msgstr "" msgid "Year of Birth" msgstr "" -#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py -msgid "Enrollment Date" -msgstr "" - #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py msgid "Currently Enrolled" msgstr "" @@ -7325,8 +7138,8 @@ msgstr "" #: lms/djangoapps/learner_dashboard/programs.py #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "" @@ -7938,6 +7751,15 @@ msgstr "" msgid "Currency" msgstr "" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "" @@ -8081,14 +7903,6 @@ msgstr "" msgid "View and regenerate certificates." msgstr "" -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "" - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -8167,43 +7981,8 @@ msgstr "" msgid "User Disabled Successfully" msgstr "" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" msgstr "" #: lms/djangoapps/teams/models.py @@ -8823,8 +8602,8 @@ msgid "Allow" msgstr "" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "" @@ -9206,8 +8985,8 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "" @@ -9243,11 +9022,10 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -9655,6 +9433,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -10026,6 +9808,10 @@ msgstr "" msgid "Schedule start < course start" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "" @@ -10034,6 +9820,15 @@ msgstr "" msgid "Experience" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -10235,6 +10030,7 @@ msgid "" msgstr "" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "" @@ -10464,7 +10260,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -10491,8 +10286,8 @@ msgid "Success" msgstr "" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "" @@ -10653,6 +10448,14 @@ msgstr "" msgid "There was an error receiving your login information. Please email us." msgstr "" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -10669,17 +10472,17 @@ msgstr "" #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" -"As {allowed_domain} user, You must login with your {allowed_domain} " -"{link_start}{provider} account{link_end}." +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"As {allowed_domain} user, You must login with your {allowed_domain} " +"{link_start}{provider} account{link_end}." msgstr "" #. Translators: These instructions appear on the login form, immediately @@ -10697,6 +10500,12 @@ msgstr "" msgid "Create Account" msgstr "" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -10709,6 +10518,11 @@ msgid "" "password." msgstr "" +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "" @@ -10728,11 +10542,6 @@ msgid "" "created. {bold_start}{email}{bold_end} is now your primary login email." msgstr "" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "" @@ -10960,6 +10769,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "" @@ -10978,6 +10799,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "" @@ -11650,8 +11475,8 @@ msgid "Vertical" msgstr "" #: cms/djangoapps/contentstore/views/helpers.py -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "" @@ -11920,6 +11745,18 @@ msgstr "" msgid "Transcript Ready" msgstr "" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "" @@ -12063,8 +11900,8 @@ msgstr "" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "" @@ -12112,14 +11949,14 @@ msgstr "" msgid "Course Run:" msgstr "" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "" @@ -12143,8 +11980,9 @@ msgstr "" msgid "Requirements" msgstr "" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "" @@ -12198,15 +12036,15 @@ msgstr "" msgid "Choose Language" msgstr "" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -12278,8 +12116,8 @@ msgstr "" msgid "Usermenu dropdown" msgstr "" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "" @@ -12441,8 +12279,8 @@ msgstr "" msgid "View all Courses" msgstr "" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "" @@ -12461,8 +12299,8 @@ msgstr "" #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "" @@ -12480,7 +12318,7 @@ msgstr "" msgid "Search Your Courses" msgstr "" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "" @@ -12505,7 +12343,7 @@ msgstr "" msgid "Save Settings" msgstr "" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -12515,8 +12353,86 @@ msgstr "" msgid "Unenroll" msgstr "" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html @@ -12549,7 +12465,7 @@ msgstr "" msgid "You should Register before trying to access the Unit" msgstr "" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "" @@ -12649,7 +12565,7 @@ msgid "" "available on the {link_start}progress page{link_end}." msgstr "" -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "" @@ -12785,17 +12701,15 @@ msgstr "" msgid "working" msgstr "" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" #: lms/templates/module-error.html @@ -12835,7 +12749,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "" #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -12897,28 +12819,6 @@ msgstr "" msgid "Return To %s" msgstr "" -#: lms/templates/reset_deadlines_banner.html -msgid "It looks like you've missed some important deadlines. Visit " -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "edx.org" -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid " to reset your deadlines and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "" @@ -12967,7 +12867,7 @@ msgstr "" msgid "Sequence" msgstr "" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -13096,18 +12996,18 @@ msgstr "" msgid "Reset Learner's Attempts to Zero" msgstr "" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "" @@ -13145,7 +13045,7 @@ msgstr "" msgid "Textbook Navigation" msgstr "" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "" @@ -13256,9 +13156,9 @@ msgstr "" msgid "Recent git load activity for {course_id}" msgstr "" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -13314,7 +13214,7 @@ msgid "" " not mean to do this, {undo_link_start}you can re-subscribe{link_end}." msgstr "" -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "" @@ -13322,8 +13222,8 @@ msgstr "" msgid "More options" msgstr "" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "" @@ -14499,35 +14399,6 @@ msgstr "" msgid "About edX Certificates" msgstr "" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "" - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -14726,11 +14597,11 @@ msgid "This content is graded" msgstr "" #: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." +msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" #: lms/templates/courseware/course_about.html -msgid "An error has occurred. Please ensure that you are logged in to enroll." +msgid "An error occurred. Please try again later." msgstr "" #: lms/templates/courseware/course_about.html @@ -14744,10 +14615,6 @@ msgstr "" msgid "View Course" msgstr "" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "" @@ -14760,10 +14627,6 @@ msgstr "" msgid "Enrollment is Closed" msgstr "" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "" @@ -14885,6 +14748,13 @@ msgstr "" msgid "Courseware" msgstr "" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "" @@ -14913,7 +14783,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -14921,14 +14791,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" msgstr "" -#: lms/templates/courseware/error-message.html -msgid "" -"We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible." +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -15565,7 +15432,7 @@ msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html @@ -15576,7 +15443,7 @@ msgstr "" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html @@ -16251,129 +16118,6 @@ msgid "" "verification process on your dashboard." msgstr "" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -16536,8 +16280,8 @@ msgstr "" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "" @@ -16558,17 +16302,9 @@ msgstr "" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html -msgid "Sysadmin" -msgstr "" - -#: lms/templates/header/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" +msgid "Sysadmin" msgstr "" #: lms/templates/header/navbar-not-authenticated.html @@ -16607,6 +16343,12 @@ msgstr "" msgid "Enter information about the coupon code below." msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "" @@ -17150,6 +16892,11 @@ msgstr "" msgid "Coupon Codes" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "" @@ -18407,6 +18154,10 @@ msgstr "" msgid "Purchase order number (if any)" msgstr "" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "" @@ -18696,6 +18447,10 @@ msgid_plural "" msgstr[0] "" msgstr[1] "" +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "" @@ -18907,46 +18662,6 @@ msgstr "" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "" @@ -19081,7 +18796,7 @@ msgstr "" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" #: lms/templates/verify_student/reverify_not_allowed.html @@ -19645,8 +19360,8 @@ msgid "Already registered?" msgstr "" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "" @@ -19741,9 +19456,7 @@ msgid "The page that you were looking for was not found." msgstr "" #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" #: cms/templates/500.html @@ -19766,10 +19479,6 @@ msgid "" "error as soon as possible." msgstr "" -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "" - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "" @@ -20376,9 +20085,7 @@ msgstr "" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" #: cms/templates/error.html @@ -20389,9 +20096,7 @@ msgstr "" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" #: cms/templates/error.html @@ -23342,8 +23047,8 @@ msgstr "" msgid "%(file)s has been saved." msgstr "" -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "" @@ -23535,8 +23240,8 @@ msgstr "" msgid "Search..." msgstr "" -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "" diff --git a/conf/locale/en/LC_MESSAGES/djangojs.po b/conf/locale/en/LC_MESSAGES/djangojs.po index 2cd2413b0daeb9004e21197998cbd49b8ddbe49f..77c87a018cc1d39e4447210b7eef296152225862 100644 --- a/conf/locale/en/LC_MESSAGES/djangojs.po +++ b/conf/locale/en/LC_MESSAGES/djangojs.po @@ -32,8 +32,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:53+0000\n" -"PO-Revision-Date: 2020-04-12 20:53:38.541186\n" +"POT-Creation-Date: 2020-06-21 20:50+0000\n" +"PO-Revision-Date: 2020-06-21 20:50:24.441486\n" "Last-Translator: \n" "Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n" "Language: en\n" @@ -41,7 +41,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -77,6 +77,7 @@ msgstr "" #: cms/templates/js/signatory-editor.underscore #: cms/templates/js/video-transcripts.underscore #: cms/templates/js/xblock-outline.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Delete" msgstr "" @@ -105,6 +106,7 @@ msgstr "" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -127,6 +129,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -156,6 +159,7 @@ msgstr "" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "" @@ -741,7 +745,6 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "" @@ -788,6 +791,7 @@ msgstr "" #: cms/templates/js/show-textbook.underscore #: cms/templates/js/signatory-details.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Edit" msgstr "" @@ -1190,6 +1194,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "" @@ -1531,6 +1536,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/course-instructor-details.underscore #: cms/templates/js/signatory-details.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Title" msgstr "" @@ -1977,6 +1983,7 @@ msgid "Your request could not be processed. Refresh the page and try again." msgstr "" #: common/static/common/js/discussion/utils.js +#: common/static/common/templates/discussion/templates.underscore msgid "…" msgstr "" @@ -2161,6 +2168,7 @@ msgid "Your post will be discarded." msgstr "" #: common/static/common/js/discussion/views/response_comment_show_view.js +#: common/static/common/templates/discussion/templates.underscore msgid "anonymous" msgstr "" @@ -2420,7 +2428,15 @@ msgid "Other" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx @@ -2428,12 +2444,15 @@ msgid "Details" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx @@ -2441,8 +2460,7 @@ msgid "Sign in to {platform} so we can help you better." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2459,6 +2477,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2482,7 +2512,8 @@ msgstr "" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2662,6 +2693,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "" +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "" @@ -3147,6 +3182,7 @@ msgid "There has been an error processing your survey." msgstr "" #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -3163,6 +3199,7 @@ msgid "HTML preview of post" msgstr "" #: lms/static/js/customwmd.js +#: common/static/common/templates/discussion/templates.underscore msgid "Your question or idea (required)" msgstr "" @@ -5169,6 +5206,10 @@ msgstr "" msgid "certificate" msgstr "" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "" @@ -5180,7 +5221,7 @@ msgid "You have not created any certificates yet." msgstr "" #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" msgstr "" #: cms/static/js/certificates/views/signatory_editor.js @@ -5231,6 +5272,7 @@ msgstr "" #: cms/static/js/factories/manage_users.js #: cms/static/js/factories/manage_users_lib.js +#: common/static/common/templates/discussion/templates.underscore msgid "Staff" msgstr "" @@ -5482,8 +5524,8 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" #: cms/static/js/models/uploads.js @@ -5658,7 +5700,7 @@ msgid "{selectedProvider} credentials saved" msgstr "" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" msgstr "" #: cms/static/js/views/edit_chapter.js @@ -6215,13 +6257,13 @@ msgstr "" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" #: cms/static/js/views/utils/move_xblock_utils.js @@ -6561,13 +6603,13 @@ msgid "Unscheduled" msgstr "" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "" @@ -6615,6 +6657,310 @@ msgstr "" msgid "Search" msgstr "" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "" @@ -6671,10 +7017,6 @@ msgid "" "new, unread activity from posts you are following." msgstr "" -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "" @@ -6908,6 +7250,10 @@ msgstr "" msgid "Join Team" msgstr "" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "" @@ -6992,94 +7338,6 @@ msgstr "" msgid "Remove unit %(unitName)s" msgstr "" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "" @@ -7207,7 +7465,7 @@ msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore @@ -7236,6 +7494,10 @@ msgid "" "{course_name}! You can expect a response in 2-4 business days." msgstr "" +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "" @@ -7572,14 +7834,6 @@ msgstr "" msgid "You can change sessions until {expiration_date}." msgstr "" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "" @@ -7795,7 +8049,27 @@ msgid "An error occurred. Please reload the page." msgstr "" #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -7993,17 +8267,13 @@ msgid "What You Need for Verification" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" +msgid "Device with Camera" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8011,9 +8281,7 @@ msgid "Photo Identification" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8039,14 +8307,10 @@ msgstr "" msgid "Your entire face fits inside the frame." msgstr "" -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "" - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8063,12 +8327,9 @@ msgid "Why does %(platformName)s need my photo?" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8080,13 +8341,11 @@ msgstr "" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8146,15 +8405,13 @@ msgid "Take a Photo of Your ID" msgstr "" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" #: lms/templates/verify_student/id_photo_step.underscore @@ -8179,6 +8436,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8225,6 +8489,22 @@ msgstr "" msgid "Can we match the photo you took with the one on your ID?" msgstr "" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -8253,6 +8533,13 @@ msgid "" "and photo" msgstr "" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8340,6 +8627,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "" +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "" @@ -8377,6 +8669,36 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "" @@ -8405,6 +8727,10 @@ msgid "" "%(platformName)s to verify your identity." msgstr "" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "" @@ -8413,7 +8739,7 @@ msgstr "" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" @@ -8449,10 +8775,6 @@ msgstr "" msgid "Does the photo of you show your whole face?" msgstr "" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "" @@ -9861,6 +10183,21 @@ msgstr "" msgid "Exam Types" msgstr "" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "" @@ -10029,11 +10366,11 @@ msgid "Read more" msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" +msgid "No transcript uploaded." msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "No transcript uploaded." +msgid "Show transcripts ({totalTranscripts})" msgstr "" #: cms/templates/js/xblock-access-editor.underscore diff --git a/conf/locale/eo/LC_MESSAGES/django.mo b/conf/locale/eo/LC_MESSAGES/django.mo index e53818fb5d3d36d30c47c8793639af83b3a00316..26a21d7089000b4e8e1c75794d9b7ccbf784906b 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 53fce78913167541ebbfea7a043d40b1015d4b55..f1e1df5b877203e7cf9ced6b1a4a23445ee4a25c 100644 --- a/conf/locale/eo/LC_MESSAGES/django.po +++ b/conf/locale/eo/LC_MESSAGES/django.po @@ -38,8 +38,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:53+0000\n" -"PO-Revision-Date: 2020-04-12 20:53:38.526475\n" +"POT-Creation-Date: 2020-06-21 20:50+0000\n" +"PO-Revision-Date: 2020-06-21 20:50:24.457974\n" "Last-Translator: \n" "Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n" "Language: eo\n" @@ -47,7 +47,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (0.1a) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -72,8 +72,8 @@ msgstr "Éntränçé Éxäm â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "Ûnït â± 'σÑєм ι#" @@ -445,17 +445,17 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." +msgid "An account with the Email '{email}' already exists." msgstr "" -"Àn äççöünt wïth thé Püßlïç Ûsérnämé '{username}' älréädý éxïsts. â± 'σÑєм " -"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" +"Àn äççöünt wïth thé Émäïl '{email}' älréädý éxïsts. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " +"αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." +msgid "An account with the Public Username '{username}' already exists." msgstr "" -"Àn äççöünt wïth thé Émäïl '{email}' älréädý éxïsts. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " -"αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" +"Àn äççöünt wïth thé Püßlïç Ûsérnämé '{username}' älréädý éxïsts. â± 'σÑєм " +"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2441,7 +2441,7 @@ msgstr "Àlwäýs â± 'σÑєм ιÏÑ•Ï…#" msgid "Never" msgstr "Névér â± 'σÑєм ιÏÑ•#" -#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/capa_base.py lms/templates/courseware/dates.html msgid "Past Due" msgstr "Päst Düé â± 'σÑєм ιÏѕυм ∂#" @@ -2652,9 +2652,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -4953,12 +4953,12 @@ msgstr "" "¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт " "ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι σƒƒι¢ια ∂єѕєÑυηт мσłłιт αηιм ι∂ єѕт łαвσÑυм#" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "Énröllmént Träçk Gröüps â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σ#" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "" "Pärtïtïön för ségméntïng üsérs ßý énröllmént träçk â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " @@ -5739,17 +5739,17 @@ msgstr "Ûnlöçk Àççöünt â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "Çlösé â± 'σÑєм ιÏÑ•#" @@ -6890,63 +6890,6 @@ msgstr "" "À réfünd réqüést häs ßéén ïnïtïätéd för {username} ({email}). Tö pröçéss " "thïs réqüést, pléäsé vïsït thé lïnk(s) ßélöw. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "Réçéïpt â± 'σÑєм ιÏѕυм #" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "Päýmént Fäïléd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "" -"Théré wäs ä prößlém wïth thïs tränsäçtïön. Ãöü hävé nöt ßéén çhärgéd. â± 'σÑєм" -" ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" -"Mäké süré ýöür ïnförmätïön ïs çörréçt, ör trý ägäïn wïth ä dïfférént çärd ör" -" änöthér förm öf päýmént. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" -"À sýstém érrör öççürréd whïlé pröçéssïng ýöür päýmént. Ãöü hävé nöt ßéén " -"çhärgéd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тє#" - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "" -"Pléäsé wäït ä féw mïnütés änd thén trý ägäïn. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "" -"För hélp, çöntäçt {payment_support_link}. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "" -"Àn érrör öççürréd whïlé çréätïng ýöür réçéïpt. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"ÃŒf ýöür çöürsé döés nöt äppéär ön ýöür däshßöärd, çöntäçt " -"{payment_support_link}. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "Éärn ä çértïfïçäté â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" @@ -7018,11 +6961,26 @@ msgstr "" "Ãöü dö nöt hävé äççéss tö thïs çöürsé ön ä mößïlé dévïçé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ " "ѕιт αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" +"Ãöü müst ßé énrölléd ïn thé çöürsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєт#" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" +"Ãöü müst ßé löggéd ïn tö séé thïs çöürsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"¢σηѕє¢тєтυÑ#" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "Ûpgrädé tö Vérïfïéd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "Fïnänçïäl Àssïstänçé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "Àssïgnmént â± 'σÑєм ιÏѕυм ∂σłσ#" @@ -7042,6 +7000,11 @@ msgstr "{relative} ägö - {absolute} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" msgid "in {relative} - {absolute}" msgstr "ïn {relative} - {absolute} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" +#: lms/djangoapps/courseware/date_summary.py +#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py +msgid "Enrollment Date" +msgstr "Énröllmént Däté â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + #: lms/djangoapps/courseware/date_summary.py msgid "Course Starts" msgstr "Çöürsé Stärts â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" @@ -7802,18 +7765,22 @@ msgid "Good" msgstr "Gööd â± 'σÑєм ι#" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" -msgstr "" -"%(comment_username)s réplïéd tö <b>%(thread_title)s</b>: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ " -"ѕιт αмєт, ¢σηѕ#" +msgid "%(comment_username)s replied to" +msgstr "%(comment_username)s réplïéd tö â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt msgid "View discussion" msgstr "Vïéw dïsçüssïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "" +"%(comment_username)s réplïéd tö <b>%(thread_title)s</b>: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ " +"ѕιт αмєт, ¢σηѕ#" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -7985,8 +7952,8 @@ msgid "Student" msgstr "Stüdént â± 'σÑєм ιÏѕυм #" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "Stäff â± 'σÑєм ιÏÑ•#" @@ -8128,37 +8095,6 @@ msgstr "" "Çöüld nöt fïnd prößlém wïth thïs löçätïön. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " "Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "" -"ÃŒnvöïçé nümßér '{num}' döés nöt éxïst. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"¢σηѕє¢тєтυ#" - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "" -"Thé sälé ässöçïätéd wïth thïs ïnvöïçé häs älréädý ßéén ïnvälïdätéd. â± 'σÑєм " -"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "" -"ÃŒnvöïçé nümßér {0} häs ßéén ïnvälïdätéd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"¢σηѕє¢тєтυÑ#" - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "Thïs ïnvöïçé ïs älréädý äçtïvé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "" -"Thé régïsträtïön çödés för ïnvöïçé {0} hävé ßéén ré-äçtïvätéd. â± 'σÑєм ιÏѕυм " -"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "ÇöürséÌD â± 'σÑєм ιÏѕυм ∂#" @@ -8189,9 +8125,8 @@ msgstr "Ûsér ÃŒD â± 'σÑєм ιÏѕυм #" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "Ûsérnämé â± 'σÑєм ιÏѕυм ∂#" @@ -8315,54 +8250,6 @@ msgstr "" "Thé fïlé müst çöntäïn ä 'üsérnämé' çölümn, än 'émäïl' çölümn, ör ßöth. " "â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "Çöüpön Çödé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "Çöürsé ÃŒd â± 'σÑєм ιÏѕυм ∂σł#" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% Dïsçöünt â± 'σÑєм ιÏѕυм ∂σłσ#" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "Désçrïptïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "Éxpïrätïön Däté â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "ÃŒs Àçtïvé â± 'σÑєм ιÏѕυм ∂σł#" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "Çödé Rédééméd Çöünt â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "Tötäl Dïsçöüntéd Séäts â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "Tötäl Dïsçöüntéd Àmöünt â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σ#" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -8383,17 +8270,6 @@ msgstr "sürvéý â± 'σÑєм ιÏÑ•Ï…#" msgid "proctored exam results" msgstr "pröçtöréd éxäm résülts â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "" -"Çöüld nöt pärsé ämöünt äs ä déçïmäl â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєт#" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" -"Ûnäßlé tö généräté rédéém çödés ßéçäüsé öf çöürsé mïsçönfïgürätïön. â± 'σÑєм " -"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -8696,83 +8572,6 @@ msgstr "" "νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт " "¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι σƒƒι¢ια ∂єѕєÑυηт мσłłιт αηι#" -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "çöüpön ïd ïs Nöné â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "" -"çöüpön wïth thé çöüpön ïd ({coupon_id}) DöésNötÉxïst â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " -"αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "" -"çöüpön wïth thé çöüpön ïd ({coupon_id}) ïs älréädý ïnäçtïvé â± 'σÑєм ιÏѕυм " -"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "" -"çöüpön wïth thé çöüpön ïd ({coupon_id}) üpdätéd süççéssfüllý â± 'σÑєм ιÏѕυм " -"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" -"Thé çödé ({code}) thät ýöü hävé trïéd tö défïné ïs älréädý ïn üsé äs ä " -"régïsträtïön çödé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢#" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "" -"Pléäsé Éntér thé ÃŒntégér Välüé för Çöüpön Dïsçöünt â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " -"αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "" -"Pléäsé Éntér thé Çöüpön Dïsçöünt Välüé Léss thän ör Éqüäl tö 100 â± 'σÑєм " -"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "" -"Pléäsé éntér thé däté ïn thïs förmät ï-é mönth/däý/ýéär â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ " -"ѕιт αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "" -"çöüpön wïth thé çöüpön çödé ({code}) äddéd süççéssfüllý â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ " -"ѕιт αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "" -"çöüpön wïth thé çöüpön çödé ({code}) älréädý éxïsts för thïs çöürsé â± 'σÑєм " -"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "çöüpön ïd nöt föünd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "" -"çöüpön wïth thé çöüpön ïd ({coupon_id}) üpdätéd Süççéssfüllý â± 'σÑєм ιÏѕυм " -"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "ÃŒnstrüçtör â± 'σÑєм ιÏѕυм ∂σłσ#" @@ -8892,39 +8691,6 @@ msgstr "Çömplété â± 'σÑєм ιÏѕυм ∂#" msgid "Incomplete" msgstr "ÃŒnçömplété â± 'σÑєм ιÏѕυм ∂σłσ#" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "" -"Thé énröllmént çödé ({code}) wäs nöt föünd för thé {course_name} çöürsé. " -"â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "" -"Thïs énröllmént çödé häs ßéén çänçéléd. ÃŒt çän nö löngér ßé üséd. â± 'σÑєм " -"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "" -"Thïs énröllmént çödé häs ßéén märkéd äs ünüséd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт," -" Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "" -"Thé énröllmént çödé häs ßéén réstöréd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"¢σηѕє¢тєтυÑ#" - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "" -"Thé rédémptïön döés nöt éxïst ägäïnst énröllmént çödé ({code}). â± 'σÑєм ιÏѕυм" -" âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -9151,10 +8917,6 @@ msgstr "Tïtlé â± 'σÑєм ιÏÑ•#" msgid "Year of Birth" msgstr "Ãéär öf Bïrth â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" -#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py -msgid "Enrollment Date" -msgstr "Énröllmént Däté â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" - #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py msgid "Currently Enrolled" msgstr "Çürréntlý Énrölléd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" @@ -9394,8 +9156,8 @@ msgstr " (öüt öf {total}) â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" #: lms/djangoapps/learner_dashboard/programs.py #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Prögräms â± 'σÑєм ιÏѕυм ∂#" @@ -10245,6 +10007,15 @@ msgstr "Tötäl Çöst â± 'σÑєм ιÏѕυм ∂σłσ#" msgid "Currency" msgstr "Çürrénçý â± 'σÑєм ιÏѕυм ∂#" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "Désçrïptïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "Çömménts â± 'σÑєм ιÏѕυм ∂#" @@ -10413,16 +10184,6 @@ msgid "View and regenerate certificates." msgstr "" "Vïéw änd régénéräté çértïfïçätés. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тє#" -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "Mänüäl Réfünd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "" -"Träçk réfünds ïssüéd dïréçtlý thröügh ÇýßérSöürçé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " -"αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -10512,49 +10273,9 @@ msgstr "Ûsér Énäßléd Süççéssfüllý â± 'σÑєм ιÏѕυм ∂σłσ msgid "User Disabled Successfully" msgstr "Ûsér Dïsäßléd Süççéssfüllý â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕ#" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "Émäïl Àddréss â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "Çöürsé ÃŒD â± 'σÑєм ιÏѕυм ∂σł#" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "Ûsér nöt föünd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "" -"Çöürsé {course_id} nöt päst thé réfünd wïndöw. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"¢σηѕє¢тєтυÑ#" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "" -"Nö ördér föünd för {user} ïn çöürsé {course_id} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт," -" ¢σηѕє¢тєтυ#" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "Ûnénrölléd {user} fröm {course_id} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σ#" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "" -"Réfündéd {cost} för ördér ïd {order_id} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢#" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "Ãöü müst çömplété ä sürvéý â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕ#" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -11352,8 +11073,8 @@ msgid "Allow" msgstr "Àllöw â± 'σÑєм ιÏÑ•#" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "Érrör â± 'σÑєм ιÏÑ•#" @@ -11799,8 +11520,8 @@ msgstr "" " hélp. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "Àttäçhménts â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" @@ -11838,11 +11559,10 @@ msgstr "" "ön öthér ärtïçlés whïçh mäý ör mäý nöt ßé ä gööd thïng. â± #" #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -12342,6 +12062,10 @@ msgstr "" "Çönfïgürätïön mäý nöt ßé spéçïfïéd ät möré thän öné lévél ät önçé. â± 'σÑєм " "ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "Léärnïng Séqüénçés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -12857,6 +12581,10 @@ msgstr "Knöwn Érrör Çäsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" msgid "Schedule start < course start" msgstr "Sçhédülé stärt < çöürsé stärt â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢#" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "Çöürsé ÃŒd â± 'σÑєм ιÏѕυм ∂σł#" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "Àll â± 'σÑєм#" @@ -12865,6 +12593,15 @@ msgstr "Àll â± 'σÑєм#" msgid "Experience" msgstr "Éxpérïénçé â± 'σÑєм ιÏѕυм ∂σłσ#" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "Çöürsé ÃŒD â± 'σÑєм ιÏѕυм ∂σł#" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -13156,6 +12893,7 @@ msgstr "" " ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢α#" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "Ûpgrädé nöw â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" @@ -13447,7 +13185,6 @@ msgstr "" "¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι σƒƒι¢ια ∂єѕєÑυηт мσłłιт αηιм ι∂#" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -13476,8 +13213,8 @@ msgid "Success" msgstr "Süççéss â± 'σÑєм ιÏѕυм #" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "Àçtïöns â± 'σÑєм ιÏѕυм #" @@ -13689,6 +13426,23 @@ msgstr "" "Théré wäs än érrör réçéïvïng ýöür lögïn ïnförmätïön. Pléäsé émäïl üs. â± 'σÑєм" " ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" +"Tö prötéçt ýöür äççöünt, ït’s ßéén témpörärïlý löçkéd. Trý ägäïn ïn " +"{locked_out_period} mïnütés.{li_start}Tö ßé ön thé säfé sïdé, ýöü çän rését " +"ýöür pässwörd {link_start}héré{link_end} ßéföré ýöü trý ägäïn. â± 'σÑєм ιÏѕυм " +"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ " +"ιη¢ι∂ι∂υηт Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ " +"ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ " +"¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє " +"¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт " +"ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι σƒƒι¢#" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -13713,6 +13467,24 @@ msgstr "" "Töö mäný fäïléd lögïn ättémpts. Trý ägäïn lätér. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " "αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" +"Émäïl ör pässwörd ïs ïnçörréçt.{li_start}Ãöü hävé {remaining_attempts} möré " +"sïgn-ïn ättémpts ßéföré ýöür äççöünt ïs témpörärïlý " +"löçkéd.{li_end}{li_start}ÃŒf ýöü'vé förgöttén ýöür pässwörd, çlïçk " +"{link_start}héré{link_end} tö rését.{li_end} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт " +"∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση " +"υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” " +"âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα" +" ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт#" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -13723,15 +13495,6 @@ msgstr "" "{link_start}{provider} äççöünt{link_end}. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " "Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "üsérnämé@dömäïn.çöm â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -13749,6 +13512,12 @@ msgstr "" msgid "Create Account" msgstr "Çréäté Àççöünt â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "üsérnämé@dömäïn.çöm â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -13765,6 +13534,13 @@ msgstr "" "Thé üsér äççöünt ässöçïätéd wïth thïs é-mäïl äddréss çännöt rését thé " "pässwörd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєт#" +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" +"Ãöür prévïöüs réqüést ïs ïn prögréss, pléäsé trý ägäïn ïn ä féw möménts. " +"â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєтυÑ#" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "Pässwörd rését ünsüççéssfül â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє#" @@ -13790,13 +13566,6 @@ msgstr "" "çréätéd. {bold_start}{email}{bold_end} ïs nöw ýöür prïmärý lögïn émäïl. " "â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ #" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" -"Ãöür prévïöüs réqüést ïs ïn prögréss, pléäsé trý ägäïn ïn ä féw möménts. " -"â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєтυÑ#" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "" @@ -14087,6 +13856,21 @@ msgstr "" "Ûsérnämé çréätéd för Vïdéö Pïpélïné ÃŒntégrätïön, é.g. védä_sérvïçé_üsér. " "â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєтυÑ#" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" +"Öäüth çlïént nämé öf VÉM sérvïçé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тє#" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "vïdéö énçödé mänägér ÀPÃŒ ÛRL. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢#" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" +"Ûsérnämé çréätéd för VÉM ÃŒntégrätïön, é.g. vém_sérvïçé_üsér. â± 'σÑєм ιÏѕυм " +"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "Förçé Ön â± 'σÑєм ιÏѕυм ∂#" @@ -14109,6 +13893,12 @@ msgstr "" "Thïs çöntént ïs önlý äççéssïßlé tö énrölléd léärnérs. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ " "ѕιт αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" +"Thé äßöüt mé fïéld müst ßé ät möst {} çhäräçtérs löng. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ " +"ѕιт αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "Thïs välüé ïs ïnvälïd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" @@ -14997,8 +14787,8 @@ msgid "Vertical" msgstr "Vértïçäl â± 'σÑєм ιÏѕυм ∂#" #: cms/djangoapps/contentstore/views/helpers.py -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "Séçtïön â± 'σÑєм ιÏѕυм #" @@ -15319,6 +15109,18 @@ msgstr "Tränsçrïptïön ïn Prögréss â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ• msgid "Transcript Ready" msgstr "Tränsçrïpt Réädý â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "Pärtïäl Fäïlüré â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "Tränsçrïpt Fäïléd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "Àn ïmägé fïlé ïs réqüïréd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕ#" @@ -15485,8 +15287,8 @@ msgstr "Çöntént â± 'σÑєм ιÏѕυм #" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "Séttïngs â± 'σÑєм ιÏѕυм ∂#" @@ -15534,14 +15336,14 @@ msgstr "Çöürsé Nümßér: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" msgid "Course Run:" msgstr "Çöürsé Rün: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "Çöürsés â± 'σÑєм ιÏѕυм #" @@ -15565,8 +15367,9 @@ msgstr "ÃŒnstrüçtörs â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" msgid "Requirements" msgstr "Réqüïréménts â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "Détäïls â± 'σÑєм ιÏѕυм #" @@ -15622,15 +15425,15 @@ msgstr "" msgid "Choose Language" msgstr "Çhöösé Längüägé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "Àççöünt â± 'σÑєм ιÏѕυм #" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -15709,8 +15512,8 @@ msgstr "Ûsérménü â± 'σÑєм ιÏѕυм ∂#" msgid "Usermenu dropdown" msgstr "Ûsérménü dröpdöwn â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "Sïgn Öüt â± 'σÑєм ιÏѕυм ∂#" @@ -15888,8 +15691,8 @@ msgstr "Stärts: {date} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" msgid "View all Courses" msgstr "Vïéw äll Çöürsés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "Däshßöärd â± 'σÑєм ιÏѕυм ∂σł#" @@ -15911,8 +15714,8 @@ msgstr "" #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "Éxplöré çöürsés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" @@ -15930,7 +15733,7 @@ msgstr "Çöürsé-löädïng érrörs â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹ msgid "Search Your Courses" msgstr "Séärçh Ãöür Çöürsés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "Çléär séärçh â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" @@ -15943,31 +15746,158 @@ msgstr "Skïp tö lïst öf ännöünçéménts â± 'σÑєм ιÏѕυм ∂σł msgid "Account Status Info" msgstr "Àççöünt Stätüs ÃŒnfö â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" -#: lms/templates/dashboard.html themes/edx.org/lms/templates/dashboard.html -msgid "Email Settings for {course_number}" -msgstr "Émäïl Séttïngs för {course_number} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" +#: lms/templates/dashboard.html themes/edx.org/lms/templates/dashboard.html +msgid "Email Settings for {course_number}" +msgstr "Émäïl Séttïngs för {course_number} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" + +#: lms/templates/dashboard.html themes/edx.org/lms/templates/dashboard.html +msgid "Receive course emails" +msgstr "Réçéïvé çöürsé émäïls â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" + +#: lms/templates/dashboard.html themes/edx.org/lms/templates/dashboard.html +msgid "Save Settings" +msgstr "Sävé Séttïngs â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" + +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html +#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_entitlement_actions.html +#: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/instructor/instructor_dashboard_2/membership.html +#: themes/edx.org/lms/templates/dashboard.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +msgid "Unenroll" +msgstr "Ûnénröll â± 'σÑєм ιÏѕυм ∂#" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" +"ÃŒt lööks lïké ýöü mïsséd sömé ïmpörtänt déädlïnés ßäséd ön öür süggéstéd " +"sçhédülé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" +"Tö kéép ýöürsélf ön träçk, ýöü çän üpdäté thïs sçhédülé änd shïft thé päst " +"düé ässïgnménts ïntö thé fütüré ßý vïsïtïng â± 'σÑєм ιÏѕυм#" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" +" Dön't wörrý—ýöü wön't lösé äný öf thé prögréss ýöü'vé mädé whén ýöü shïft " +"ýöür düé dätés. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕ#" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" +"ÃŒt lööks lïké ýöü mïsséd sömé ïmpörtänt déädlïnés ßäséd ön öür süggéstéd " +"sçhédülé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тє#" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" +"Tö kéép ýöürsélf ön träçk, ýöü çän üpdäté thïs sçhédülé änd shïft thé päst " +"düé ässïgnménts ïntö thé fütüré. Dön't wörrý—ýöü wön't lösé äný öf thé " +"prögréss ýöü'vé mädé whén ýöü shïft ýöür düé dätés. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " +"αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ " +"łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ " +"єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ " +"αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ " +"Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι#" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "Shïft düé dätés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "Ãöü äré äüdïtïng thïs çöürsé, â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢#" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" +" whïçh méäns thät ýöü äré ünäßlé tö pärtïçïpäté ïn grädéd ässïgnménts. " +"â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" +" ÃŒt lööks lïké ýöü mïsséd sömé ïmpörtänt déädlïnés ßäséd ön öür süggéstéd " +"sçhédülé. Grädéd ässïgnménts änd sçhédülé ädjüstmént äré äväïläßlé tö " +"Vérïfïéd Träçk léärnérs. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ " +"α∂ιÏιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα" +" αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ " +"ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· " +"ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα " +"ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι " +"域#" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" +" ÃŒt lööks lïké ýöü mïsséd sömé ïmpörtänt déädlïnés ßäséd ön öür süggéstéd " +"sçhédülé. Tö çömplété grädéd ässïgnménts äs pärt öf thïs çöürsé änd shïft " +"thé päst düé ässïgnménts ïntö thé fütüré, ýöü çän üpgrädé tödäý. â± 'σÑєм " +"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ " +"ιη¢ι∂ι∂υηт Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ " +"ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ " +"¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє " +"¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ¢є#" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "Ûpgrädé tö shïft düé dätés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕ#" -#: lms/templates/dashboard.html themes/edx.org/lms/templates/dashboard.html -msgid "Receive course emails" -msgstr "Réçéïvé çöürsé émäïls â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" +"Grädéd ässïgnménts äré äväïläßlé tö Vérïfïéd Träçk léärnérs. â± 'σÑєм ιÏѕυм " +"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" -#: lms/templates/dashboard.html themes/edx.org/lms/templates/dashboard.html -msgid "Save Settings" -msgstr "Sävé Séttïngs â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" +" Tö çömplété grädéd ässïgnménts äs pärt öf thïs çöürsé, ýöü çän üpgrädé " +"tödäý. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєт#" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html -#: lms/templates/dashboard/_dashboard_course_listing.html -#: lms/templates/dashboard/_dashboard_entitlement_actions.html -#: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html -#: lms/templates/instructor/instructor_dashboard_2/membership.html -#: themes/edx.org/lms/templates/dashboard.html -#: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html -msgid "Unenroll" -msgstr "Ûnénröll â± 'σÑєм ιÏѕυм ∂#" +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" +"Wé'vé ßüïlt ä süggéstéd sçhédülé tö hélp ýöü stäý ön träçk. â± 'σÑєм ιÏѕυм " +"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "Vïéw Ûnït ïn Stüdïö â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" +"Büt dön't wörrý—ït's fléxïßlé sö ýöü çän léärn ät ýöür öwn päçé. ÃŒf ýöü " +"häppén tö fäll ßéhïnd ön öür süggéstéd dätés, ýöü'll ßé äßlé tö ädjüst thém " +"tö kéép ýöürsélf ön träçk. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ " +"α∂ιÏιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα" +" αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ " +"ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· " +"ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα " +"ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα#" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -16009,7 +15939,7 @@ msgstr "" "Ãöü shöüld Régïstér ßéföré trýïng tö äççéss thé Ûnït â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " "αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "Énröll â± 'σÑєм ιÏÑ•Ï…#" @@ -16133,7 +16063,7 @@ msgstr "" "Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт " "ιη ¢υłÏα qυι σƒƒι¢ια#" -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "Séärçh för ä çöürsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" @@ -16303,29 +16233,20 @@ msgstr "(rélöäd ýöür pägé tö réfrésh) â± 'σÑєм ιÏѕυм ∂σł msgid "working" msgstr "wörkïng â± 'σÑєм ιÏѕυм #" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "" "Théré häs ßéén än érrör ön thé {platform_name} sérvérs â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ " "ѕιт αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" "Wé'ré sörrý, thïs mödülé ïs témpörärïlý ünäväïläßlé. Öür stäff ïs wörkïng tö" -" fïx ït äs söön äs pössïßlé. Pléäsé émäïl üs ät {tech_support_email} tö " -"répört äný prößléms ör döwntïmé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ " -"α∂ιÏιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα" -" αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ " -"ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· " -"ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα " -"ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι " -"σƒƒι¢ια ∂є#" +" fïx ït äs söön äs pössïßlé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ #" #: lms/templates/module-error.html msgid "Raw data:" @@ -16366,10 +16287,16 @@ msgstr "" "âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" -msgstr "" -"Vïéw thïs ünït ïn thé néw éxpérïénçé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"¢σηѕє¢тєтυ#" +msgid "View in the new experience" +msgstr "Vïéw ïn thé néw éxpérïénçé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕ#" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "Vïéw ïn Stüdïö â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" + +#: lms/templates/preview_menu.html +msgid "View in Insights" +msgstr "Vïéw ïn ÃŒnsïghts â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" #: lms/templates/problem.html msgid "You have used {num_used} of {num_total} attempt" @@ -16447,34 +16374,6 @@ msgstr "É-mäïl â± 'σÑєм ιÏÑ•Ï…#" msgid "Return To %s" msgstr "Rétürn Tö %s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" -#: lms/templates/reset_deadlines_banner.html -msgid "It looks like you've missed some important deadlines. Visit " -msgstr "" -"ÃŒt lööks lïké ýöü'vé mïsséd sömé ïmpörtänt déädlïnés. Vïsït â± 'σÑєм ιÏѕυм " -"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/templates/reset_deadlines_banner.html -msgid "edx.org" -msgstr "édx.örg â± 'σÑєм ιÏѕυм #" - -#: lms/templates/reset_deadlines_banner.html -msgid " to reset your deadlines and get started today." -msgstr "" -" tö rését ýöür déädlïnés änd gét stärtéd tödäý. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт," -" Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" -"ÃŒt lööks lïké ýöü'vé mïsséd sömé ïmpörtänt déädlïnés. Rését ýöür déädlïnés " -"änd gét stärtéd tödäý. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "Rését mý déädlïnés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "Ré-süßsçrïßé Süççéssfül! â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢ση#" @@ -16532,7 +16431,7 @@ msgstr "Néxt â± 'σÑєм ι#" msgid "Sequence" msgstr "Séqüénçé â± 'σÑєм ιÏѕυм ∂#" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "Çömplétéd â± 'σÑєм ιÏѕυм ∂σł#" @@ -16674,18 +16573,18 @@ msgid "Reset Learner's Attempts to Zero" msgstr "" "Rését Léärnér's Àttémpts tö Zérö â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тє#" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "Délété Léärnér's Stäté â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "Résçöré Léärnér's Süßmïssïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢#" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "Résçöré Önlý ÃŒf Sçöré ÃŒmprövés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" @@ -16723,7 +16622,7 @@ msgstr "{course_number} Téxtßöök â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" msgid "Textbook Navigation" msgstr "Téxtßöök Nävïgätïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "Pägé â± 'σÑєм ι#" @@ -16845,9 +16744,9 @@ msgstr "" "Réçént gït löäd äçtïvïtý för {course_id} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " "¢σηѕє¢тє#" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -16916,7 +16815,7 @@ msgstr "" "¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт " "ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι σƒƒι¢ια ∂єѕ#" -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "Däshßöärd för: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" @@ -16924,8 +16823,8 @@ msgstr "Däshßöärd för: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" msgid "More options" msgstr "Möré öptïöns â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "Möré Öptïöns â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" @@ -18557,48 +18456,6 @@ msgstr "" msgid "About edX Certificates" msgstr "Àßöüt édX Çértïfïçätés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "Çhéçköüt Çänçélléd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"Ãöür tränsäçtïön häs ßéén çänçélléd. ÃŒf ýöü féél än érrör häs öççürréd, " -"çöntäçt {email}. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "Çhéçköüt Érrör â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" -"Àn érrör häs öççürréd wïth ýöür päýmént. {b_start}Ãöü hävé nöt ßéén " -"çhärgéd.{b_end} Pléäsé trý tö süßmït ýöür päýmént ägäïn. ÃŒf thïs prößlém " -"pérsïsts, çöntäçt {email}. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ " -"α∂ιÏιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα" -" αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ " -"ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· " -"ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα " -"ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι " -"σƒƒι¢ια ∂єѕєÑυηт мσłłι#" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "Löädïng Ördér Dätä... â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "" -"Pléäsé wäït whïlé wé rétrïévé ýöür ördér détäïls. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " -"αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -18876,18 +18733,18 @@ msgstr "{section_format} düé {{date}} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" msgid "This content is graded" msgstr "Thïs çöntént ïs grädéd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "" -"Àn érrör öççürréd. Pléäsé trý ägäïn lätér. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" "Àn érrör häs öççürréd. Pléäsé énsüré thät ýöü äré löggéd ïn tö énröll. " "â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "" +"Àn érrör öççürréd. Pléäsé trý ägäïn lätér. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "Ãöü äré énrölléd ïn thïs çöürsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" @@ -18899,12 +18756,6 @@ msgstr "Ãöü äré énrölléd ïn thïs çöürsé â± 'σÑєм ιÏѕυм msgid "View Course" msgstr "Vïéw Çöürsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" -"Thïs çöürsé ïs ïn ýöür {start_cart_link}çärt{end_cart_link}. â± 'σÑєм ιÏѕυм " -"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєт#" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "Çöürsé ïs füll â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" @@ -18919,12 +18770,6 @@ msgstr "" msgid "Enrollment is Closed" msgstr "Énröllmént ïs Çlöséd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" -"Àdd {course_name} tö Çärt {start_span}({price} ÛSD){end_span} â± 'σÑєм ιÏѕυм " -"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "Énröll Nöw â± 'σÑєм ιÏѕυм ∂σłσ#" @@ -19059,6 +18904,15 @@ msgstr "Çöürsé Ûtïlïtïés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α msgid "Courseware" msgstr "Çöürséwäré â± 'σÑєм ιÏѕυм ∂σłσ#" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" +"Wé'ré sörrý, thïs mödülé ïs témpörärïlý ünäväïläßlé. Öür stäff ïs wörkïng tö" +" fïx ït äs söön äs pössïßlé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "Çöürsé Séärçh â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" @@ -19095,27 +18949,20 @@ msgid "Important Dates" msgstr "ÃŒmpörtänt Dätés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" #: lms/templates/courseware/dates.html -msgid "Due Today" -msgstr "Düé Tödäý â± 'σÑєм ιÏѕυм ∂σł#" +msgid "Today" +msgstr "Tödäý â± 'σÑєм ιÏÑ•#" #: lms/templates/courseware/dates.html msgid "Verified Only" msgstr "Vérïfïéd Önlý â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." -msgstr "" -"{a_start}Ûpgrädé{a_end}{space}tö ä Vérïfïéd Çértïfïçäté för füll äççéss. " -"â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" +msgid "Due Next" +msgstr "Düé Néxt â± 'σÑєм ιÏѕυм ∂#" -#: lms/templates/courseware/error-message.html -msgid "" -"We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible." -msgstr "" -"Wé'ré sörrý, thïs mödülé ïs témpörärïlý ünäväïläßlé. Öür stäff ïs wörkïng tö" -" fïx ït äs söön äs pössïßlé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" +#: lms/templates/courseware/dates.html +msgid "Not yet released" +msgstr "Nöt ýét réléäséd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" #: lms/templates/courseware/gradebook.html msgid "Gradebook" @@ -19905,10 +19752,10 @@ msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" "Ãöü wïll séé ä méssägé ön ýöür däshßöärd whén thé vérïfïçätïön pröçéss ïs " -"çömplété (üsüällý wïthïn 1-2 däýs). â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" +"çömplété (üsüällý wïthïn 5-7 däýs). â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -19920,11 +19767,11 @@ msgstr "" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" "Ãöü hävé süßmïttéd ýöür révérïfïçätïön ïnförmätïön. Ãöü wïll séé ä méssägé " "ön ýöür däshßöärd whén thé vérïfïçätïön pröçéss ïs çömplété (üsüällý wïthïn " -"1-2 däýs). â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ" +"5-7 däýs). â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ" " єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ " "мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ " "єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє " @@ -20785,169 +20632,6 @@ msgstr "" "υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” " "âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ι#" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "" -"Thänk ýöü för pürçhäsïng énröllménts ïn {course_name}. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ " -"ѕιт αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"Àn ïnvöïçé för {currency_symbol}{total_price} ïs ättäçhéd. Päýmént ïs düé " -"üpön réçéïpt. Ãöü çän fïnd ïnförmätïön äßöüt päýmént méthöds ön thé ïnvöïçé." -" â± 'σÑєм#" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -"À .çsv fïlé thät lïsts ýöür énröllmént çödés ïs ättäçhéd. Ãöü çän üsé thé " -"émäïl témpläté ßélöw tö dïstrïßüté énröllmént çödés tö ýöür stüdénts. Éäçh " -"stüdént müst üsé ä sépäräté énröllmént çödé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт " -"∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση " -"υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” " -"âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα" -" ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт #" - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"Thänks,\n" -"Thé {platform_name} Téäm â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "Déär [[Nämé]]: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"Wé hävé prövïdéd ä çöürsé énröllmént çödé för ýöü ïn {course_name}. Tö " -"énröll ïn thé çöürsé, çlïçk thé föllöwïng lïnk: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "" -"HTML lïnk fröm thé ättäçhéd ÇSV fïlé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"¢σηѕє¢тєтυ#" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"Àftér ýöü énröll, ýöü çän séé thé çöürsé ön ýöür stüdént däshßöärd. Ãöü çän " -"séé çöürsé mätérïäls äftér thé çöürsé stärt däté. â± 'σÑєм #" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"Sïnçérélý,\n" -"[[Ãöür Sïgnätüré]] â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "ÃŒNVÖÌÇÉ â± 'σÑєм ιÏѕυм #" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "Däté: {date} â± 'σÑєм ιÏѕυм ∂σł#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "ÃŒnvöïçé Nö: {invoice_number} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "Térms: Düé Ûpön Réçéïpt â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σ#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "Düé Däté: {date} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "Bïll tö: â± 'σÑєм ιÏѕυм ∂#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "" -"Çüstömér Référénçé Nümßér: {reference_number} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"¢σηѕє¢т#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "" -"Bälänçé Düé: {currency_symbol}{sale_price} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "Çöürsé: {course_name} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"Prïçé: {currency_symbol}{course_price} Qüäntïtý: {quantity} " -"Süß-Tötäl: {currency_symbol}{sub_total} Dïsçöünt: " -"{currency_symbol}{discount} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тє#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "" -"Tötäl: {currency_symbol}{sale_price} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "Päýmént ÃŒnstrüçtïöns â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"ÃŒf wé dö nöt réçéïvé päýmént, thé léärnér énröllménts thät üsé thésé çödés " -"wïll ßé çänçéléd änd léärnérs wïll nöt ßé äßlé tö äççéss çöürsé mätérïäls. " -"Àll pürçhäsés äré fïnäl. För möré ïnförmätïön, séé thé {site_name} " -"çänçéllätïön pölïçý. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg " -"єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ " -"єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ " -"αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη " -"νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” Ñ”#" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "" -"För päýmént qüéstïöns, çöntäçt {contact_email} â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"¢σηѕє¢тєт#" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -21209,8 +20893,8 @@ msgstr "Àpplý för Fïnänçïäl Àssïstänçé â± 'σÑєм ιÏѕυм ∂ #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} Hömé Pägé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" @@ -21234,19 +20918,11 @@ msgstr "Dïsçövér Néw â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "Sýsädmïn â± 'σÑєм ιÏѕυм ∂#" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "Shöppïng Çärt â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "Süppléméntäl Lïnks â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" @@ -21285,6 +20961,12 @@ msgstr "" "Éntér ïnförmätïön äßöüt thé çöüpön çödé ßélöw. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " "Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "Çöüpön Çödé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "Dïsçöünt Pérçéntägé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" @@ -22010,6 +21692,11 @@ msgstr "Döwnlöäd Çöüpön Çödés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹ msgid "Coupon Codes" msgstr "Çöüpön Çödés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "Éxpïrätïön Däté â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "Çöüpön (%) â± 'σÑєм ιÏѕυм ∂σłσ#" @@ -23591,6 +23278,10 @@ msgstr "Pürçhäsïng örgänïzätïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ• msgid "Purchase order number (if any)" msgstr "Pürçhäsé ördér nümßér (ïf äný) â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "Émäïl Àddréss â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "émäïl@éxämplé.çöm â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" @@ -23954,6 +23645,10 @@ msgstr[1] "" "{course_names} hävé ßéén rémövéd ßéçäüsé thé énröllmént pérïöd häs çlöséd. " "â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "Shöppïng Çärt â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "Çövér ÃŒmägé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" @@ -24195,46 +23890,6 @@ msgstr "Stüdént Süppört: Mänägé Ûsér â± 'σÑєм ιÏѕυм ∂σłσ msgid "Program Enrollments Inspector" msgstr "Prögräm Énröllménts ÃŒnspéçtör â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢#" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "Àßöüt tö réfünd thïs ördér: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє#" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "Ördér ÃŒd: â± 'σÑєм ιÏѕυм ∂σł#" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "Énröllmént: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "énrölléd â± 'σÑєм ιÏѕυм ∂#" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "ünénrölléd â± 'σÑєм ιÏѕυм ∂σłσ#" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "Çöst: â± 'σÑєм ιÏÑ•#" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "ÇértïfïçätéÌtém Stätüs: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σ#" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "Ördér Stätüs: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "Fülfïlléd Tïmé: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "Réfünd Réqüést Tïmé: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "Ûsér Sürvéý â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" @@ -24410,11 +24065,11 @@ msgstr "ÃŒdéntïtý Vérïfïçätïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ• msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" "Ãöü hävé älréädý süßmïttéd ýöür vérïfïçätïön ïnförmätïön. Ãöü wïll séé ä " "méssägé ön ýöür däshßöärd whén thé vérïfïçätïön pröçéss ïs çömplété (üsüällý" -" wïthïn 1-2 däýs). â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg " +" wïthïn 5-7 däýs). â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg " "єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ " "єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ " "αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη " @@ -25113,8 +24768,8 @@ msgid "Already registered?" msgstr "Àlréädý régïstéréd? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "Lög ïn â± 'σÑєм ιÏÑ•Ï…#" @@ -25269,12 +24924,8 @@ msgstr "" "αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." -msgstr "" -"Gö ßäçk tö thé {homepage} ör lét üs knöw äßöüt äný pägés thät mäý hävé ßéén " -"mövéd ät {email}. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тє#" +msgid "Go back to the {homepage}." +msgstr "Gö ßäçk tö thé {homepage}. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -25302,12 +24953,6 @@ msgstr "" "Wé'vé löggéd thé érrör änd öür stäff ïs çürréntlý wörkïng tö résölvé thïs " "érrör äs söön äs pössïßlé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "" -"ÃŒf thé prößlém pérsïsts, pléäsé émäïl üs ät {email_link}. â± 'σÑєм ιÏѕυм ∂σłσÑ" -" ѕιт αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "Stüdïö Àççéssïßïlïtý Pölïçý â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє#" @@ -26126,19 +25771,11 @@ msgstr "" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" "Wé'ré sörrý. Wé çöüldn't fïnd thé {studio_name} pägé ýöü'ré löökïng för. Ãöü" -" mäý wänt tö rétürn tö thé {studio_name} Däshßöärd änd trý ägäïn. ÃŒf ýöü äré" -" stïll hävïng prößléms äççéssïng thïngs, pléäsé féél fréé tö " -"{link_start}çöntäçt {studio_name} süppört{link_end} för fürthér hélp. â± 'σÑєм" -" ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ " -"ιη¢ι∂ι∂υηт Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ " -"ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ " -"¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє " -"¢ιł#" +" mäý wänt tö rétürn tö thé {studio_name} Däshßöärd änd trý ägäïn. â± 'σÑєм " +"ιÏÑ•Ï…#" #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -26148,18 +25785,16 @@ msgstr "Thé Sérvér Énçöüntéréd än Érrör â± 'σÑєм ιÏѕυм ∂ msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" "Wé'ré sörrý. Théré wäs ä prößlém wïth thé sérvér whïlé trýïng tö pröçéss " "ýöür läst réqüést. Ãöü mäý wänt tö rétürn tö thé {studio_name} Däshßöärd ör " -"trý thïs réqüést ägäïn. ÃŒf ýöü äré stïll hävïng prößléms äççéssïng thïngs, " -"pléäsé féél fréé tö {link_start}çöntäçt {studio_name} süppört{link_end} för " -"fürthér hélp. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂" -" ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ " -"мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ " -"єα ¢σммσ∂#" +"trý thïs réqüést ägäïn. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg" +" єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚" +" єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ " +"αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη " +"νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ " +"σ¢¢αє¢αт ¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι σƒƒι¢ια ∂єѕ#" #: cms/templates/error.html msgid "Back to dashboard" @@ -30099,8 +29734,8 @@ msgstr "" msgid "%(file)s has been saved." msgstr "%(file)s häs ßéén sävéd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "ÃŒmägés â± 'σÑєм ιÏÑ•Ï…#" @@ -30328,8 +29963,8 @@ msgstr "Çléär nötïfïçätïöns lïst â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ msgid "Search..." msgstr "Séärçh... â± 'σÑєм ιÏѕυм ∂σł#" -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "Sïgn üp â± 'σÑєм ιÏѕυм #" diff --git a/conf/locale/eo/LC_MESSAGES/djangojs.mo b/conf/locale/eo/LC_MESSAGES/djangojs.mo index 918c328c2ed81b7165e7758d5afb853793d87a72..f00ef7d0d807e9e50fa2d537341c85b435b19784 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 8b406722d7ad8303df29b5ee385e129d1f20ff6e..e691b7e353c956465031a1a79bcb256801b6c75e 100644 --- a/conf/locale/eo/LC_MESSAGES/djangojs.po +++ b/conf/locale/eo/LC_MESSAGES/djangojs.po @@ -32,8 +32,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:53+0000\n" -"PO-Revision-Date: 2020-04-12 20:53:38.541186\n" +"POT-Creation-Date: 2020-06-21 20:50+0000\n" +"PO-Revision-Date: 2020-06-21 20:50:24.441486\n" "Last-Translator: \n" "Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n" "Language: eo\n" @@ -41,7 +41,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -77,6 +77,7 @@ msgstr "Sävïng â± 'σÑєм ιÏÑ•Ï…#" #: cms/templates/js/signatory-editor.underscore #: cms/templates/js/video-transcripts.underscore #: cms/templates/js/xblock-outline.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Delete" msgstr "Délété â± 'σÑєм ιÏÑ•Ï…#" @@ -105,6 +106,7 @@ msgstr "Délété â± 'σÑєм ιÏÑ•Ï…#" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -127,6 +129,7 @@ msgstr "Ûplöädïng â± 'σÑєм ιÏѕυм ∂σł#" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -156,6 +159,7 @@ msgstr "Çhöösé Fïlé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "ÖK â± 'σÑ#" @@ -787,7 +791,6 @@ msgstr "Délété täßlé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Désçrïptïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" @@ -834,6 +837,7 @@ msgstr "Édït HTML â± 'σÑєм ιÏѕυм ∂σł#" #: cms/templates/js/show-textbook.underscore #: cms/templates/js/signatory-details.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Edit" msgstr "Édït â± 'σÑєм ι#" @@ -1236,6 +1240,7 @@ msgstr "Néw wïndöw â± 'σÑєм ιÏѕυм ∂σłσ#" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Néxt â± 'σÑєм ι#" @@ -1585,6 +1590,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/course-instructor-details.underscore #: cms/templates/js/signatory-details.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Title" msgstr "Tïtlé â± 'σÑєм ιÏÑ•#" @@ -2095,6 +2101,7 @@ msgstr "" "ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" #: common/static/common/js/discussion/utils.js +#: common/static/common/templates/discussion/templates.underscore msgid "…" msgstr "… â± #" @@ -2326,6 +2333,7 @@ msgid "Your post will be discarded." msgstr "Ãöür pöst wïll ßé dïsçärdéd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢#" #: common/static/common/js/discussion/views/response_comment_show_view.js +#: common/static/common/templates/discussion/templates.underscore msgid "anonymous" msgstr "änönýmöüs â± 'σÑєм ιÏѕυм ∂σł#" @@ -2616,24 +2624,42 @@ msgid "Other" msgstr "Öthér â± 'σÑєм ιÏÑ•#" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" +msgid "Course Discussion Forum" +msgstr "Çöürsé Dïsçüssïön Förüm â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σ#" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." msgstr "" -"Whät çän wé hélp ýöü wïth, {username}? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" +"Whïlé öür süppört téäm ïs häppý tö ässïst wïth thé édX plätförm, thé çöürsé " +"stäff häs thé éxpértïsé för spéçïfïç ässïgnmént qüéstïöns, grädïng ör thé " +"pröpér pröçédürés ïn éäçh çöürsé. Pléäsé pöst äll çöürsé rélätéd qüéstïöns " +"wïthïn thé Dïsçüssïön Förüm whéré thé Çöürsé Stäff çän dïréçtlý réspönd. " +"â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ " +"тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм," +" qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση Ï…Å‚#" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Details" msgstr "Détäïls â± 'σÑєм ιÏѕυм #" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" -"Thé möré ýöü téll üs, thé möré qüïçklý änd hélpfüllý wé çän réspönd! â± 'σÑєм " -"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" +"thé möré qüïçklý änd hélpfüllý wé çän réspönd! â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Süßmït â± 'σÑєм ιÏÑ•Ï…#" +msgid "Create Support Ticket" +msgstr "Çréäté Süppört Tïçkét â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "" +"Whät çän wé hélp ýöü wïth, {username}? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." @@ -2642,11 +2668,8 @@ msgstr "" "αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." -msgstr "" -"ÃŒf ýöü äré ünäßlé tö äççéss ýöür äççöünt çöntäçt üs vïä émäïl üsïng {email}." -" â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєтυÑ#" +msgid "Need help logging in?" +msgstr "Nééd hélp löggïng ïn? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "" @@ -2668,6 +2691,28 @@ msgstr "" "Éntér sömé détäïls för ýöür süppört réqüést. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " "Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" +"Düé tö thé réçént ïnçréäsé ïn ïntérést ïn önlïné édüçätïön änd édX, wé äré " +"çürréntlý éxpérïénçïng än ünüsüällý hïgh völümé öf süppört réqüésts. Wé " +"äppréçïäté ýöür pätïénçé äs wé wörk tö révïéw éäçh réqüést. Pléäsé çhéçk thé" +" â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ " +"тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм," +" qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ " +"¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє " +"¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт #" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" +" äs mäný qüéstïöns mäý hävé älréädý ßéén änswéréd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " +"αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2693,10 +2738,11 @@ msgstr "Gö tö {platform} Hömé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" -"Thänk ýöü för süßmïttïng ä réqüést! Wé wïll çöntäçt ýöü wïthïn 24 höürs. " -"â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєтυÑ#" +"Thänk ýöü för süßmïttïng ä réqüést! Wé äppréçïäté ýöür pätïénçé whïlé wé " +"wörk tö révïéw ýöür réqüést. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx msgid "Cancel upload" @@ -2908,6 +2954,10 @@ msgstr "Vïéw {span_start} {team_name} {span_end} â± 'σÑєм ιÏѕυм ∂σ msgid "An error occurred. Try again." msgstr "Àn érrör öççürréd. Trý ägäïn. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢#" +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "Nö ässïgnménts för téäm â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σ#" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Léävé thïs téäm? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" @@ -3525,6 +3575,7 @@ msgstr "" " Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -3541,6 +3592,7 @@ msgid "HTML preview of post" msgstr "HTML prévïéw öf pöst â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" #: lms/static/js/customwmd.js +#: common/static/common/templates/discussion/templates.underscore msgid "Your question or idea (required)" msgstr "" "Ãöür qüéstïön ör ïdéä (réqüïréd) â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тє#" @@ -6188,6 +6240,10 @@ msgstr "" msgid "certificate" msgstr "çértïfïçäté â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "Déäçtïvätïng â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Sét üp ýöür çértïfïçäté â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σ#" @@ -6201,9 +6257,9 @@ msgstr "" "Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" msgstr "" -"Délété \"<%= signatoryName %>\" fröm thé lïst öf sïgnätörïés? â± 'σÑєм ιÏѕυм " +"Délété \"<%- signatoryName %>\" fröm thé lïst öf sïgnätörïés? â± 'σÑєм ιÏѕυм " "âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" #: cms/static/js/certificates/views/signatory_editor.js @@ -6256,6 +6312,7 @@ msgstr "" #: cms/static/js/factories/manage_users.js #: cms/static/js/factories/manage_users_lib.js +#: common/static/common/templates/discussion/templates.underscore msgid "Staff" msgstr "Stäff â± 'σÑєм ιÏÑ•#" @@ -6567,11 +6624,11 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" -"Önlý <%= fileTypes %> fïlés çän ßé üplöädéd. Pléäsé séléçt ä fïlé éndïng ïn " -"<%= fileExtensions %> tö üplöäd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєт#" +"Önlý <%- fileTypes %> fïlés çän ßé üplöädéd. Pléäsé séléçt ä fïlé éndïng ïn " +"<%- (fileExtensions) %> tö üplöäd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєт#" #: cms/static/js/models/uploads.js #: lms/templates/student_account/hinted_login.underscore @@ -6775,8 +6832,8 @@ msgid "{selectedProvider} credentials saved" msgstr "{selectedProvider} çrédéntïäls sävéd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" -msgstr "Ûplöäd ä néw PDF tö “<%= name %>†Ⱡ'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕ#" +msgid "Upload a new PDF to “<%- name %>â€" +msgstr "Ûplöäd ä néw PDF tö “<%- name %>†Ⱡ'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕ#" #: cms/static/js/views/edit_chapter.js msgid "Please select a PDF file to upload." @@ -7477,18 +7534,18 @@ msgstr "Wé'ré sörrý, théré wäs än érrör â± 'σÑєм ιÏѕυм ∂σ #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" "Thé çömßïnéd léngth öf thé örgänïzätïön, çöürsé nümßér, änd çöürsé rün " -"fïélds çännöt ßé möré thän <%=limit%> çhäräçtérs. â± 'σÑєм ιÏѕυм ∂σłσ#" +"fïélds çännöt ßé möré thän <%- limit %> çhäräçtérs. â± 'σÑєм ιÏѕυм ∂σłσ#" #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" "Thé çömßïnéd léngth öf thé örgänïzätïön änd lïßrärý çödé fïélds çännöt ßé " -"möré thän <%=limit%> çhäräçtérs. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" +"möré thän <%- limit %> çhäräçtérs. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -7880,13 +7937,13 @@ msgid "Unscheduled" msgstr "Ûnsçhédüléd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Däté â± 'σÑєм ι#" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Prévïöüs â± 'σÑєм ιÏѕυм ∂#" @@ -7936,6 +7993,335 @@ msgstr "Çléär séärçh â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" msgid "Search" msgstr "Séärçh â± 'σÑєм ιÏÑ•Ï…#" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "Àdd ä Réspönsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "Thïs thréäd ïs çlöséd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "Àdd ä réspönsé: â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Süßmït â± 'σÑєм ιÏÑ•Ï…#" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" +"dïsçüssïön pöstéd %(time_ago)s ßý %(author)s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"¢σηѕє¢#" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" +"qüéstïön pöstéd %(time_ago)s ßý %(author)s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"¢σηѕ#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "Pïnnéd â± 'σÑєм ιÏÑ•Ï…#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "Répörtéd â± 'σÑєм ιÏѕυм ∂#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "Çlöséd â± 'σÑєм ιÏÑ•Ï…#" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "Rélätéd tö: %(courseware_title_linked)s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" +"Thïs pöst ïs vïsïßlé önlý tö %(group_name)s. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"¢σηѕє¢тє#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" +"Thïs pöst ïs vïsïßlé tö évérýöné. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тє#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "Édïtïng pöst â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" +"Àdd ä çléär änd désçrïptïvé tïtlé tö énçöürägé pärtïçïpätïön. (Réqüïréd) " +"â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєтυÑ#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "Édït ýöür pöst ßélöw. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "Ûpdäté pöst â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "Shöw Çömmént (%(num_comments)s) â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" +msgstr[1] "Shöw Çömménts (%(num_comments)s) â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "Àdd ä çömmént â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹#" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" +"märkéd äs änswér %(time_ago)s ßý %(user)s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"¢σηѕє#" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "märkéd äs änswér %(time_ago)s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "éndörséd %(time_ago)s ßý %(user)s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "éndörséd %(time_ago)s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "Édïtïng réspönsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "Ûpdäté réspönsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "pöstéd %(time_ago)s ßý %(author)s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "Édïtïng çömmént â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "Ûpdäté çömmént â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "dïsçüssïön â± 'σÑєм ιÏѕυм ∂σłσ#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "änswéréd qüéstïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "ünänswéréd qüéstïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "Föllöwïng â± 'σÑєм ιÏѕυм ∂σł#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "Çömmünïtý TÀ â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "{unread_comments_count} néw â± 'σÑєм ιÏѕυм #" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" +"%(comments_count)s %(span_sr_open)sçömménts (%(unread_comments_count)s " +"ünréäd çömménts)%(span_close)s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєтυÑ#" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" +"%(comments_count)s %(span_sr_open)sçömménts %(span_close)s â± 'σÑєм ιÏѕυм " +"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "Àdd ä Pöst â± 'σÑєм ιÏѕυм ∂σłσ#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "Vïsïßlé tö â± 'σÑєм ιÏѕυм ∂σłσ#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" +"Dïsçüssïön ädmïns, mödérätörs, änd TÀs çän mäké théïr pösts vïsïßlé tö äll " +"stüdénts ör spéçïfý ä sïnglé gröüp. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "Àll Gröüps â± 'σÑєм ιÏѕυм ∂σłσ#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "föllöw thïs pöst â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "pöst änönýmöüslý â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "pöst änönýmöüslý tö çlässmätés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "Érrör pöstïng ýöür méssägé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє#" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" +"Thïs pöst wïll ßé vïsïßlé önlý tö %(group_name)s. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " +"αмєт, ¢σηѕє¢тєтυÑ#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" +"Thïs pöst wïll ßé vïsïßlé tö évérýöné. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"¢σηѕє¢тєтυÑ#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "Töpïç äréä â± 'σÑєм ιÏѕυм ∂σłσ#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" +"Àdd ýöür pöst tö ä rélévänt töpïç tö hélp öthérs fïnd ït. (Réqüïréd) â± 'σÑєм " +"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "(Çömmünïtý TÀ) â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "(Stäff) â± 'σÑєм ιÏѕυм #" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "Àll Pösts â± 'σÑєм ιÏѕυм ∂σł#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "Rétürn tö äll pösts â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "Vïéw dïsçüssïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "Löäd möré â± 'σÑєм ιÏѕυм ∂σł#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "Pöst týpé â± 'σÑєм ιÏѕυм ∂σł#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" +"Qüéstïöns räïsé ïssüés thät nééd änswérs. Dïsçüssïöns shäré ïdéäs änd stärt " +"çönvérsätïöns. (Réqüïréd) â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "Qüéstïön â± 'σÑєм ιÏѕυм ∂#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "Dïsçüssïön â± 'σÑєм ιÏѕυм ∂σłσ#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "Éndörsé â± 'σÑєм ιÏѕυм #" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "Ûnéndörsé â± 'σÑєм ιÏѕυм ∂σł#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "Märk äs Ànswér â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "Ûnmärk äs Ànswér â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "Föllöw â± 'σÑєм ιÏÑ•Ï…#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "Ûnföllöw â± 'σÑєм ιÏѕυм ∂#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "Vöté för thïs pöst, â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "Répört äßüsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "Répört â± 'σÑєм ιÏÑ•Ï…#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "Ûnrépört â± 'σÑєм ιÏѕυм ∂#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "Pïn â± 'σÑєм#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "Ûnpïn â± 'σÑєм ιÏÑ•#" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "Öpén â± 'σÑєм ι#" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "Dïsçüssïön Hömé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" @@ -7999,10 +8385,6 @@ msgstr "" "Çhéçk thïs ßöx tö réçéïvé än émäïl dïgést önçé ä däý nötïfýïng ýöü äßöüt " "néw, ünréäd äçtïvïtý fröm pösts ýöü äré föllöwïng. â± 'σÑєм ιÏ#" -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "Àll Pösts â± 'σÑєм ιÏѕυм ∂σł#" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "üsérnämé ör émäïl â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" @@ -8252,6 +8634,10 @@ msgstr "" msgid "Join Team" msgstr "Jöïn Téäm â± 'σÑєм ιÏѕυм ∂σł#" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "Téäm Àssïgnménts â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αм#" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "Téäm Détäïls â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" @@ -8339,115 +8725,6 @@ msgstr "" msgid "Remove unit %(unitName)s" msgstr "Rémövé ünït %(unitName)s â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" -"Ãöü stïll nééd tö vïsït thé %(display_name)s wéßsïté tö çömplété thé çrédït " -"pröçéss. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєтυÑ#" - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"Tö fïnälïzé çöürsé çrédït, %(display_name)s réqüïrés %(platform_name)s " -"léärnérs tö süßmït ä çrédït réqüést. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тє#" - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Gét Çrédït â± 'σÑєм ιÏѕυм ∂σłσ#" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" -"Thänk ýöü %(full_name)s! Wé hävé réçéïvéd ýöür päýmént för %(course_name)s. " -"â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"Pléäsé prïnt thïs pägé för ýöür réçörds; ït sérvés äs ýöür réçéïpt. Ãöü wïll" -" älsö réçéïvé än émäïl wïth thé sämé ïnförmätïön. â± 'σÑєм #" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "Ördér Nö. â± 'σÑєм ιÏѕυм ∂σł#" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Àmöünt â± 'σÑєм ιÏÑ•Ï…#" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Tötäl â± 'σÑєм ιÏÑ•#" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Pléäsé Nöté â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "" -"Çrösséd öüt ïtéms hävé ßéén réfündéd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"¢σηѕє¢тєтυ#" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Bïlléd tö â± 'σÑєм ιÏѕυм ∂σł#" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Nö réçéïpt äväïläßlé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Gö tö Däshßöärd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" -"ÃŒf ýöü dön't vérïfý ýöür ïdéntïtý nöw, ýöü çän stïll éxplöré ýöür çöürsé " -"fröm ýöür däshßöärd. Ãöü wïll réçéïvé pérïödïç rémïndérs fröm {platformName}" -" tö vérïfý ýöür ïdéntïtý. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ " -"α∂ιÏιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα" -" αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ " -"ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· " -"ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα " -"ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι " -"σƒƒι¢ια ∂є#" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "" -"Wänt tö çönfïrm ýöür ïdéntïtý lätér? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"¢σηѕє¢тєтυ#" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Vérïfý Nöw â± 'σÑєм ιÏѕυм ∂σłσ#" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Märk Éxäm Às Çömplétéd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" @@ -8584,10 +8861,10 @@ msgstr "Àßöüt Ãöü â± 'σÑєм ιÏѕυм ∂σł#" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" "Thé föllöwïng ïnförmätïön ïs älréädý ä pärt öf ýöür {platform} pröfïlé. " -"Wé\\'vé ïnçlüdéd ït héré för ýöür äpplïçätïön. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" +"Wé'vé ïnçlüdéd ït héré för ýöür äpplïçätïön. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•#" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -8617,6 +8894,10 @@ msgstr "" "Thänk ýöü för süßmïttïng ýöür fïnänçïäl ässïstänçé äpplïçätïön för " "{course_name}! Ãöü çän éxpéçt ä réspönsé ïn 2-4 ßüsïnéss däýs. â± 'σÑєм ιÏѕυм#" +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Gö tö Däshßöärd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "Bülk Éxçéptïöns â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ α#" @@ -9019,14 +9300,6 @@ msgstr "" "Ãöü çän çhängé séssïöns üntïl {expiration_date}. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " "αмєт, ¢σηѕє¢тєт#" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "Fïnäl Grädé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "för {courseName} â± 'σÑєм ιÏѕυм #" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "Vïéw Àrçhïvéd Çöürsé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" @@ -9275,8 +9548,29 @@ msgstr "" "Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" -msgstr "Nééd hélp löggïng ïn? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" +msgid "Need help signing in?" +msgstr "Nééd hélp sïgnïng ïn? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "Förgöt mý pässwörd â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "Öthér sïgn-ïn ïssüés â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" +"Sïgn ïn wïth ýöür çömpäný ör sçhööl â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєт#" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "Nééd öthér hélp sïgnïng ïn? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє#" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" +msgstr "Çréäté än äççöünt â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" #: lms/templates/student_account/hinted_login.underscore #: lms/templates/student_account/login.underscore @@ -9521,38 +9815,26 @@ msgid "What You Need for Verification" msgstr "Whät Ãöü Nééd för Vérïfïçätïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Wéßçäm â± 'σÑєм ιÏÑ•Ï…#" +msgid "Device with Camera" +msgstr "Dévïçé wïth Çämérä â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт#" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" -"Ãöü nééd ä çömpütér ör çéll phöné thät häs ä wéßçäm. Whén ýöü réçéïvé ä " -"ßröwsér prömpt, mäké süré thät ýöü ällöw äççéss tö thé çämérä. â± 'σÑєм ιÏѕυм " -"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ " -"ιη¢ι∂ι∂υηт Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ " -"ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ " -"¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє " -"¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт " -"ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι σƒƒι¢ια ∂єѕєÑυηт мσłłιт αηιм ι∂ єѕт łαвσÑυм#" +"Ãöü nééd ä dévïçé thät häs ä wéßçäm. ÃŒf ýöü réçéïvé ä ßröwsér prömpt för " +"äççéss tö ýöür çämérä, pléäsé mäké süré tö çlïçk 'Àllöw'. â± '#" #: lms/templates/verify_student/face_photo_step.underscore msgid "Photo Identification" msgstr "Phötö ÃŒdéntïfïçätïön â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"Ãöü nééd ä drïvér's lïçénsé, pässpört, ör öthér gövérnmént-ïssüéd ÃŒD thät " -"häs ýöür nämé änd phötö. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт,#" +"Ãöü nééd ä välïd ÃŒD thät çöntäïns ýöür füll nämé änd phötö. â± 'σÑєм ιÏѕυм " +"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -9583,19 +9865,13 @@ msgstr "" "Ãöür éntïré fäçé fïts ïnsïdé thé främé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " "¢σηѕє¢тєтυÑ#" -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "" -"Thé phötö öf ýöür fäçé mätçhés thé phötö ön ýöür ÃŒD. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ " -"αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" -"Tö üsé thé çürrént phötö, séléçt thé Täké Phötö ßüttön {icon}. Tö täké " -"änöthér phötö, séléçt thé Rétäké Phötö ßüttön {icon}. â± 'σÑєм ιÏѕυм #" +"Tö täké thé phötö öf ýöür fäçé, çlïçk ön thé çämérä ßüttön {icon}. ÃŒf ýöü " +"nééd tö trý ägäïn, çlïçk 'Rétäké Phötö'. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -9612,21 +9888,12 @@ msgstr "" "Whý döés %(platformName)s nééd mý phötö? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє#" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"Às pärt öf thé vérïfïçätïön pröçéss, ýöü täké ä phötö öf ßöth ýöür fäçé änd " -"ä gövérnmént-ïssüéd phötö ÃŒD. Öür äüthörïzätïön sérvïçé çönfïrms ýöür " -"ïdéntïtý ßý çömpärïng thé phötö ýöü täké wïth thé phötö ön ýöür ÃŒD. â± 'σÑєм " -"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ " -"ιη¢ι∂ι∂υηт Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ " -"ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ " -"¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє " -"¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ#" +"Wé üsé ýöür vérïfïçätïön phötös tö çönfïrm ýöür ïdéntïtý änd énsüré thé " +"välïdïtý öf ýöür çértïfïçäté. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмє#" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -9639,22 +9906,20 @@ msgstr "" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"Wé üsé thé hïghést lévéls öf séçürïtý äväïläßlé tö énçrýpt ýöür phötö änd " -"sénd ït tö öür äüthörïzätïön sérvïçé för révïéw. Ãöür phötö änd ïnförmätïön " -"äré nöt sävéd ör vïsïßlé änýwhéré ön %(platformName)s äftér thé vérïfïçätïön" -" pröçéss ïs çömplété. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg " -"єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ " -"єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ " -"αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη " -"νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм#" +"Wé séçürélý énçrýpt ýöür phötö änd sénd ït tö öür äüthörïzätïön sérvïçé för " +"révïéw. Ãöür phötö änd ïnförmätïön äré nöt sävéd ör vïsïßlé änýwhéré ön " +"%(platformName)s äftér thé vérïfïçätïön pröçéss ïs çömplété. â± 'σÑєм ιÏѕυм " +"âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ " +"ιη¢ι∂ι∂υηт Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ " +"ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ " +"¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє " +"¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αт#" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -9733,20 +9998,18 @@ msgid "Take a Photo of Your ID" msgstr "Täké ä Phötö öf Ãöür ÃŒD â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σ#" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"Ûsé ýöür wéßçäm tö täké ä phötö öf ýöür ÃŒD. Wé wïll mätçh thïs phötö wïth " -"thé phötö öf ýöür fäçé änd thé nämé ön ýöür äççöünt. â± 'σÑєм#" +"Ûsé ýöür wéßçäm tö täké ä phötö öf ýöür ÃŒD. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Ãöü nééd än ÃŒD wïth ýöür nämé änd phötö. À drïvér's lïçénsé, pässpört, ör " -"öthér gövérnmént-ïssüéd ÃŒDs äré äll äççéptäßlé. â± 'σÑєм ιÏÑ•Ï…#" +"Ãöü nééd än ÃŒD wïth ýöür nämé änd phötö. À drïvér's lïçénsé, pässpört, ör ÃŒD" +" äré äll äççéptäßlé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -9777,6 +10040,21 @@ msgstr "" "Ûsé thé Rétäké Phötö ßüttön ïf ýöü äré nöt pléäséd wïth ýöür phötö â± 'σÑєм " "ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" +"Às pärt öf thé vérïfïçätïön pröçéss, ýöü täké ä phötö öf ßöth ýöür fäçé änd " +"ä phötö ÃŒD. Öür äüthörïzätïön sérvïçé çönfïrms ýöür ïdéntïtý ßý çömpärïng " +"thé phötö ýöü täké wïth thé phötö ön ýöür ÃŒD. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт " +"∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση " +"υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” " +"âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα" +" ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αт#" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -9841,6 +10119,38 @@ msgstr "" "Çän wé mätçh thé phötö ýöü töök wïth thé öné ön ýöür ÃŒD? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ " "ѕιт αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"Às pärt öf thé vérïfïçätïön pröçéss, ýöü täké ä phötö öf ßöth ýöür fäçé änd " +"ä gövérnmént-ïssüéd phötö ÃŒD. Öür äüthörïzätïön sérvïçé çönfïrms ýöür " +"ïdéntïtý ßý çömpärïng thé phötö ýöü täké wïth thé phötö ön ýöür ÃŒD. â± 'σÑєм " +"ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ " +"ιη¢ι∂ι∂υηт Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ " +"ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ " +"¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє " +"¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα ÏαÑιαтυÑ. єχ#" + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"Wé üsé thé hïghést lévéls öf séçürïtý äväïläßlé tö énçrýpt ýöür phötö änd " +"sénd ït tö öür äüthörïzätïön sérvïçé för révïéw. Ãöür phötö änd ïnförmätïön " +"äré nöt sävéd ör vïsïßlé änýwhéré ön %(platformName)s äftér thé vérïfïçätïön" +" pröçéss ïs çömplété. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±âˆ‚Î¹Ïιѕι¢ιηg " +"єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα αłιqυα. Ï…Ñ‚ " +"єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ ηιѕι Ï…Ñ‚ " +"αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· ÑÑ”ÏÑєнєη∂єÑιт ιη " +"νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм#" + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -9881,6 +10191,13 @@ msgstr "" "À drïvér's lïçénsé, pässpört, ör öthér gövérnmént-ïssüéd ÃŒD wïth ýöür nämé " "änd phötö â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢т#" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Wéßçäm â± 'σÑєм ιÏÑ•Ï…#" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -10005,6 +10322,11 @@ msgstr "" "Çhéçk ýöür émäïl för än äçtïvätïön méssägé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " "Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Tötäl â± 'σÑєм ιÏÑ•#" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "" @@ -10057,6 +10379,40 @@ msgstr "" "Thänk ýöü! Wé hävé réçéïvéd ýöür päýmént för {courseName}. â± 'σÑєм ιÏѕυм " "âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ Î±#" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"Pléäsé prïnt thïs pägé för ýöür réçörds; ït sérvés äs ýöür réçéïpt. Ãöü wïll" +" älsö réçéïvé än émäïl wïth thé sämé ïnförmätïön. â± 'σÑєм #" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "Ördér Nö. â± 'σÑєм ιÏѕυм ∂σł#" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Àmöünt â± 'σÑєм ιÏÑ•Ï…#" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Pléäsé Nöté â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ #" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "" +"Çrösséd öüt ïtéms hävé ßéén réfündéd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"¢σηѕє¢тєтυ#" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Bïlléd tö â± 'σÑєм ιÏѕυм ∂σł#" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Nö réçéïpt äväïläßlé â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, #" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "" @@ -10099,6 +10455,12 @@ msgstr "" " ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт ηση ÏÑσι∂єηт, ѕυηт ιη ¢υłÏα qυι" " σƒƒι¢ια ∂є#" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "" +"Wänt tö çönfïrm ýöür ïdéntïtý lätér? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " +"¢σηѕє¢тєтυ#" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "" @@ -10108,12 +10470,12 @@ msgstr "" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" "Wé hävé réçéïvéd ýöür ïnförmätïön änd äré vérïfýïng ýöür ïdéntïtý. Ãöü wïll " "séé ä méssägé ön ýöür däshßöärd whén thé vérïfïçätïön pröçéss ïs çömplété " -"(üsüällý wïthïn 1-2 däýs). ÃŒn thé méäntïmé, ýöü çän stïll äççéss äll " +"(üsüällý wïthïn 5-7 däýs). ÃŒn thé méäntïmé, ýöü çän stïll äççéss äll " "äväïläßlé çöürsé çöntént. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ " "α∂ιÏιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα" " αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ " @@ -10156,12 +10518,6 @@ msgstr "" "Döés thé phötö öf ýöü shöw ýöür whölé fäçé? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " "Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "" -"Döés thé phötö öf ýöü mätçh ýöür ÃŒD phötö? â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, " -"Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ #" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "" @@ -11833,6 +12189,36 @@ msgstr "Sét äs ä Spéçïäl Éxäm â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹ msgid "Exam Types" msgstr "Éxäm Týpés â± 'σÑєм ιÏѕυм ∂σłσ#" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" +"Thïs süßséçtïön wäs réléäséd tö léärnérs äs ä spéçïäl éxäm, ßüt wäs révértéd" +" ßäçk tö ä ßäsïç éxäm. Ãöü mäý nöt çönfïgüré ït äs ä spéçïäl éxäm nöw. " +"Çöntäçt édX Süppört för ässïstänçé. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σηѕє¢тєтυÑ" +" α∂ιÏιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” " +"мαgηα αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ " +"łαвσÑιѕ ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· " +"ÑÑ”ÏÑєнєη∂єÑιт ιη νσłυÏтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσÑÑ” єυ Æ’Ï…gιαт ηυłłα " +"ÏαÑιαтυÑ. єχ¢єÏÑ‚Ñ”Ï…Ñ Ñ•Î¹Î·Ñ‚ σ¢¢αє¢αт ¢υÏι∂αтαт ηση ÏÑσι∂єηт, Ñ•Ï…#" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" +"Thïs spéçïäl éxäm häs ßéén réléäséd tö léärnérs. Ãöü mäý nöt çönvért ït tö " +"änöthér týpé öf spéçïäl éxäm. Ãöü mäý révért thïs süßséçtïön ßäçk tö ßéïng ä" +" ßäsïç éxäm ßý séléçtïng 'Nöné', ßüt ýöü wïll NÖT ßé äßlé tö çönfïgüré ït äs" +" ä spéçïäl éxäm ïn thé fütüré. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, Â¢ÏƒÎ·Ñ•Ñ”Â¢Ñ‚Ñ”Ñ‚Ï…Ñ " +"α∂ιÏιѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємÏÏƒÑ Î¹Î·Â¢Î¹âˆ‚Î¹âˆ‚Ï…Î·Ñ‚ Ï…Ñ‚ łαвσÑÑ” єт ∂σłσÑÑ” мαgηα" +" αłιqυα. Ï…Ñ‚ єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтÑυ∂ єχєÑ¢ιтαтιση υłłαм¢σ łαвσÑιѕ " +"ηιѕι Ï…Ñ‚ αłιqÏ…Î¹Ï Ñ”Ï‡ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ αυтє ιÑÏ…ÑÑ” âˆ‚ÏƒÅ‚ÏƒÑ Î¹Î· Ñ#" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Tïméd â± 'σÑєм ιÏÑ•#" @@ -12078,14 +12464,14 @@ msgstr "" msgid "Read more" msgstr "Réäd möré â± 'σÑєм ιÏѕυм ∂σł#" -#: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" -msgstr "Shöw tränsçrïpts ({totalTranscripts}) â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" - #: cms/templates/js/video-transcripts.underscore msgid "No transcript uploaded." msgstr "Nö tränsçrïpt üplöädéd. â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢σ#" +#: cms/templates/js/video-transcripts.underscore +msgid "Show transcripts ({totalTranscripts})" +msgstr "Shöw tränsçrïpts ({totalTranscripts}) â± 'σÑєм ιÏѕυм âˆ‚ÏƒÅ‚ÏƒÑ Ñ•Î¹Ñ‚ αмєт, ¢#" + #: cms/templates/js/xblock-access-editor.underscore msgid "Set Access" msgstr "Sét Àççéss â± 'σÑєм ιÏѕυм ∂σłσ#" diff --git a/conf/locale/es_419/LC_MESSAGES/django.mo b/conf/locale/es_419/LC_MESSAGES/django.mo index 80ff90daf2dec0a4d90a5fda667cd70ec2067d90..d4f99c1f74d56ae7c2a23dacdd141bd90843cc1e 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 a45a0c3a3ecc29aae2b4b1764b591a7e2a72934d..eda2746b51b4e30e4f84bb8f7f2a90327865a1a5 100644 --- a/conf/locale/es_419/LC_MESSAGES/django.po +++ b/conf/locale/es_419/LC_MESSAGES/django.po @@ -5,7 +5,7 @@ # # Translators: # Adolfo Michel <Michel.14.993@gmail.com>, 2017 -# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2019 +# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2020 # arrow1234 <aleoncavallo@gmail.com>, 2014 # Anatoli F. Peña Castillo <djanatoli@gmail.com>, 2016 # AngelesAlvarez, 2019 @@ -23,13 +23,14 @@ # David Salazar <imdjsg@gmail.com>, 2014 # Eduardo Zambrano <ezambrano@edx.org>, 2017-2019 # Elias Estay <eestay@u.uchile.cl>, 2015 +# Felipe Espinoza <felipe.espinoza.r@uchile.cl>, 2020 # Felipe Montoya <felipe.montoya@edunext.co>, 2019 # Félix Antonio Valdez Noverola <felix@itesm.mx>, 2015 # Fernando Abramowitz <ferabra@gmail.com>, 2014 # Fernando Abramowitz <ferabra@gmail.com>, 2014 # jorgebarrero <jorgebarrero@gmail.com>, 2014 # Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2013 -# Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2015-2018 +# Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2015-2018,2020 # Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2013-2014 # Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2013 # Juan <juan.marrero@utec.edu.uy>, 2015 @@ -49,7 +50,7 @@ # Matt Tuchfarber <matt@tuchfarber.com>, 2018 # Miguel Bonilla <mbonilla@edx.org>, 2018 # MarnyLopez, 2014 -# Muhammad Adeel Khan <adeel@edx.org>, 2019 +# Muhammad Adeel Khan <adeel@edx.org>, 2019-2020 # Natalia, 2013 # Natalia, 2013-2014,2018 # Ned Batchelder <ned@edx.org>, 2016 @@ -76,7 +77,7 @@ # # Translators: # Addi Hazel Mendoza Sánchez <addictivoh@gmail.com>, 2015 -# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2019 +# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2020 # Andres Garcia <afgarcia0479@misena.edu.co>, 2019 # Antonio Pardo <apardo@alabs.org>, 2013 # Antonio Pardo <apardo@alabs.org>, 2013 @@ -113,10 +114,10 @@ # Translators: # Addi Hazel Mendoza Sánchez <addictivoh@gmail.com>, 2014 # Adolfo Michel <Michel.14.993@gmail.com>, 2017 -# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2019 +# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2020 # Anatoli F. Peña Castillo <djanatoli@gmail.com>, 2016 -# andreslucena <inactive+andreslucena@transifex.com>, 2013 -# andreslucena <inactive+andreslucena@transifex.com>, 2013 +# 15d70039da093fd796cb78400efe6224_d9c7fb5 <9dafa8baa31ffa87b3f23172673a99b8_107209>, 2013 +# 15d70039da093fd796cb78400efe6224_d9c7fb5 <9dafa8baa31ffa87b3f23172673a99b8_107209>, 2013 # AngelesAlvarez, 2019 # Angel Kurten <angelkurten@hotmail.com>, 2016 # Anthony Mangano <amangano@edx.org>, 2017 @@ -145,14 +146,14 @@ # 1673e3cf8bd85685e54576636ae7f409, 2014 # jorgebarrero <jorgebarrero@gmail.com>, 2014 # Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2013-2014 -# Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2015-2019 +# Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2015-2020 # Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2013-2014 # Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2013 # Juan Fernando Villa <elite.linux@gmail.com>, 2015 # Juan <juan.marrero@utec.edu.uy>, 2015 # Lalo Cabrera <laloogcabrera@yahoo.com.mx>, 2014 # Laura Silva <lingison@edx.org>, 2016-2017 -# camilomaiden <inactive+camilomaiden@transifex.com>, 2014 +# 5d3923a435bd1af79454b9836d4c0111_a3a4fae <556e7ad92465a56b545f9e78fb091a63_215518>, 2014 # Luis Benites <lbenitesanchez@gmail.com>, 2016 # Luis Ricardo Ruiz <luislicardo1307@gmail.com>, 2013 # Luis Manuel Moreno <luis.moreno@edunext.co>, 2019 @@ -173,6 +174,7 @@ # Ned Weitzman <nweitzman@edx.org>, 2017-2018 # Nestor Alejandro Mendoza Espinoza <name1984@gmail.com>, 2015 # Nicolas CS <nicolascs23@gmail.com>, 2016 +# Omar Al-Ithawi <i@omardo.com>, 2020 # Cristian Salamea <ovnicraft@gmail.com>, 2013 # palichis <palichis@solid-ec.org>, 2015 # Etna PretelÃn Ricárdez, 2014 @@ -192,9 +194,9 @@ # # Translators: # Addi Hazel Mendoza Sánchez <addictivoh@gmail.com>, 2015 -# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018 +# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018,2020 # Andres Garcia <afgarcia0479@misena.edu.co>, 2019 -# andreslucena <inactive+andreslucena@transifex.com>, 2013 +# 15d70039da093fd796cb78400efe6224_d9c7fb5 <9dafa8baa31ffa87b3f23172673a99b8_107209>, 2013 # Antonio Pardo <apardo@alabs.org>, 2013 # Armindo Perozo-Mena <aperozomena@gmail.com>, 2016 # Aylén <aylen_00@hotmail.com>, 2014 @@ -253,7 +255,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2019\n" "Language-Team: Spanish (Latin America) (https://www.transifex.com/open-edx/teams/6205/es_419/)\n" @@ -262,7 +264,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -287,8 +289,8 @@ msgstr "Examen de Admisión" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "Unidad" @@ -599,8 +601,8 @@ msgstr "" #, python-format msgid "%(count)d student account was unlocked." msgid_plural "%(count)d student accounts were unlocked." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%(count)d cuenta de estudiante fue desbloqueda." +msgstr[1] "%(count)d cuentas de estudiantes fueron desbloqueadas." #: common/djangoapps/student/admin.py #, python-brace-format @@ -608,25 +610,28 @@ msgid "" "Please add a key/value 'THIRD_PARTY_AUTH_ONLY_DOMAIN/{site_email_domain}' in" " SiteConfiguration model's site_values field." msgstr "" +"Por favor digite una combinación key/value " +"'THIRD_PARTY_AUTH_ONLY_DOMAIN/{site_email_domain}' en el campo site_values " +"del modelo SiteConfiguration." #: common/djangoapps/student/admin.py #, python-brace-format msgid "Email doesn't have {domain_name} domain name." -msgstr "" +msgstr "El correo electrónico no tiene el nombre de dominio {domain_name} " #: common/djangoapps/student/admin.py msgid "User with this email doesn't exist in system." -msgstr "" +msgstr "No existe usuario con este correo electrónico en el sistema." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "Ya existe una cuenta con el nombre de usuario '{username}'." +msgid "An account with the Email '{email}' already exists." +msgstr "Ya existe una cuenta con el correo electrónico '{email}'." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "Ya existe una cuenta con el correo electrónico '{email}'." +msgid "An account with the Public Username '{username}' already exists." +msgstr "Ya existe una cuenta con el nombre de usuario '{username}'." #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -872,6 +877,10 @@ msgid "" "follows: user_id, username, email, course_id, " "is_verified, verification_date" msgstr "" +"Se espera que los datos se proporcionen en un formato de archivo csv con" +" la primera fila es el encabezado y las columnas serán " +"las siguientes: user_id, username, email, course_id, " +"is_verified, verification_date" #: common/djangoapps/student/models.py msgid "Name of this user attribute." @@ -898,6 +907,12 @@ msgid "" "and password. And if any employee's email doesn't exist in this model then " "that employee can login via third party authentication backend only." msgstr "" +"Un empleado (un usuario cuyo correo electrónico tiene el nombre de dominio " +"del sitio actual) cuyo correo electrónico existe en este modelo, puede " +"iniciar sesión desde la pantalla de inicio de sesión mediante correo " +"electrónico y contraseña. Y si el correo electrónico de cualquier empleado " +"no existe en este modelo, ese empleado puede iniciar sesión solo a través de" +" backend de autenticación de terceros." #: common/djangoapps/student/models.py msgid "" @@ -905,6 +920,9 @@ msgid "" " first row being the header and columns will be as " "follows: username, email, new_email" msgstr "" +"Se espera que los datos se proporcionen en un formato de archivo csv con la " +"primera fila como encabezado y las columnas serán las siguientes: nombre de " +"usuario, correo electrónico, correo electrónico nuevo" #: common/djangoapps/student/views/dashboard.py msgid " and " @@ -1861,7 +1879,7 @@ msgstr "" #: common/lib/capa/capa/capa_problem.py msgid "Question {}" -msgstr "" +msgstr "Pregunta {}" #: common/lib/capa/capa/capa_problem.py #: common/lib/xmodule/xmodule/capa_base.py @@ -2382,7 +2400,7 @@ msgstr "Siempre" msgid "Never" msgstr "Nunca" -#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/capa_base.py lms/templates/courseware/dates.html msgid "Past Due" msgstr "Vencido" @@ -2577,9 +2595,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -3678,6 +3696,16 @@ msgid "" "{default_max}In \"id\" values, the only supported special characters are " "underscore, hyphen, and period." msgstr "" +"Especifique el tamaño máximo del equipo y los temas para los equipos dentro " +"del conjunto proporcionado de llaves. Asegúrese de incluir todos los " +"conjuntos de valores de tema dentro de un conjunto de corchetes, con una " +"coma después de la llave de cierre para cada tema y otra coma después de los" +" corchetes de cierre. Por ejemplo, para especificar que los equipos deben " +"tener un máximo de 5 participantes y proporcionar una lista de 2 temas, " +"ingrese la configuración en este formato: {example_format}. Si no se " +"proporciona max_size, el valor predeterminado será {default_max}. En los " +"valores \"id\", los únicos caracteres especiales admitidos son guión bajo, " +"guión y punto." #: common/lib/xmodule/xmodule/course_module.py msgid "Enable Proctored Exams" @@ -4150,6 +4178,10 @@ msgid "" "{docs_anchor_open}the edX LTI documentation{anchor_close} for more details " "on this setting." msgstr "" +"Ingrese el URL de la herramienta externa que inicia este Componente. Esta " +"configuración solo se usa cuando la herramienta externa falso {break_tag} " +"Consulte {docs_anchor_open} la documentación de edX LTI {anchor_close} para " +"obtener más detalles sobre esta configuración." #: common/lib/xmodule/xmodule/lti_module.py msgid "Custom Parameters" @@ -4163,6 +4195,11 @@ msgid "" "component.{break_tag}See {docs_anchor_open}the edX LTI " "documentation{anchor_close} for more details on this setting." msgstr "" +"Agregue la clave / valor para cualquier parámetro personalizado, como la " +"página en la que su libro electrónico deberÃa abrirse o el color de fondo " +"de este Componente. {break_tag} Consulte {docs_anchor_open} la documentación" +" LTI de edX {anchor_close} para obtener más detalles sobre esta " +"configuración ." #: common/lib/xmodule/xmodule/lti_module.py msgid "Open in New Page" @@ -4558,12 +4595,12 @@ msgstr "" "Ingrese true o false. Si se ingresa true, los envÃos realizados para los " "problemas serán tenidos en cuenta en la puntuación del Examen de ingreso." -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "Grupos de Ruta de Inscripción" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "Partición para segmentar usuarios por seguimiento de inscripción." @@ -5259,17 +5296,17 @@ msgstr "Desbloquea la cuenta" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "Cerrar" @@ -5280,10 +5317,12 @@ msgid "" "This is a routed Account Activation email for %(routed_user)s " "(%(routed_user_email)s): %(routed_profile_name)s" msgstr "" +"Este es un correo electrónico de activación de cuenta enrutado para " +"%(routed_user)s (%(routed_user_email)s): %(routed_profile_name)s" #: common/templates/student/edx_ace/accountactivation/email/body.html msgid "Account Activation" -msgstr "" +msgstr "Activación de cuenta" #: common/templates/student/edx_ace/accountactivation/email/body.html #: common/templates/student/edx_ace/accountactivation/email/body.txt @@ -5293,16 +5332,19 @@ msgid "" "engaging, high-quality %(platform_name)s courses. Note that you will not be " "able to log back into your account until you have activated it." msgstr "" +"¡Su cuenta está casi lista! Use el enlace debajo para activar su Cuenta y " +"acceder a cursos interesantes y de alta calidad en %(platform_name)s. Note " +"que no podrá iniciar sesión de nuevo hasta que su cuenta esté activa." #: common/templates/student/edx_ace/accountactivation/email/body.html msgid "Activate Your Account" -msgstr "" +msgstr "Activar su cuenta" #: common/templates/student/edx_ace/accountactivation/email/body.html #: common/templates/student/edx_ace/accountactivation/email/body.txt #, python-format msgid "Enjoy learning with %(platform_name)s." -msgstr "" +msgstr "Disfrute aprendiendo en %(platform_name)s." #: common/templates/student/edx_ace/accountactivation/email/body.html #, python-format, python-brace-format @@ -5311,6 +5353,9 @@ msgid "" "{start_anchor_web}%(support_url)s{end_anchor} or email " "{start_anchor_email}%(support_email)s{end_anchor}." msgstr "" +"Si requiere ayuda, Por favor use el formulario web en " +"{start_anchor_web}%(support_url)s{end_anchor} o envÃe un mensaje a " +"{start_anchor_email}%(support_email)s{end_anchor}." #: common/templates/student/edx_ace/accountactivation/email/body.html #: common/templates/student/edx_ace/accountactivation/email/body.txt @@ -5320,6 +5365,9 @@ msgid "" "attempted to create an account on %(platform_name)s using this email " "address." msgstr "" +"Este mensaje fue enviado automáticamente por %(lms_url)s porque alguien " +"trató de crear una cuenta en %(platform_name)s usando esta dirección de " +"correo electrónico." #: common/templates/student/edx_ace/accountactivation/email/body.txt #, python-format @@ -5327,11 +5375,13 @@ msgid "" "If you need help, please use our web form at %(support_url)s or email " "%(support_email)s." msgstr "" +"Si necesita asistencia, utilice el formulario en %(support_url)s o escriba " +"un correo a %(support_email)s." #: common/templates/student/edx_ace/accountactivation/email/subject.txt #, python-format msgid "Action Required: Activate your %(platform_name)s account" -msgstr "" +msgstr "Acción Requerida: Active su cuenta en %(platform_name)s " #: common/templates/student/edx_ace/accountrecovery/email/body.html msgid "Create Password" @@ -5441,7 +5491,7 @@ msgstr "" #: common/templates/student/edx_ace/emailchangeconfirmation/email/subject.txt #, python-format msgid "Email Change Confirmation for %(platform_name)s" -msgstr "" +msgstr "Confirmación de cambio de correo electrónico para %(platform_name)s" #: common/templates/student/edx_ace/emailchangeconfirmation/email/body.html #: common/templates/student/edx_ace/emailchangeconfirmation/email/body.txt @@ -6254,54 +6304,6 @@ msgstr "" "Se ha solicitado una devolución para {username} ({email}). Para procesar " "esta solicitud, visite el vÃnculo(s) a continuación." -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "Recibo" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "El pago falló" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "Hubo un problema con la transacción. No se realizó ningún cobro." - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" -"Asegures que su información es correcta o intente nuevamente con otra " -"tarjeta o con otro medio de pago." - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "Ocurrió un error procesando su pago. No se realizó ningún cobro." - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "Por favor espere unos minutos e intente nuevamente." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "Para obtener asistencia, contacte a {payment_support_link}." - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "Ha ocurrido un error creando su recibo." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"Si su curso no aparece en el panel de control, contacte a " -"{payment_support_link}." - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "Obtén un certificado" @@ -6364,14 +6366,26 @@ msgstr "Usted no tiene acceso a este curso" msgid "You do not have access to this course on a mobile device" msgstr "Usted no tiene acceso a este curso desde dispositivos móviles" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "Debe estar inscrito en el curso" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "Debe iniciar sesión para acceder a este curso" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "Optar por el Certificado Verificado" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "Asistencia financiera" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" -msgstr "" +msgstr "Tarea" #. Translators: 'absolute' is a date such as "Jan 01, #. 2020". 'relative' is a fuzzy description of the time until @@ -6442,11 +6456,11 @@ msgstr "Este curso acaba en {time_remaining_string} a las {course_end_time}." #: lms/djangoapps/courseware/date_summary.py msgid "You lose all access to this course, including your progress." -msgstr "" +msgstr "Pierde todo el acceso a este curso, incluido su progreso." #: lms/djangoapps/courseware/date_summary.py msgid "Audit Access Expires" -msgstr "" +msgstr "El acceso de Asistente expira" #: lms/djangoapps/courseware/date_summary.py msgid "Certificate Available" @@ -6645,7 +6659,7 @@ msgstr "Libros de texto" #: lms/djangoapps/courseware/tabs.py msgid "Dates" -msgstr "" +msgstr "Fechas" #: lms/djangoapps/courseware/views/index.py #, python-brace-format @@ -6820,7 +6834,7 @@ msgstr "Ingresos anuales en tu hogar" #: lms/djangoapps/courseware/views/views.py msgid "Use between 1250 and 2500 characters or so in your response." -msgstr "" +msgstr "Use entre 1250 y 2500 caracteres más o menos en su respuesta" #: lms/djangoapps/courseware/views/views.py msgid "" @@ -7074,16 +7088,20 @@ msgid "Good" msgstr "Bien" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" -msgstr "%(comment_username)s ha respondido a <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" +msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt msgid "View discussion" msgstr "Ver discusión" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "%(comment_username)s ha respondido a <b>%(thread_title)s</b>:" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -7232,8 +7250,8 @@ msgid "Student" msgstr "Estudiante" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "Equipo" @@ -7364,29 +7382,6 @@ msgstr "Respuestas al problema" msgid "Could not find problem with this location." msgstr "No se pudo encontrar el problema con este identificador." -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "La factura número '{num}' no existe." - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "La venta asociada a esta factura ha sido invalidada" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "La factura número {0} ha sido invalidada" - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "Esta factura está activa." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "Los códigos de registro para la factura {0} han sido reactivados." - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "ID del curso" @@ -7417,9 +7412,8 @@ msgstr "ID de usuario" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "Nombre de usuario" @@ -7490,11 +7484,11 @@ msgstr "Estado de verificación" #: lms/djangoapps/instructor/views/api.py msgid "Last Login" -msgstr "" +msgstr "Último inicio de sesión" #: lms/djangoapps/instructor/views/api.py msgid "Date Joined" -msgstr "" +msgstr "Fecha de Registro" #: lms/djangoapps/instructor/views/api.py msgid "Cohort" @@ -7543,54 +7537,6 @@ msgstr "" "El archivo debe contener una columna con el 'nombre de usuario', una columna" " con eñ 'email', o ambos" -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "Código de cupón" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "Id de Curso" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% de Descuento" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "Descripción" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "Fecha de expiración" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "Activo" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "Conteo de códigos redimidos" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "Total de asientos descontados" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "Cantidad Total descontada" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -7611,16 +7557,6 @@ msgstr "encuesta" msgid "proctored exam results" msgstr "resultados del examen supervisado" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "No fue posible leer la cantidad como un decimal" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" -"No fue posible generar ningún código de redención debido a una configuración" -" incorrecta del curso." - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -7869,67 +7805,6 @@ msgstr "" "favor verifique que el nombre de usuario, correo electrónico y el curso " "seleccionado sean correctos e intente nuevamente." -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "El id del cupón está vacio" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "el cupón con el id ({coupon_id}) no existe." - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "el cupón con el id ({coupon_id}) ya está inactivo." - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "el cupón con el id ({coupon_id}) fue actualizado exitósamente." - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" -"El código que está intentando utilizar ({code}) ya se encuentra en uso como " -"un código de registro" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "Por favor introduzca el valor entero del cupón de descuento" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "" -"Por favor introduzca el valor entero del cupón de descuento menor o igual a " -"100" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "Por favor ingrese la fecha en este formato mes/dÃa/año" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "el cupón con el código ({code}) fue añadido exitósamente." - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "el cupón con el código ({code}) ya existe para este curso." - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "no se encontró el id del cupón" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "el cupón con el id ({coupon_id}) fue actualizado exitósamente" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "Instructor" @@ -8041,31 +7916,6 @@ msgstr "Completo" msgid "Incomplete" msgstr "Incompleto" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "" -"El cógido de inscripción ({code}) no ha sido encontrado para el curso " -"{course_name}." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "Este código de inscripción ha sido cancelado. No puede ser utilizado." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "Este código de inscripción ha sido marcado como no utilizado" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "Este código de inscripción ha sido restaurado." - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "No existe una redención para el código de inscripción ({code})." - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -8084,7 +7934,7 @@ msgstr "No se encontró un módulo para la url: {0}" #: lms/djangoapps/instructor/views/tools.py msgid "Could not find student enrollment in the course." -msgstr "" +msgstr "No se encontraron incripciones de estudiante en el curso" #: lms/djangoapps/instructor/views/tools.py #, python-brace-format @@ -8480,14 +8330,16 @@ msgstr " (ignorando {skipped})" msgid " (out of {total})" msgstr " (de los {total})" +#: lms/djangoapps/learner_dashboard/programs.py #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Programas" +#: lms/djangoapps/learner_dashboard/programs.py #: lms/templates/learner_dashboard/program_details.html msgid "Program Details" msgstr "Detalles del programa" @@ -8692,12 +8544,16 @@ msgid "{mode_name} for course {course}" msgstr "{mode_name} para el curso {course}" #: lms/djangoapps/shoppingcart/models.py +#, python-brace-format msgid "" -"You can unenroll in the course and receive a full refund for 14 days after " -"the course start date. " +"To receive a refund you may unenroll from the course on your edX Dashboard " +"({dashboard_url}) up to 14 days after your payment or 14 days after your " +"course starts (up to six months after your payment).\n" msgstr "" -"Puede des inscribirse del curso y recibir un reembolso completo hasta 14 " -"dÃas después de la fecha de inicio." +"Para recibir un reembolso, puede cancelar la inscripción del curso en su " +"panel de control de edX ({dashboard_url}) hasta 14 dÃas después de su pago o" +" 14 dÃas después de que comience su curso (hasta seis meses después de su " +"pago).\n" #: lms/djangoapps/shoppingcart/models.py #, python-brace-format @@ -8711,21 +8567,20 @@ msgstr "" #: lms/djangoapps/shoppingcart/models.py msgid "" "You can unenroll in the course and receive a full refund for 2 days after " -"the course start date. " +"the course start date.\n" msgstr "" "Puede des inscribirse del curso y recibir un reembolso completo hasta 2 dÃas" -" después de la fecha de inicio." +" después de la fecha de inicio.\n" #: lms/djangoapps/shoppingcart/models.py #, python-brace-format msgid "" -"{refund_reminder_msg}To receive your refund, contact {billing_email}. Please" -" include your order number in your email. Please do NOT include your credit " -"card information." +"{refund_reminder_msg}For help unenrolling, Please see How do I unenroll from" +" a course? ({how_to_unenroll_link}) in our edX HelpCenter." msgstr "" -"{refund_reminder_msg} Para recibir su reembolso, contacte a {billing_email}." -" Por favor incluya su número de orden en su correo. Y NO incluya ninguna " -"información de su tarjeta de crédito." +"{refund_reminder_msg}Para ayuda a desinscribirse, Por favor ver ¿Cómo anular" +" la inscripción de un curso? ({how_to_unenroll_link}) en nuestro centro de " +"asistencia de edX." #: lms/djangoapps/shoppingcart/models.py #, python-brace-format @@ -9256,6 +9111,15 @@ msgstr "Costo total" msgid "Currency" msgstr "Moneda" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "Descripción" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "Comentarios" @@ -9404,14 +9268,6 @@ msgstr "Usted no tiene permisos para ver esta página" msgid "View and regenerate certificates." msgstr "Ver y regenerar certificados" -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "Devolución manual" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "Rastrear devoluciones emitidas directamente a través de CyberSource" - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -9450,20 +9306,25 @@ msgid "View feature based enrollment settings" msgstr "Ver configuración de Inscripción basada en caracterÃsticas" #: lms/djangoapps/support/views/index.py +#: lms/templates/support/link_program_enrollments.html msgid "Link Program Enrollments" -msgstr "Enlace para inscripciones en el programa " +msgstr "Enlace para inscripciones en el programa" #: lms/djangoapps/support/views/index.py msgid "Link LMS users to program enrollments" msgstr "" +"enlace usuarios de LMS a las inscripciones de los programas\n" +"vincule usuarios de LMS a las inscripciones de programas" #: lms/djangoapps/support/views/index.py msgid "Program Enrollments Inspector Tool" -msgstr "" +msgstr "Herramienta de inspección de inscripciones de programa" #: lms/djangoapps/support/views/index.py msgid "Find information related to a learner's program enrollments" msgstr "" +"Encuentre información relacionada con las inscripciones en el programa de un" +" alumno" #: lms/djangoapps/support/views/manage_user.py msgid "user_support_url" @@ -9489,45 +9350,9 @@ msgstr "Usuario activado con éxito" msgid "User Disabled Successfully" msgstr "Usuario Desactivado Exitosamente" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "Dirección de correo electrónico" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "Id de Curso" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "Usuario no encontrado" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "TodavÃa se pueden tramitar devoluciones en el curso {course_id}." - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "" -"No se encontró alguna orden del usuario {user} en el curso {course_id} " - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "Desmatriculé a {user} de {course_id}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "Devolvà {cost} por la orden {order_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "Debe completar una encuesta" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -9576,28 +9401,33 @@ 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 "You are already in a team in this course." -msgstr "Ya está en un equipo para este curso." +msgid "topic_id is required" +msgstr "topic_id es requerido" #: lms/djangoapps/teams/views.py msgid "You can't create a team in an instructor managed topic." msgstr "" +"No es posible crear un equipo en un tema administrado por un instructor." + +#: lms/djangoapps/teams/views.py +msgid "You are already in a team in this teamset." +msgstr "Usted ya hace parte de un equipo dentro de este conjunto de equipos." #: lms/djangoapps/teams/views.py msgid "teamset_id and team_id are mutually exclusive options." -msgstr "" +msgstr "teamset_id y team_id son opciones mutuamente excluyentes." #: lms/djangoapps/teams/views.py msgid "teamset_id requires course_id to also be provided." -msgstr "" +msgstr "teamset_id requiere que course_id también sea suministrado." #: lms/djangoapps/teams/views.py msgid "No teamset found in given course with given id" -msgstr "" +msgstr "No se encontraron equipos en el curso dado con la identificación dada" #: lms/djangoapps/teams/views.py msgid "username or (team_id or teamset_id) must be specified." -msgstr "" +msgstr "se debe especificar el nombre de usuario o (team_id o teamset_id)." #: lms/djangoapps/teams/views.py msgid "Username is required." @@ -9613,7 +9443,7 @@ msgstr "El equipo ya está lleno." #: lms/djangoapps/teams/views.py msgid "You can't join an instructor managed team." -msgstr "" +msgstr "No puede unirse a un equipo administrado por un instructor." #: lms/djangoapps/teams/views.py #, python-brace-format @@ -9629,7 +9459,7 @@ msgstr "" #: lms/djangoapps/teams/views.py msgid "You can't leave an instructor managed team." -msgstr "" +msgstr "No puedes dejar un equipo administrado por un instructor." #: lms/djangoapps/verify_student/models.py msgid "The course for which this deadline applies" @@ -9779,7 +9609,7 @@ msgstr "Se recomienda que cambies tu contraseña." #: lms/templates/instructor/edx_ace/accountcreationandenrollment/email/body.html msgid "You may access your course." -msgstr "" +msgstr "Puede acceder a su curso." #: lms/templates/instructor/edx_ace/accountcreationandenrollment/email/body.html #: lms/templates/instructor/edx_ace/accountcreationandenrollment/email/body.txt @@ -9799,7 +9629,7 @@ msgstr "" #: lms/templates/instructor/edx_ace/accountcreationandenrollment/email/body.txt #, python-format msgid "You may access your course at: %(course_url)s." -msgstr "" +msgstr "Puede acceder a su curso en: %(course_url)s." #: lms/templates/instructor/edx_ace/accountcreationandenrollment/email/subject.txt #: lms/templates/instructor/edx_ace/enrollenrolled/email/subject.txt @@ -10149,6 +9979,7 @@ msgid "" "{start_anchor}Click here{end_anchor} to delete your single signed on (SSO) " "session." msgstr "" +"{start_anchor}hacer clic aquÃ{end_anchor} para eliminar su sesión (SSO)." #: lms/templates/logout.html msgid "We are signing you in." @@ -10160,6 +9991,9 @@ msgid "" " This may take a minute. If you are not redirected, go to the home page.\n" " " msgstr "" +"\n" +" Esto podrÃa tomar un minuto. Si no es redirigido, vaya a la página de inicio.\n" +" " #: lms/templates/logout.html #, python-brace-format @@ -10167,6 +10001,8 @@ msgid "" "If you are not redirected within 5 seconds, {start_anchor}click here to go " "to the home page{end_anchor}." msgstr "" +"Si no eres redireccionado en 5 segundos, {start_anchor} debes hacer clic " +"aquà para ir a la página principal{end_anchor}. " #: lms/templates/main_django.html cms/templates/base.html #: lms/templates/main.html @@ -10203,6 +10039,9 @@ msgstr "" #: lms/templates/oauth2_provider/authorize.html #: openedx/core/djangoapps/user_api/admin.py +#: cms/templates/course-create-rerun.html cms/templates/index.html +#: cms/templates/manage_users.html cms/templates/manage_users_lib.html +#: cms/templates/videos_index_pagination.html msgid "Cancel" msgstr "Cancelar" @@ -10211,8 +10050,8 @@ msgid "Allow" msgstr "Permitir" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "Error" @@ -10231,7 +10070,7 @@ msgstr "Hola %(full_name)s," #: lms/templates/verify_student/edx_ace/verificationexpiry/email/body.txt #, python-format msgid "Your %(platform_name)s ID verification has expired. " -msgstr "" +msgstr "Tu %(platform_name)s verificación de ID ha expirado " #: lms/templates/verify_student/edx_ace/verificationexpiry/email/body.html #: lms/templates/verify_student/edx_ace/verificationexpiry/email/body.txt @@ -10239,12 +10078,16 @@ msgid "" "You must have a valid ID verification to take proctored exams and qualify " "for certificates." msgstr "" +"Debe tener una verificación de identificación válida para tomar exámenes " +"supervisados ​​y calificar para los certificados." #: lms/templates/verify_student/edx_ace/verificationexpiry/email/body.html #: lms/templates/verify_student/edx_ace/verificationexpiry/email/body.txt msgid "" "Follow the link below to submit your photos and renew your ID verification." msgstr "" +"Siga el enlace a continuación para enviar sus fotos y renovar su " +"verificación de ID" #: lms/templates/verify_student/edx_ace/verificationexpiry/email/body.html #: lms/templates/verify_student/edx_ace/verificationexpiry/email/body.txt @@ -10262,6 +10105,7 @@ msgstr "Volver a enviar la verificación: %(lms_verification_link)s" #, python-format msgid "ID verification FAQ : %(help_center_link)s " msgstr "" +"Preguntas frecuentes sobre la verificación de ID: %(help_center_link)s" #: lms/templates/verify_student/edx_ace/verificationexpiry/email/body.html #: lms/templates/verify_student/edx_ace/verificationexpiry/email/body.txt @@ -10490,6 +10334,8 @@ msgid "" "You need to {anchor_start_login}log in{anchor_end} or " "{anchor_start_signup}sign up{anchor_end} to use this function." msgstr "" +"Necesitas {anchor_start_login}iniciar sesión{anchor_end} o " +"{anchor_start_signup}registrarte{anchor_end} para poder usar esta función." #: lms/templates/wiki/includes/anonymous_blocked.html msgid "You need to log in or sign up to use this function." @@ -10510,6 +10356,9 @@ msgid "" "several useful guides online. See any of the links below for in-depth " "details:" msgstr "" +"Este wiki utiliza {start_strong}Reducción{end_strong} para limpiar. Hay " +"varias guÃas útiles en lÃnea. Consulta cualquiera de los enlaces a " +"continuación para obtener detalles en profundidad:" #: lms/templates/wiki/includes/cheatsheet.html msgid "Markdown: Basics" @@ -10610,8 +10459,8 @@ msgstr "" "de wiki%(end_link)s para más información." #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "Adjuntos" @@ -10650,11 +10499,10 @@ msgstr "" "conveniente." #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -10771,6 +10619,7 @@ msgstr "Ve a la página principal de %(platform_name)s " #: openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/base_body.html #: themes/red-theme/lms/templates/ace_common/edx_ace/common/base_body.html +#: cms/templates/widgets/header.html msgid "Sign In" msgstr "Iniciar sesión" @@ -10821,7 +10670,7 @@ msgstr "Nuestra dirección de correo es" #: openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/base_body.html msgid "Unsubscribe from these emails." -msgstr "" +msgstr "Dejar de recibir estos correos." #: openedx/core/djangoapps/ace_common/templates/ace_common/edx_ace/common/base_head.html msgid "edX Email" @@ -10922,7 +10771,7 @@ msgstr "" #: openedx/core/djangoapps/auth_exchange/forms.py #, python-format msgid "'%s' is not a valid scope." -msgstr "" +msgstr "'%s' no es un alcance válido." #: openedx/core/djangoapps/bookmarks/apps.py #: openedx/features/course_bookmarks/plugins.py @@ -11030,6 +10879,13 @@ msgid "" "the org that the course is in, then the more specific context overrides the " "more general context." msgstr "" +"Estos definen el contexto para habilitar esta configuración. Si no se " +"definen valores, la configuración aplica de forma global. Si se establece un" +" solo valor, la configuración aplica a todos los cursos dentro de ese " +"contexto. Como máximo se puede establecer un valor a la vez.{br} Si " +"múltiples contextos aplican al curso (por ejemplo, si la configuración es " +"establecida para el curso especÃficamente y para la organización del curso, " +"el contexto más especÃfico sobreescribe el contexto más general." #: openedx/core/djangoapps/config_model_utils/admin.py msgid "" @@ -11038,11 +10894,16 @@ msgid "" "For example, if \"Enabled\" is left as \"Unknown\" in the course context, " "then that course will be Enabled only if the org that it is in is Enabled." msgstr "" +"Si alguno de estos valores son dejados vacÃos o \"Desconocidos\", entonces " +"su valor en tiempo de ejecución se recuperará del siguiente contexto más " +"especÃfico que aplique. Por ejemplo, si \"Habilitado\" se deja como " +"\"Desconocido\" en el contexto del curso, entonces ese curso se habilitará " +"solo si la organización en la que se encuentra está habilitada." #: openedx/core/djangoapps/config_model_utils/models.py #, python-format msgid "%(value)s should have the form ORG+COURSE" -msgstr "" +msgstr "%(value)s deberÃa tener la estructura ORG+COURSE" #: openedx/core/djangoapps/config_model_utils/models.py msgid "Enabled" @@ -11050,23 +10911,29 @@ msgstr "Habilitado" #: openedx/core/djangoapps/config_model_utils/models.py msgid "Configure values for all course runs associated with this site." -msgstr "" +msgstr "Configura los valores para todos los cursos asociados con este sitio." #: openedx/core/djangoapps/config_model_utils/models.py msgid "" "Configure values for all course runs associated with this Organization. This" " is the organization string (i.e. edX, MITx)." msgstr "" +"Configure valores para todas las ejecuciones de cursos asociadas con esta " +"Organización. Esta es la cadena correspondiente a esta organización (por " +"ejemplo, edX, MITx)." #: openedx/core/djangoapps/config_model_utils/models.py msgid "Course in Org" -msgstr "" +msgstr "Curso en organización" #: openedx/core/djangoapps/config_model_utils/models.py msgid "" "Configure values for all course runs associated with this course. This is " "should be formatted as 'org+course' (i.e. MITx+6.002x, HarvardX+CS50)." msgstr "" +"Configurar los valores para todas las ejecuciones asociadas con este curso. " +"Este deberÃa ser formateado como 'org+course' (i.e. MITx+6.002x, " +"HarvardX+CS50)." #: openedx/core/djangoapps/config_model_utils/models.py #: cms/templates/course-create-rerun.html cms/templates/index.html @@ -11079,26 +10946,33 @@ msgid "" "Configure values for this course run. This should be formatted as the " "CourseKey (i.e. course-v1://MITx+6.002x+2019_Q1)" msgstr "" +"Configurar los valores para todas las ejecuciones asociadas con este curso. " +"Este deberÃa ser formateado como el CourseKey (i.e. " +"course-v1://MITx+6.002x+2019_Q1)" #: openedx/core/djangoapps/config_model_utils/models.py msgid "Configuration may not be specified at more than one level at once." msgstr "La configuración no se puede especificar en más de un nivel a la vez." +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" -msgstr "" +msgstr "Administrar usuarios y contenido de autor" #: openedx/core/djangoapps/content_libraries/models.py msgid "Author content" -msgstr "" +msgstr "contenido del autor" #: openedx/core/djangoapps/content_libraries/models.py msgid "Read-only" -msgstr "" +msgstr "Solo Lectura" #: openedx/core/djangoapps/content_libraries/models.py msgid "One and only one of 'user' and 'group' must be set." -msgstr "" +msgstr "Se debe establecer uno y solo uno de 'usuario' y 'grupo'." #: openedx/core/djangoapps/cors_csrf/models.py msgid "" @@ -11412,6 +11286,7 @@ msgid "" "Comma-separated list of filters that this application will be allowed to " "request." msgstr "" +"Lista de filtros separados por comas que esta aplicación podrá solicitar." #: openedx/core/djangoapps/oauth_dispatch/models.py msgid "Content Provider" @@ -11514,6 +11389,10 @@ msgstr "Tipo de error conocido" msgid "Schedule start < course start" msgstr "Horario de inicio < Inicio de curso" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "Id de Curso" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "Todos" @@ -11522,6 +11401,15 @@ msgstr "Todos" msgid "Experience" msgstr "Experiencia" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "Id de Curso" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -11601,6 +11489,8 @@ msgid "" "We hope you're enjoying {start_strong}{course_name}{end_strong}! We want to " "let you know what you can look forward to in the coming weeks:" msgstr "" +"¡ Esperamos que esté disfrutando {start_strong}{course_name}{end_strong} ! " +"Queremos que conozca lo que puede esperar en las próximas semanas:" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/instructorledcourseupdate/email/body.html #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/instructorledcourseupdate/email/body.txt @@ -11608,6 +11498,8 @@ msgid "" "We encourage you to spend time with the course each week. Your focused " "attention will pay off in the end!" msgstr "" +"Lo invitamos a invertir tiempo en el curso cada semana. ¡Su atención " +"enfocada dará sus frutos al final!" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/instructorledcourseupdate/email/body.txt #, python-format @@ -11615,11 +11507,13 @@ msgid "" "We hope you're enjoying %(course_name)s! We want to let you know what you " "can look forward to in the coming weeks:" msgstr "" +"¡ Esperamos que esté disfrutando%(course_name)s! Queremos que conozca lo que" +" puede esperar en las próximas semanas:" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/instructorledcourseupdate/email/subject.txt #, python-format msgid "%(course_name)s Weekly Update" -msgstr "" +msgstr "%(course_name)s Actualización semanal" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.html #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.txt @@ -11762,6 +11656,7 @@ msgstr "" "Verificado antes del %(user_schedule_upgrade_deadline_time)s." #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "Cambia ahora a la opción con Certificado Verificado" @@ -12018,7 +11913,6 @@ msgstr "" "en blanco." #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -12047,8 +11941,8 @@ msgid "Success" msgstr "Éxito" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "Acciones" @@ -12218,6 +12112,13 @@ msgid "" "your dashboard. {blank_lines}If you don't have an account on {platform_name}" " yet, click {register_label_strong} at the top of the page." msgstr "" +"Has iniciado sesión exitosamente en tu Cuenta de {provider_name}, sin " +"embargo, esta cuenta aún no está vinculada con tu cuenta de {platform_name}." +" {blank_lines} Utiliza tu nombre de usuario y contraseña de {platform_name} " +"para iniciar sesión en {platform_name}, y luego vincula tu Cuenta de " +"{platform_name} con {provider_name} desde tu panel principal. {blank_lines} " +"Si aún no tienes una Cuenta en {platform_name}, puedes hacer clic en " +"{register_label_strong} en la parte superior de la página." #: openedx/core/djangoapps/user_authn/views/login.py #: lms/templates/header/navbar-not-authenticated.html @@ -12233,6 +12134,14 @@ msgstr "" "Ocurrió un error en la recepción de su información de ingreso. Por favor " "escrÃbanos al correo electrónico." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -12241,6 +12150,10 @@ msgid "" "check your spam folders or {link_start}contact {platform_name} " "Support{link_end}." msgstr "" +"Para iniciar sesión, debes activar su cuenta. {blank_lines} Hemos enviado un" +" enlace de activación a {email_strong}. Si no recibes un correo electrónico," +" revisa tus carpetas de correo no deseado o {link_start} comunÃcate con " +"{platform_name} Soporte {link_end}." #: openedx/core/djangoapps/user_authn/views/login.py msgid "Too many failed login attempts. Try again later." @@ -12248,21 +12161,23 @@ msgstr "" "Demasiados intentos fallidos de inicio de sesión. Inténtelo de nuevo más " "tarde." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" "As {allowed_domain} user, You must login with your {allowed_domain} " "{link_start}{provider} account{link_end}." msgstr "" - -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "nombredeusuario@dominio.com" +"Como usuario {allowed_domain}, debe iniciar sesión con su {allowed_domain} " +"{link_start}{provider} Cuenta{link_end}." #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. @@ -12281,6 +12196,12 @@ msgstr "" msgid "Create Account" msgstr "Crear cuenta" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "nombredeusuario@dominio.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -12297,6 +12218,13 @@ msgstr "" "La cuenta de usuario asociada con esta dirección de correo electrónico no " "puede restablecer la contraseña." +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" +"Su solicitud anterior está en progreso, por favor intente de nuevo en unos " +"minutos." + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "El cambio de contraseña no ha sido exitoso" @@ -12319,13 +12247,6 @@ msgstr "" " creada. {bold_start}{email}{bold_end} es ahora su correo de acceso " "principal." -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" -"Su solicitud anterior está en progreso, por favor intente de nuevo en unos " -"minutos." - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "" @@ -12520,6 +12441,11 @@ msgid "" "process your personal data in accordance with the " "{privacy_policy_link_start}Privacy Policy{privacy_policy_link_end}." msgstr "" +"Al Crear una Cuenta, estás accediendo a los " +"{terms_of_service_link_start}{terms_of_service}{terms_of_service_link_end} y" +" reconoces que {platform_name} y todos sus miembros, pueden procesar tu " +"datos personales de acuerdo a la{privacy_policy_link_start}PolÃtica de " +"Privacidad{privacy_policy_link_end}." #. Translators: "Terms of service" is a legal document users must agree to #. in order to register a new account. @@ -12568,6 +12494,18 @@ msgstr "" "Nombre de usuario creado por la integración de canal de vÃdeo, por ejemplo, " "veda_service_user." +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "Forzar encendido" @@ -12581,9 +12519,15 @@ msgid "" "This content is only accessible to registered learners. Sign in or register " "to view it." msgstr "" +"Este contenido solo puede ser accedido por usuarios registrados. Inicie " +"sesión o cree una cuenta para ver el contenido." #: openedx/core/djangoapps/xblock/runtime/mixin.py msgid "This content is only accessible to enrolled learners. " +msgstr "Este contenido solo puede ser accedido por usuarios inscritos" + +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." msgstr "" #: openedx/core/lib/api/view_utils.py @@ -12655,28 +12599,28 @@ msgstr "" #: openedx/features/calendar_sync/ics.py #, python-brace-format msgid "{assignment} is due for {course}." -msgstr "" +msgstr "{assignment} tiene vencimiento en {course}." #: openedx/features/calendar_sync/plugins.py msgid "Calendar Sync" -msgstr "" +msgstr "Sincronizar Calendario" #: openedx/features/calendar_sync/plugins.py msgid "Unsubscribe from calendar updates" -msgstr "" +msgstr "Desuscribirse de las actualizaciones de calendario" #: openedx/features/calendar_sync/plugins.py msgid "Subscribe to calendar updates" -msgstr "" +msgstr "Suscribirse a las actualizaciones de calendario" #: openedx/features/calendar_sync/views/management.py #, python-brace-format msgid "Updates for Your {course} Schedule" -msgstr "" +msgstr "Actualizaciones para su calendario de {course}" #: openedx/features/calendar_sync/views/management.py msgid "Update Your Calendar" -msgstr "" +msgstr "Actualice su calendario" #: openedx/features/calendar_sync/views/management.py #, python-brace-format @@ -12684,14 +12628,17 @@ msgid "" "Your assignment due dates for {course} were recently adjusted. Update your " "calendarwith your new schedule to ensure that you stay on track!" msgstr "" +"Las fechas de vencimiento de su tarea para {course} se ajustaron " +"recientemente. Actualice su calendario con su nuevo horario para asegurarse " +"de mantenerse en el camino correcto!" #: openedx/features/calendar_sync/views/management.py msgid "Stay on Track" -msgstr "" +msgstr "Manténgase al dÃa" #: openedx/features/calendar_sync/views/management.py msgid "Mark Your Calendar" -msgstr "" +msgstr "Marque su calendario" #: openedx/features/calendar_sync/views/management.py #, python-brace-format @@ -12700,6 +12647,9 @@ msgid "" "complete your self-paced course. This schedule of assignment due dates for " "{course} will help you stay on track!" msgstr "" +"Cumplir con un horario es la mejor manera de asegurarse de completar con " +"éxito su curso a su propio ritmo. ¡Este cronograma de fechas de vencimiento " +"de tareas para {course} lo ayudará a mantenerse en el camino!" #: openedx/features/content_type_gating/models.py #: openedx/features/course_duration_limits/models.py @@ -12841,6 +12791,9 @@ msgid "" "You must be enrolled in the course to see course content. Please contact " "your degree administrator or edX Support if you have questions." msgstr "" +"Debes estar inscrito en el curso para ver el contenido del curso. Por favor " +"póngase en contacto con su administrador de curso o con el soporte de edX si" +" tiene alguna pregunta." #: openedx/features/course_experience/views/course_home_messages.py #, python-brace-format @@ -12885,6 +12838,14 @@ msgid "" "specifically, and for the org that the course is in, then the more specific " "context overrides the more general context." msgstr "" +"Estos definen el contexto para deshabilitar los descuentos controlados por " +"lms. Si no se establecen valores, la configuración se aplica globalmente. Si" +" se establece un único valor, la configuración se aplica a todos los cursos " +"dentro de ese contexto. Como máximo, se puede establecer un valor a la vez. " +"<br>Si se aplican múltiples contextos a un curso (por ejemplo, si la " +"configuración se especifica especÃficamente para el curso y para la " +"organización en la que se encuentra el curso, el contexto más especÃfico " +"anulará al contexto más general." #: openedx/features/discounts/admin.py msgid "" @@ -12893,6 +12854,12 @@ msgid "" "For example, if \"Disabled\" is left as \"Unknown\" in the course context, " "then that course will be Disabled only if the org that it is in is Disabled." msgstr "" +"Si alguno de estos valores se deja vacÃo o \"Desconocido\", entonces su " +"valor en tiempo de ejecución se será recuperado y tomado del siguiente " +"contexto más especÃfico al que puede aplicar. Por ejemplo, si " +"\"Deshabilitado\" se deja como \"Desconocido\" en el contexto del curso, ese" +" curso se deshabilitará solo si la organización en la que se encuentra está" +" también deshabilitada." #: openedx/features/discounts/admin.py msgid "" @@ -12928,6 +12895,10 @@ msgid "" "[{strikeout_price}]{span_close}{br}Use code {b_open}{code}{b_close} at " "checkout! {a_open}Upgrade Now{a_close}{div_close}" msgstr "" +"{banner_open} Realice su Upgrade antes del {discount_expiration_date} y " +"ahorre {percentage}% [{strikeout_price}]{span_close}{br}Use el código " +"{b_open}{code}{b_close} durante el pago! {a_open}Haga el Upgrade " +"ahora{a_close}{div_close}" #: openedx/features/enterprise_support/api.py #, python-brace-format @@ -13058,6 +13029,8 @@ msgid "" "Non writable git url provided. Expecting something like: " "git@github.com:edx/edx4edx_lite.git" msgstr "" +"URL git proporcionada no es escribible. Esperando algo como: " +"git@github.com:edx/edx4edx_lite.git" #: cms/djangoapps/contentstore/git_export_utils.py msgid "" @@ -13251,7 +13224,7 @@ msgstr "HTML" #: cms/djangoapps/contentstore/views/component.py msgid "Problem" -msgstr "" +msgstr "Problemas" #: cms/djangoapps/contentstore/views/component.py lms/templates/video.html msgid "Video" @@ -13350,11 +13323,13 @@ msgstr "Curso exportado exitósamente al repositorio de git" msgid "Vertical" msgstr "Vertical" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/djangoapps/contentstore/views/helpers.py +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "Sección" +#: cms/djangoapps/contentstore/views/helpers.py #: lms/templates/ccx/schedule.html msgid "Subsection" msgstr "Subsección" @@ -13636,6 +13611,18 @@ msgstr "Transcripción en progreso" msgid "Transcript Ready" msgstr "Transcripción lista" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "Falla parcial" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "Falló la transcripción" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "Un archivo de imagen es requerido." @@ -13722,13 +13709,15 @@ msgstr "" #: cms/djangoapps/maintenance/views.py msgid "Edit Announcements" -msgstr "" +msgstr "Editar anuncios" #: cms/djangoapps/maintenance/views.py msgid "" "This view shows the announcement editor to create or alter announcements " "that are shown on the rightside of the dashboard." msgstr "" +"Esta vista muestra el editor de anuncios para crear o editar anuncios que " +"son mostrados en la parte derecha del panel de control." #: cms/djangoapps/maintenance/views.py msgid "Please provide course id." @@ -13786,8 +13775,8 @@ msgstr "Contenido" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "Configuración" @@ -13814,7 +13803,7 @@ msgstr "Estructura del curso" #: cms/templates/course_outline.html #: lms/templates/dashboard/_dashboard_status_verification.html msgid "Warning" -msgstr "" +msgstr "Advertencia" #: cms/templates/html_error.html lms/templates/module-error.html msgid "Error:" @@ -13835,14 +13824,14 @@ msgstr "Número de curso:" msgid "Course Run:" msgstr "Edición del Curso:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "Cursos" @@ -13866,8 +13855,9 @@ msgstr "Instructores" msgid "Requirements" msgstr "Requerimientos" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "Detalles" @@ -13914,6 +13904,8 @@ msgid "" "edX, Open edX, and the edX and Open edX logos are registered trademarks of " "{link_start}edX Inc.{link_end}" msgstr "" +"edX, Open edX, y los logos de edX y Open edX son marcas registradas de " +"{link_start}edX Inc.{link_end}" #: cms/templates/widgets/header.html lms/templates/header/header.html #: lms/templates/navigation/navigation.html @@ -13921,15 +13913,15 @@ msgstr "" msgid "Choose Language" msgstr "Seleccionar idioma" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "Cuenta" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -14001,8 +13993,8 @@ msgstr "Menú de usuario" msgid "Usermenu dropdown" msgstr "Menú desplegable de usuario" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "Cerrar sesión" @@ -14081,13 +14073,14 @@ msgstr "Lista de discusiones" #: lms/djangoapps/discussion/templates/discussion/discussion_private_fragment.html msgid "Private Discussion" -msgstr "" +msgstr "Discusión Privada" #: lms/djangoapps/discussion/templates/discussion/discussion_private_fragment.html msgid "" "This is a private discussion. You do not have permissions to view this " "discussion" msgstr "" +"Esta es una discusión privada. Usted no tiene permisos para ver esta página" #: lms/djangoapps/discussion/templates/discussion/discussion_profile_page.html #: lms/templates/discussion/_user_profile.html @@ -14173,19 +14166,19 @@ msgstr "Inicia: {date}" msgid "View all Courses" msgstr "Ver todos los cursos" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "Panel de control" #: lms/templates/dashboard.html themes/edx.org/lms/templates/dashboard.html msgid "results successfully populated," -msgstr "" +msgstr "resultados populados exitosamente," #: lms/templates/dashboard.html themes/edx.org/lms/templates/dashboard.html msgid "Click to load all enrolled courses" -msgstr "" +msgstr "Haz click para cargar todos los cursos inscritos" #: lms/templates/dashboard.html themes/edx.org/lms/templates/dashboard.html msgid "You are not enrolled in any courses yet." @@ -14193,8 +14186,8 @@ msgstr "No está inscrito en ningún curso aún." #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "Explorar cursos" @@ -14212,14 +14205,14 @@ msgstr "Errores en la carga del curso" msgid "Search Your Courses" msgstr "Busca en tus cursos" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "Reiniciar búsqueda" #: lms/templates/dashboard.html msgid "Skip to list of announcements" -msgstr "" +msgstr "Saltar a la lista de anuncios" #: lms/templates/dashboard.html themes/edx.org/lms/templates/dashboard.html msgid "Account Status Info" @@ -14237,7 +14230,7 @@ msgstr "Recibir mensajes de correo electrónico del curso" msgid "Save Settings" msgstr "Guardar ajustes" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -14247,9 +14240,98 @@ msgstr "Guardar ajustes" msgid "Unenroll" msgstr "Cancelar la inscripción" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "Ver la Unidad en Studio" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" +"Parece que no cumplió algunos plazos importantes según nuestro calendario " +"sugerido." + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "Está auditando, tomando de forma gratuita, este curso," + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr " lo que significa que no podrá participar en tareas calificadas." + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" +"Parece que no cumplió algunos plazos importantes según nuestro calendario " +"sugerido. Para completar las tareas calificadas como parte de este curso y " +"cambiar las tareas vencidas hacia el futuro, puede hacer upgrade hoy." + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "Actualizar a fechas de vencimiento de turno" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" +"Para completar las asignaciones calificables como parte de este curso, puede" +" mejorar su inscripción hoy." + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" +"Hemos creado un cronograma sugerido para ayudarlo a mantenerse encaminado." + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" +"Pero no te preocupes—es flexible, por lo que puedes aprender a tu propio " +"ritmo. Si te pierdes las fechas sugeridas, podrás ajustarlas para asegurar " +"que puedes mantenerte al dÃa." #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -14284,7 +14366,7 @@ msgstr "Ya existe una cuenta con la nueva dirección de correo electrónico." msgid "You should Register before trying to access the Unit" msgstr "Debes registrarte antes de intentar acceder a la unidad" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "Realizar la inscripción" @@ -14327,7 +14409,7 @@ msgstr "Autenticación externa fallida" #: lms/templates/footer.html msgid "organization logo" -msgstr "" +msgstr "logo de la organización" #: lms/templates/forgot_password_modal.html msgid "" @@ -14394,7 +14476,7 @@ msgstr "" "disponible.{line_break}Si has completado esta tarea, tu nota está disponible" " en la {link_start}página de progreso{link_end}." -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "Buscar curso" @@ -14407,7 +14489,7 @@ msgstr "Bienvenido a la plataforma {platform_name}" #. untranslated. See http://open.edx.org for more information. #: lms/templates/index_overlay.html msgid "It works! Powered by Open edX{registered_trademark}" -msgstr "" +msgstr "¡Funciona! Impulsado por Open edX{registered_trademark}" #: lms/templates/invalid_email_key.html msgid "Invalid email change key" @@ -14540,23 +14622,16 @@ msgstr "(Recargar la página para actualizar)" msgid "working" msgstr "trabajando" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "Ha habido un error en los servidores de {platform_name}" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html -#: lms/templates/courseware/error-message.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"Lo sentimos, este módulo está temporalmente NO disponible. Estamos " -"trabajando para solucionarlo lo antes posible. Por favor escrÃbenos a " -"{tech_support_email} para reportar este tipo de problemas o caidas en el " -"servicio." #: lms/templates/module-error.html msgid "Raw data:" @@ -14595,7 +14670,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "Ahora estás viendo el curso como {i_start}{user_name}{i_end}." #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -14627,7 +14710,7 @@ msgstr "Restablecer respuesta" #: lms/templates/problem.html msgid "Answers are displayed within the problem" -msgstr "" +msgstr "Las respuestas son mostradas en el problema" #: lms/templates/problem_notifications.html msgid "Next Hint" @@ -14663,16 +14746,6 @@ msgstr "Correo electrónico" msgid "Return To %s" msgstr "Regresar a %s" -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "Re suscripción exitosa!" @@ -14714,22 +14787,22 @@ msgstr "¡Importante!" #: lms/templates/seq_module.html msgctxt "unit" msgid "Previous" -msgstr "" +msgstr "Anterior" #. Translators: A button for showing the Next Unit #: lms/templates/seq_module.html msgctxt "unit" msgid "Next" -msgstr "" +msgstr "Siguiente" #: lms/templates/seq_module.html msgid "Sequence" msgstr "Secuencia" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" -msgstr "" +msgstr "Completado" #: lms/templates/signup_modal.html msgid "Sign Up for {platform_name}" @@ -14749,7 +14822,7 @@ msgstr "Ej: Tu nombre (asà aparecerá en los certificados)" #: lms/templates/signup_modal.html msgid "{start_li}Welcome{end_li} {name}" -msgstr "" +msgstr "{start_li}Bienvenido{end_li} {name}" #: lms/templates/signup_modal.html #: themes/stanford-style/lms/templates/register-shib.html @@ -14857,18 +14930,18 @@ msgstr "Puntaje (únicamente para sobreescribir)" msgid "Reset Learner's Attempts to Zero" msgstr "Reiniciar los intentos del estudiante" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "Borrar estado del estudiante" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "Calificar el envÃo del estudiante nuevamente" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "Calificar de nuevo. Solo si el estudiante mejora la calificación" @@ -14906,7 +14979,7 @@ msgstr "Libro de texto para {course_number}" msgid "Textbook Navigation" msgstr "Navegación del libro de texto" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "Página" @@ -15019,9 +15092,9 @@ msgstr "Página {current_page} de {total_pages}" msgid "Recent git load activity for {course_id}" msgstr "Actividad de carga de git reciente para {course_id}" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -15081,7 +15154,7 @@ msgstr "" " al panel de control. Si deseas volver a suscribirte a las notificaciones, " "haz clic {undo_link_start}aquÃ{link_end}." -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "Panel de Control para:" @@ -15089,8 +15162,8 @@ msgstr "Panel de Control para:" msgid "More options" msgstr "Más opciones" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "Más opciones" @@ -16079,32 +16152,35 @@ msgstr "" #: lms/templates/bulk_email/confirm_unsubscribe.html #: lms/templates/bulk_email/unsubscribe_success.html msgid "Unsubscribe" -msgstr "" +msgstr "Darse de baja" #: lms/templates/bulk_email/confirm_unsubscribe.html msgid "confirm unsubscribe from {org} {course} emails." msgstr "" +"Confirme su retiro de la lista para los correos del curso {org} - {course}." #: lms/templates/bulk_email/confirm_unsubscribe.html msgid "Note:" -msgstr "" +msgstr "Nota:" #: lms/templates/bulk_email/confirm_unsubscribe.html msgid "" "You will still receive course emails from other courses you are enrolled in." msgstr "" +"TodavÃa recibirá correos electrónicos de otros cursos en los que esté " +"inscrito." #: lms/templates/bulk_email/unsubscribe_success.html msgid "You have successfully unsubscribed from {org} {course} emails." -msgstr "" +msgstr "Se ha dado de baja para los correos del curso {org} {course}." #: lms/templates/bulk_email/unsubscribe_success.html msgid "You have not been unsubscribed from {org} {course} emails." -msgstr "" +msgstr "No ha sido dado de baja para los correos del curso {org} {course}." #: lms/templates/bulk_email/unsubscribe_success.html msgid "{link_start}Return to edX.org{link_end}" -msgstr "" +msgstr "{link_start}Volver a edX.org{link_end}" #: lms/templates/calculator/toggle_calculator.html msgid "Open Calculator" @@ -16634,37 +16710,6 @@ msgstr "" msgid "About edX Certificates" msgstr "Acerca de los Certificados de edX" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "Transacción de pago cancelada" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"Tu transacción ha sido cancelada. Si consideras que ocurrió un error, " -"contacta a {email}." - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "Error en el proceso de pago" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "Cargando datos solicitados" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "Por favor, espera mientras recuperamos el detalle de tu orden" - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -16903,28 +16948,27 @@ msgstr "{section_format} fecha lÃmite {{date}}" msgid "This content is graded" msgstr "Este contenido es calificable" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "Ocurrió un error. Por favor intenta nuevamente más tarde." - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +"Ha ocurrido un error. Por favor asegúrese que ha iniciado sesión para " +"inscribirse." + +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "Ocurrió un error. Por favor intenta nuevamente más tarde." #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "Usted está inscrito en este curso:" #: lms/templates/courseware/course_about.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: lms/templates/shoppingcart/registration_code_receipt.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "View Course" msgstr "Ver curso" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "Inscripciones cerradas" @@ -16937,13 +16981,9 @@ msgstr "La inscripción en este curso es sólo por invitación" msgid "Enrollment is Closed" msgstr "Inscripción cerrada" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "Añadir {course_name} al carrito {start_span}({price} USD){end_span}" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" -msgstr "" +msgstr "IncrÃbase ahora" #: lms/templates/courseware/course_about.html msgid "View About Page in studio" @@ -17067,6 +17107,15 @@ msgstr "Utilidades de curso" msgid "Courseware" msgstr "Contenidos" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" +"Lo sentimos, este módulo está temporalmente NO disponible. Estamos " +"trabajando para solucionarlo lo antes posible." + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "Buscar cursos" @@ -17094,20 +17143,23 @@ msgstr "Información del curso {course.display_number_with_default}" #: lms/templates/courseware/dates.html msgid "Important Dates" -msgstr "" +msgstr "Fechas importantes" #: lms/templates/courseware/dates.html -msgid "Due Today" -msgstr "" +msgid "Today" +msgstr "Hoy" #: lms/templates/courseware/dates.html msgid "Verified Only" -msgstr "" +msgstr "Solo verificado" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." -msgstr "" +msgid "Due Next" +msgstr "Próximo vencimiento" + +#: lms/templates/courseware/dates.html +msgid "Not yet released" +msgstr "Aún no liberado" #: lms/templates/courseware/gradebook.html msgid "Gradebook" @@ -17161,8 +17213,9 @@ msgid "Welcome to {course_title}!" msgstr "¡ Bienvenido a {course_title}!" #: lms/templates/courseware/info.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "Resume Course" msgstr "Continuar con el curso" @@ -17316,6 +17369,7 @@ msgstr "Ver las calificaciones en Studio" #: lms/templates/courseware/progress.html msgid "Course Progress for '{username}' ({email})" msgstr "" +"Progreso del curso para el estudiante '{username}' con el correo ({email})" #: lms/templates/courseware/progress.html msgid "View Certificate" @@ -17541,7 +17595,7 @@ msgstr "Tu nota final:" #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "Grades will be finalized on {cert_available_date}" -msgstr "" +msgstr "Las calificaciones terminarán el {cert_available_date}" #: lms/templates/dashboard/_dashboard_certificate_information.html msgid "Grade required for a {cert_name_short}:" @@ -17809,10 +17863,10 @@ msgstr "Tú has enviado tu información de verificación." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" "Recibirás un mensaje en su panel de control cuando el proceso de " -"verificación esté completado (usualmente entre 1-2 dÃas)." +"verificación esté completado (usualmente entre 5-7 dÃas)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -17822,11 +17876,11 @@ msgstr "¡Tu verificación actual vencerá pronto!" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" -"Tú has enviado tu información de verificación de identidad. Recibirás un " -"mensaje en tu Panel principal cuando el proceso de verificación esté " -"completado (usualmente entre 1-2 dÃas)." +"Ha enviado su información de verificación de identidad. Recibirá un mensaje " +"en su Panel de usuario cuando el proceso de verificación esté completado " +"(usualmente entre 5-7 dÃas)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -17876,6 +17930,8 @@ msgid "" "You have completed this course and are eligible to purchase course credit. " "Select {strong_start}Get Credit{strong_end} to get started." msgstr "" +"Ha completado este curso y es elegible para comprar crédito para curso. " +"Seleccionar {strong_start}Obtener crédito{strong_end} para iniciar." #: lms/templates/dashboard/_dashboard_credit_info.html msgid "You are now eligible for credit from {provider}. Congratulations!" @@ -17894,6 +17950,9 @@ msgid "" "credit at the {link_to_provider_site} website. Select {start_bold}Request " "Credit{end_bold} to get started." msgstr "" +"Gracias por su pago. Para recibir crédito para un curso, debe solicitar " +"crédito en el enlace de la página web {link_to_provider_site}. Seleccionar " +"{start_bold}Solicitar crédito{end_bold} para iniciar." #: lms/templates/dashboard/_dashboard_credit_info.html msgid "Request Credit" @@ -17921,6 +17980,9 @@ msgid "" "request for course credit. To see your course credit, visit the " "{link_to_provider_site} website." msgstr "" +"{start_bold}Felicidades!{end_bold} {provider_name} ha aprovado su solicitud " +"de crédito para el curso. Para ver el crédito para el curso, por favor " +"visite la página web {link_to_provider_site}." #: lms/templates/dashboard/_dashboard_credit_info.html msgid "View Credit" @@ -17979,6 +18041,10 @@ msgid "" "photo verification can take up to three days once initiated and you will not" " be able to earn a certificate or take a proctored exam until approved." msgstr "" +"Su verificación de identidad por foto expira el {verification_expiry}. Tenga" +" en cuenta que el proceso puede tomar hasta tres dÃas una vez iniciado y no " +"podrá obtener un certificado o tomar un examen supervisado hasta que el " +"proceso haya concluÃdo." #: lms/templates/dashboard/_dashboard_status_verification.html msgid "Resubmit Verification" @@ -18034,6 +18100,9 @@ msgid "" " and you will not be able to earn a certificate or take a proctored exam " "until approved." msgstr "" +"Tenga en cuenta que el proceso de verificación de identidad por foto puede " +"tomar hasta tres dÃas una vez iniciado y no podrá obtener un certificado o " +"tomar un examen supervisado hasta que el proceso haya concluido." #: lms/templates/dashboard/_dashboard_third_party_error.html msgid "Could Not Link Accounts" @@ -18059,30 +18128,32 @@ msgid "" "We're sorry to see you go! Read the following statements and rate your level" " of agreement." msgstr "" +"¡Lamentamos que te vayas! Lee las siguientes frases y califica tu nivel de " +"acuerdo." #: lms/templates/dashboard/_entitlement_reason_survey.html msgid "Price is too high for me" -msgstr "" +msgstr "El precio es muy alto para mi" #: lms/templates/dashboard/_entitlement_reason_survey.html msgid "I was not satisfied with my experience taking the courses" -msgstr "" +msgstr "No estaba satisfecho con mi experiencia tomando los cursos." #: lms/templates/dashboard/_entitlement_reason_survey.html msgid "Content of the courses was too difficult" -msgstr "" +msgstr "El contenido de los cursos era muy dÃficil" #: lms/templates/dashboard/_entitlement_reason_survey.html msgid "I did not have enough time to complete the courses" -msgstr "" +msgstr "No tenia tiempo suficiente para completar los cursos" #: lms/templates/dashboard/_entitlement_reason_survey.html msgid "The content was not available when I wanted to start" -msgstr "" +msgstr "El contenido no estaba disponible cuando queria empezar" #: lms/templates/dashboard/_entitlement_reason_survey.html msgid "Can we contact you via email for follow up?" -msgstr "" +msgstr "¿Podemos contactarlo vÃa correo para hacer seguimiento?" #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html @@ -18571,151 +18642,6 @@ msgstr "" "dÃas para confirmar si su verificación fue exitosa. Puede también revisar el" " estado del proceso de verificación en su panel de control." -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "Gracias por su inscripción al curso {course_name}." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"Se adjunta una factura por {currency_symbol} {total_price}. El pago debe " -"realizarse de inmediato. La información sobre los métodos de pago puede " -"encontrarse en la factura." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -"Se adjunta un archivo .csv con la lista de códigos de inscripción. Puede " -"usar la plantilla de correo a continuación para distribuir los códigos a sus" -" estudiantes. Cada estudiante debe usar un código de inscripción." - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"Gracias,\n" -"El equipo {platform_name} " - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "Estimado/a [[Name]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"Hemos generado un código de inscripción para usted para {course_name}. Para" -" inscribirse en el curso, haga clic en el siguiente vÃnculo:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "VÃnculo HTML del archivo CSV adjunto" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"Después de inscribirse, podra ver el curso en su panel de control. Podrá ver" -" los materiales del curso, solo a partir de la fecha de inicio." - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"Cordialmente,\n" -"[[Your Signature]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "FACTURA" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "Fecha: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "Factura Nº: {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "Condiciones: Vencimiento Inmediato" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "Fecha lÃmite: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "Facturar a:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "Número de referencia del cliente: {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "Saldo Vencido: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "Curso: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"Precio: {currency_symbol}{course_price} Cantidad: {quantity} Sub-Total: " -"{currency_symbol}{sub_total} Descuento: {currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "Total: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "Instrucciones de pago" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"Si no recibimos el pago, las inscripciones que utilizan estos códigos serán " -"canceladas y los estudiantes no podrán acceder a los materiales del curso. " -"Todas las compras son definitivas. Para más información, vea la polÃtica de " -"cancelaciones de {site_name}." - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "" -"Si tiene inquietudes relacionadas con el pago, por favor contacte a " -"{contact_email}." - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -18924,8 +18850,8 @@ msgstr "Solicitar asistencia financiera" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} Página de inicio" @@ -18948,19 +18874,11 @@ msgstr "Encontrar curso" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "Sysadmin" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "Carro de compras" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "Enlaces complementarios" @@ -18997,6 +18915,12 @@ msgstr "Añadir código de cupón" msgid "Enter information about the coupon code below." msgstr "Ingrese la información del código de cupón a continuación." +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "Código de cupón" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "Porcentaje de descuento" @@ -19436,6 +19360,8 @@ msgid "" "The reports listed below are available for download, identified by UTC date " "and time of generation." msgstr "" +"Los reportes listados debajo están disponibles para descargar, identificados" +" por fecha y hora de generación en formato UTC." #: lms/templates/instructor/instructor_dashboard_2/data_download.html msgid "" @@ -19459,6 +19385,13 @@ msgid "" "store the files, in accordance with your institution's data security " "policies.{li_end}{ul_end}" msgstr "" +"{strong_start}Nota{strong_end}: {ul_start}{li_start}Para mantener los datos " +"del estudiante seguros, no puede guardar o enviar estos enlaces para acceso " +"directo. Copias de los enlaces expiran en 5 " +"minutos.{li_end}{li_start}Archivos de reportes son borrados 90 dÃas después " +"de la generación. Si va a necesitar acceso a reportes antiguos, descargue y " +"guarde los archivos, en acuerdo con las polÃticas de seguridad de datos de " +"su institución. {li_end}{ul_end}" #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Enrollment Codes" @@ -19633,6 +19566,11 @@ msgstr "Descargar códigos de cupón" msgid "Coupon Codes" msgstr "Códigos de cupón" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "Fecha de expiración" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "Cupón (%)" @@ -19864,6 +19802,10 @@ msgid "" "always taken; you cannot use this tool to make an assignment due earlier for" " a particular student." msgstr "" +"En esta sección, puede otorgar extensiones individuales a estudiantes en " +"subsecciones especÃficas. Por favor note que siempre se toma la fecha más " +"reciente; no puede usar esta herramienta para configurar la fecha de una " +"asignación más antes para un estudiante especÃfico." #: lms/templates/instructor/instructor_dashboard_2/extensions.html msgid "" @@ -19878,7 +19820,7 @@ msgstr "Correo electrónico o nombre de usuario del estudiante" #: lms/templates/instructor/instructor_dashboard_2/extensions.html msgid "Choose the graded subsection:" -msgstr "" +msgstr "Elija la subsección calificable:" #. Translators: "format_string" is the string MM/DD/YYYY HH:MM, as that is the #. format the system requires. @@ -19892,7 +19834,7 @@ msgstr "" #: lms/templates/instructor/instructor_dashboard_2/extensions.html msgid "Reason for extension" -msgstr "" +msgstr "Motivo de la extensión" #: lms/templates/instructor/instructor_dashboard_2/extensions.html msgid "Change due date for student" @@ -19907,12 +19849,16 @@ msgid "" "Here you can see what extensions have been granted on particular subsection " "or for a particular student." msgstr "" +"Aquà puede ver que extensiones han sido otorgadas en una subsección o " +"estudiante en particular." #: lms/templates/instructor/instructor_dashboard_2/extensions.html msgid "" "Choose a graded subsection and click the button to obtain a list of all " "students who have extensions for the given subsection." msgstr "" +"Escoja una subsección calificable. Debe hacer clic en el botón para obtener " +"una lista de estudiantes con extensiones para la subsección dada." #: lms/templates/instructor/instructor_dashboard_2/extensions.html msgid "List all students with due date extensions" @@ -19936,10 +19882,13 @@ msgid "" "on a particular subsection. This will revert the due date for the student " "back to the problem's original due date." msgstr "" +"Restablecer la fecha lÃmite de un problema anula la extensión de la fecha " +"lÃmite para un estudiante en una subsección en particular. Se revertirá la " +"fecha lÃmite para el estudiante a la fecha lÃmite original del problema." #: lms/templates/instructor/instructor_dashboard_2/extensions.html msgid "Reason for reset" -msgstr "" +msgstr "Motivos para el reinicio" #: lms/templates/instructor/instructor_dashboard_2/extensions.html msgid "Reset due date for student" @@ -20287,15 +20236,17 @@ msgstr "Añadir Administrador de foros de discusiones" #: lms/templates/instructor/instructor_dashboard_2/membership.html msgid "Course Data Researcher" -msgstr "" +msgstr "Investigador de datos del curso" #: lms/templates/instructor/instructor_dashboard_2/membership.html msgid "Course Data Researchers can access the data download tab." msgstr "" +"Los Investigadores de datos del curso pueden acceder a la pestaña de " +"descarga de datos." #: lms/templates/instructor/instructor_dashboard_2/membership.html msgid "Add Course Data Researcher" -msgstr "" +msgstr "Añadir Investigador de datos del curso" #: lms/templates/instructor/instructor_dashboard_2/membership.html msgid "Discussion Moderators" @@ -21010,6 +20961,10 @@ msgid "" " your password, go to the {start_link}sign-in{end_link} page and select " "{start_strong}Forgot password{end_strong}." msgstr "" +"El link de recuperación de contraseña es inválido. Puede que ya haya sido " +"usado. Para restaurar su contraseña, visite la página de " +"{start_link}Login{end_link} y seleccione {start_strong}Olvide mi " +"contraseña{end_strong}." #: lms/templates/registration/password_reset_done.html msgid "Password reset successful" @@ -21050,6 +21005,10 @@ msgstr "Organización que efectúa la compra" msgid "Purchase order number (if any)" msgstr "Número de orden de compra (si aplica)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "Dirección de correo electrónico" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "email@example.com" @@ -21372,6 +21331,10 @@ msgstr[1] "" "{course_names} han sido removidos porque el periodo de inscripción ha sido " "cerrado." +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "Carro de compras" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "Imagen del portada" @@ -21461,12 +21424,10 @@ msgstr "Confirmación" #: lms/templates/static_templates/404.html msgid "" "The page that you were looking for was not found. Go back to the " -"{link_start}homepage{link_end} or let us know about any pages that may have " -"been moved at {email}." +"{link_start}homepage{link_end} ." msgstr "" "La página que está buscando no fue encontrada. Regrese a la " -"{link_start}página de inicio{link_end} o háganos saber acerca de las páginas" -" que hayan podido ser removidas al correo {email}." +"{link_start}página de inicio{link_end}." #: lms/templates/static_templates/about.html #: lms/templates/static_templates/blog.html @@ -21522,23 +21483,17 @@ msgstr "Actualmente los servidores de {platform_name} están inactivos" #: lms/templates/static_templates/server-overloaded.html msgid "" "Our staff is currently working to get the site back up as soon as possible. " -"Please email us at {tech_support_email} to report any problems or downtime." msgstr "" -"Nuestro equipo está trabajando para restablecer el sitio de nuevo tan pronto" -" como sea posible. Por favor envÃenos un correo a {tech_support_email} para " -"informar de cualquier problema o tiempo de inactividad." +"El equipo está trabajando para que el sitio retorne a la normalidad a la " +"mayor brevedad posible." #: lms/templates/static_templates/server-error.html msgid "There has been a 500 error on the {platform_name} servers" msgstr "Se ha producido un error 500 en los servidores de {platform_name}" #: lms/templates/static_templates/server-error.html -msgid "" -"Please wait a few seconds and then reload the page. If the problem persists," -" please email us at {email}." -msgstr "" -"Espere unos segundos y vuelva a cargar la página Por favor. Si el problema " -"persiste, por favor envÃenos un email a {email}." +msgid "Please wait a few seconds and then reload the page." +msgstr "Por favor espere unos segundos y luego recargue la página." #: lms/templates/static_templates/server-overloaded.html msgid "Currently the {platform_name} servers are overloaded" @@ -21553,6 +21508,8 @@ msgid "" " and access to private sites offered by MIT Open Learning, Wharton Executive" " Education, and Harvard Medical School" msgstr "" +"y acceder a los sitios privados ofrecidos por MIT Open Learning, Wharton " +"Executive Education, y Harvard Medical School" #: lms/templates/student_account/finish_auth.html msgid "Please Wait" @@ -21584,11 +21541,11 @@ msgstr "Soporte al estudiante: inscripciones basadas en caracterÃsticas" #: lms/templates/support/feature_based_enrollments.html msgid "Content Type Gating" -msgstr "" +msgstr "Cierre de tipo de contenido" #: lms/templates/support/feature_based_enrollments.html msgid "Course Duration Limits" -msgstr "" +msgstr "LÃmites a la duración del curso" #: lms/templates/support/feature_based_enrollments.html msgid "Is Enabled" @@ -21604,47 +21561,7 @@ msgstr "Soporte a Estudiantes: Administrar Usuario" #: lms/templates/support/program_enrollments_inspector.html msgid "Program Enrollments Inspector" -msgstr "" - -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "A punto de realizar la devolución de esta orden:" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "Clave de identificación de la orden:" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "Inscripción:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "inscritos" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "no inscritos" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "Costo" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "Estado del certificado:" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "Estado de la orden:" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "Hora a que fue completada:" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "Hora a que la devolución fue solicitada:" +msgstr "Inspector de inscripciones para el programa" #: lms/templates/survey/survey.html msgid "User Survey" @@ -21800,11 +21717,11 @@ msgstr "Verificación de identidad" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" "Ya ha enviado su información de verificación de identidad. Recibirá un " "mensaje en su Panel principal cuando el proceso de verificación esté " -"completado (usualmente entre 1-2 dÃas)." +"completado (usualmente entre 5-7 dÃas)." #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -21900,7 +21817,7 @@ msgstr "Algunos Derechos Reservados" #: openedx/features/course_experience/templates/course_experience/course-dates-fragment.html msgid "Upcoming Dates" -msgstr "" +msgstr "Próximas fechas" #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html msgid "Goal: " @@ -21925,8 +21842,8 @@ msgstr "Expandir todo" #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "({number} Question)" msgid_plural "({number} Questions)" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "({number} Pregunta)" +msgstr[1] "({number} Preguntas)" #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Prerequisite: " @@ -22032,7 +21949,11 @@ msgstr "Última actualización" #: openedx/features/course_experience/templates/course_experience/next-up-banner-fragment.html msgid "Get started on what's next: " -msgstr "" +msgstr "Comience con los siguientes pasos:" + +#: openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html +msgid "Show More" +msgstr "Mostrar más" #: openedx/features/course_search/templates/course_search/course-search-fragment.html msgid "Search Results" @@ -22125,11 +22046,11 @@ msgstr "" #: themes/edx.org/lms/templates/dashboard.html msgid "Take advantage of free coaching!" -msgstr "" +msgstr "Aproveche el entrenamiento gratuito!" #: themes/edx.org/lms/templates/dashboard.html msgid "Get Started" -msgstr "" +msgstr "Comenzar" #: themes/edx.org/lms/templates/footer.html msgid "Page Footer" @@ -22145,7 +22066,7 @@ msgstr "Contáctanos" #: themes/edx.org/lms/templates/footer.html msgid "© {year} edX Inc. All rights reserved." -msgstr "" +msgstr "© {year} edX Inc. Todos los derechos reservados." #: themes/edx.org/lms/templates/certificates/_about-accomplishments.html msgid "About edX Verified Certificates" @@ -22227,6 +22148,8 @@ msgid "" "All rights reserved except where noted. edX, Open edX and the edX and Open " "edX logos are registered trademarks of edX Inc." msgstr "" +"Todos los derechos reservados, excepto donde se indique. edX, Open edX, y " +"los logos de edX y Open edX son marcas registradas o marcas de edX Inc." #: themes/edx.org/lms/templates/course_modes/choose.html msgid "" @@ -22401,6 +22324,8 @@ msgid "" "Required fields are noted by {strong_indicator}bold text and an asterisk " "(*).{strong_close}" msgstr "" +"Los campos requeridos se denotan con {strong_indicator}texto en negrita y un" +" asterisco (*){strong_close}." #: themes/stanford-style/lms/templates/register-shib.html msgid "Update My Account" @@ -22415,8 +22340,8 @@ msgid "Already registered?" msgstr "¿Ya estás registrado?" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "Iniciar sesión" @@ -22535,12 +22460,8 @@ msgid "The page that you were looking for was not found." msgstr "La página que usted está buscando no se encontró." #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" -"Regrese a la {homepage} o infórmenos sobre cualquier página que pueda haber " -"sido movida al correo electrónico {email}." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -22567,10 +22488,6 @@ msgstr "" "Hemos registrado el error y nuestro equipo estará trabajando en resolverlo " "lo más pronto posible." -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "Si el problema persiste, por favor escrÃbanos a {email_link}." - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "PolÃtica de Accesibilidad a Studio." @@ -23280,15 +23197,8 @@ msgstr "La página que ha solicitado no pudo ser encontrada." #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" -"Lo sentimos. No se puede encontrar la página {studio_name} que esta " -"buscando. Es posible que desee volver a la {studio_name} en el panel de " -"Control y tratar nuevamente. Si usted continua con problemas para acceder, " -"no dude en {link_start} para contactarse {studio_name} con soporte " -"{link_end} para obtener más ayuda." #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -23298,15 +23208,8 @@ msgstr "El servidor encontró un error" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" -"Lo sentimos. Hubo un problema con el servidor mietras se procesaba su última" -" petición. Es posible que desee regresar al Panel de control {studio_name} o" -" interntarloi nuevamente. Si usted aún tienen problemas para acceder, por " -"favor no dude {link_start} contactarse {studio_name} soorte {link_end} " -"para obtener más ayuda." #: cms/templates/error.html msgid "Back to dashboard" @@ -24967,6 +24870,8 @@ msgid "" "Please note that changes here may take up to a business day to appear on " "your course summary page." msgstr "" +"Por favor note que los cambios hechos aquà pueden tomar hasta un dÃa hábil " +"para aparecer en la página de descripción de su curso." #: cms/templates/settings.html msgid "Course Credit Requirements" @@ -25102,15 +25007,17 @@ msgstr "Hora de finalización de inscripciones" #: cms/templates/settings.html msgid "Upgrade Deadline Date" -msgstr "" +msgstr "Actualizar la fecha lÃmite" #: cms/templates/settings.html msgid "Last day students can upgrade to a verified enrollment." msgstr "" +"Último dÃa para que los estudiantes puedan mejorar a una inscripción " +"verificada." #: cms/templates/settings.html msgid "Upgrade Deadline Time" -msgstr "" +msgstr "Actualizar fecha lÃmite" #: cms/templates/settings.html msgid "Course Details" @@ -25851,23 +25758,23 @@ msgstr "{platform_name} {studio_name}: Estado de la Tarea Actualizado" #: cms/templates/maintenance/_announcement_delete.html msgid "Delete Announcement" -msgstr "" +msgstr "Eliminar anuncio" #: cms/templates/maintenance/_announcement_delete.html msgid "Are you sure you want to delete this Announcement?" -msgstr "" +msgstr "¿Está seguro de que quiere Eliminar este anuncio?" #: cms/templates/maintenance/_announcement_delete.html msgid "Confirm" -msgstr "" +msgstr "Confirmar" #: cms/templates/maintenance/_announcement_edit.html msgid "Edit Announcement" -msgstr "" +msgstr "Editar anuncio" #: cms/templates/maintenance/_announcement_index.html msgid "Create New" -msgstr "" +msgstr "Crear nuevo" #: cms/templates/maintenance/_force_publish_course.html msgid "Required data to force publish course." @@ -25946,7 +25853,7 @@ msgstr "Estructura" #: cms/templates/widgets/header.html msgid "Publisher" -msgstr "" +msgstr "Editor" #: cms/templates/widgets/header.html msgid "Import" @@ -26022,7 +25929,7 @@ msgstr "Editor Avanzado" #: cms/templates/widgets/problem-edit.html msgid "Markdown Help" -msgstr "" +msgstr "Ayuda de Markdown " #: cms/templates/widgets/problem-edit.html msgid "Label" @@ -26741,8 +26648,8 @@ msgstr "%(file)s ha sido cambiado a la revisión #%(revision)d" msgid "%(file)s has been saved." msgstr "%(file)s ha sido guardado." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "Imágenes" @@ -26952,8 +26859,8 @@ msgstr "Borrar la lista de notificaciones" msgid "Search..." msgstr "Buscar..." -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "Registrarse" diff --git a/conf/locale/es_419/LC_MESSAGES/djangojs.mo b/conf/locale/es_419/LC_MESSAGES/djangojs.mo index cc44742b6eb010839eb63624927d8dc78a356ebc..15819b12d41508698ec4877019fa406e11679ab0 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 62c48a55d297c7ed01c6883b3dcb9d9db7c7b39f..8ff2a9e9902a798e7b5daaf5067b475a67ec911d 100644 --- a/conf/locale/es_419/LC_MESSAGES/djangojs.po +++ b/conf/locale/es_419/LC_MESSAGES/djangojs.po @@ -5,7 +5,7 @@ # # Translators: # Addi Hazel Mendoza Sánchez <addictivoh@gmail.com>, 2015 -# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2019 +# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2020 # Andres Garcia <afgarcia0479@misena.edu.co>, 2019 # Antonio Pardo <apardo@alabs.org>, 2013 # Antonio Pardo <apardo@alabs.org>, 2013 @@ -23,7 +23,7 @@ # Gerardo Laster, 2014 # Javier Galnares Arias <javigalnares@yahoo.es>, 2015 # Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2013 -# Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2015-2018 +# Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2015-2018,2020 # Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2013-2014 # Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2013 # karlman72 <karlman72@gmail.com>, 2014 @@ -56,7 +56,7 @@ # This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE. # # Translators: -# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2019 +# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2020 # Anatoli F. Peña Castillo <djanatoli@gmail.com>, 2016 # Andres Garcia <afgarcia0479@misena.edu.co>, 2019 # Antonio Pardo <apardo@alabs.org>, 2013 @@ -81,6 +81,7 @@ # Natalia, 2013 # Natalia, 2014,2018 # Ned Batchelder <ned@edx.org>, 2017 +# Omar Al-Ithawi <i@omardo.com>, 2020 # Cristian Salamea <ovnicraft@gmail.com>, 2013 # palichis <palichis@solid-ec.org>, 2015 # Pedro Guimarães Martins <pedrogmartins7@gmail.com>, 2014 @@ -102,7 +103,7 @@ # This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE. # # Translators: -# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2019 +# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2020 # Lohenrex <lohenrex.ragnarok@gmail.com>, 2018 # Alex Dzul <alexexc2@gmail.com>, 2016 # Anatoli F. Peña Castillo <djanatoli@gmail.com>, 2016 @@ -113,7 +114,7 @@ # Eduardo Zambrano <ezambrano@edx.org>, 2018 # Giancarlo De Agostini <giancarlo.deagostini@iaen.edu.ec>, 2015 # 1673e3cf8bd85685e54576636ae7f409, 2014 -# Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2015-2018 +# Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2015-2018,2020 # Juan Camilo Montoya Franco <juan.montoya@edunext.co>, 2014 # Juan Fernando Villa <elite.linux@gmail.com>, 2015 # Juan <juan.marrero@utec.edu.uy>, 2015 @@ -121,11 +122,14 @@ # Leandro AgustÃn Barrientos <agustinbarrientos@outlook.com>, 2016 # Luis Manuel Moreno <luis.moreno@edunext.co>, 2019 # Marcos Buccella <marcosfiore07@hotmail.com>, 2018 +# Marina Pastor <mpastor@edx.org>, 2020 # Mecabotware <mecabotware.ideas@gmail.com>, 2015 -# Natalia Aguillon, 2016 +# Muhammad Adeel Khan <adeel@edx.org>, 2020 +# 71c030450a123456214226ab52e4d43a_450c5ca, 2016 # Natalia, 2018 # Ned Weitzman <nweitzman@edx.org>, 2017 # Nuri Plans Toral <nplans@gmail.com>, 2014 +# Omar Al-Ithawi <i@omardo.com>, 2020 # Patricia Colmenares <patrusca38@hotmail.com>, 2015 # palichis <palichis@solid-ec.org>, 2015 # Sergio A. Salazar <sergiosalazar@live.ru>, 2016 @@ -138,7 +142,7 @@ # This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE. # # Translators: -# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2019 +# Albeiro Gonzalez <albeiro.gonzalez@edunext.co>, 2018-2020 # Anatoli F. Peña Castillo <djanatoli@gmail.com>, 2016 # Andres Garcia <afgarcia0479@misena.edu.co>, 2019 # Morphyne <cirrosis60@gmail.com>, 2014 @@ -163,8 +167,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Spanish (Latin America) (http://www.transifex.com/open-edx/edx-platform/language/es_419/)\n" "Language: es_419\n" @@ -172,7 +176,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -193,6 +197,22 @@ msgstr "Guardando" #: cms/static/js/views/manage_users_and_roles.js #: cms/static/js/views/show_textbook.js #: lms/djangoapps/teams/static/teams/js/views/instructor_tools.js +#: cms/templates/js/certificate-details.underscore +#: cms/templates/js/certificate-editor.underscore +#: cms/templates/js/content-group-editor.underscore +#: cms/templates/js/course-instructor-details.underscore +#: cms/templates/js/course-outline.underscore +#: cms/templates/js/course-settings-learning-fields.underscore +#: cms/templates/js/course_grade_policy.underscore +#: cms/templates/js/course_info_update.underscore +#: cms/templates/js/group-configuration-details.underscore +#: cms/templates/js/group-configuration-editor.underscore +#: cms/templates/js/partition-group-details.underscore +#: cms/templates/js/show-textbook.underscore +#: cms/templates/js/signatory-editor.underscore +#: cms/templates/js/video-transcripts.underscore +#: cms/templates/js/xblock-outline.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Delete" msgstr "Borrar" @@ -221,6 +241,7 @@ msgstr "Borrar" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -243,6 +264,7 @@ msgstr "Subiendo" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -272,6 +294,7 @@ msgstr "Elegir archivo" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "Aceptar" @@ -366,7 +389,7 @@ msgstr "Sus cambios han sido guardados." #: cms/static/js/views/xblock_validation.js #: common/static/common/js/discussion/views/discussion_inline_view.js msgid "Warning" -msgstr "" +msgstr "Advertencia" #. Translators: This message will be added to the front of messages of type #. error, @@ -439,32 +462,32 @@ msgstr "Responder a la anotación" #: common/lib/xmodule/xmodule/js/src/capa/display.js msgid "{num_points} point possible (graded, results hidden)" msgid_plural "{num_points} points possible (graded, results hidden)" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "{num_points} punto posible (calificable, resultado oculto)" +msgstr[1] "{num_points} puntos posibles (calificables, resultados ocultos)" #. Translators: {num_points} is the number of points possible (examples: 1, 3, #. 10).; #: common/lib/xmodule/xmodule/js/src/capa/display.js msgid "{num_points} point possible (ungraded, results hidden)" msgid_plural "{num_points} points possible (ungraded, results hidden)" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "{num_points} punto posible (no calificable, resultado oculto)" +msgstr[1] "{num_points} puntos posibles (no calificables, resultados ocultos)" #. Translators: {num_points} is the number of points possible (examples: 1, 3, #. 10).; #: common/lib/xmodule/xmodule/js/src/capa/display.js msgid "{num_points} point possible (graded)" msgid_plural "{num_points} points possible (graded)" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "{num_points} punto posible (calificable)" +msgstr[1] "{num_points} puntos posibles (calificables)" #. Translators: {num_points} is the number of points possible (examples: 1, 3, #. 10).; #: common/lib/xmodule/xmodule/js/src/capa/display.js msgid "{num_points} point possible (ungraded)" msgid_plural "{num_points} points possible (ungraded)" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "{num_points} punto posible (no calificable)" +msgstr[1] "{num_points} puntos posibles (no calificables)" #. Translators: {earned} is the number of points earned. {possible} is the #. total number of points (examples: 0/1, 1/1, 2/3, 5/10). The total number of @@ -473,8 +496,8 @@ msgstr[1] "" #: common/lib/xmodule/xmodule/js/src/capa/display.js msgid "{earned}/{possible} point (graded)" msgid_plural "{earned}/{possible} points (graded)" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "{earned}/{possible} punto (calificado)" +msgstr[1] "{earned}/{possible} puntos (calificado)" #. Translators: {earned} is the number of points earned. {possible} is the #. total number of points (examples: 0/1, 1/1, 2/3, 5/10). The total number of @@ -483,8 +506,8 @@ msgstr[1] "" #: common/lib/xmodule/xmodule/js/src/capa/display.js msgid "{earned}/{possible} point (ungraded)" msgid_plural "{earned}/{possible} points (ungraded)" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "{earned}/{possible} punto (no calificado)" +msgstr[1] "{earned}/{possible} puntos (no calificado)" #: common/lib/xmodule/xmodule/js/src/capa/display.js msgid "The grading process is still running. Refresh the page to see updates." @@ -541,6 +564,7 @@ msgstr "No enviado" msgid "" "{paragraph}=p;{preformatted}=pre;{heading3}=h3;{heading4}=h4;{heading5}=h5;{heading6}=h6" msgstr "" +"{paragraph}=p;{preformatted}=pre;{heading3}=h3;{heading4}=h4;{heading5}=h5;{heading6}=h6" #. Translators: this is a message from the raw HTML editor displayed in the #. browser when a user needs to edit HTML @@ -863,7 +887,6 @@ msgstr "Borrar tabla" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Descripción" @@ -898,9 +921,19 @@ msgstr "Propiedades del documento" msgid "Edit HTML" msgstr "Editar HTML" +#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-# #. Translators: this is a message from the raw HTML editor displayed in the #. browser when a user needs to edit HTML #: common/lib/xmodule/xmodule/js/src/html/edit.js +#: cms/templates/js/certificate-details.underscore +#: cms/templates/js/course_info_handouts.underscore +#: cms/templates/js/course_info_update.underscore +#: cms/templates/js/group-configuration-details.underscore +#: cms/templates/js/partition-group-details.underscore +#: cms/templates/js/show-textbook.underscore +#: cms/templates/js/signatory-details.underscore +#: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Edit" msgstr "Editar" @@ -1303,6 +1336,7 @@ msgstr "Nueva ventana" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Siguiente" @@ -1646,9 +1680,13 @@ msgstr "" "La URL que introdujiste parece ser un vÃnculo externo. ¿Desea agregarle el " "prefijo requerido http://?" +#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-# #. Translators: this is a message from the raw HTML editor displayed in the #. browser when a user needs to edit HTML #: common/lib/xmodule/xmodule/js/src/html/edit.js +#: cms/templates/js/course-instructor-details.underscore +#: cms/templates/js/signatory-details.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Title" msgstr "TÃtulo" @@ -2130,6 +2168,7 @@ msgstr "" "Tu solicitud no pudo ser completada. Recarga la página e intenta nuevamente." #: common/static/common/js/discussion/utils.js +#: common/static/common/templates/discussion/templates.underscore msgid "…" msgstr "..." @@ -2343,6 +2382,7 @@ msgid "Your post will be discarded." msgstr "Tu publicación será descartada." #: common/static/common/js/discussion/views/response_comment_show_view.js +#: common/static/common/templates/discussion/templates.underscore msgid "anonymous" msgstr "anónimo" @@ -2585,11 +2625,11 @@ msgstr "MaestrÃas" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "MicroMasters" -msgstr "" +msgstr "MicroMasters" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "MicroBachelors" -msgstr "" +msgstr "MicroBachelors" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Photo Verification" @@ -2601,7 +2641,7 @@ msgstr "Supervisión" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Security" -msgstr "" +msgstr "Seguridad" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx #: cms/templates/js/asset-library.underscore @@ -2609,32 +2649,45 @@ msgid "Other" msgstr "Otro" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" -msgstr "¿En qué podemos ayudarte, {username}?" +msgid "Course Discussion Forum" +msgstr "Foro de discusión del curso" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." +msgstr "" +"Si bien nuestro equipo de soporte está encantado de ayudar con la plataforma" +" edX, el personal del curso tiene la experiencia para preguntas especÃficas " +"del curso, calificación o los procedimientos adecuados en cada curso. " +"Publique todas las preguntas relacionadas con el curso en el Foro de " +"discusión donde el personal del curso pueda responder directamente." #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Details" msgstr "Detalles" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" -msgstr "Cuanto más nos digas, antes y mejor podremos ayudarte." +msgid "the more quickly and helpfully we can respond!" +msgstr "¡lo más rápido y servicial que podemos responder!" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Enviar" +msgid "Create Support Ticket" +msgstr "Crear caso de soporte" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "¿En qué podemos ayudarte, {username}?" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "Ingrese a {platform} para que podamos ayudarle mejor." #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." -msgstr "" -"Si no puedes acceder a tu cuenta, contáctanos por correo electrónico a " -"{email}." +msgid "Need help logging in?" +msgstr "¿Necesita ayuda para iniciar sesión?" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "" @@ -2652,6 +2705,22 @@ msgstr "Elige un tema para tu petición de ayuda." msgid "Enter some details for your support request." msgstr "Describe los detalles de tu solicitud de ayuda." +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" +"Debido al reciente aumento en el interés en la educación en lÃnea y en edX, " +"actualmente estamos experimentando un volumen inusualmente alto de " +"solicitudes de soporte. Agradecemos su paciencia mientras trabajamos para " +"revisar cada solicitud. Por favor, consulte el" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "ya que muchas preguntas comunes pueden ya haber sido respondidas." + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2676,10 +2745,11 @@ msgstr "Ir a la página inicial de {platform}" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" -"Gracias por mandarnos un mensaje. Te contactaremos dentro de las siguientes " -"24 horas." +"¡Gracias por su envÃo! Agradecemos su paciencia mientras trabajamos para " +"revisar su solicitud." #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx msgid "Cancel upload" @@ -2816,6 +2886,8 @@ msgid "" "This learner will be removed from the team,allowing another learner to take " "the available spot." msgstr "" +"Este estudiante será removido del equipo, permitiendo a otro estudiante " +"tomar su lugar." #: lms/djangoapps/teams/static/teams/js/views/instructor_tools.js msgid "Delete this team?" @@ -2826,6 +2898,9 @@ msgid "" "Deleting a team is permanent and cannot be undone.All members are removed " "from the team, and team discussions can no longer be accessed." msgstr "" +"Borrar un equipo es una acción permanente y no puede ser revertida. Todos " +"los miembros son removidos del equipo, y las discusiones creadas en el " +"equipo no pueden ser accedidas de nuevo." #: lms/djangoapps/teams/static/teams/js/views/instructor_tools.js msgid "Team \"{team}\" successfully deleted." @@ -2834,7 +2909,7 @@ msgstr "Equipo \"{team}\" eliminado exitosamente." #: lms/djangoapps/teams/static/teams/js/views/manage.js #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "Manage" -msgstr "" +msgstr "Administrar" #: lms/djangoapps/teams/static/teams/js/views/my_teams.js msgid "You are not currently a member of any team." @@ -2850,17 +2925,21 @@ msgstr "y otros" #. * relative timestamp (see: http://momentjs.com/) #: lms/djangoapps/teams/static/teams/js/views/team_card.js msgid "Last activity {date}" -msgstr "" +msgstr "Última actividad {date}" #: lms/djangoapps/teams/static/teams/js/views/team_card.js msgid "View {span_start} {team_name} {span_end}" -msgstr "" +msgstr "Ver {span_start} {team_name} {span_end}" #: lms/djangoapps/teams/static/teams/js/views/team_profile.js #: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js msgid "An error occurred. Try again." msgstr "Ocurrió un error. Intenta nuevamente." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "¿Deseas abandonar este equipo?" @@ -2870,6 +2949,8 @@ msgid "" "If you leave, you can no longer post in this team's discussions.Your place " "will be available to another learner." msgstr "" +"Si deja el equipo, no puede volver a publicar discusiones dentro del equipo." +" Su lugar en el quipo estará disponible para otro estudiante." #: lms/djangoapps/teams/static/teams/js/views/team_profile.js #: lms/static/js/verify_student/views/reverify_view.js @@ -2879,7 +2960,7 @@ msgstr "Confirmar" #: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js msgid "You already belong to another team in this team set." -msgstr "" +msgstr "Usted ya pertenece a otro equipo en este conjunto." #: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js msgid "This team is full." @@ -2887,13 +2968,13 @@ msgstr "Este equipo está lleno." #: lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js msgid "Cannot join instructor managed team" -msgstr "" +msgstr "No se puede unir al equipo administrado por el instructor" #: lms/djangoapps/teams/static/teams/js/views/team_utils.js msgid " Member" msgid_plural " Members" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Miembro" +msgstr[1] "Miembros" #: lms/djangoapps/teams/static/teams/js/views/teams.js msgid "All teams" @@ -2909,7 +2990,7 @@ msgstr "Temas" #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "My Teams" -msgstr "" +msgstr "Mis equipos" #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore @@ -2986,16 +3067,21 @@ msgid "" "by topic. Join an open public team to collaborate with other learners who " "are interested in the same topic as you are." msgstr "" +"Vea todos los equipos a los que pertenece y todos los equipos públicos en su" +" curso, organizados por tema. Únase a un equipo público abierto para " +"colaborar con otros estudiantes interesados en el mismo tema que usted." #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "" "See all teams you belong to and all public teams in your course, organized " "by topic." msgstr "" +"Vea todos los equipos a los que pertenece y todos los equipos públicos en su" +" curso, organizados por tema." #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js msgid "See all teams you belong to." -msgstr "" +msgstr "Ver todos los equipos a los que usted pertenece." #: lms/djangoapps/teams/static/teams/js/views/teams_tab.js #: lms/djangoapps/discussion/static/discussion/templates/fake-breadcrumbs.underscore @@ -3017,8 +3103,8 @@ msgstr "El equipo \"{team}\" no pudo ser encontrado." #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "{team_count} Team" msgid_plural "{team_count} Teams" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "{team_count} equipo" +msgstr[1] "{team_count} Equipos" #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "Topic" @@ -3026,7 +3112,7 @@ msgstr "Tema" #: lms/djangoapps/teams/static/teams/js/views/topic_card.js msgid "View Teams in the {topic_name} Topic" -msgstr "" +msgstr "Ver equipos en el tema {topic_name}" #: lms/djangoapps/teams/static/teams/js/views/topic_teams.js msgid "" @@ -3400,6 +3486,7 @@ msgid "There has been an error processing your survey." msgstr "Ocurrió un error al procesar tu encuesta." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -3416,6 +3503,7 @@ msgid "HTML preview of post" msgstr "previsiualización en HTML" #: lms/static/js/customwmd.js +#: common/static/common/templates/discussion/templates.underscore msgid "Your question or idea (required)" msgstr "Su pregunta o idea (requerido)" @@ -4821,6 +4909,11 @@ msgid "" "{strongStart}you will no longer be able to use the same email on " "{platformName}.{strongEnd}" msgstr "" +"{strongStart}Advertencia: La eliminación de la cuenta es " +"permanente.{strongEnd} Por favor lea cuidadosamente la información en la " +"parte superior antes de proceder. Esta es una acción irreversible, y " +"{strongStart}no podrá volver a usar el mismo correo electrónico en " +"{platformName}.{strongEnd}" #: lms/static/js/student_account/components/StudentAccountDeletion.jsx msgid "" @@ -4828,12 +4921,17 @@ msgid "" "cannot be undone. {platformName} will not be able to recover your account or" " the data that is deleted." msgstr "" +"Cuidado: la eliminación de su cuenta y datos personales es permanente e " +"irreversible. {platformName} no podrá recuperar ni su cuenta ni los datos " +"eliminados." #: lms/static/js/student_account/components/StudentAccountDeletion.jsx msgid "" "Once your account is deleted, you cannot use it to take courses on the " "{platformName} app, {siteName}, or any other site hosted by {platformName}." msgstr "" +"Una vez tu cuenta es borrada, no podrás usarla ni tomar cursos en la app " +"{platformName}, {siteName}, ni en cualquier otro sitio de {platformName}." #: lms/static/js/student_account/components/StudentAccountDeletion.jsx #: lms/static/js/student_account/components/StudentAccountDeletionModal.jsx @@ -4841,6 +4939,8 @@ msgid "" "This includes access to {siteName} from your employer’s or university’s " "system{additionalSiteSpecificDeletionText}." msgstr "" +"Esto incluye acceso a {siteName} desde el sistema de tu empleador o " +"universidad{additionalSiteSpecificDeletionText}." #: lms/static/js/student_account/components/StudentAccountDeletion.jsx msgid "We’re sorry to see you go!" @@ -4881,6 +4981,9 @@ msgid "" " data is permanent and cannot be undone. {platformName} will not be able to " "recover your account or the data that is deleted." msgstr "" +"Ha seleccionado “Eliminar mi cuentaâ€. La eliminación de su cuenta y datos " +"personales es permanente e irreversible. {platformName} no podrá recuperar " +"su cuenta o los datos que se hayan borrado." #: lms/static/js/student_account/components/StudentAccountDeletionModal.jsx msgid "" @@ -4888,6 +4991,8 @@ msgid "" "the {platformName} app, {siteName}, or any other site hosted by " "{platformName}." msgstr "" +"Si procedes, no podrás usarla ni tomar cursos en la app {platformName}, " +"{siteName}, ni en cualquier otro sitio de {platformName}." #: lms/static/js/student_account/components/StudentAccountDeletionModal.jsx msgid "" @@ -4992,7 +5097,7 @@ msgstr "" #: lms/static/js/student_account/views/LoginView.js msgid "An unexpected error has occurred." -msgstr "" +msgstr "Ha ocurrido un error inesperado." #: lms/static/js/student_account/views/LoginView.js msgid "" @@ -5541,6 +5646,16 @@ msgstr "Expandir todo" msgid "Collapse All" msgstr "Colapsar todo" +#: openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show More" +msgstr "Mostrar más" + +#: openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show Less" +msgstr "Mostrar menos" + #: openedx/features/course_search/static/course_search/js/views/search_results_view.js msgid "{total_results} result" msgid_plural "{total_results} results" @@ -5695,6 +5810,10 @@ msgstr "Si, permitir modificaciones al certificado activo." msgid "certificate" msgstr "certificado" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Configurar su certificado" @@ -5706,8 +5825,8 @@ msgid "You have not created any certificates yet." msgstr "TodavÃa no ha creado ningún certificado." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "¿Desea borrar \"<%= signatoryName %>\" de la lista de signatarios?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5759,6 +5878,7 @@ msgstr "" #: cms/static/js/factories/manage_users.js #: cms/static/js/factories/manage_users_lib.js +#: common/static/common/templates/discussion/templates.underscore msgid "Staff" msgstr "Equipo del curso" @@ -5847,7 +5967,7 @@ msgstr "Ha habido un error con la subida del archivo" #: cms/static/js/features_jsx/studio/CourseOrLibraryListing.jsx msgid "Organization:" -msgstr "" +msgstr "Organización:" #: cms/static/js/features_jsx/studio/CourseOrLibraryListing.jsx msgid "Course Number:" @@ -5855,7 +5975,7 @@ msgstr "Número del curso:" #: cms/static/js/features_jsx/studio/CourseOrLibraryListing.jsx msgid "Course Run:" -msgstr "" +msgstr "Edición del Curso:" #: cms/static/js/features_jsx/studio/CourseOrLibraryListing.jsx msgid "(Read-only)" @@ -5863,8 +5983,9 @@ msgstr "(Solo-lectura)" #: cms/static/js/features_jsx/studio/CourseOrLibraryListing.jsx msgid "Re-run Course" -msgstr "" +msgstr "Relanzar Curso" +#: cms/static/js/features_jsx/studio/CourseOrLibraryListing.jsx #: cms/templates/js/show-textbook.underscore msgid "View Live" msgstr "Ver en vivo" @@ -6028,11 +6149,11 @@ msgstr "Todos los capÃtulos deben tener un nombre y un recurso" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" -"Sólo pueden cargarse archivos de tipo <%= fileTypes %>. Por favor selecciona" -" un archivo que termine en <%= fileExtensions %> para ser cargado." +"Solo archivos <%- fileTypes %> pueden ser cargados. Por favor seleccione un " +"archivo que finalice en <%- (fileExtensions) %> para cargarlo." #: cms/static/js/models/uploads.js #: lms/templates/student_account/hinted_login.underscore @@ -6215,8 +6336,8 @@ msgid "{selectedProvider} credentials saved" msgstr "{selectedProvider} credenciales guardadas" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" -msgstr "Subir un nuevo PDF a “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" +msgstr "cargar un nuevo PDF a “<%- name %>â€" #: cms/static/js/views/edit_chapter.js msgid "Please select a PDF file to upload." @@ -6589,7 +6710,7 @@ msgstr "Fecha de adición" #. edited. #: cms/static/js/views/pages/container.js msgid "Editing access for: {title}" -msgstr "" +msgstr "Editando acceso para: {title}" #: cms/static/js/views/pages/container_subviews.js msgid "Publishing" @@ -6797,7 +6918,7 @@ msgstr "Subir tu miniatura de la imagen del video" #: cms/static/js/views/show_textbook.js msgid "Delete “<%- name %>â€?" -msgstr "" +msgstr "Eliminar “<%- name %>â€?" #: cms/static/js/views/show_textbook.js msgid "" @@ -6831,18 +6952,14 @@ msgstr "Lo sentimos, ha habido un error" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" -"La longitud combinada de los campos para la organización, número de curso y " -"grupo no puede superar los <%=limit%> caracteres." #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" -"La longitud combinada de los campos para la organización y código de la " -"librerÃa no puede superar los <%=limit%> caracteres." #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -7205,13 +7322,13 @@ msgid "Unscheduled" msgstr "No programado" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Fecha" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Anterior" @@ -7259,6 +7376,321 @@ msgstr "Reiniciar búsqueda" msgid "Search" msgstr "Buscar" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "Añade una respuesta" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "Este hilo está cerrado." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "Añade tu respuesta:" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Enviar" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "discusión publicada hace %(time_ago)s por %(author)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "pregunta publicada hace %(time_ago)s por %(author)s" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "Marcado" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "Denunciado" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "Cerrado" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "Relacionado con: %(courseware_title_linked)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "Este post es visible solo para %(group_name)s." + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "Esta publicación es visible para todos." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "Editando publicación" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" +"Agrega un tÃtulo claro y descriptivo para fomentar la participación. " +"(Requerido)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "Edita tu publicación a continuación." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "Actualiza publicación" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "Mostrar comentario (%(num_comments)s)" +msgstr[1] "Mostrar comentarios (%(num_comments)s)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "Añade un comentario" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "marcado como respuesta hace %(time_ago)s por %(user)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "marcado como respuesta hace %(time_ago)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "Validado hace %(time_ago)s por %(user)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "Validado hace %(time_ago)s" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "Editando respuesta" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "Actualiza respuesta" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "publicado hace %(time_ago)s por %(author)s" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "Editando comentario" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "Actualizar comentario" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "discusión" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "pregunta respondida" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "pregunta sin responder" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "Siguiendo" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "Profesor asistente de la comunidad" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "{unread_comments_count} nuevos" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" +"%(comments_count)s %(span_sr_open)s comentarios (%(unread_comments_count)s " +"comentarios no leÃdos)%(span_close)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "%(comments_count)s %(span_sr_open)s comentarios %(span_close)s" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "Añade una publicación" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "Visible para" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" +"Los administradores de la discusión, moderadores, y profesores asociados " +"pueden hacer sus publicaciones visibles a todos los estudiantes o " +"especificar un grupo en particular." + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "Todos los grupos" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "sigue esta publicación" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "Escribe una publicación de forma anónima" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "publica anónimamente a tus compañeros de curso" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "Error al publicar tu mensaje." + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "Esta publicación será visible solo para %(group_name)s." + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "Esta publicación será visible para todos." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "Ãrea temática" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" +"Añade tu publicación a un tema relevante para que los demás la puedan " +"encontrar. (Requerido)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "(Profesor ayudante de la comunidad)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "(Equipo del curso)" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "Todas las publicaciones" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "Volver a todas las publicaciones" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "Ver discusión" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "Cargar más" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "Tipo de publicación" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" +"Utiliza Pregunta para plantear temas que necesitan respuestas. Utiliza " +"Discusión para compartir tus ideas y comenzar conversaciones. (Requerido)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "Pregunta" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "Discusión" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "Validar" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "Invalidar" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "Marcar como respuesta" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "Desmarcar como respuesta" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "Seguir" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "Dejar de seguir" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "Votar esta publicación" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "Denunciar un abuso" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "Denunciar" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "Dejar de denunciar" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "Marcar" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "Desmarcar" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "Abrir" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "Inicio de la discusión" @@ -7318,10 +7750,6 @@ msgstr "" "con notificaciones de actividad nueva y sin leer de las conversaciones que " "está siguiendo." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "Todas las publicaciones" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "nombre de usuario o correo electrónico" @@ -7534,23 +7962,23 @@ msgstr "Editar membresÃa" #: lms/djangoapps/teams/static/teams/templates/manage.underscore msgid "View Current Team Memberships" -msgstr "" +msgstr "Ver las membresÃas actuales del equipo" #: lms/djangoapps/teams/static/teams/templates/manage.underscore msgid "Download Memberships" -msgstr "" +msgstr "Descargar membresÃas" #: lms/djangoapps/teams/static/teams/templates/manage.underscore msgid "Assign Team Memberships" -msgstr "" +msgstr "Asignar membresÃas de equipo" #: lms/djangoapps/teams/static/teams/templates/manage.underscore msgid "Upload Memberships" -msgstr "" +msgstr "Subir membresÃas" #: lms/djangoapps/teams/static/teams/templates/manage.underscore msgid "Error assigning team memberships" -msgstr "" +msgstr "Error al asignar membresÃas de equipo" #: lms/djangoapps/teams/static/teams/templates/team-actions.underscore msgid "Are you having trouble finding a team to join?" @@ -7560,6 +7988,10 @@ msgstr "¿Tiene problemas para encontrar un equipo al cual unirse?" msgid "Join Team" msgstr "Unirse al equipo" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "Detalles del equipo" @@ -7647,111 +8079,13 @@ msgstr "Borrar subsección %(subsectionDisplayName)s" msgid "Remove unit %(unitName)s" msgstr "Borrar unidad %(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" -"TodavÃa debe visitar el sitio web de %(display_name)s para completar el " -"proceso de crédito." - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"Para finalizar un crédito de curso, %(display_name)s requieres " -"%(platform_name)s profesores para postular una solicitud de crédito." - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Obtenga créditos" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" -"Gracias %(full_name)s! Hemos recibido su pago para el curso %(course_name)s." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"Por favor imprima esta página para sus registros; la misma es válida como su" -" recibo. También recibirá un correo electrónico con la esta información." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "Orden Num." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Cantidad" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Total" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Por favor tener en cuenta" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "Los items tachados han tenido devolución" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Facturado a" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "No hay recibo disponible" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Ir al panel de control" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" -"Si no verifica su identidad ahora, de todas formas podrá explorar el curso " -"desde su Panel de Control. Recibirá recordatorios periódicos de " -"{platformName} para realizar la verificación de identidad." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "¿Desea confirmar su identidad después?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Verificar ahora" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Marcar el examen como completado" #: lms/templates/courseware/proctored-exam-status.underscore msgid "You are taking \"{exam_link}\" as {exam_type}. " -msgstr "" +msgstr "Estás tomando \"{exam_link}\" como {exam_type}. " #: lms/templates/courseware/proctored-exam-status.underscore msgid "a timed exam" @@ -7771,14 +8105,6 @@ msgstr "" "Para recibir crédito por problemas, debe seleccionar \"Enviar\" para cada " "problema antes de seleccionar \"Finalizar mi examen\"." -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show More" -msgstr "Mostrar más" - -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show Less" -msgstr "Mostrar menos" - #: lms/templates/courseware/proctored-exam-status.underscore msgid "Exam timer and end exam button" msgstr "Cronometro del examen y botón de finalizar examen" @@ -7886,10 +8212,10 @@ msgstr "Acerca de usted" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" "La siguiente información ya es parte de su perfil en {platform} . La hemos " -"incluido aquà para su aplicación." +"incluido aquà para su aplicación" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7919,6 +8245,10 @@ msgstr "" "Gracias por enviar tu aplicación de financiamiento para {course_name}!. " "Espera una respuesta de 2-4 dias hábiles." +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Ir al panel de control" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "Excepciones en lote" @@ -8294,14 +8624,6 @@ msgstr "Ya no puede cambiar ediciones." msgid "You can change sessions until {expiration_date}." msgstr "Puede cambiar ediciones hasta {expiration_date}." -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "Calificación Final" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "Para {courseName}" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "Ver curso archivado" @@ -8528,8 +8850,28 @@ msgid "An error occurred. Please reload the page." msgstr "Ocurrió un error. Por favor recargue la página." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" -msgstr "¿Necesita ayuda para iniciar sesión?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" +msgstr "" #: lms/templates/student_account/hinted_login.underscore #: lms/templates/student_account/login.underscore @@ -8641,7 +8983,7 @@ msgstr "" #: lms/templates/student_account/login.underscore msgid "Use my university info" -msgstr "" +msgstr "Usar información de mi universidad" #: lms/templates/student_account/login.underscore msgid "or sign in with" @@ -8745,30 +9087,24 @@ msgid "What You Need for Verification" msgstr "Lo que necesita para la verificación" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Cámara web" +msgid "Device with Camera" +msgstr "Dispositivo con cámara" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" +"Necesita un dispositivo que tenga una cámara web. Si recibe un mensaje del " +"navegador para acceder a su cámara, asegúrese de hacer clic en \"Permitir\"." #: lms/templates/verify_student/face_photo_step.underscore msgid "Photo Identification" msgstr "Identificación fotográfica." #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." -msgstr "" -"Necesita el documento de identidad, licencia de conducir, pasaporte u otra " -"identificación certificada por el gobierno, que contenga su foto y nombre." +msgid "You need a valid ID that contains your full name and photo." +msgstr "Necesita un ID válida que contenga su nombre completo y foto." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8780,6 +9116,8 @@ msgid "" "When your face is in position, use the Take Photo button {icon} below to " "take your photo." msgstr "" +"Cuando su cara esté en posición, use el botón Tomar foto {icon} a " +"continuación para tomar su foto." #: lms/templates/verify_student/face_photo_step.underscore msgid "To take a successful photo, make sure that:" @@ -8793,15 +9131,13 @@ msgstr "El rostro esté bien iluminado" msgid "Your entire face fits inside the frame." msgstr "Su cara está completamente dentro del marco de la foto." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "La foto de su documento coincide con la foto de su cara." - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" +"Para tomar la foto de su cara, haga clic en el botón de la cámara {icon}. Si" +" necesita volver a intentarlo, haga clic en 'Retomar foto'." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8817,17 +9153,12 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Por qué %(platformName)s necesita mi foto ?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"Como parte del proceso de verificación, usted debe tomar una foto de su cara" -" y de su documento de identidad. Nuestro servicio de autorización confirmará" -" su identidad comparando la foto que usted se toma con la foto en su " -"documento." +"Utilizamos sus fotos de verificación para confirmar su identidad y " +"garantizar la validez de su certificado." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8838,19 +9169,16 @@ msgstr "¿Qué hace %(platformName)s con esta imagen?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"Usamos los más altos niveles de seguridad disponibles para encriptar su foto" -" y enviarla a nuestro servicio de autorización para revisión. Su foto y su " -"información no son guardadas ni quedan visibles en ninguna parte de " -"%(platformName)s despúes de que el proceso de verificación haya sido " -"completado." +"Ciframos su foto de forma segura y la enviamos a nuestro servicio de " +"autorización para su revisión. Su foto e información no se guardan ni son " +"visibles en ningún lugar de %(platformName)s después de que se complete el " +"proceso de verificación." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8859,6 +9187,8 @@ msgid "" "What if I can't see the camera image, or if I can't see my photo do " "determine which side is visible?" msgstr "" +"¿Qué sucede si no puedo ver la imagen de la cámara, o si no puedo ver mi " +"foto para determinar qué lado es visible?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8870,6 +9200,13 @@ msgid "" " (30-45 centimeters) from the camera, with your head centered relative to " "the computer screen. " msgstr "" +"Es posible que pueda completar el procedimiento de captura de imágenes sin " +"ayuda, pero puede tomar un par de intentos de envÃo para obtener la posición" +" correcta de la cámara. El posicionamiento óptimo de la cámara varÃa con " +"cada computadora, pero generalmente la mejor posición para la doma de la " +"cabeza es de aproximadamente 12-18 pulgadas (30-45 centÃmetros) de la " +"cámara, con la cabeza centrada en relación con la pantalla de la " +"computadora." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8879,6 +9216,10 @@ msgid "" "orientation to change the lighting angle. The most common reason for " "rejection is inability to read the text on the ID card." msgstr "" +"Si las fotos que envÃa son rechazadas, intente mover la computadora o la " +"orientación de la cámara para cambiar el ángulo de iluminación. La razón más" +" común para el rechazo es la imposibilidad de leer el texto en la tarjeta de" +" identificación." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8886,6 +9227,8 @@ msgid "" "What if I have difficulty holding my head in position relative to the " "camera?" msgstr "" +"¿Qué sucede si tengo dificultades para mantener la cabeza en posición con " +"respecto a la cámara?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8895,6 +9238,8 @@ msgid "" "If you require assistance with taking either photo for submission, contact " "%(platformName)s support for additional suggestions." msgstr "" +"Si requiere asistencia tomando cualquiera de las fotos para enviarlas, " +"contacte soporte%(platformName)s para sugerencias adicionales." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8909,21 +9254,18 @@ msgid "Take a Photo of Your ID" msgstr "Toma una Foto de tu Identificación" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"Use su cámara web para tomar una fotografÃa de su documento de identidad. " -"Usaremos esta foto para verificarla contra la fotografÃa de su cara y el " -"nombre de su cuenta." +"Use su cámara web para tomar una fotografÃa de su documento de " +"identificación." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Necesitas un ID con tu nombre y foto. Licencia, pasaporte, cédula todos son " -"aceptados." +"Necesita un documento de identificación con su nombre y foto. Licencia de " +"conducir, pasaporte o cédula son aceptados." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8943,11 +9285,23 @@ msgstr "Asegurese que su documento está bien iluminado" #: lms/templates/verify_student/id_photo_step.underscore msgid "Once in position, use the Take Photo button {icon} to capture your ID" msgstr "" +"Una vez en posición, use el botón Tomar foto {icon} para captura su ID" #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore msgid "Use the Retake Photo button if you are not pleased with your photo" +msgstr "Use el botón Retomar foto si no está satisfecho con su foto" + +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." msgstr "" +"Como parte del proceso de verificación, usted tomará una foto de su cara y " +"de su documento de identificación con foto. Nuestro servicio de autorización" +" confirma su identidad comparando la foto que toma con la foto en su " +"identificación." #: lms/templates/verify_student/id_photo_step.underscore msgid "" @@ -8958,11 +9312,19 @@ msgid "" "(20-30 centimeters) from the camera, with the ID card centered relative to " "the camera. " msgstr "" +"Es posible que pueda completar el procedimiento de captura de imágenes sin " +"ayuda, pero puede tomar un par de intentos de envÃo para obtener la posición" +" correcta de la cámara. El posicionamiento óptimo de la cámara varÃa con " +"cada computadora, pero en general, la mejor posición para una foto de una " +"tarjeta de identificación es de 8 a 12 pulgadas (20-30 centÃmetros) de la " +"cámara, con la tarjeta de identificación centrada en relación con la cámara." #: lms/templates/verify_student/id_photo_step.underscore msgid "" "What if I have difficulty holding my ID in position relative to the camera?" msgstr "" +"¿Qué sucede si tengo dificultades para mantener mi identificación en " +"posición con respecto a la cámara?" #: lms/templates/verify_student/image_input.underscore msgid "Preview of uploaded image" @@ -8992,6 +9354,7 @@ msgstr "Verifique que su cara está completamente dentro del marco de la foto" msgid "" "Once in position, use the Take Photo button {icon} to capture your photo" msgstr "" +"Una vez en posición, use el botón Tomar foto {icon} para captura su foto" #: lms/templates/verify_student/incourse_reverify.underscore msgid "Can we match the photo you took with the one on your ID?" @@ -8999,6 +9362,31 @@ msgstr "" "¿Podemos verificar la foto que usted acaba de tomar contra la foto en su " "documento de identificación?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"Como parte del proceso de verificación, usted debe tomar una foto de su cara" +" y de su documento de identidad. Nuestro servicio de autorización confirmará" +" su identidad comparando la foto que usted se toma con la foto en su " +"documento." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"Usamos los más altos niveles de seguridad disponibles para encriptar su foto" +" y enviarla a nuestro servicio de autorización para revisión. Su foto y su " +"información no son guardadas ni quedan visibles en ninguna parte de " +"%(platformName)s despúes de que el proceso de verificación haya sido " +"completado." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "Gracias por regresar a verificar tu ID en: {courseName}" @@ -9033,6 +9421,13 @@ msgstr "" "Una licencia de conducir, pasaporte, cédula o otra identificación oficial " "con su nombre y foto" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Cámara web" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -9136,6 +9531,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "Revise sus correos electrónicos para un mensaje de activación." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Total" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "Certificado Profesional para {courseName}" @@ -9181,6 +9581,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "¡Gracias! Hemos recibido tu pago para {courseName}." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"Por favor imprima esta página para sus registros; la misma es válida como su" +" recibo. También recibirá un correo electrónico con la esta información." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "Orden Num." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Cantidad" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Por favor tener en cuenta" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "Los items tachados han tenido devolución" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Facturado a" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "No hay recibo disponible" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "Siguiente paso: Confirmación de identidad" @@ -9217,6 +9649,10 @@ msgstr "" "desde su Panel de Control. Recibirá recordatorios periódicos de " "%(platformName)s para realizar la verificación de identidad." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "¿Desea confirmar su identidad después?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "Verificación de identidad en progreso" @@ -9225,13 +9661,13 @@ msgstr "Verificación de identidad en progreso" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"Hemos recibido la información enviada y estamos verificando su identidad. " -"Recibir un mensaje en su Panel principal cuando el proceso de verificación " -"esté completado (usualmente entre 1-2 dÃas). Durante este tiempo, igualmente" -" tendrá acceso a todo el contenido de su curso." +"Hemos recibido su información y estamos verificando su identidad. Verá un " +"mensaje en su tablero cuando se complete el proceso de verificación " +"(generalmente dentro de 5-7 dÃas). Mientras tanto, aún puede acceder a todo " +"el contenido del curso disponible." #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -9267,10 +9703,6 @@ msgstr "Requerimientos para las fotos:" msgid "Does the photo of you show your whole face?" msgstr "¿Muestra la foto su cara completa?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "¿Su foto corresponde a la foto en su identificación?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "¿Está su nombre legible en su identificación?" @@ -9407,6 +9839,8 @@ msgid "" "Create a {link_start}Mozilla Backpack{link_end} account, or log in to your " "existing account" msgstr "" +"Crear una {link_start}cuenta en Mozilla Backpack{link_end} o iniciar sesión " +"en una cuenta existente." #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "" @@ -9414,6 +9848,9 @@ msgid "" "as){link_end} and then {upload_link_start}upload{link_end} it to your " "backpack." msgstr "" +"{download_link_start}descargar esta imagen (clic derecho, guardar " +"como){link_end} y luego {upload_link_start} carguela {link_end} a su bolsa " +"en Mozilla Backpack." #: cms/templates/js/access-editor.underscore msgid "Limit Access" @@ -9776,7 +10213,7 @@ msgstr "" #: cms/templates/js/copy-clipboard-button.underscore msgid "Copy Component Location" -msgstr "" +msgstr "Copiar la ubicación del Componente" #: cms/templates/js/course-highlights-enable.underscore msgid "Weekly Highlight Emails" @@ -10221,7 +10658,7 @@ msgstr "Añadir capÃtulo" #: cms/templates/js/edit-title-button.underscore msgid "Edit Title" -msgstr "" +msgstr "Editar tÃtulo" #: cms/templates/js/grading-editor.underscore msgid "Grading" @@ -10793,6 +11230,21 @@ msgstr "Establecer como Examen especial" msgid "Exam Types" msgstr "Tipos de exámen" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Cronometrado" @@ -11000,14 +11452,14 @@ msgstr "" msgid "Read more" msgstr "Leer más" -#: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" -msgstr "Mostrar transcripciones ({totalTranscripts})" - #: cms/templates/js/video-transcripts.underscore msgid "No transcript uploaded." msgstr "No se ha subido ninguna transcripción" +#: cms/templates/js/video-transcripts.underscore +msgid "Show transcripts ({totalTranscripts})" +msgstr "Mostrar transcripciones ({totalTranscripts})" + #: cms/templates/js/xblock-access-editor.underscore msgid "Set Access" msgstr "Configuración de Acceso" diff --git a/conf/locale/eu_ES/LC_MESSAGES/django.mo b/conf/locale/eu_ES/LC_MESSAGES/django.mo index d77ef1c72b8503b4d29523fa26046f35bc88d703..bd543c7ae22216c242a9c4c484cfa9be6637522b 100644 Binary files a/conf/locale/eu_ES/LC_MESSAGES/django.mo and b/conf/locale/eu_ES/LC_MESSAGES/django.mo differ diff --git a/conf/locale/eu_ES/LC_MESSAGES/django.po b/conf/locale/eu_ES/LC_MESSAGES/django.po index 5c9943fc50e8aab417e42ba793ae962d358d05fa..cf56ffe38ac1a68ec7cdd1d9946711d2f9d83c3b 100644 --- a/conf/locale/eu_ES/LC_MESSAGES/django.po +++ b/conf/locale/eu_ES/LC_MESSAGES/django.po @@ -64,7 +64,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Abel Camacho <abelcama@gmail.com>, 2019\n" "Language-Team: Basque (Spain) (https://www.transifex.com/open-edx/teams/6205/eu_ES/)\n" @@ -73,7 +73,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -98,8 +98,8 @@ msgstr "Sarrera-azterketa" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "Unitatea" @@ -413,14 +413,14 @@ msgstr "Sisteman ez dago e-posta helbidea duen erabiltzailerik." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "" -"Badago dagoeneko '{username}' erabiltzaile-izen publikoa duen kontu bat." +msgid "An account with the Email '{email}' already exists." +msgstr "Dagoeneko badago '{email}' e-posta duen kontu bat." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "Dagoeneko badago '{email}' e-posta duen kontu bat." +msgid "An account with the Public Username '{username}' already exists." +msgstr "" +"Badago dagoeneko '{username}' erabiltzaile-izen publikoa duen kontu bat." #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2239,9 +2239,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -3949,12 +3949,12 @@ msgid "" " considered in the Entrance Exam scoring/gating algorithm." msgstr "" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "" @@ -4557,17 +4557,17 @@ msgstr "Desblokeatu kontua" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "Itxi" @@ -5463,54 +5463,6 @@ msgid "" "this request, please visit the link(s) below." msgstr "" -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "Ordainagiria" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "Ordainketak kale egin du" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" -"Ziurtatu zure informazioa zuzena dela edo saiatu berriz beste txartel " -"batekin edo ordaintzeko beste era batean." - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "Mesedez, itxaron minutu batzuk eta saiatu berriz." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "Laguntza lortzeko, jarri harremanetan {payment_support_link}-rekin." - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "Errorea gertatu da zure ordainagiria sortzean." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"Zure ikastaroa ez bada zure aginte-panelean agertzen, jarri harremanetan " -"{payment_support_link}-rekin." - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "" @@ -5573,11 +5525,23 @@ msgstr "Ez duzu ikastaro honetarako sarbiderik" msgid "You do not have access to this course on a mobile device" msgstr "Ez duzu ikastaro honetarako sarbiderik gailu mugikor bidez" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -6217,9 +6181,8 @@ msgid "Good" msgstr "Ona" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html @@ -6227,6 +6190,11 @@ msgstr "" msgid "View discussion" msgstr "Ikusi eztabaida" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6356,8 +6324,8 @@ msgid "Student" msgstr "Ikaslea" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "Arduradunak" @@ -6476,29 +6444,6 @@ msgstr "" msgid "Could not find problem with this location." msgstr "Ezin izan da kokapen hau duen ariketa aurkitu." -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "Ez dago '{num}' zenbakia duen faktura." - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "Faktura honekin lotutako salmenta baliogabetu egin da." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "{0} zenbakia duen faktura baliogabetu egin da." - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "Dagoeneko faktura hau aktibo dago." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "Berriz aktibatu da {0} fakturarako erregistro-kodea." - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "IkastaroIDa" @@ -6529,9 +6474,8 @@ msgstr "Erabiltzailearen IDa" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "Erabiltzaile-izena" @@ -6653,54 +6597,6 @@ msgstr "" "Fitxategiak 'erabiltzaile-izena' zutabea, 'e-posta' zutabea izan behar du, " "edo biak." -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "Kupoiaren kodea" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "Ikastaroan IDa" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% deskontua" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "Deskribapena" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "Iraungitze-data" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "Aktibo dago" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "Guztira deskontatutako kopurua" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -6721,14 +6617,6 @@ msgstr "" msgid "proctored exam results" msgstr "" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -6941,65 +6829,6 @@ msgid "" " try again." msgstr "" -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" -"Definitzen saiatu zaren ({code}) kodea dagoeneko erabilita dago " -"erregistratzeko kode gisa" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "Mesedez, idatzi data formatu honetan: hil/egu/urtea" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "Ez da kupoiaren IDa aurkitu" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "Irakaslea" @@ -7108,31 +6937,6 @@ msgstr "Osatu" msgid "Incomplete" msgstr "Osatu gabea" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "" -"The enrollment code ({code}) was not found for the {course_name} course." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "" -"Matrikulazio-kode hau bertan behera utzi da. Ezin da aurrerantzean erabili." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "Matrikulazio-kode hau ez erabilitzat markatu da.." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "Matrikulazio-kodea berreskuratu da." - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "" - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7531,8 +7335,8 @@ msgstr " ({total}-tik)" #: lms/djangoapps/learner_dashboard/programs.py #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Programak" @@ -7711,9 +7515,11 @@ msgid "{mode_name} for course {course}" msgstr "{mode_name} {course} ikastarorako" #: lms/djangoapps/shoppingcart/models.py +#, python-brace-format msgid "" -"You can unenroll in the course and receive a full refund for 14 days after " -"the course start date. " +"To receive a refund you may unenroll from the course on your edX Dashboard " +"({dashboard_url}) up to 14 days after your payment or 14 days after your " +"course starts (up to six months after your payment).\n" msgstr "" #: lms/djangoapps/shoppingcart/models.py @@ -7726,15 +7532,14 @@ msgstr "" #: lms/djangoapps/shoppingcart/models.py msgid "" "You can unenroll in the course and receive a full refund for 2 days after " -"the course start date. " +"the course start date.\n" msgstr "" #: lms/djangoapps/shoppingcart/models.py #, python-brace-format msgid "" -"{refund_reminder_msg}To receive your refund, contact {billing_email}. Please" -" include your order number in your email. Please do NOT include your credit " -"card information." +"{refund_reminder_msg}For help unenrolling, Please see How do I unenroll from" +" a course? ({how_to_unenroll_link}) in our edX HelpCenter." msgstr "" #: lms/djangoapps/shoppingcart/models.py @@ -8163,6 +7968,15 @@ msgstr "Denerako kostua" msgid "Currency" msgstr "Moneta" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "Deskribapena" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "Iruzkinak" @@ -8306,14 +8120,6 @@ msgstr "Ez duzu baimenik orri hau ikusteko." msgid "View and regenerate certificates." msgstr "" -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "" - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -8392,43 +8198,8 @@ msgstr "Erabiltzailea ondo gaitu da" msgid "User Disabled Successfully" msgstr "" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "E-posta helbidea" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "Ikastaroaren IDa" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "Ez da erabiltzailea aurkitu" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "Desmatrikulatua {user} {course_id} ikastarotik" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" msgstr "" #: lms/djangoapps/teams/models.py @@ -8477,13 +8248,17 @@ msgid "The supplied course_id {course_id} is not valid." msgstr "Emandako {course_id} ikastaro_id-a ez da baliagarria." #: lms/djangoapps/teams/views.py -msgid "You are already in a team in this course." -msgstr "Dagoeneko ikastaro honetan taldean zaude." +msgid "topic_id is required" +msgstr "" #: lms/djangoapps/teams/views.py msgid "You can't create a team in an instructor managed topic." msgstr "" +#: lms/djangoapps/teams/views.py +msgid "You are already in a team in this teamset." +msgstr "" + #: lms/djangoapps/teams/views.py msgid "teamset_id and team_id are mutually exclusive options." msgstr "" @@ -9057,8 +8832,8 @@ msgid "Allow" msgstr "" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "Errorea" @@ -9444,8 +9219,8 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "Eranskinak" @@ -9481,11 +9256,10 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -9893,6 +9667,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -10270,6 +10048,10 @@ msgstr "" msgid "Schedule start < course start" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "Ikastaroan IDa" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "Guztiak" @@ -10278,6 +10060,15 @@ msgstr "Guztiak" msgid "Experience" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "Ikastaroaren IDa" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -10479,6 +10270,7 @@ msgid "" msgstr "" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "" @@ -10712,7 +10504,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -10741,8 +10532,8 @@ msgid "Success" msgstr "Ondo" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "Ekintzak" @@ -10905,6 +10696,14 @@ msgstr "" "Errorea gertatu da sartzeko informazioa jasotzean. Mesedez, bidali gure " "e-posta mezua." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -10918,6 +10717,15 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "Saioa hasteko saiakera oker gehiegi. Saiatu berriz beranduago." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -10925,15 +10733,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "erabiltzaile-izena@domeinua.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -10950,6 +10749,12 @@ msgstr "" msgid "Create Account" msgstr "Sortu kontua" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "erabiltzaile-izena@domeinua.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -10962,6 +10767,11 @@ msgid "" "password." msgstr "" +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "Pasahitza ez da ondo berrezarri" @@ -10978,12 +10788,7 @@ msgstr "" #, python-brace-format msgid "" "{html_start}Password Creation Complete{html_end}Your password has been " -"created. {bold_start}{email}{bold_end} is now your primary login email." -msgstr "" - -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." +"created. {bold_start}{email}{bold_end} is now your primary login email." msgstr "" #: openedx/core/djangoapps/user_authn/views/password_reset.py @@ -11213,6 +11018,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "" @@ -11231,6 +11048,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "Balore hau ez da baliagarria." @@ -11908,8 +11729,8 @@ msgid "Vertical" msgstr "Bertikala" #: cms/djangoapps/contentstore/views/helpers.py -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "Atala" @@ -12182,6 +12003,18 @@ msgstr "" msgid "Transcript Ready" msgstr "" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "" @@ -12325,8 +12158,8 @@ msgstr "Edukia" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "Ezarpenak" @@ -12374,14 +12207,14 @@ msgstr "Ikastaro-zenbakia" msgid "Course Run:" msgstr "Ikastaroa ematea:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "Ikastaroak" @@ -12405,8 +12238,9 @@ msgstr "Irakasleak" msgid "Requirements" msgstr "Eskakizunak" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "Xehetasunak" @@ -12460,15 +12294,15 @@ msgstr "" msgid "Choose Language" msgstr "Aukeratu hizkuntza" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "Kontua" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -12540,8 +12374,8 @@ msgstr "Erabiltzailearen menua" msgid "Usermenu dropdown" msgstr "Zabaltzen den erabiltzailearen menua " -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "Amaitu saioa" @@ -12703,8 +12537,8 @@ msgstr "Hasiera: {date}" msgid "View all Courses" msgstr "Ikusi ikastaro guztiak" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "Aginte-panela" @@ -12723,8 +12557,8 @@ msgstr "Oraindik ez zaude inongo ikastarotan matrikulatuta." #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "Arakatu ikastaroak" @@ -12742,7 +12576,7 @@ msgstr "Erroreak ikastaroa igotzean" msgid "Search Your Courses" msgstr "Bilatu zure ikastaroetan" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "Garbitu bilaketa" @@ -12767,7 +12601,7 @@ msgstr "Jaso ikastaroko e-postak" msgid "Save Settings" msgstr "Gorde ezarpenak" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -12777,9 +12611,87 @@ msgstr "Gorde ezarpenak" msgid "Unenroll" msgstr "Desmatrikulatu" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "Ikusi unitatea Studio-n" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -12812,7 +12724,7 @@ msgstr "Dagoeneko bada e-posta helbide berria duen kontua." msgid "You should Register before trying to access the Unit" msgstr "Unitatera sartzen saiatu aurrertik, erregistratu behar zenuke. " -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "Matrikulazioa" @@ -12915,7 +12827,7 @@ msgid "" "available on the {link_start}progress page{link_end}." msgstr "" -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "Bilatu ikastaro bat" @@ -13051,18 +12963,15 @@ msgstr "(kargatu berriz zure orria freskatzeko)" msgid "working" msgstr "lanean" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "Errorea gertatu da {platform_name} plataformako zerbitzarietan" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html -#: lms/templates/courseware/error-message.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" #: lms/templates/module-error.html @@ -13102,7 +13011,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "" #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -13164,16 +13081,6 @@ msgstr "E-posta" msgid "Return To %s" msgstr "Itzuli hona: %s" -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "" @@ -13222,7 +13129,7 @@ msgstr "Hurrengoa" msgid "Sequence" msgstr "Sekuentzia" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "Osatua" @@ -13351,18 +13258,18 @@ msgstr "" msgid "Reset Learner's Attempts to Zero" msgstr "" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "Ezabatu ikasleen egoera" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "" @@ -13400,7 +13307,7 @@ msgstr "{course_number} Testu-liburua" msgid "Textbook Navigation" msgstr "Testu-liburuaren nabigazioa" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "Orria" @@ -13511,9 +13418,9 @@ msgstr "{current_page} orri {total_pages}-tik" msgid "Recent git load activity for {course_id}" msgstr "" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -13569,7 +13476,7 @@ msgid "" " not mean to do this, {undo_link_start}you can re-subscribe{link_end}." msgstr "" -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "Norentzako aginte-panela:" @@ -13577,8 +13484,8 @@ msgstr "Norentzako aginte-panela:" msgid "More options" msgstr "Aukera gehiago" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "Aukera gehiago" @@ -14758,37 +14665,6 @@ msgstr "" msgid "About edX Certificates" msgstr "edX ziurtagiriei buruz" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "Ordainketa bertan behera utzi da" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"Zure transakzioa bertan behera utzi da. Errorea gertatu dela uste baduzu, " -"jarri harrremanetan {email}." - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "Eskabideen datuak kargatzen..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "" - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -14992,28 +14868,25 @@ msgstr "" msgid "This content is graded" msgstr "" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "Errorea gertatu da. Mesedez, saiatu berriz beranduago." - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "Errorea gertatu da. Mesedez, saiatu berriz beranduago." + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "Ikastaro honetan matrikulatuta zaude" #: lms/templates/courseware/course_about.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: lms/templates/shoppingcart/registration_code_receipt.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "View Course" msgstr "Ikusi ikastaroa" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "Ikastaroa beteta dago" @@ -15026,10 +14899,6 @@ msgstr "Ikastaro honetan gonbidapenarekin bakarrik matrikula daiteke" msgid "Enrollment is Closed" msgstr "Matrikulazioa itxita dago" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "Matrikulatu orain" @@ -15153,6 +15022,13 @@ msgstr "" msgid "Courseware" msgstr "Ikasgunea" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "Ikastaro-bilaketa" @@ -15182,7 +15058,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -15190,8 +15066,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" +msgstr "" + +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -15244,8 +15123,9 @@ msgid "Welcome to {course_title}!" msgstr "" #: lms/templates/courseware/info.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "Resume Course" msgstr "" @@ -15831,7 +15711,7 @@ msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html @@ -15842,7 +15722,7 @@ msgstr "" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html @@ -16533,140 +16413,6 @@ msgid "" "verification process on your dashboard." msgstr "" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"Eskerrik asko ,\n" -"{platform_name} -ko taldea" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "Kaixo [[Name]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"Ikastaroan matrikulatzeko kodea egin dugu zuretzat {course_name}-n. " -"Ikastaroan matrikulatzeko, sakatu ondorengo estekari:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"Matrikulatutakoanl, ikastaroa zure ikaslearen aginte-panelean ikus dezakezu." -" Ikastaroko materialak ikastaroaren hasiera-dataren ondoren ikus ditzakezu." - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"Adeitasunez,\n" -"[[Your Signature]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "FAKTURA" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "Data: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "Entregatze-data: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "Ikastaroa: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"Prezioa: {currency_symbol}{course_price} Kantitatea: {quantity}" -" Guztizko partziala: {currency_symbol}{sub_total} Deskontua: " -"{currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "Denera: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "Ordainketarako argibideak" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "Ordainketa-kontuetarako, harremana {contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -16841,8 +16587,8 @@ msgstr "" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} Hasiera-orria" @@ -16863,19 +16609,11 @@ msgstr "Aurkitu beste ikastaroren bat" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "Sistemako kudeatzailea" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "Erosketa-saskia" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "" @@ -16912,6 +16650,12 @@ msgstr "Gehitu kupoiaren kodea" msgid "Enter information about the coupon code below." msgstr "Idatzi kupoiaren kodeari buruzko informazioa behean." +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "Kupoiaren kodea" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "" @@ -17469,6 +17213,11 @@ msgstr "Jaitsi kupoiaren kodeak" msgid "Coupon Codes" msgstr "Kupoiaren kodeak" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "Iraungitze-data" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "Kupoia: (%)" @@ -18749,6 +18498,10 @@ msgstr "" msgid "Purchase order number (if any)" msgstr "Erosketa-aginduaren zenbakia (balego)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "E-posta helbidea" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "e-posta@adibidea.com" @@ -19048,6 +18801,10 @@ msgstr[0] "" msgstr[1] "" "{course_names} kendu egin dira matrikulazio-aldia itxi egin delako." +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "Erosketa-saskia" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "" @@ -19135,12 +18892,8 @@ msgstr "Konfirmazioa" #: lms/templates/static_templates/404.html msgid "" "The page that you were looking for was not found. Go back to the " -"{link_start}homepage{link_end} or let us know about any pages that may have " -"been moved at {email}." +"{link_start}homepage{link_end} ." msgstr "" -"Bilatzen ari zaren orria ez da aurkitu. Itzuli {link_start}hasiera-" -"orrira{link_end} edo jakinarazi guri zein orri ezabatu edo desagertu diren " -"hona idatziz: {email}." #: lms/templates/static_templates/about.html #: lms/templates/static_templates/blog.html @@ -19189,7 +18942,6 @@ msgstr "" #: lms/templates/static_templates/server-overloaded.html msgid "" "Our staff is currently working to get the site back up as soon as possible. " -"Please email us at {tech_support_email} to report any problems or downtime." msgstr "" #: lms/templates/static_templates/server-error.html @@ -19197,12 +18949,8 @@ msgid "There has been a 500 error on the {platform_name} servers" msgstr "500 errorea gertatu da {platform_name} zerbitzarietan" #: lms/templates/static_templates/server-error.html -msgid "" -"Please wait a few seconds and then reload the page. If the problem persists," -" please email us at {email}." +msgid "Please wait a few seconds and then reload the page." msgstr "" -"Mesedez, itxaron segundu batzuk eta ondoren eguneratu orria. Arazoak irauten" -" badu, mesedez, bidali e-posta {email}-ra." #: lms/templates/static_templates/server-overloaded.html msgid "Currently the {platform_name} servers are overloaded" @@ -19270,46 +19018,6 @@ msgstr "Ikasleentzako laguntza: kudeatu erabiltzailea" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "Aginduaren ID-a:" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "Matrikulazioa:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "matrikulatua" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "matrikulatu gabea" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "Prezioa:" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "Aginduaren egoera:" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "Erabiltzailearen inkesta" @@ -19450,7 +19158,7 @@ msgstr "" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" #: lms/templates/verify_student/reverify_not_allowed.html @@ -19667,6 +19375,10 @@ msgstr "" msgid "Get started on what's next: " msgstr "" +#: openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html +msgid "Show More" +msgstr "" + #: openedx/features/course_search/templates/course_search/course-search-fragment.html msgid "Search Results" msgstr "Bilaketaren emaitzak" @@ -20019,8 +19731,8 @@ msgid "Already registered?" msgstr "Ba al zaude erregistratuta?" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "Sartu" @@ -20130,12 +19842,8 @@ msgid "The page that you were looking for was not found." msgstr "Ez da bilatzen ari zaren orria aurkitu." #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" -"Itzuli {homepage} edo jakinarazi guri zein orri ezabatu edo desagertu diren " -"hona idatziz: {email}." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -20159,12 +19867,6 @@ msgid "" "error as soon as possible." msgstr "" -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "" -"Arazoa konpondu ezean, mesedez idatz iezaguzu e-posta honetara: " -"{email_link}." - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "Studioko Irisgarritasun-politika" @@ -20773,9 +20475,7 @@ msgstr "" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" #: cms/templates/error.html @@ -20786,9 +20486,7 @@ msgstr "Zerbitzariak errorea aurkitu du" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" #: cms/templates/error.html @@ -23758,8 +23456,8 @@ msgstr "" msgid "%(file)s has been saved." msgstr "%(file)s gorde dira." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "Irudiak" @@ -23951,8 +23649,8 @@ msgstr "" msgid "Search..." msgstr "Bilatu..." -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "Eman izena" diff --git a/conf/locale/eu_ES/LC_MESSAGES/djangojs.mo b/conf/locale/eu_ES/LC_MESSAGES/djangojs.mo index b223a78b1c0ac3847920f670fe0fb3d1b4e0ac01..1d9fdc88f9a931ce0e07dbff73d9199c0d267a86 100644 Binary files a/conf/locale/eu_ES/LC_MESSAGES/djangojs.mo and b/conf/locale/eu_ES/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/eu_ES/LC_MESSAGES/djangojs.po b/conf/locale/eu_ES/LC_MESSAGES/djangojs.po index 028de2a1926af4d289d7b27473be45036a661473..1530e0458f050f008398eefe84b9407ad2276ee6 100644 --- a/conf/locale/eu_ES/LC_MESSAGES/djangojs.po +++ b/conf/locale/eu_ES/LC_MESSAGES/djangojs.po @@ -50,16 +50,16 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" -"PO-Revision-Date: 2020-03-05 10:11+0000\n" -"Last-Translator: Abel Camacho <abelcama@gmail.com>\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" +"Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Basque (Spain) (http://www.transifex.com/open-edx/edx-platform/language/eu_ES/)\n" "Language: eu_ES\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -80,21 +80,6 @@ msgstr "Gordetzen" #: cms/static/js/views/manage_users_and_roles.js #: cms/static/js/views/show_textbook.js #: lms/djangoapps/teams/static/teams/js/views/instructor_tools.js -#: cms/templates/js/certificate-details.underscore -#: cms/templates/js/certificate-editor.underscore -#: cms/templates/js/content-group-editor.underscore -#: cms/templates/js/course-instructor-details.underscore -#: cms/templates/js/course-outline.underscore -#: cms/templates/js/course-settings-learning-fields.underscore -#: cms/templates/js/course_grade_policy.underscore -#: cms/templates/js/course_info_update.underscore -#: cms/templates/js/group-configuration-details.underscore -#: cms/templates/js/group-configuration-editor.underscore -#: cms/templates/js/partition-group-details.underscore -#: cms/templates/js/show-textbook.underscore -#: cms/templates/js/signatory-editor.underscore -#: cms/templates/js/video-transcripts.underscore -#: cms/templates/js/xblock-outline.underscore msgid "Delete" msgstr "Ezabatu" @@ -123,6 +108,7 @@ msgstr "Ezabatu" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -145,6 +131,7 @@ msgstr "Kargatzen" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -174,6 +161,7 @@ msgstr "Aukeratu fitxategia" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "Ondo" @@ -767,7 +755,6 @@ msgstr "Ezabatu taula" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Deskribapena" @@ -802,18 +789,9 @@ msgstr "Dokumentuaren propietateak" msgid "Edit HTML" msgstr "Editatu HTMLa" -#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-# #. Translators: this is a message from the raw HTML editor displayed in the #. browser when a user needs to edit HTML #: common/lib/xmodule/xmodule/js/src/html/edit.js -#: cms/templates/js/certificate-details.underscore -#: cms/templates/js/course_info_handouts.underscore -#: cms/templates/js/course_info_update.underscore -#: cms/templates/js/group-configuration-details.underscore -#: cms/templates/js/partition-group-details.underscore -#: cms/templates/js/show-textbook.underscore -#: cms/templates/js/signatory-details.underscore -#: cms/templates/js/xblock-string-field-editor.underscore msgid "Edit" msgstr "Editatu" @@ -1216,6 +1194,7 @@ msgstr "Beste lehio bat" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Hurrengoa" @@ -1559,12 +1538,9 @@ msgstr "" "Badirudi sartu duzun URL-a kanporako esteka dela. Nahi al duzu beharrezko " "den http:// aurrizkia gehitzea?" -#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-# #. Translators: this is a message from the raw HTML editor displayed in the #. browser when a user needs to edit HTML #: common/lib/xmodule/xmodule/js/src/html/edit.js -#: cms/templates/js/course-instructor-details.underscore -#: cms/templates/js/signatory-details.underscore msgid "Title" msgstr "Izenburua" @@ -2475,30 +2451,39 @@ msgid "Other" msgstr "Bestelako bat" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" -msgstr "Zertan lagundu ahal dizugu, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Details" msgstr "Xehetasunak" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" -"Zenbat eta gehiago esan, orduan eta azkarrago eta hobeto erantzungo dizugu!" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Bidali" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "Zertan lagundu ahal dizugu, {username}?" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "Hasi saioa {platform} plataforman laguntza hobea eman ahal izateko." #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2509,12 +2494,24 @@ msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "Select a subject for your support request." -msgstr "Aukeratu laguntza-eskaeraren gaia." +msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "Enter some details for your support request." msgstr "Idatzi laguntza-eskaeraren xehetasunak" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2538,7 +2535,8 @@ msgstr "Joan {platform} plataformako Hasierara" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2720,6 +2718,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "Errorea gertatu da. Saiatu berriz." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Talde hau utzi nahi duzu?" @@ -3210,6 +3212,7 @@ msgid "There has been an error processing your survey." msgstr "Errorea gertatu da zure inkesta prozesatzean." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -5117,6 +5120,14 @@ msgstr "Zabaldu guztiak" msgid "Collapse All" msgstr "Tolestu guztiak" +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show More" +msgstr "Erakutsi gehiago" + +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show Less" +msgstr "Erakutsi gutxiago" + #: openedx/features/course_search/static/course_search/js/views/search_results_view.js msgid "{total_results} result" msgid_plural "{total_results} results" @@ -5262,6 +5273,10 @@ msgstr "" msgid "certificate" msgstr "ziurtagiria" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "" @@ -5273,8 +5288,8 @@ msgid "You have not created any certificates yet." msgstr "Ez duzu oraindik ziurtagiririk sortu." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "\"<%= signatoryName %>\" ezabatu nahi duzu sinatzaileen zerrendatik?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5584,8 +5599,8 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" #: cms/static/js/models/uploads.js @@ -5760,7 +5775,7 @@ msgid "{selectedProvider} credentials saved" msgstr "" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" msgstr "" #: cms/static/js/views/edit_chapter.js @@ -6318,13 +6333,13 @@ msgstr "Sentitzen dugu, errorea gertatu da" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" #: cms/static/js/views/utils/move_xblock_utils.js @@ -6666,13 +6681,13 @@ msgid "Unscheduled" msgstr "Programatu gabea" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Data" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Aurrekoa" @@ -6720,6 +6735,310 @@ msgstr "Garbitu bilaketa" msgid "Search" msgstr "Bilatu" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Bidali" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "Mezu guztiak" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "Foroaren hasiera" @@ -6778,10 +7097,6 @@ msgstr "" "Markatu lauki hau egunero mezu bat jaso nahi baduzu jarraitzen ari zaren " "foroko irakurri gabeko mezuen eta azken berrien laburpenarekin." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "Mezu guztiak" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "erabiltzaie-izena edo e-posta" @@ -7017,6 +7332,10 @@ msgstr "Ba al duzu talderen batekin bat egiteko arazorik?" msgid "Join Team" msgstr "Bat egin taldearekin" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "Taldearen xehetasunak" @@ -7101,96 +7420,6 @@ msgstr "Ezabatu %(subsectionDisplayName)sazpiatala" msgid "Remove unit %(unitName)s" msgstr "Ezabatu %(unitName)s unitatea" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Lortu kreditua" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" -"Eskerrik asko %(full_name)s! Zure ordainketa jaso dugu %(course_name)s dela-" -"eta." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "Agindu-zenbakia" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Kopurua" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Denerakoa" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Hartu kontuan" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Faktura ondokoari egin zaio: " - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Ordainagiria ez dago eskura" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Joan aginte-panelera" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "Nahi al duzu nortasuna beranduago egiaztatu?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Egiaztatu orain!" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Markatu azterketa osatutzat " @@ -7213,14 +7442,6 @@ msgid "" "before you select \"End My Exam\"." msgstr "" -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show More" -msgstr "Erakutsi gehiago" - -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show Less" -msgstr "Erakutsi gutxiago" - #: lms/templates/courseware/proctored-exam-status.underscore msgid "Exam timer and end exam button" msgstr "" @@ -7326,7 +7547,7 @@ msgstr "Zuri buruz" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore @@ -7355,6 +7576,10 @@ msgid "" "{course_name}! You can expect a response in 2-4 business days." msgstr "" +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Joan aginte-panelera" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "Salbuespen masiboak" @@ -7691,14 +7916,6 @@ msgstr "" msgid "You can change sessions until {expiration_date}." msgstr "" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "Azken kalifikazioa" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "Ikusi artxibatutako ikastaroa" @@ -7914,7 +8131,27 @@ msgid "An error occurred. Please reload the page." msgstr "Errorea gertatu da. Mesedez, kargatu berriz orria." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -8114,17 +8351,13 @@ msgid "What You Need for Verification" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Web-kamera" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8132,9 +8365,7 @@ msgid "Photo Identification" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8160,14 +8391,10 @@ msgstr "" msgid "Your entire face fits inside the frame." msgstr "" -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "" - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8184,12 +8411,9 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Zergatik behar du %(platformName)s plataformak nire argazkia?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8201,13 +8425,11 @@ msgstr "" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8267,15 +8489,13 @@ msgid "Take a Photo of Your ID" msgstr "Egin argazkia zure ID-ari" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" #: lms/templates/verify_student/id_photo_step.underscore @@ -8300,6 +8520,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8346,6 +8573,22 @@ msgstr "" msgid "Can we match the photo you took with the one on your ID?" msgstr "" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -8374,6 +8617,13 @@ msgid "" "and photo" msgstr "" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Web-kamera" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8461,6 +8711,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "Egiaztatu posta elektronikoa aktibazio-mezua ikusteko." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Denerakoa" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "Zirtagiri profesionala {courseName} ikastarorako" @@ -8498,6 +8753,36 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "Eskerrik asko! Zure ordainketa jaso dugu {courseName} ikastarorako." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "Agindu-zenbakia" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Kopurua" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Hartu kontuan" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Faktura ondokoari egin zaio: " + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Ordainagiria ez dago eskura" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "Hurrengo aldia: berritsi zure nortasuna" @@ -8526,6 +8811,10 @@ msgid "" "%(platformName)s to verify your identity." msgstr "" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "Nahi al duzu nortasuna beranduago egiaztatu?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "" @@ -8534,7 +8823,7 @@ msgstr "" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" @@ -8570,10 +8859,6 @@ msgstr "" msgid "Does the photo of you show your whole face?" msgstr "" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "" @@ -9982,6 +10267,21 @@ msgstr "" msgid "Exam Types" msgstr "" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "" @@ -10149,14 +10449,14 @@ msgstr "" msgid "Read more" msgstr "Irakurri gehiago" -#: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" -msgstr "" - #: cms/templates/js/video-transcripts.underscore msgid "No transcript uploaded." msgstr "Ez da transkripzioa kargatu." +#: cms/templates/js/video-transcripts.underscore +msgid "Show transcripts ({totalTranscripts})" +msgstr "" + #: cms/templates/js/xblock-access-editor.underscore msgid "Set Access" msgstr "Ezarri sarbidea" diff --git a/conf/locale/fr/LC_MESSAGES/djangojs.mo b/conf/locale/fr/LC_MESSAGES/djangojs.mo index 04609d92c6dd20f74954ce146e35ff5ec3461185..1b4f741b4196a64af519aedb5141d5a1b5672332 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 ca90b186841a4f88166260a051f8ca9ff16fc010..3335223a9d3ad8252fb8d022f721353ac1b3a49a 100644 --- a/conf/locale/fr/LC_MESSAGES/djangojs.po +++ b/conf/locale/fr/LC_MESSAGES/djangojs.po @@ -15,8 +15,8 @@ # Daniel Le Berre, 2015 # Dosto92 <hakim.poubelle@gmail.com>, 2014 # Education Sahel <tech.sahel.education@gmail.com>, 2019 -# Encolpe Degoute <inactive+encolpe@transifex.com>, 2013 -# Encolpe Degoute <inactive+encolpe@transifex.com>, 2013 +# b37bd6faa8631249767025c90cffb237_c33f832 <d0bf341d6cab6374cbc873fbbf166cb5_105987>, 2013 +# b37bd6faa8631249767025c90cffb237_c33f832 <d0bf341d6cab6374cbc873fbbf166cb5_105987>, 2013 # Eric Fortin, 2014,2016 # Eric Fortin, 2014,2016 # Fox <florent.dijx@gmail.com>, 2016 @@ -79,12 +79,13 @@ # # Translators: # SALHI Aissam <ais.salhy@gmail.com>, 2014 +# Alexandre DS <alexandre@cleverm8.com>, 2020 # Benjamin PENA <benjamin.pena@fun-mooc.fr>, 2019 # Bertrand Marron <bertrand.marron@gmail.com>, 2014 # Christopher Castermane <christopher.castermane@student.uclouvain.be>, 2014 # Dosto92 <hakim.poubelle@gmail.com>, 2014 -# Encolpe Degoute <inactive+encolpe@transifex.com>, 2013 -# Encolpe Degoute <inactive+encolpe@transifex.com>, 2013 +# b37bd6faa8631249767025c90cffb237_c33f832 <d0bf341d6cab6374cbc873fbbf166cb5_105987>, 2013 +# b37bd6faa8631249767025c90cffb237_c33f832 <d0bf341d6cab6374cbc873fbbf166cb5_105987>, 2013 # Eric Fortin, 2014,2016 # Eric Fortin, 2014,2016 # Françoise Docq, 2014 @@ -134,6 +135,7 @@ # laurentFUN <laurent.at.fun@gmail.com>, 2019 # moocit-france <contact@moocit.fr>, 2019 # Nicolas François Leperlier <leperlier.n@gmail.com>, 2019 +# Alexandre DS <alexandre@cleverm8.com>, 2020 # # #-#-#-#-# underscore.po (edx-platform) #-#-#-#-# # edX community translations have been downloaded from French (http://www.transifex.com/open-edx/edx-platform/language/fr/) @@ -141,6 +143,7 @@ # This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE. # # Translators: +# Alexandre DS <alexandre@cleverm8.com>, 2020 # ASSYASS Mahmoud <mahmoud.assyass@gmail.com>, 2015 # Aurélien Croq <sysadmin@themoocagency.com>, 2017 # bekairi tahar <tahar48omar@gmail.com>, 2014 @@ -201,16 +204,16 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" -"PO-Revision-Date: 2019-12-13 16:54+0000\n" -"Last-Translator: Sébastien Vigneau <sebastien.vigneau@gmail.com>\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" +"Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: French (http://www.transifex.com/open-edx/edx-platform/language/fr/)\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -259,6 +262,7 @@ msgstr "Supprimer" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -281,6 +285,7 @@ msgstr "Chargement en cours" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -310,6 +315,7 @@ msgstr "Choisir le fichier" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "OK" @@ -900,7 +906,6 @@ msgstr "Supprimer le tableau" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Description" @@ -1340,6 +1345,7 @@ msgstr "Nouvelle fenêtre" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Suivant" @@ -2645,7 +2651,15 @@ msgid "Other" msgstr "Autre" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx @@ -2653,21 +2667,23 @@ msgid "Details" msgstr "Détails" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Soumettre" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2684,6 +2700,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "Saisissez un détail pour votre demande de soutien." +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2707,7 +2735,8 @@ msgstr "" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2894,6 +2923,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "Une erreur est survenue. Réessayez." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Quitter cette équipe ?" @@ -3429,6 +3462,7 @@ msgid "There has been an error processing your survey." msgstr "Il y a eu une erreur lors du traitement de votre enquête." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -5501,6 +5535,16 @@ msgstr "Tout déplier" msgid "Collapse All" msgstr "Tout replier" +#: openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show More" +msgstr "" + +#: openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show Less" +msgstr "" + #: openedx/features/course_search/static/course_search/js/views/search_results_view.js msgid "{total_results} result" msgid_plural "{total_results} results" @@ -5652,6 +5696,10 @@ msgstr "Oui, permettre les modifications du certificat actif" msgid "certificate" msgstr "certificat" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Configurer votre certificat" @@ -5663,8 +5711,8 @@ msgid "You have not created any certificates yet." msgstr "Vous n'avez pas encore crée de certificat." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "Supprimer \"<%= signatoryName %>\" de la liste de signataires." +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5983,8 +6031,8 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -6167,7 +6215,7 @@ msgid "{selectedProvider} credentials saved" msgstr "" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" msgstr "" #: cms/static/js/views/edit_chapter.js @@ -6759,18 +6807,14 @@ msgstr "" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" -"La longueur totale des champs organisation, numéro du cours et session du " -"cours ne peut dépasser <%=limit%> caractères." #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" -"La longueur totale des champs organisation et codes de bibliothèque ne doit " -"pas dépasser <%=limit%> caractères." #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -7112,13 +7156,13 @@ msgid "Unscheduled" msgstr "Non programmé" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Date" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Précédent" @@ -7167,6 +7211,310 @@ msgstr "Effacer la recherche" msgid "Search" msgstr "Recherche" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Soumettre" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "Tous les posts" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "Page d'accueil de Discussion" @@ -7225,10 +7573,6 @@ msgstr "" "Cocher cette case pour recevoir une fois par jour un e-mail récapitulatif " "des nouveautés dans les fils de discussion que vous suivez." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "Tous les posts" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "nom d'utilisateur ou email" @@ -7468,6 +7812,10 @@ msgstr "Avez-vous de la difficulté à trouver une équipe à rejoindre?" msgid "Join Team" msgstr "Rejoindre l'équipe" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "Détails de l'équipe" @@ -7555,101 +7903,6 @@ msgstr "Supprimer la sous-section %(subsectionDisplayName)s" msgid "Remove unit %(unitName)s" msgstr "Supprimer l'unité %(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" -"Vous devez encore visiter le site web de %(display_name)s afinn de compléter" -" le processus de crédit." - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"Pour finaliser l'obtention de crédit de cours, %(display_name)s demande aux " -"apprenants de %(platform_name)s de soumettre une demande de crédit." - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Obtenir un crédit" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" -"Merci %(full_name)s! Nous avons reçu votre paiement pour %(course_name)s." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"Veuillez imprimer et conserver cette page; elle vous servira de reçu. Vous " -"recevrez également un e-mail avec les mêmes informations." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "Commande N°" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Montant" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Total" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Veuillez noter" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "Les éléments barrés ont été remboursés." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Facturé à " - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Pas de reçu disponible" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Aller au tableau de bord" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "Voulez-vous confirmer votre identité plus tard?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Vérifier Maintenant" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Marquer l'examen comme complété" @@ -7674,14 +7927,6 @@ msgstr "" "Pour recevoir des crédits pour votre problème, cliquez sur « Soumettre » " "pour chaque exercice avant de sélectionner « Terminer mon examen »." -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show More" -msgstr "" - -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show Less" -msgstr "" - #: lms/templates/courseware/proctored-exam-status.underscore msgid "Exam timer and end exam button" msgstr "" @@ -7787,10 +8032,8 @@ msgstr "A propos de vous" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" -"L'information suivante fait déjà partie de votre profil {platform}. Nous " -"l\\'avons inclus ici pour votre demander." #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7820,6 +8063,10 @@ msgstr "" "Merci d'avoir soumis votre demande d'aide financière pour {course_name}! " "Vous aurez une réponse dans 2-4 jours ouvrables." +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Aller au tableau de bord" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "Dérogations en lot" @@ -8185,14 +8432,6 @@ msgstr "" msgid "You can change sessions until {expiration_date}." msgstr "" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "pour {courseName}" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "Voir le cours archivé" @@ -8416,7 +8655,27 @@ msgid "An error occurred. Please reload the page." msgstr "Une erreur est survenue. Merci de rafraîchir la page." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -8624,17 +8883,13 @@ msgid "What You Need for Verification" msgstr "Ce qui est nécésaire pour la vérification" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Webcam" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8642,12 +8897,8 @@ msgid "Photo Identification" msgstr "Photo d'identité" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"Vous avez besoin d'un permis de conduire, d'un passeport ou d'une pièce " -"d'identité avec votre nom et photo." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8672,15 +8923,10 @@ msgstr "Votre visage est bien éclairé" msgid "Your entire face fits inside the frame." msgstr " Votre visage est entièrement dans le cadre." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "" -"La photo de votre visage concorde avec la photo sur votre pièce d'identité." - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8697,17 +8943,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Pourquoi %(platformName)s a besoin de ma photo ?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"Participant au processus de vérification, vous prenez une photo de votre " -"visage ainsi que de votre pièce d'identité. Notre service d'autorisation " -"confirme votre identité en comparant votre visage à la photo de la pièce " -"d'identité." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8718,19 +8957,12 @@ msgstr "Que fait %(platformName)s avec cette photo ?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"Nous utilisons le niveau de sécurité le plus élevé pour chiffrer votre photo" -" et l'envoyer à notre service d’autorisation afin d'y être examinée. Votre " -"photo et vos informations ne sont pas enregistrées, et ils ne sont pas " -"visible nulle part sur %(platformName)s après l'accomplissement de " -"processus de vérification." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8789,21 +9021,14 @@ msgid "Take a Photo of Your ID" msgstr "Prenez une photo de votre pièce d'identité" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"Utilisez votre webcam pour prendre une photo de votre pièce d'identité. Nous" -" allons vérifier sa concordance avec la photo de votre visage et le nom de " -"votre compte." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Vous avez besoin d'un permis de conduire, un passeport ou toute pièce " -"d'identité avec votre nom et photo." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8827,6 +9052,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8879,6 +9111,31 @@ msgstr "" "Peut-on vérifier la concordance entre la photo que vous avez prise et celle " "de vos identifiants ?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"Participant au processus de vérification, vous prenez une photo de votre " +"visage ainsi que de votre pièce d'identité. Notre service d'autorisation " +"confirme votre identité en comparant votre visage à la photo de la pièce " +"d'identité." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"Nous utilisons le niveau de sécurité le plus élevé pour chiffrer votre photo" +" et l'envoyer à notre service d’autorisation afin d'y être examinée. Votre " +"photo et vos informations ne sont pas enregistrées, et ils ne sont pas " +"visible nulle part sur %(platformName)s après l'accomplissement de " +"processus de vérification." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "Merci pour votre vérification d'ID pour: {courseName}" @@ -8912,6 +9169,13 @@ msgstr "" "Un permis de conduire, un passeport ou toute pièce d'identité avec votre nom" " et photo." +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Webcam" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -9017,6 +9281,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "Vérifiez dans vos emails que vous avez reçu le message d'activation" +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Total" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "Certificat professionnel pour {courseName}" @@ -9060,6 +9329,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "Merci. Nous avons reçu votre paiement pour {courseName}." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"Veuillez imprimer et conserver cette page; elle vous servira de reçu. Vous " +"recevrez également un e-mail avec les mêmes informations." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "Commande N°" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Montant" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Veuillez noter" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "Les éléments barrés ont été remboursés." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Facturé à " + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Pas de reçu disponible" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "Étape suivante: Confirmer votre identité" @@ -9095,6 +9396,10 @@ msgstr "" "parcourir vos cours depuis votre tableau de bord. Vous recevrez des rappels " "régulier de %(platformName)s pour vérifier votre identité." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "Voulez-vous confirmer votre identité plus tard?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "Vérification d'identité en cours" @@ -9103,12 +9408,9 @@ msgstr "Vérification d'identité en cours" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"Nous avons reçus vos informations et nous vérifions votre identité. Un " -"message sera visible sur votre tableau de bord (1-2 jours de délai). Entre " -"temps, vous avez toujours accès à l'ensemble du cours." #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -9144,10 +9446,6 @@ msgstr "Conditions requises pour la photo:" msgid "Does the photo of you show your whole face?" msgstr "Votre photo montre-t-elle votre visage en entier ?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "Votre photo correspond-elle à celle de votre document d'identité ?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "Le nom sur votre ID est-il lisible ?" @@ -10659,6 +10957,21 @@ msgstr "Définir comme un examen spécial" msgid "Exam Types" msgstr "Types d'examen" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Minuté" @@ -10846,11 +11159,11 @@ msgid "Read more" msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" +msgid "No transcript uploaded." msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "No transcript uploaded." +msgid "Show transcripts ({totalTranscripts})" msgstr "" #: cms/templates/js/xblock-access-editor.underscore diff --git a/conf/locale/id/LC_MESSAGES/django.mo b/conf/locale/id/LC_MESSAGES/django.mo index 76e6b13d0ec947439d34b0b61b9b2d73578360da..2c14120786fae7cf3eb53d946ff264f23f2b0ec9 100644 Binary files a/conf/locale/id/LC_MESSAGES/django.mo and b/conf/locale/id/LC_MESSAGES/django.mo differ diff --git a/conf/locale/id/LC_MESSAGES/django.po b/conf/locale/id/LC_MESSAGES/django.po index 2d459f5c93bc9a5e0b7178111e393e8014bc978f..1cadce295fa0c224743ecb5c0faf1ed8bba20f61 100644 --- a/conf/locale/id/LC_MESSAGES/django.po +++ b/conf/locale/id/LC_MESSAGES/django.po @@ -99,7 +99,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Aprisa Chrysantina <aprisa.chrysantina@gmail.com>, 2019\n" "Language-Team: Indonesian (https://www.transifex.com/open-edx/teams/6205/id/)\n" @@ -108,7 +108,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -133,8 +133,8 @@ msgstr "Ujian Masuk" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "Unit" @@ -458,13 +458,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "Akun dengan Nama Publik '{username}' sudah digunakan." +msgid "An account with the Email '{email}' already exists." +msgstr "Akun dengan Email '{email}' sudah digunakan." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "Akun dengan Email '{email}' sudah digunakan." +msgid "An account with the Public Username '{username}' already exists." +msgstr "Akun dengan Nama Publik '{username}' sudah digunakan." #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2357,9 +2357,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -4288,12 +4288,12 @@ msgstr "" "Masukkan benar atau salah. Jika benar, jawab kiriman untuk modul problem " "akan dipertimbangkan dalam algoritma penentuan skor / gating Ujian Masuk." -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "Grup Jalur Pendaftaran" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "Partisi untuk mengelompokkan pengguna berdasarkan jalur pendaftaran" @@ -4959,17 +4959,17 @@ msgstr "Buka Kunci Akun" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "Tutup" @@ -5932,56 +5932,6 @@ msgstr "" "Permintaan pengembalian dana telah diajukan untuk {username} ({email}). " "Untuk memproses permintaan ini, silakan kunjungi tautan(s) di bawah ini." -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "Tanda Terima" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "Pembayaran Gagal" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "Ada masalah dengan transaksi ini. Anda belum dikenakan biaya." - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" -"Pastikan informasi Anda benar, atau coba lagi dengan kartu yang berbeda atau" -" bentuk pembayaran lain." - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" -"Terjadi kesalahan sistem saat memproses pembayaran Anda. Anda belum dikenai " -"biaya." - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "Harap tunggu sebentar dan kemudian coba kembali." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "Untuk bantuan, kontak {payment_support_link}." - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "Eror terjadi saat membuat bukti pembayaran Anda." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"Jika pelatihan tidak muncul di dasbor Anda, silahkan kontak " -"{payment_support_link}." - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "Dapatkan sertifikat" @@ -6044,11 +5994,23 @@ msgstr "Anda tidak memiliki akses terhadap pelatihan ini" msgid "You do not have access to this course on a mobile device" msgstr "Anda tidak memiliki akses ke pelatihan ini di perangkat seluler" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "Tingkatkan ke Terverifikasi" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -6742,16 +6704,20 @@ msgid "Good" msgstr "Baik" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" -msgstr "%(comment_username)s balas ke <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" +msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt msgid "View discussion" msgstr "Lihat diskusi" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "%(comment_username)s balas ke <b>%(thread_title)s</b>:" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6897,8 +6863,8 @@ msgid "Student" msgstr "Siswa" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "Staf" @@ -7027,29 +6993,6 @@ msgstr "Tanggapan masalah" msgid "Could not find problem with this location." msgstr "Tidak dapat menemunkan problem dengan lokasi ini." -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "Tagihan dengan nomor '{num}' tidak ada." - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "Penjualan yang terkait dengan tagihan ini telah dibatalkan." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "Tagihan dengan nomor {0} telah dibatalkan." - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "Tagihan ini suda aktif." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "Kode registrasi untuk tagihan {0} telah direaktivasi." - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "ID Pelatihan" @@ -7080,9 +7023,8 @@ msgstr "ID Pengguna" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "Nama Pengguna" @@ -7204,54 +7146,6 @@ msgstr "" "File harus mengandung sebuah kolom 'username', sebuah kolom 'email', atau " "keduanya." -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "kode Kupon" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "Id pelatihan" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% Diskon" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "Deskripsi" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "Tanggal Kadaluarsa" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "Aktif" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "Jumlah Kode Tertebus" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "Total Kursi yang Didiskon" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "Total Jumlah yang Didiskon" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -7272,16 +7166,6 @@ msgstr "Survei" msgid "proctored exam results" msgstr "Hasil Ujian Tersupervisi" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "Tidak dapat menguraikan jumlah sebagai desimal" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" -"Tidak dapat menghasilkan kode yang diperoleh karena salah konfigurasi " -"pelatihan." - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -7527,65 +7411,6 @@ msgstr "" "verifikasi username/email siswa dan pelatihan yang dipilih apakah sudah " "benar dan coba lagi." -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "id kupon tidak ada" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "kupon dengan id kupon ({coupon_id}) tidak ada" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "kupon dengan id kupon ({coupon_id}) sudah tidak aktif" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "kupon dengan id kupon ({coupon_id}) telah berhasil diperbarui" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" -"Kode ({code}) yang Anda telah coba definisikan telah digunakan sebagai kode" -" registrasi" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "Silahkan masukkan Nilai Integer untuk Diskon Kupon" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "Silahkan Masukkan Nilai Diskon Kupon kurang dari atau sama dengan 100" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "Silahkan masukkan tanggal dengan format berikut bulan/hari/tahun" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "Kupon dengan kode kupon ({code}) sudah digunakan pada pelatihan ini" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "Kupon tidak dapat digunakan" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "Kupon dengan id kupon ({coupon_id}) berhasil diperbarui" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "Instruktur" @@ -7695,31 +7520,6 @@ msgstr "Selesai" msgid "Incomplete" msgstr "Belum selesai" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "" -"Kode pendaftaran ({code}) tidak ditemukan pada pelatihan {course_name}." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "" -"Kode pendaftaran ini telah dibatalkan. Kode ini tidak bisa digunakan lagi." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "Kode pendaftaran ini telah ditandai sebagai tidak digunakan." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "Kode pendaftaran telah dipulihkan kembali." - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "" - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -8125,8 +7925,8 @@ msgstr " (out of {total})" #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Program" @@ -8302,9 +8102,11 @@ msgid "{mode_name} for course {course}" msgstr "{mode_name} untuk kursus {course}" #: lms/djangoapps/shoppingcart/models.py +#, python-brace-format msgid "" -"You can unenroll in the course and receive a full refund for 14 days after " -"the course start date. " +"To receive a refund you may unenroll from the course on your edX Dashboard " +"({dashboard_url}) up to 14 days after your payment or 14 days after your " +"course starts (up to six months after your payment).\n" msgstr "" #: lms/djangoapps/shoppingcart/models.py @@ -8317,15 +8119,14 @@ msgstr "" #: lms/djangoapps/shoppingcart/models.py msgid "" "You can unenroll in the course and receive a full refund for 2 days after " -"the course start date. " +"the course start date.\n" msgstr "" #: lms/djangoapps/shoppingcart/models.py #, python-brace-format msgid "" -"{refund_reminder_msg}To receive your refund, contact {billing_email}. Please" -" include your order number in your email. Please do NOT include your credit " -"card information." +"{refund_reminder_msg}For help unenrolling, Please see How do I unenroll from" +" a course? ({how_to_unenroll_link}) in our edX HelpCenter." msgstr "" #: lms/djangoapps/shoppingcart/models.py @@ -8743,6 +8544,15 @@ msgstr "Jumlah Biaya" msgid "Currency" msgstr "Mata uang" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "Deskripsi" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "Komentar" @@ -8886,14 +8696,6 @@ msgstr "Anda tidak memiliki izin untuk melihat halaman ini." msgid "View and regenerate certificates." msgstr "" -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "Panduan Pengembalian Dana" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "" - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -8972,45 +8774,10 @@ msgstr "" msgid "User Disabled Successfully" msgstr "" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "Alamat Email" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "ID Kursus" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "Pengguna tidak ditemukan" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" msgstr "" -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "Membatalkan pendaftaran {user} dari {course_id}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "{cost} telah direfund untuk pesanan ID {order_id}" - #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." msgstr "" @@ -9057,13 +8824,17 @@ msgid "The supplied course_id {course_id} is not valid." msgstr "" #: lms/djangoapps/teams/views.py -msgid "You are already in a team in this course." +msgid "topic_id is required" msgstr "" #: lms/djangoapps/teams/views.py msgid "You can't create a team in an instructor managed topic." msgstr "" +#: lms/djangoapps/teams/views.py +msgid "You are already in a team in this teamset." +msgstr "" + #: lms/djangoapps/teams/views.py msgid "teamset_id and team_id are mutually exclusive options." msgstr "" @@ -9659,8 +9430,8 @@ msgid "Allow" msgstr "Perbolehkan" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "Kesalahan" @@ -10054,8 +9825,8 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "Sisipan" @@ -10093,11 +9864,10 @@ msgstr "" "diperbarui jika berkas artikel lainnya diperbarui." #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -10509,6 +10279,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -10881,6 +10655,10 @@ msgstr "Kasus Kesalahan Diketahui" msgid "Schedule start < course start" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "Id pelatihan" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "semua" @@ -10889,6 +10667,15 @@ msgstr "semua" msgid "Experience" msgstr "Pengalaman" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "ID Kursus" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -11352,7 +11139,6 @@ msgstr "" "ini." #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -11381,8 +11167,8 @@ msgid "Success" msgstr "Berhasil" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "Tindakan" @@ -11562,6 +11348,14 @@ msgstr "Daftar" msgid "There was an error receiving your login information. Please email us." msgstr "Ada kesalahan saat menerima informasi login Anda. Mohon email kami." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11575,6 +11369,15 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "Terlalu sering gagal login. Coba lagi nanti." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11582,15 +11385,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "username@domain.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -11606,6 +11400,12 @@ msgstr "Alamat email yang anda gunakan untuk mendaftar di {platform_name}" msgid "Create Account" msgstr "Buat Akun" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "username@domain.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -11622,6 +11422,11 @@ msgstr "" "Akun pengguna terasosiasi dengan alamat e-mail ini tidak dapat mengatur " "ulang kata sandi." +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "Reset Kata sandi tidak berhasil" @@ -11643,11 +11448,6 @@ msgstr "" "{html_start}Sandi Anda telah Dibuat{html_end}Sandi Anda telah dibuat. " "{bold_start}{email}{bold_end} adalah email login utama Anda." -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "Terjadi kesalahan saat mengubah sandi. Silakan coba kembali." @@ -11888,6 +11688,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "" @@ -11906,6 +11718,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "Isian tidak valid" @@ -12595,8 +12411,8 @@ msgstr "" msgid "Vertical" msgstr "Vertikal" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "Bagian" @@ -12868,6 +12684,18 @@ msgstr "" msgid "Transcript Ready" msgstr "Transkrip Siap" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "" @@ -13013,8 +12841,8 @@ msgstr "Konten" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "Setelan" @@ -13062,14 +12890,14 @@ msgstr "Nomor Kursus:" msgid "Course Run:" msgstr "Course Run:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "Kursus" @@ -13093,8 +12921,9 @@ msgstr "instruktur" msgid "Requirements" msgstr "Kebutuhan" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "Detil" @@ -13150,15 +12979,15 @@ msgstr "" msgid "Choose Language" msgstr "Pilih Bahasa" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "Akun" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -13230,8 +13059,8 @@ msgstr "Menu Pengguna" msgid "Usermenu dropdown" msgstr "Dropdown menu pengguna" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "Keluar" @@ -13399,8 +13228,8 @@ msgstr "Mulai: {date}" msgid "View all Courses" msgstr "Tampilkan Seluruh Kursus" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "Dashboard" @@ -13419,8 +13248,8 @@ msgstr "Anda belum terdaftar di kursus yang ada" #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "Lihat kursus" @@ -13438,7 +13267,7 @@ msgstr "Kesalahan menampilkan kursus" msgid "Search Your Courses" msgstr "Cari Kursus Anda" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "Bersihkan pencarian" @@ -13463,7 +13292,7 @@ msgstr "Terima email kursus" msgid "Save Settings" msgstr "Simpan Pengaturan" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -13473,9 +13302,87 @@ msgstr "Simpan Pengaturan" msgid "Unenroll" msgstr "Batalkan Pendaftaran" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "Tampilkan Unit dalam Studio" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -13508,7 +13415,7 @@ msgstr "Akun dengan alamat email baru telah ada sebelumnya." msgid "You should Register before trying to access the Unit" msgstr "Anda harus Mendaftar sebelum mengakses Unit ini" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "Daftar" @@ -13616,7 +13523,7 @@ msgstr "" "{line_break} Jika Anda telah menyelesaikan tugas ini, nilai Anda tersedia di" " halaman progres {link_start} {link_end}." -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "Cari kursus" @@ -13757,22 +13664,16 @@ msgstr "(Muat ulang halaman Anda untuk refresh)" msgid "working" msgstr "proses" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "Terjadi kesalahan pada server {platform_name}" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html -#: lms/templates/courseware/error-message.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"Maaf, modul ini untuk sementara tidak tersedia. Staf kami sedang bekerja " -"untuk memperbaikinya sesegera mungkin. Silahkan email kami di " -"{tech_support_email} untuk melaporkan masalah atau terhenti." #: lms/templates/module-error.html msgid "Raw data:" @@ -13811,7 +13712,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "Anda sekarang mengikuti kursus sebagai {i_start} {user_name} {i_end}." #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -13877,16 +13786,6 @@ msgstr "Email" msgid "Return To %s" msgstr "Kembali ke %s" -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "Kembali Berlangganan Berhasil!" @@ -13940,7 +13839,7 @@ msgstr "Selanjutnya" msgid "Sequence" msgstr "Urutan" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -14071,18 +13970,18 @@ msgstr "Skor (hanya untuk pengganti)" msgid "Reset Learner's Attempts to Zero" msgstr "Setel ulang pekerjaan peserta didik ke awal lagi" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "Hapus Status Peserta" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "Pengiriman penilaian ulang peserta didik" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "Reskor hanya jika skor meningkat" @@ -14120,7 +14019,7 @@ msgstr "Buku teks {course_number}" msgid "Textbook Navigation" msgstr "Navigasi Buku teks" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "Halaman" @@ -14233,9 +14132,9 @@ msgstr "Halaman {current_page} dari {total_pages}" msgid "Recent git load activity for {course_id}" msgstr "Aktivitas git load terbaru untuk {course_id}" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -14295,7 +14194,7 @@ msgstr "" "Anda{link_end}. Jika Anda tidak bermaksud melakukan ini, " "{undo_link_start}Anda dapat berlanganan kembali{link_end}." -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "Dashboard untuk:" @@ -14303,8 +14202,8 @@ msgstr "Dashboard untuk:" msgid "More options" msgstr "Pilihan lain" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "Pilihan lain" @@ -15822,40 +15721,6 @@ msgstr "" msgid "About edX Certificates" msgstr "Tentang Sertifikat edX" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "Pemeriksaan Batal" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"Transaksi Anda telah dibatalkan. Jika Anda merasa kesalahan telah terjadi, " -"hubungi {email}." - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "Terjadi kesalahan saat checkout" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" -"Terjadi kesalahan dengan pembayaran Anda. {b_start}Anda belum " -"ditagih.{b_end} Silakan ulangi pengiriman pembayaran Anda. Jika permasalahan" -" tetap terjadi, hubungi {email}." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "Memuat Permintaan Data..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "Harap tunggu ketika kami mencari detil permintaan Anda." - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -16095,30 +15960,25 @@ msgstr "{section_format} sesuai {{date}}" msgid "This content is graded" msgstr "Konten ini telah dinilai" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "Terjadi kesalahan. Silakan coba lagi nanti." - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "Terjadi error. Pastikan Anda telah masuk untuk mendaftar." +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "Terjadi kesalahan. Silakan coba lagi nanti." + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "Anda terdaftar pada pelatihan ini" #: lms/templates/courseware/course_about.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: lms/templates/shoppingcart/registration_code_receipt.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "View Course" msgstr "Lihat Kursus" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" -"Kursus ini ada di dalam {start_cart_link}keranjang belanja{end_cart_link} " -"Anda." - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "Kursus ini penuh" @@ -16131,12 +15991,6 @@ msgstr "Pendaftaran kursus ini hanya melalui undangan" msgid "Enrollment is Closed" msgstr "Pendaftaran Ditutup" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" -"Tambahkan {course_name} ke dalam Keranjang Belanja {start_span}({price} " -"USD){end_span}" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "Daftar Sekarang" @@ -16264,6 +16118,13 @@ msgstr "Kegunaan Kursus" msgid "Courseware" msgstr "Perangkat Kursus" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "Pencarian Kursus" @@ -16297,7 +16158,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -16305,8 +16166,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" +msgstr "" + +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -16361,8 +16225,9 @@ msgid "Welcome to {course_title}!" msgstr "Selamat datang di {course_title}!" #: lms/templates/courseware/info.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "Resume Course" msgstr "Ringkas Pelatihan" @@ -17006,10 +16871,8 @@ msgstr "Anda telah mengirimkan informasi verifikasi Anda." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" -"Anda akan mendapatkan pesan di halaman dashboard saat proses verifikasi " -"selesai (biasanya dalam 1-2 hari)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -17019,10 +16882,8 @@ msgstr "Verifikasi Anda saat ini akan segera kedaluwarsa!" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" -"Anda telah mengirimkan informasi reverifikasi Anda. Anda akan melihat pesan " -"di dashboard saat proses verifikasi selesai (biasanya dalam 1-2 hari)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -17779,149 +17640,6 @@ msgstr "" "verifikasi telah berhasil. Anda juga dapat mengecek status proses verifikasi" " pada dashboard Anda." -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "Terima kasih telah melakukan pembelian di {course_name}." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"Tagihan sebesar {currency_symbol}{total_price} terlampir. Pembayaran jatuh " -"tempo saat tagihan diterima. Anda dapat mencari tahu informasi tentang " -"metode pembayaran di tagihan." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -"File .csv yang terdaftar di kode pendaftaran Anda terlampir. Anda dapat " -"menggunakan template email di bawah untuk mendistribusikan kode pendaftaran " -"kepada siswa Anda. Setiap siswa harus menggunakan kode pendaftaran berbeda." - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"Terima kasih,\n" -"Tim {platform_name}" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "Halo [[Name]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"Kami menyediakan kode pendaftaran kursus untuk Anda di {course_name}. Untuk " -"mendaftar kursus, klik tautan berikut:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "Tautan HTML dari file CSV terlampir" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"Setelah Anda mendaftar, Anda dapat melihat kursus di dashboard siswa Anda. " -"Anda dapat melihat materi kursus ketika tanggal kursus dimulai. " - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"Salam,\n" -"[[Your Signature]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "TAGIHAN" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "Tanggal: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "Nomor Tagihan: {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "Ketentuan: Tanda Terima Jatuh Tempo" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "Jatuh Tempo: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "Tagihan kepada:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "Nomor Referensi Pelanggan: {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "Saldo Minimum Jatuh Tempo: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "Kursus: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"Harga: {currency_symbol}{course_price} Jumlah: {quantity} Sub-" -"Total: {currency_symbol}{sub_total} Diskon: {currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "Total: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "Instruksi Pembayaran" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"Jika kami tidak menerima pembayaran, pendaftaran siswa yang menggunakan kode" -" ini akan dibatalkan dan siswa tidak dapat mengakses materi kursus. Setiap " -"pembelian adalah final. Untuk informasi lebih lanjut, lihat kebijakan " -"pembatalan {site_name}." - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "Untuk pertanyaan seputar pembayaran, kontak {contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -18130,8 +17848,8 @@ msgstr "Ajukan Keringanan Biaya" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} Beranda" @@ -18155,19 +17873,11 @@ msgstr "Temukan Baru" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "Sysadmin" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "Troli Belanja" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "Tautan Pendukung" @@ -18204,6 +17914,12 @@ msgstr "Tambahkan Kode Kupon" msgid "Enter information about the coupon code below." msgstr "Masuk Informasi tentang kode kupon di bawah." +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "kode Kupon" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "Persentase Diskon" @@ -18818,6 +18534,11 @@ msgstr "Unduh Kode Kupon" msgid "Coupon Codes" msgstr "Kode Kupon" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "Tanggal Kadaluarsa" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "Kupon (%)" @@ -20225,6 +19946,10 @@ msgstr "Pembelian oleh lembaga" msgid "Purchase order number (if any)" msgstr "Nomor pesanan pembelian (jika ada)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "Alamat Email" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "email@example.com" @@ -20543,6 +20268,10 @@ msgid_plural "" msgstr[0] "" "{course_names} telah dihapus karena periode pendaftaran telah ditutup." +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "Troli Belanja" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "Cover Image" @@ -20632,12 +20361,8 @@ msgstr "Konfirmasi" #: lms/templates/static_templates/404.html msgid "" "The page that you were looking for was not found. Go back to the " -"{link_start}homepage{link_end} or let us know about any pages that may have " -"been moved at {email}." +"{link_start}homepage{link_end} ." msgstr "" -"Halaman yang Anda cari tidak ditemukan. Kembali ke {link_start} beranda " -"{link_end} atau beri tahu kami tentang laman apa pun yang mungkin telah " -"dipindahkan ke {email}." #: lms/templates/static_templates/about.html #: lms/templates/static_templates/blog.html @@ -20693,23 +20418,15 @@ msgstr "Saat ini, server {platform_name} sedang down" #: lms/templates/static_templates/server-overloaded.html msgid "" "Our staff is currently working to get the site back up as soon as possible. " -"Please email us at {tech_support_email} to report any problems or downtime." msgstr "" -"Staf kami saat ini sedang berusaha mengembalikan situs sesegera mungkin. " -"Silakan kirim email kepada kami di {tech_support_email} untuk melaporkan " -"masalah atau downtime apa pun." #: lms/templates/static_templates/server-error.html msgid "There has been a 500 error on the {platform_name} servers" msgstr "Terjadi eror 500 di server {platform_name}" #: lms/templates/static_templates/server-error.html -msgid "" -"Please wait a few seconds and then reload the page. If the problem persists," -" please email us at {email}." +msgid "Please wait a few seconds and then reload the page." msgstr "" -"Harap tunggu beberapa detik lalu muat ulang halaman. Jika permasalahan masih" -" terjadi, silahkan kirim email kepada kami di {email}." #: lms/templates/static_templates/server-overloaded.html msgid "Currently the {platform_name} servers are overloaded" @@ -20777,46 +20494,6 @@ msgstr "Student Support: Kelola Pengguna" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "Tentang pengembalian dana pesanan ini:" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "Id Pesanan:" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "Pendaftaran:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "Terdaftar" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "Tidak terdaftar" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "Harga" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "Status CertificateItem:" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "Status Pesanan:" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "Waktu yang terpenuhi:" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "Waktu Permintaan Pengembalian Dana:" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "Survei pengguna" @@ -20972,11 +20649,8 @@ msgstr "Verifikasi Identitas" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" -"Anda telah mengirimkan informasi verifikasi Anda. Anda akan mendapatkan " -"pesan di dasbor Anda ketika proses verifikasi selesai (biasanya dalam 1-2 " -"hari)." #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -21204,6 +20878,10 @@ msgstr "Perbaruan terakhir" msgid "Get started on what's next: " msgstr "" +#: openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html +msgid "Show More" +msgstr "" + #: openedx/features/course_search/templates/course_search/course-search-fragment.html msgid "Search Results" msgstr "Hasil pencarian" @@ -21580,8 +21258,8 @@ msgid "Already registered?" msgstr "Sudah terdaftar?" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "Masuk" @@ -21697,12 +21375,8 @@ msgid "The page that you were looking for was not found." msgstr "Halaman yang Anda cari tidak ditemukan." #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" -"Kembali ke {homepage} atau beri tahu kami tentang halaman yang mungkin " -"dipindah ke {email}." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -21726,10 +21400,6 @@ msgstr "" "Kami telah mencatat kesalahannya dan staff kami saat ini bekerja untuk " "mengatasi masalah ini sesegera mungkin." -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "Jika permasalahan tetap terjadi, email kami di {email_link}" - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "" @@ -22350,9 +22020,7 @@ msgstr "Halaman Yang Anda Minta Tidak Dapat Ditemukan" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" #: cms/templates/error.html @@ -22363,9 +22031,7 @@ msgstr "Server Mengalami Masalah" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" #: cms/templates/error.html @@ -25441,8 +25107,8 @@ msgstr "%(file)s telah diubah menjadi revisi #%(revision)d" msgid "%(file)s has been saved." msgstr "%(file)s telah disimpan." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "Gambar-gambar" @@ -25648,8 +25314,8 @@ msgstr "Hapus daftar notifikasi" msgid "Search..." msgstr "Cari" -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "Daftar" diff --git a/conf/locale/id/LC_MESSAGES/djangojs.mo b/conf/locale/id/LC_MESSAGES/djangojs.mo index f62e9966c5ab6eeebeaca98e74be1dd5e2dce714..bde15bb2d9318cfd800ffa58ca4c9dc54d7aaa06 100644 Binary files a/conf/locale/id/LC_MESSAGES/djangojs.mo and b/conf/locale/id/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/id/LC_MESSAGES/djangojs.po b/conf/locale/id/LC_MESSAGES/djangojs.po index d8346042540698d8e9a14d3f12b2a86184dad412..d9d2ed4886e1dc7fe4d1b6686e39d25e96c67b3d 100644 --- a/conf/locale/id/LC_MESSAGES/djangojs.po +++ b/conf/locale/id/LC_MESSAGES/djangojs.po @@ -80,8 +80,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Indonesian (http://www.transifex.com/open-edx/edx-platform/language/id/)\n" "Language: id\n" @@ -89,7 +89,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -110,21 +110,6 @@ msgstr "Menyimpan" #: cms/static/js/views/manage_users_and_roles.js #: cms/static/js/views/show_textbook.js #: lms/djangoapps/teams/static/teams/js/views/instructor_tools.js -#: cms/templates/js/certificate-details.underscore -#: cms/templates/js/certificate-editor.underscore -#: cms/templates/js/content-group-editor.underscore -#: cms/templates/js/course-instructor-details.underscore -#: cms/templates/js/course-outline.underscore -#: cms/templates/js/course-settings-learning-fields.underscore -#: cms/templates/js/course_grade_policy.underscore -#: cms/templates/js/course_info_update.underscore -#: cms/templates/js/group-configuration-details.underscore -#: cms/templates/js/group-configuration-editor.underscore -#: cms/templates/js/partition-group-details.underscore -#: cms/templates/js/show-textbook.underscore -#: cms/templates/js/signatory-editor.underscore -#: cms/templates/js/video-transcripts.underscore -#: cms/templates/js/xblock-outline.underscore msgid "Delete" msgstr "Hapus" @@ -153,6 +138,7 @@ msgstr "Hapus" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -175,6 +161,7 @@ msgstr "Mengunggah" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -204,6 +191,7 @@ msgstr "Pilih Berkas" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "OK" @@ -788,7 +776,6 @@ msgstr "Hapus tabel" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Deskripsi" @@ -823,18 +810,9 @@ msgstr "Properti dokumen" msgid "Edit HTML" msgstr "Edit HTML" -#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-# #. Translators: this is a message from the raw HTML editor displayed in the #. browser when a user needs to edit HTML #: common/lib/xmodule/xmodule/js/src/html/edit.js -#: cms/templates/js/certificate-details.underscore -#: cms/templates/js/course_info_handouts.underscore -#: cms/templates/js/course_info_update.underscore -#: cms/templates/js/group-configuration-details.underscore -#: cms/templates/js/partition-group-details.underscore -#: cms/templates/js/show-textbook.underscore -#: cms/templates/js/signatory-details.underscore -#: cms/templates/js/xblock-string-field-editor.underscore msgid "Edit" msgstr "Edit" @@ -1237,6 +1215,7 @@ msgstr "Window baru" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Selanjutnya" @@ -1580,12 +1559,9 @@ msgstr "" "URL anda seperti tautan eksternal. Apakah anda ingin menambahkan prefiks " "http:// ?" -#. #-#-#-#-# djangojs-partial.po (edx-platform) #-#-#-#-# #. Translators: this is a message from the raw HTML editor displayed in the #. browser when a user needs to edit HTML #: common/lib/xmodule/xmodule/js/src/html/edit.js -#: cms/templates/js/course-instructor-details.underscore -#: cms/templates/js/signatory-details.underscore msgid "Title" msgstr "Judul" @@ -2518,30 +2494,40 @@ msgid "Other" msgstr "Lainnya" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" -msgstr "Ada yang bisa kami bantu, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Details" msgstr "Detil" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" -msgstr "Semakin lengkap informasimu, semakin cepat dan tepat respon kami!" +msgid "the more quickly and helpfully we can respond!" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Kirim" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "Ada yang bisa kami bantu, {username}?" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "Masuk ke {platform} supaya kami dapat membantumu lebih baik." #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." -msgstr "Jika Anda tidak dapat masuk, hubungi kami melalui email ke {email}." +msgid "Need help logging in?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "" @@ -2553,12 +2539,24 @@ msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "Select a subject for your support request." -msgstr "Berikan judul untuk permintaan dukungan Anda." +msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "Enter some details for your support request." msgstr "Berikan detil untuk permintaan dukungan Anda." +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2582,9 +2580,9 @@ msgstr "Menuju Beranda {platform}" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" -"Terima kasih atas permintaan Anda! Kami akan menghubungi Anda dalam 24 jam." #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx msgid "Cancel upload" @@ -2765,6 +2763,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "Terjadi kesalahan. Coba kembali." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Keluar dari tim ini?" @@ -3300,6 +3302,7 @@ msgid "There has been an error processing your survey." msgstr "Terjadi error dalam memproses survei Anda." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -5380,6 +5383,14 @@ msgstr "Buka Semua" msgid "Collapse All" msgstr "Tutup Semua" +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show More" +msgstr "Tampilkan Lagi" + +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show Less" +msgstr "Tampilkan Lebih Sedikit" + #: openedx/features/course_search/static/course_search/js/views/search_results_view.js msgid "{total_results} result" msgid_plural "{total_results} results" @@ -5529,6 +5540,10 @@ msgstr "" msgid "certificate" msgstr "" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "" @@ -5540,7 +5555,7 @@ msgid "You have not created any certificates yet." msgstr "" #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" msgstr "" #: cms/static/js/certificates/views/signatory_editor.js @@ -5844,11 +5859,9 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" -"Hanya berkas <%= fileTypes %> yang dapat diunggah. Harap pilih berkas dengan" -" ekstensi <%= fileExtensions %> untuk diunggah." #: cms/static/js/models/uploads.js #: lms/templates/student_account/hinted_login.underscore @@ -6025,8 +6038,8 @@ msgid "{selectedProvider} credentials saved" msgstr "Kredensial {selectedProvider} disimpan" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" -msgstr "Unggah berkas PDF baru ke “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" +msgstr "" #: cms/static/js/views/edit_chapter.js msgid "Please select a PDF file to upload." @@ -6585,13 +6598,13 @@ msgstr "Kami mohon maaf, ada kesalahan" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" #: cms/static/js/views/utils/move_xblock_utils.js @@ -6938,13 +6951,13 @@ msgid "Unscheduled" msgstr "Tidak terjadwal" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Tanggal" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Sebelumnya" @@ -6992,6 +7005,309 @@ msgstr "Bersihkan pencarian" msgid "Search" msgstr "Cari" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Kirim" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "Semua Post" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "Beranda Diskusi" @@ -7050,10 +7366,6 @@ msgstr "" "Centang kotak ini untuk menerima email sehari sekali mengenai aktivitas baru" " yang belum dibaca dari post yang Anda ikuti." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "Semua Post" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "nama pengguna atau email" @@ -7287,6 +7599,10 @@ msgstr "" msgid "Join Team" msgstr "" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "" @@ -7371,94 +7687,6 @@ msgstr "" msgid "Remove unit %(unitName)s" msgstr "" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Dapatkan kredit" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "Nomer order" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Jumlah" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Total" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Silakan catat" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "Item yang dicoret telah direfund." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Ditagihkan kepada:" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Tidak ada tanda terima yang tersedia" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Menuju dashboard" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "Ingin konfirmasi identitas anda nanti?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Verifikasi sekarang" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Tandai Ujian Sebagai Selesai" @@ -7483,14 +7711,6 @@ msgstr "" "Untuk menerima kredit untuk permasalahan, Anda harus memilih \"Kirim\" untuk" " setiap permasalahan sebelum Anda memilih \"Akhiri Ujian Saya\"." -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show More" -msgstr "Tampilkan Lagi" - -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show Less" -msgstr "Tampilkan Lebih Sedikit" - #: lms/templates/courseware/proctored-exam-status.underscore msgid "Exam timer and end exam button" msgstr "Timer ujian dan tombol akhiri ujian" @@ -7598,10 +7818,8 @@ msgstr "Tentang Anda" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" -"Informasi berikut merupakan bagian dari profil {platform}. Kami " -"memasukkannya untuk aplikasi Anda." #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7631,6 +7849,10 @@ msgstr "" "Terimakasih sudah mengirimkan aplikasi bantuan finansial untuk " "{course_name}. Anda dapat mengharapkan balasan dalam 2-4 hari kerja." +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Menuju dashboard" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "Pengecualian Massal" @@ -7968,14 +8190,6 @@ msgstr "Anda tidak bisa lagi mengubah sesi." msgid "You can change sessions until {expiration_date}." msgstr "Anda dapat mengubah sesi sampai {expiration_date}." -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "Nilai Akhir" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "untuk {courseName}" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "Lihat Kursus Diarsip" @@ -8201,8 +8415,28 @@ msgid "An error occurred. Please reload the page." msgstr "Terjadi eror, silakan muat halaman kembali" #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" -msgstr "Butuh bantuan untuk masuk?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" +msgstr "" #: lms/templates/student_account/hinted_login.underscore #: lms/templates/student_account/login.underscore @@ -8413,17 +8647,13 @@ msgid "What You Need for Verification" msgstr "Apa yang anda perlukan untuk verifikasi" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Webcam" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8431,12 +8661,8 @@ msgid "Photo Identification" msgstr "Identifikasi Photo" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"Anda memerlukan surat izin mengemudi, paspor, atau kartu identitas lain yang" -" diterbitkan pemerintah yang memiliki nama dan foto Anda." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8461,14 +8687,10 @@ msgstr "Wajah anda remang remang" msgid "Your entire face fits inside the frame." msgstr "Seluruh wajah anda pas kan ke dalam frame" -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "Photo wajah anda sesuai dengan photo pada ID anda" - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8485,16 +8707,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Mengapa %(platformName)s membutuhkan photo saya?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"Sebagai bagian dari proses verifikasi, kami menggunakan foto wajah Anda dan " -"foto dari kartu identitas Anda. Layanan otorisasi kami mengkonfirmasi " -"identitas Anda dengan membandingkan keduanya." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8505,18 +8721,12 @@ msgstr "Apa yang dilakukan %(platformName)s terhadap foto ini?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"Kami menggunakan keamanan tertinggi untuk mengenkripsi foto Anda dan " -"mengirimkannya ke layanan otorisasi kami untuk ditinjau. Foto dan informasi " -"Anda tidak kami simpan atau ditampilkan di manapun di " -"%(platformName)ssetelah verifikasi selesai." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8575,21 +8785,14 @@ msgid "Take a Photo of Your ID" msgstr "Ambil photo ID anda" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"Gunakan webcan untuk mengambil foto ID Anda. Kami akan mencocokkan foto ini " -"dengan foto wajah Anda dan nama di akun Anda." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Anda membutuhkan kartu identitas dengan nama dan foto Anda. Surat izin " -"mengemudi, paspor, atau kartu identitas lain yang diterbitkan oleh " -"pemerintah dapat digunakan." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8613,6 +8816,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8663,6 +8873,29 @@ msgstr "" "Dapatkah kita menyesuaikan photo yang anda telah ambil dengan salah satu " "pada ID anda?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"Sebagai bagian dari proses verifikasi, kami menggunakan foto wajah Anda dan " +"foto dari kartu identitas Anda. Layanan otorisasi kami mengkonfirmasi " +"identitas Anda dengan membandingkan keduanya." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"Kami menggunakan keamanan tertinggi untuk mengenkripsi foto Anda dan " +"mengirimkannya ke layanan otorisasi kami untuk ditinjau. Foto dan informasi " +"Anda tidak kami simpan atau ditampilkan di manapun di " +"%(platformName)ssetelah verifikasi selesai." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -8696,6 +8929,13 @@ msgstr "" "SIM, phasphor, atau ID yg diterbitkan oleh pemerintah dengan nama dan photo " "anda" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Webcam" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8789,6 +9029,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "Periksa email Anda untuk pesan aktivasi." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Total" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "Sertifikat Profesional untuk {courseName}" @@ -8827,6 +9072,36 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "Nomer order" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Jumlah" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Silakan catat" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "Item yang dicoret telah direfund." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Ditagihkan kepada:" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Tidak ada tanda terima yang tersedia" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "Langkah Selanjutnya: konfirmasi identitas anda" @@ -8860,6 +9135,10 @@ msgstr "" "melihat kursus Anda dari dashboard Anda. Anda akan menerima pengingat dari " "%(platformName)s secara periodik untuk memverifikasi identitas Anda." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "Ingin konfirmasi identitas anda nanti?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "" @@ -8868,7 +9147,7 @@ msgstr "" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" @@ -8906,10 +9185,6 @@ msgstr "Syarat photo" msgid "Does the photo of you show your whole face?" msgstr "Apakah photo anda menunjukkan seluruh wajah?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "Apakah photo anda sesuai dengan photo ID?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "Apakah nama pada ID anda bisa terbaca?" @@ -10368,6 +10643,21 @@ msgstr "Atur sebagai Ujian Spesial" msgid "Exam Types" msgstr "Jenis Ujian" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Terjadwal" @@ -10553,14 +10843,14 @@ msgstr "" msgid "Read more" msgstr "Baca lebih lanjut" -#: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" -msgstr "Tampilkan transkrip ({totalTranscripts})" - #: cms/templates/js/video-transcripts.underscore msgid "No transcript uploaded." msgstr "Tidak ada transkrip tersedia." +#: cms/templates/js/video-transcripts.underscore +msgid "Show transcripts ({totalTranscripts})" +msgstr "Tampilkan transkrip ({totalTranscripts})" + #: cms/templates/js/xblock-access-editor.underscore msgid "Set Access" msgstr "Atur Akses" diff --git a/conf/locale/ja_JP/LC_MESSAGES/django.mo b/conf/locale/ja_JP/LC_MESSAGES/django.mo index 5490268e26a12123502701df4bd62c6ef80f6d57..a672dbd5515a173428772f7b179ec42293828142 100644 Binary files a/conf/locale/ja_JP/LC_MESSAGES/django.mo and b/conf/locale/ja_JP/LC_MESSAGES/django.mo differ diff --git a/conf/locale/ja_JP/LC_MESSAGES/django.po b/conf/locale/ja_JP/LC_MESSAGES/django.po index 34da89386863683519101416ed3906e4b4887810..d0de0d590d54de9243cadb45561bd7101c2493eb 100644 --- a/conf/locale/ja_JP/LC_MESSAGES/django.po +++ b/conf/locale/ja_JP/LC_MESSAGES/django.po @@ -113,7 +113,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed <waheed@edx.org>, 2019\n" "Language-Team: Japanese (Japan) (https://www.transifex.com/open-edx/teams/6205/ja_JP/)\n" @@ -122,7 +122,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -147,8 +147,8 @@ msgstr "å—講å‰è©¦é¨“" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "ユニット" @@ -462,13 +462,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "ユーザーå'{username}' ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯æ—¢ã«å˜åœ¨ã—ã¦ã„ã¾ã™ã€‚" +msgid "An account with the Email '{email}' already exists." +msgstr "メール'{email}'ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯æ—¢ã«å˜åœ¨ã—ã¦ã„ã¾ã™ã€‚" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "メール'{email}'ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯æ—¢ã«å˜åœ¨ã—ã¦ã„ã¾ã™ã€‚" +msgid "An account with the Public Username '{username}' already exists." +msgstr "ユーザーå'{username}' ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯æ—¢ã«å˜åœ¨ã—ã¦ã„ã¾ã™ã€‚" #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2249,9 +2249,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -3945,12 +3945,12 @@ msgid "" " considered in the Entrance Exam scoring/gating algorithm." msgstr "trueã¾ãŸã¯falseを入力ã—ã¦ãã ã•ã„。trueã®å ´åˆã€å—講å‰è©¦é¨“採点アルゴリズムã§å•é¡Œãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®è§£ç”æ出ãŒè€ƒæ…®ã•ã‚Œã¾ã™ã€‚" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "å—講登録トラックグループ" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "å—講者をå—講登録トラックã”ã¨ã«åˆ†ã‘ã‚‹" @@ -4547,17 +4547,17 @@ msgstr "" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "é–‰ã˜ã‚‹" @@ -5449,50 +5449,6 @@ msgid "" msgstr "" "{username} ({email}) ã®æ‰•ã„戻ã—請求ãŒé–‹å§‹ã•ã‚Œã¾ã—ãŸã€‚ã“ã®è«‹æ±‚手続をã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®ãƒªãƒ³ã‚¯(複数ã®å ´åˆã‚ã‚Š)ã‚’ã”覧ãã ã•ã„。" -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "é ˜åŽæ›¸" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "支払失敗" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "手続ä¸ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã¾ã 請求ã•ã‚Œã¾ã›ã‚“。" - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "入力ã—ãŸæƒ…å ±ã«é–“é•ã„ãŒãªã„ã‹ã”確èªã„ãŸã ãã‹ã€åˆ¥ã®ã‚«ãƒ¼ãƒ‰ã¾ãŸã¯æ”¯æ‰•æ–¹æ³•ã§ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。" - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "支払手続ãã®å‡¦ç†ä¸ã«ã‚·ã‚¹ãƒ†ãƒ エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã¾ã 請求ã•ã‚Œã¾ã›ã‚“。" - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "数分待ã£ã¦ã€ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "ヘルプã¯{payment_support_link}ã¸ãŠå•ã„åˆã‚ã›ãã ã•ã„。" - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "é ˜åŽæ›¸ã®ä½œæˆä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "ダッシュボードã«å—講講座ãŒè¡¨ç¤ºã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€{payment_support_link} ã¾ã§ã”連絡ãã ã•ã„。" - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "" @@ -5554,10 +5510,22 @@ msgstr "ã“ã®è¬›åº§ã«ã¯ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã„ã¾ã›ã‚“" msgid "You do not have access to this course on a mobile device" msgstr "モãƒã‚¤ãƒ«ãƒ‡ãƒã‚¤ã‚¹ã§ã¯ã“ã®è¬›åº§ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "èªè¨¼ä»˜ãã«ã‚¢ãƒƒãƒ—グレードã™ã‚‹" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -6189,9 +6157,8 @@ msgid "Good" msgstr "良ã„" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html @@ -6199,6 +6166,11 @@ msgstr "" msgid "View discussion" msgstr "" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6328,8 +6300,8 @@ msgid "Student" msgstr "å—講者" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "スタッフ" @@ -6446,29 +6418,6 @@ msgstr "å•é¡Œè§£ç”" msgid "Could not find problem with this location." msgstr "ã“ã®ãƒã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã®å•é¡Œã‚’見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚" -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "è«‹æ±‚æ›¸ç•ªå· '{num}' ã¯å˜åœ¨ã—ã¾ã›ã‚“。" - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "ã“ã®è«‹æ±‚書ã«é–¢é€£ã™ã‚‹å£²ä¸Šã¯æ—¢ã«ç„¡åŠ¹ã§ã™ã€‚" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "請求書番å·{0}ã¯æ—¢ã«ç„¡åŠ¹ã§ã™ã€‚" - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "ã“ã®è«‹æ±‚書ã¯æ—¢ã«æœ‰åŠ¹ã§ã™ã€‚" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "請求書{0}ã®ç™»éŒ²ã‚³ãƒ¼ãƒ‰ã¯å†æœ‰åŠ¹åŒ–ã•ã‚Œã¾ã—ãŸã€‚" - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "講座ID" @@ -6499,9 +6448,8 @@ msgstr "ユーザーID" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "ユーザーå" @@ -6621,54 +6569,6 @@ msgstr "ファイルã«ã¯ã‚³ãƒ›ãƒ¼ãƒˆåã‚’å«ã‚€'コホート'ã®åˆ—ãŒå¿…è¦ msgid "The file must contain a 'username' column, an 'email' column, or both." msgstr "ファイルã«ã¯'ユーザーå'ã®åˆ—ã€'メール'ã®åˆ—ã¾ãŸã¯ä¸¡æ–¹ã‚’å«ã‚€å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚" -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "クーãƒãƒ³ã‚³ãƒ¼ãƒ‰" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "講座ID" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% 割引" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "説明" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "有効期é™" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "ã¯ã‚¢ã‚¯ãƒ†ã‚£ãƒ–" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "å–り戻ã•ã‚ŒãŸã‚³ãƒ¼ãƒ‰æ•°" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "ç·å‰²å¼•seatæ•°" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "ç·å‰²å¼•é‡" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -6689,14 +6589,6 @@ msgstr "アンケート調査" msgid "proctored exam results" msgstr "監ç£ä»˜ã試験çµæžœ" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "数値ã¨ã—ã¦è§£æžã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸ" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "講座è¨å®šãƒŸã‚¹ã®ãŸã‚å–戻コードを生æˆã§ãã¾ã›ã‚“。" - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -6914,63 +6806,6 @@ msgid "" msgstr "" "{student}ã¯{course}講座ã®ä¿®äº†è¨¼ã‚’æŒã£ã¦ã„ã¾ã›ã‚“。ユーザーå/メールãŠã‚ˆã³é¸æŠžã—ãŸè¬›åº§ãŒæ£ã—ã„ã‹ã‚’確èªã—ã¦ã€å†è©¦è¡Œã—ã¦ãã ã•ã„。" -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "クーãƒãƒ³IDãŒã‚ã‚Šã¾ã›ã‚“" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "クーãƒãƒ³ID ({coupon_id}) ã¯å˜åœ¨ã—ã¾ã›ã‚“" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "クーãƒãƒ³ID ({coupon_id}) ã¯æ—¢ã«åˆ©ç”¨ä¸å¯ã¨ãªã£ã¦ã„ã¾ã™" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "クーãƒãƒ³ID ({coupon_id}) ã¯ã‚¢ãƒƒãƒ—デートæˆåŠŸ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "定義ã—よã†ã¨ã•ã‚ŒãŸã‚³ãƒ¼ãƒ‰({code})ã¯ç™»éŒ²ç”¨ã‚³ãƒ¼ãƒ‰ã¨ã—ã¦æ—¢ã«ä½¿ç”¨ä¸ã§ã™" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "クーãƒãƒ³å€¤å¼•çŽ‡ã®æ•´æ•°å€¤ã‚’入力ã—ã¦ãã ã•ã„" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "クーãƒãƒ³å€¤å¼•çŽ‡ã¯100ã¾ãŸã¯ãれ以下ã®å€¤ã‚’入力ã—ã¦ãã ã•ã„" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "日付を月/æ—¥/å¹´ã®æ›¸å¼ã§å…¥åŠ›ã—ã¦ãã ã•ã„" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "クーãƒãƒ³ã‚³ãƒ¼ãƒ‰ ({code}) ã®è¿½åŠ æˆåŠŸ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "クーãƒãƒ³ã‚³ãƒ¼ãƒ‰ ({code}) ã¯ã“ã®è¬›åº§å‘ã‘ã«æ—¢ã«å˜åœ¨ã—ã¾ã™" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "クーãƒãƒ³IDãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "クーãƒãƒ³ID ({coupon_id}) ã®ã‚¢ãƒƒãƒ—デートæˆåŠŸ" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "講師" @@ -7078,29 +6913,6 @@ msgstr "完了" msgid "Incomplete" msgstr "未完了" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "講座 {course_name} ã®å—講登録コード ({code}) ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "ã“ã®å—講登録コードã¯ã‚ャンセルã•ã‚Œã¦ã„ã¾ã™ã€‚使用ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "ã“ã®å—講登録コードã¯ä¸ä½¿ç”¨ã¨è¨å®šã•ã‚Œã¦ã„ã¾ã™ã€‚" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "å—講登録コードãŒå¾©æ—§ã—ã¾ã—ãŸã€‚" - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "å—講登録コード ({code}) ã«å¯¾ã—ã¦å–り戻ã—ã¯ã‚ã‚Šã¾ã›ã‚“。" - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7497,8 +7309,8 @@ msgstr " (åˆè¨ˆ{total}ä¸)" #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "プãƒã‚°ãƒ©ãƒ " @@ -7679,10 +7491,12 @@ msgid "{mode_name} for course {course}" msgstr "講座 {course} ã® {mode_name}" #: lms/djangoapps/shoppingcart/models.py +#, python-brace-format msgid "" -"You can unenroll in the course and receive a full refund for 14 days after " -"the course start date. " -msgstr "講座開始日ã‹ã‚‰14日間ã¯å—講å–消をã—ã¦å…¨é¡ã®æ‰•ã„戻ã—ã‚’å—ã‘å–ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" +"To receive a refund you may unenroll from the course on your edX Dashboard " +"({dashboard_url}) up to 14 days after your payment or 14 days after your " +"course starts (up to six months after your payment).\n" +msgstr "" #: lms/djangoapps/shoppingcart/models.py #, python-brace-format @@ -7694,18 +7508,15 @@ msgstr "ã¾ã 本人èªè¨¼ã‚’ã—ã¦ã„ãªã„å ´åˆã¯ã€æœ¬äººèªè¨¼ã®æ‰‹ç¶šã #: lms/djangoapps/shoppingcart/models.py msgid "" "You can unenroll in the course and receive a full refund for 2 days after " -"the course start date. " -msgstr "講座開始日ã‹ã‚‰2日間ã¯å—講å–消をã—ã¦å…¨é¡ã®æ‰•ã„戻ã—ã‚’å—ã‘å–ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚" +"the course start date.\n" +msgstr "" #: lms/djangoapps/shoppingcart/models.py #, python-brace-format msgid "" -"{refund_reminder_msg}To receive your refund, contact {billing_email}. Please" -" include your order number in your email. Please do NOT include your credit " -"card information." +"{refund_reminder_msg}For help unenrolling, Please see How do I unenroll from" +" a course? ({how_to_unenroll_link}) in our edX HelpCenter." msgstr "" -"{refund_reminder_msg} 払ã„戻ã—ã‚’å—ã‘å–ã‚‹ãŸã‚ã«ã¯ã€{billing_email} " -"ã«é€£çµ¡ã—ã¦ãã ã•ã„。メールã«ã¯æ³¨æ–‡ç•ªå·ã‚’記載ã—ã¦ãã ã•ã„。決ã—ã¦ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆã‚«ãƒ¼ãƒ‰æƒ…å ±ã¯è¨˜è¼‰ã—ãªã„よã†ã«ã—ã¦ãã ã•ã„。" #: lms/djangoapps/shoppingcart/models.py #, python-brace-format @@ -8179,6 +7990,15 @@ msgstr "ç·ä¾¡æ ¼" msgid "Currency" msgstr "通貨" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "説明" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "コメント" @@ -8322,14 +8142,6 @@ msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã‚’見る権é™ãŒã‚ã‚Šã¾ã›ã‚“。" msgid "View and regenerate certificates." msgstr "修了証を見ã¦å†ä½œæˆã™ã‚‹ã€‚" -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "手動返金" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "CyberSource社ã‹ã‚‰ç›´æŽ¥æ‰•ã„戻ã—ã‚’å—ã‘ãŸå±¥æ´ã‚’見る。" - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -8408,44 +8220,9 @@ msgstr "" msgid "User Disabled Successfully" msgstr "" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "メールアドレス" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "講座ID" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "ユーザーãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "講座{course_id}ã¯è¿”金ウィンドウをéŽãŽã¦ã„ã¾ã›ã‚“。" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "{course_id} 㧠{user} ã®ã‚ªãƒ¼ãƒ€ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "{course_id} ã‹ã‚‰ {user} ã‚’å—講解除ã—ã¾ã—ãŸ" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "オーダーID {order_id} ã®è¿”金 {cost}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -8493,13 +8270,17 @@ msgid "The supplied course_id {course_id} is not valid." msgstr "æä¾›ã•ã‚ŒãŸè¬›åº§ID {course_id} ãŒæœ‰åŠ¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。" #: lms/djangoapps/teams/views.py -msgid "You are already in a team in this course." -msgstr "ã‚ãªãŸã¯æ—¢ã«ã“ã®è¬›åº§ã®ãƒãƒ¼ãƒ ã«å‚åŠ ã—ã¦ã„ã¾ã™ã€‚" +msgid "topic_id is required" +msgstr "" #: lms/djangoapps/teams/views.py msgid "You can't create a team in an instructor managed topic." msgstr "" +#: lms/djangoapps/teams/views.py +msgid "You are already in a team in this teamset." +msgstr "" + #: lms/djangoapps/teams/views.py msgid "teamset_id and team_id are mutually exclusive options." msgstr "" @@ -9057,8 +8838,8 @@ msgid "Allow" msgstr "許å¯" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "エラー" @@ -9422,8 +9203,8 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "添付" @@ -9454,11 +9235,10 @@ msgid "" msgstr "ファイルã¯åˆ¥ã®è¨˜äº‹ã‹ã‚‰ã‚‚å†åˆ©ç”¨ã§ãã¾ã™ã€‚ã“れらã®ãƒ•ã‚¡ã‚¤ãƒ«ã¯ã€è‰¯ã—悪ã—ã«é–¢ã‚らãšã€ä»–ã®è¨˜äº‹å†…ã§æ›´æ–°ã•ã‚Œã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚" #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -9843,6 +9623,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -10222,6 +10006,10 @@ msgstr "" msgid "Schedule start < course start" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "講座ID" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "" @@ -10230,6 +10018,15 @@ msgstr "" msgid "Experience" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "講座ID" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -10433,6 +10230,7 @@ msgid "" msgstr "" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "" @@ -10662,7 +10460,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -10687,8 +10484,8 @@ msgstr "" msgid "Success" msgstr "æˆåŠŸ" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "アクション" @@ -10847,6 +10644,14 @@ msgstr "登録" msgid "There was an error receiving your login information. Please email us." msgstr "ãƒã‚°ã‚¤ãƒ³æƒ…å ±ã®å—信時ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚管ç†è€…ã¸ãƒ¡ãƒ¼ãƒ«ã‚’ãŠé€ã‚Šãã ã•ã„。" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -10860,6 +10665,15 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "何度もãƒã‚°ã‚¤ãƒ³è©¦è¡Œã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ã時間をãŠã„ã¦å†æ“作ã—ã¦ãã ã•ã„。" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -10867,15 +10681,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "username@domain.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -10891,6 +10696,12 @@ msgstr "{platform_name}ã§ç™»éŒ²ã«ä½¿ç”¨ã—ãŸãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹" msgid "Create Account" msgstr "アカウント作æˆ" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "username@domain.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -10903,6 +10714,11 @@ msgid "" "password." msgstr "ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒç™»éŒ²ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ã¯ã€ãƒ‘スワードã®å¤‰æ›´ãŒã§ãã¾ã›ã‚“。" +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "パスワードã®å¤‰æ›´ã«å¤±æ•—" @@ -10922,11 +10738,6 @@ msgid "" "created. {bold_start}{email}{bold_end} is now your primary login email." msgstr "" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "" @@ -11153,6 +10964,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "強制オン" @@ -11171,6 +10994,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "ã“ã®å€¤ã¯ç„¡åŠ¹ã§ã™ã€‚" @@ -11853,8 +11680,8 @@ msgstr "gitレãƒã‚¸ãƒˆãƒªã¸ã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãŒå®Œäº†ã—ãŸã‚³ãƒ¼ã‚¹" msgid "Vertical" msgstr "縦" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "セクション" @@ -12125,6 +11952,18 @@ msgstr "" msgid "Transcript Ready" msgstr "" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "ç”»åƒãƒ•ã‚¡ã‚¤ãƒ«ã¯å¿…é ˆã§ã™ã€‚" @@ -12316,14 +12155,14 @@ msgstr "講座番å·: " msgid "Course Run:" msgstr "" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "講座" @@ -12347,8 +12186,9 @@ msgstr "講師" msgid "Requirements" msgstr "å¿…é ˆäº‹é …" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "詳細" @@ -12400,15 +12240,15 @@ msgstr "" msgid "Choose Language" msgstr "言語をé¸æŠž" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "アカウント" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -12480,8 +12320,8 @@ msgstr "ユーザーメニュー" msgid "Usermenu dropdown" msgstr "ドãƒãƒƒãƒ—ダウンã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ¡ãƒ‹ãƒ¥ãƒ¼" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "サインアウト" @@ -12641,8 +12481,8 @@ msgstr "開始: {date}" msgid "View all Courses" msgstr "ã™ã¹ã¦ã®è¬›åº§ã‚’見る" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "ダッシュボード" @@ -12661,8 +12501,8 @@ msgstr "ã¾ã ã©ã®è¬›åº§ã«ã‚‚å—講登録ã—ã¦ã„ã¾ã›ã‚“。" #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "講座を探ã™" @@ -12680,7 +12520,7 @@ msgstr "講座èªè¾¼ã‚¨ãƒ©ãƒ¼" msgid "Search Your Courses" msgstr "講座を検索" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "検索をクリア" @@ -12705,7 +12545,7 @@ msgstr "講座ã‹ã‚‰ã®ãƒ¡ãƒ¼ãƒ«ã‚’å—ã‘å–ã‚‹" msgid "Save Settings" msgstr "è¨å®šã‚’ä¿å˜" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -12715,9 +12555,87 @@ msgstr "è¨å®šã‚’ä¿å˜" msgid "Unenroll" msgstr "å—講登録å–消" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "Studioã§ãƒ¦ãƒ‹ãƒƒãƒˆã‚’見る" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -12749,7 +12667,7 @@ msgstr "æ–°ã—ã„メールアドレスを使ã£ãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒæ—¢ã«å˜åœ¨ msgid "You should Register before trying to access the Unit" msgstr "ユニットã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ã¾ãšç™»éŒ²ã—ã¦ãã ã•ã„" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "" @@ -12852,7 +12770,7 @@ msgid "" msgstr "" "ç· åˆ‡ãŒéŽãŽã¦ã„ã¾ã™ã®ã§ã€ã“ã®èª²é¡Œã¯ã‚‚ã†æœ‰åŠ¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。{line_break}ã™ã§ã«ã“ã®èª²é¡Œã‚’完了ã—ã¦ã„ã‚‹å ´åˆã€æˆç¸¾ã¯{link_start}進æ—ページ{link_end}ã§ã”覧ã„ãŸã ã‘ã¾ã™ã€‚" -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "講座を探ã™" @@ -12988,20 +12906,16 @@ msgstr "(ç”»é¢ã‚’å†èªè¾¼ã—ã¦ãã ã•ã„)" msgid "working" msgstr "作æ¥ä¸" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "{platform_name}サーãƒãƒ¼ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html -#: lms/templates/courseware/error-message.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"申ã—訳ã‚ã‚Šã¾ã›ã‚“。ã“ã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã¯ä¸€æ™‚çš„ã«åˆ©ç”¨ã§ãã¾ã›ã‚“。ã§ãã‚‹ã ã‘æ—©ã復旧ã§ãるよã†ä½œæ¥ä¸ã§ã™ã€‚å•é¡Œã‚„ä¸æ–時間ã®å ±å‘Šã¯{tech_support_email}ã¸ãƒ¡ãƒ¼ãƒ«ã—ã¦ãã ã•ã„。" #: lms/templates/module-error.html msgid "Raw data:" @@ -13040,7 +12954,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr " {i_start}{user_name}{i_end}ã¨ã—ã¦ã“ã®è¬›åº§ã‚’閲覧ã—ã¦ã„ã¾ã™ã€‚" #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -13103,16 +13025,6 @@ msgstr "メール" msgid "Return To %s" msgstr "%s ã«æˆ»ã‚‹" -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "å†ç”³è¾¼å®Œäº†ï¼" @@ -13163,7 +13075,7 @@ msgstr "" msgid "Sequence" msgstr "é †ç•ª" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -13292,18 +13204,18 @@ msgstr "点数 (上書ã用)" msgid "Reset Learner's Attempts to Zero" msgstr "å—講者ã®æ出数をゼãƒã«ãƒªã‚»ãƒƒãƒˆ" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "å—講者ã®çŠ¶æ…‹ã‚’削除" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "å—講者ã®è§£ç”ã‚’å†æŽ¡ç‚¹" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "点数ãŒè‰¯ããªã‚‹å ´åˆã®ã¿å†æŽ¡ç‚¹" @@ -13341,7 +13253,7 @@ msgstr "{course_number}ã®æ•™ç§‘書" msgid "Textbook Navigation" msgstr "教科書案内" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "ç”»é¢" @@ -13452,9 +13364,9 @@ msgstr "{total_pages}ページä¸{current_page}ページ目" msgid "Recent git load activity for {course_id}" msgstr "{course_id}ã®æœ€æ–°ã®gitå±¥æ´" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Date" msgstr "日付" @@ -13510,7 +13422,7 @@ msgstr "" "今後 {platform_name} ã‹ã‚‰ã®ãƒ•ã‚©ãƒ¼ãƒ©ãƒ 通知メールをå—ã‘å–らãªããªã‚Šã¾ã™ã€‚ダッシュボードã¸ã¯ " "{dashboard_link_start}ã“ã¡ã‚‰ã‹ã‚‰{link_end}戻るã“ã¨ãŒã§ãã¾ã™ã€‚登録ã—ãŸã„å ´åˆã¯ã€{undo_link_start}ã“ã¡ã‚‰ã‹ã‚‰{link_end}å†ç™»éŒ²ã§ãã¾ã™ã€‚" -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "ダッシュボード: " @@ -13518,8 +13430,8 @@ msgstr "ダッシュボード: " msgid "More options" msgstr "ãã®ä»–ã®ã‚ªãƒ—ション" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "" @@ -14718,35 +14630,6 @@ msgstr "è¨å®šã—ã¦ã„ã‚‹æƒ…å ±ã«é–“é•ã„ãŒãªã„ã¨æ€ã‚ã‚Œã‚‹å ´åˆã«ã¯ msgid "About edX Certificates" msgstr "" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "支払å–消" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "å–り扱ã„ãŒã‚ャンセルã•ã‚Œã¾ã—ãŸã€‚何ã‹å•é¡ŒãŒèµ·ããŸã¨æ€ã‚ã‚Œã‚‹å ´åˆã«ã¯ {email} ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。" - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "支払エラー" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "注文データをèªè¾¼ä¸..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "æ³¨æ–‡è©³ç´°æƒ…å ±ã‚’å¾©å…ƒã—ã¦ãŠã‚Šã¾ã™ã®ã§ã€ãŠå¾…ã¡ãã ã•ã„。" - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -14947,28 +14830,25 @@ msgstr "{section_format} ç· åˆ‡ {{date}}" msgid "This content is graded" msgstr "ã“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¯æŽ¡ç‚¹å¯¾è±¡ã§ã™" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚後ã»ã©å†è©¦è¡Œã—ã¦ãã ã•ã„。" - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚後ã»ã©å†è©¦è¡Œã—ã¦ãã ã•ã„。" + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "ã“ã®è¬›åº§ã«ç™»éŒ²ã•ã‚Œã¦ã„ã¾ã™" #: lms/templates/courseware/course_about.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: lms/templates/shoppingcart/registration_code_receipt.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "View Course" msgstr "講座画é¢ã¸" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "講座ã¯æº€å“¡ã§ã™" @@ -14981,10 +14861,6 @@ msgstr "ã“ã®è¬›åº§ã®å—講登録ã¯æ‹›å¾…制ã§ã™" msgid "Enrollment is Closed" msgstr "å—講登録ã¯çµ‚了ã—ã¾ã—ãŸ" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "" @@ -15106,6 +14982,13 @@ msgstr "コースユーティリティー" msgid "Courseware" msgstr "コースウェア" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "講座検索" @@ -15135,7 +15018,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -15143,8 +15026,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" +msgstr "" + +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -15197,8 +15083,9 @@ msgid "Welcome to {course_title}!" msgstr "" #: lms/templates/courseware/info.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "Resume Course" msgstr "講座å†é–‹" @@ -15786,8 +15673,8 @@ msgstr "èªè¨¼æƒ…å ±ã‚’æ出済ã§ã™ã€‚" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." -msgstr "èªè¨¼æ‰‹ç¶šãŒå®Œäº†ã—ã¾ã—ãŸã‚‰ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒè¡¨ç¤ºã•ã‚Œã¾ã™(通常1-2日以内)。" +"complete (usually within 5-7 days)." +msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -15797,8 +15684,8 @@ msgstr "ç¾åœ¨ã®èªè¨¼ã¯ã¾ã‚‚ãªã期é™åˆ‡ã‚Œã§ã™ï¼" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." -msgstr "å†èªè¨¼æƒ…å ±ãŒæ出ã•ã‚Œã¾ã—ãŸã€‚èªè¨¼æ‰‹ç¶šãŒå®Œäº†ã—ã¾ã—ãŸã‚‰ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒè¡¨ç¤ºã•ã‚Œã¾ã™(通常1-2日以内)。" +"5-7 days)." +msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -16478,139 +16365,6 @@ msgid "" "verification process on your dashboard." msgstr "" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "{course_name}ã®å—講登録料をãŠæ”¯æ‰•ã„ã„ãŸã ãã€ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"{currency_symbol}{total_price}ã®è«‹æ±‚書ãŒæ·»ä»˜ã•ã‚Œã¦ã„ã¾ã™ã€‚å—ã‘å–り次第ãŠæ”¯æ‰•ã„ãã ã•ã„。ãŠæ”¯æ‰•ã„方法ã«ã¤ã„ã¦ã¯è«‹æ±‚書ã«è¨˜è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -"å—講登録コードを記載ã—ãŸCSVファイルãŒæ·»ä»˜ã•ã‚Œã¦ã„ã¾ã™ã€‚å—講生ã«å—講登録コードを通知ã™ã‚‹ã«ã¯ä»¥ä¸‹ã®ãƒ¡ãƒ¼ãƒ«ãƒ†ãƒ³ãƒ—レートをãŠä½¿ã„ã„ãŸã ã‘ã¾ã™ã€‚å„å—講生ã¯ãã‚Œãžã‚Œåˆ¥ã®å—講登録コードを使用ã—ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã‚“。" - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚\n" -"{platform_name}é‹å–¶ãƒãƒ¼ãƒ より" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr " [[Name]] 様: " - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "{course_name}ã§ã‚ãªãŸã®å—講登録コードを発行ã—ã¾ã—ãŸã€‚å—講ã™ã‚‹ãŸã‚ã«ã¯æ¬¡ã®ãƒªãƒ³ã‚¯ã‚’クリックã—ã¦ãã ã•ã„: " - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "添付ã•ã‚ŒãŸCSVファイルã‹ã‚‰ã®HTMLリンク" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "å—講登録ã™ã‚‹ã¨ã€å—講生用ダッシュボードã«ãã®è¬›åº§ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚æ•™æã¯è¬›åº§é–‹å§‹æ—¥ä»¥é™è¦‹ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"敬æ„ã‚’è¾¼ã‚ã¦\n" -"[[ã”ç½²å]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "請求書" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "日付: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "請求書番å·: {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "期é™: å—å–次第" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "ç· åˆ‡: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "請求先: " - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "ãŠå®¢æ§˜å‚照番å·: {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "ä¸è¶³é¡: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "講座: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"ä¾¡æ ¼: {currency_symbol}{course_price} æ•°é‡: {quantity} å°è¨ˆ: " -"{currency_symbol}{sub_total} 値引: {currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "åˆè¨ˆ: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "支払ã„ã«ã¤ã„ã¦ã®ã”案内" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"ãŠæ”¯æ‰•ã„ã„ãŸã ã‘ãªã„å ´åˆã¯ã€ã“ã®ã‚³ãƒ¼ãƒ‰ã®å—講登録ã¯ã‚ャンセルã•ã‚Œã€æ•™æã«ã‚¢ã‚¯ã‚»ã‚¹ã§ããªããªã‚Šã¾ã™ã€‚ã„ã£ãŸã‚“購入手続をã™ã‚‹ã¨è¿”å“ã¯ã§ãã¾ã›ã‚“。詳ã—ã知りãŸã„æ–¹ã¯" -" {site_name} ã‚ャンセルãƒãƒªã‚·ãƒ¼ã‚’ã”覧ãã ã•ã„。" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "支払ã«ã¤ã„ã¦ã®ã”質å•ã¯ {contact_email} ã¸ãŠå•ã„åˆã‚ã›ãã ã•ã„" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -16785,8 +16539,8 @@ msgstr "経済支æ´ã«ç”³ã—込む" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} ホームページ" @@ -16809,19 +16563,11 @@ msgstr "" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "システム管ç†è€…" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "ショッピングカート" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "" @@ -16858,6 +16604,12 @@ msgstr "クーãƒãƒ³ã‚³ãƒ¼ãƒ‰è¿½åŠ " msgid "Enter information about the coupon code below." msgstr "クーãƒãƒ³ã‚³ãƒ¼ãƒ‰æƒ…å ±ã‚’ä»¥ä¸‹ã«å…¥åŠ›ã—ã¦ãã ã•ã„。" +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "クーãƒãƒ³ã‚³ãƒ¼ãƒ‰" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "割引率" @@ -17409,6 +17161,11 @@ msgstr "クーãƒãƒ³ã‚³ãƒ¼ãƒ‰ã‚’ダウンãƒãƒ¼ãƒ‰" msgid "Coupon Codes" msgstr "クーãƒãƒ³ã‚³ãƒ¼ãƒ‰" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "有効期é™" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "クーãƒãƒ³ (%)" @@ -18688,6 +18445,10 @@ msgstr "購入組織" msgid "Purchase order number (if any)" msgstr "注文番å·(ã‚ã‚Œã°)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "メールアドレス" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "email@example.com" @@ -18979,6 +18740,10 @@ msgid_plural "" "{course_names} have been removed because the enrollment period has closed." msgstr[0] "{course_names}ã¯å—講登録期間ãŒçµ‚了ã—ã¦ã„ã‚‹ã®ã§å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚" +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "ショッピングカート" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "ã‚«ãƒãƒ¼ç”»åƒ" @@ -19063,11 +18828,8 @@ msgstr "確èª" #: lms/templates/static_templates/404.html msgid "" "The page that you were looking for was not found. Go back to the " -"{link_start}homepage{link_end} or let us know about any pages that may have " -"been moved at {email}." +"{link_start}homepage{link_end} ." msgstr "" -"ãŠæŽ¢ã—ã®ãƒšãƒ¼ã‚¸ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 " -"{link_start}ホームページ{link_end}ã«æˆ»ã‚‹ã‹ã€ã©ã®ãƒšãƒ¼ã‚¸ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ããªã„ã‹{email}ã§ãŠçŸ¥ã‚‰ã›ãã ã•ã„。" #: lms/templates/static_templates/about.html #: lms/templates/static_templates/blog.html @@ -19119,18 +18881,15 @@ msgstr "ç¾åœ¨{platform_name}ã®ã‚µãƒ¼ãƒãƒ¼ã¯ãƒ€ã‚¦ãƒ³ã—ã¦ã„ã¾ã™" #: lms/templates/static_templates/server-overloaded.html msgid "" "Our staff is currently working to get the site back up as soon as possible. " -"Please email us at {tech_support_email} to report any problems or downtime." -msgstr "ã§ãã‚‹ã ã‘æ—©ã復旧ã™ã‚‹ã‚ˆã†ä½œæ¥ä¸ã§ã™ã€‚å•é¡Œã‚„ダウンタイムã«é–¢ã™ã‚‹å ±å‘Šã¯{tech_support_email}ã¸ãƒ¡ãƒ¼ãƒ«ã§ãŠé€ã‚Šãã ã•ã„。" +msgstr "" #: lms/templates/static_templates/server-error.html msgid "There has been a 500 error on the {platform_name} servers" msgstr "{platform_name}ã®ã‚µãƒ¼ãƒãƒ¼ã«500エラーãŒç™ºç”Ÿã—ã¾ã—ãŸ" #: lms/templates/static_templates/server-error.html -msgid "" -"Please wait a few seconds and then reload the page. If the problem persists," -" please email us at {email}." -msgstr "数秒ãŠå¾…ã¡ã„ãŸã ã„ã¦ã€ç”»é¢ã‚’å†èªè¾¼ã—ã¦ãã ã•ã„。å•é¡ŒãŒè§£æ¶ˆã—ãªã„å ´åˆã¯{email}ã¸ã”連絡ãã ã•ã„。" +msgid "Please wait a few seconds and then reload the page." +msgstr "" #: lms/templates/static_templates/server-overloaded.html msgid "Currently the {platform_name} servers are overloaded" @@ -19198,46 +18957,6 @@ msgstr "" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "返金ã—よã†ã¨ã—ã¦ã„ã¾ã™: " - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "オーダーID: " - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "å—講登録: " - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "å—講登録済" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "å—講登録解除" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "費用: " - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "CertificateItem ステータス: " - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "注文ステータス: " - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "é”æˆæ™‚é–“: " - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "返金請求時間: " - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "ユーザーアンケート" @@ -19377,8 +19096,8 @@ msgstr "本人èªè¨¼" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." -msgstr "èªè¨¼æƒ…å ±ãŒæ出ã•ã‚Œã¾ã—ãŸã€‚èªè¨¼æ‰‹ç¶šãŒå®Œäº†ã—ã¾ã—ãŸã‚‰ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒè¡¨ç¤ºã•ã‚Œã¾ã™(通常1~2日以内)。" +" within 5-7 days)." +msgstr "" #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -19593,6 +19312,10 @@ msgstr "最新更新" msgid "Get started on what's next: " msgstr "" +#: openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html +msgid "Show More" +msgstr "" + #: openedx/features/course_search/templates/course_search/course-search-fragment.html msgid "Search Results" msgstr "検索çµæžœ" @@ -20044,10 +19767,8 @@ msgid "The page that you were looking for was not found." msgstr "ãŠæŽ¢ã—ã®ãƒšãƒ¼ã‚¸ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚" #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." -msgstr "{homepage}ã¸æˆ»ã‚‹ã‹ã€ç§»å‹•ã—ãŸå¯èƒ½æ€§ã®ã‚るページã«ã¤ã„ã¦{email}ã«ãŠçŸ¥ã‚‰ã›ãã ã•ã„。" +msgid "Go back to the {homepage}." +msgstr "" #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -20069,10 +19790,6 @@ msgid "" "error as soon as possible." msgstr "我々スタッフã¯ã‚¨ãƒ©ãƒ¼ã‚’記録ã—ã€ã§ãã‚‹ã ã‘æ—©ã解決ã§ãるよã†å–り組んã§ã„ã¾ã™ã€‚" -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "ã‚‚ã—ä¸å…·åˆãŒè§£æ¶ˆã•ã‚Œãªã„å ´åˆã¯ã€{email_link}ã¸ãƒ¡ãƒ¼ãƒ«ã§ã”連絡ãã ã•ã„。" - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "" @@ -20704,12 +20421,8 @@ msgstr "リクエストã•ã‚ŒãŸãƒšãƒ¼ã‚¸ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" -"申ã—訳ã”ã–ã„ã¾ã›ã‚“。ãŠæŽ¢ã—ã®{studio_name}ã®ãƒšãƒ¼ã‚¸ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚{studio_name}ã®ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã«æˆ»ã£ã¦å†è©¦è¡Œã—ã¦ãã ã•ã„。アクセスã®å•é¡ŒãŒè§£æ±ºã—ãªã„å ´åˆã¯ã€ãŠæ°—軽ã«{link_start}{studio_name}サãƒãƒ¼ãƒˆ{link_end}" -" ã¸ã”連絡ãã ã•ã„。" #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -20719,12 +20432,8 @@ msgstr "サーãƒãƒ¼ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" -"申ã—訳ã”ã–ã„ã¾ã›ã‚“。リクエスト処ç†ä¸ã«ã‚µãƒ¼ãƒãƒ¼ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚{studio_name}ã®ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã«æˆ»ã‚Šã€å†å®Ÿè¡Œã—ã¦ãã ã•ã„。アクセスã®å•é¡ŒãŒè§£æ±ºã—ãªã„å ´åˆã¯ã€ãŠæ°—軽ã«{link_start}{studio_name}サãƒãƒ¼ãƒˆ{link_end}" -" ã¸ã”連絡ãã ã•ã„。" #: cms/templates/error.html msgid "Back to dashboard" @@ -23785,8 +23494,8 @@ msgstr "%(file)s ã¯ãƒªãƒ“ジョン #%(revision)d ã«å¤‰æ›´ã•ã‚Œã¾ã—ãŸ" msgid "%(file)s has been saved." msgstr "%(file)s ã¯ä¿å˜ã•ã‚Œã¾ã—ãŸã€‚" -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "ç”»åƒ" @@ -23978,8 +23687,8 @@ msgstr "" msgid "Search..." msgstr "" -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "" diff --git a/conf/locale/ja_JP/LC_MESSAGES/djangojs.mo b/conf/locale/ja_JP/LC_MESSAGES/djangojs.mo index bec85db9271924e48393cc6eb3a3da1802d1f8d6..0284dd2055960c972bbe3e4bb4282bf197b56255 100644 Binary files a/conf/locale/ja_JP/LC_MESSAGES/djangojs.mo and b/conf/locale/ja_JP/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/ja_JP/LC_MESSAGES/djangojs.po b/conf/locale/ja_JP/LC_MESSAGES/djangojs.po index d06ec2c4e1eb0cd056709c9e77aea9fea8fbcc3d..3b05bc914763205d1418d4206cf99500bf48ba89 100644 --- a/conf/locale/ja_JP/LC_MESSAGES/djangojs.po +++ b/conf/locale/ja_JP/LC_MESSAGES/djangojs.po @@ -77,8 +77,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Japanese (Japan) (http://www.transifex.com/open-edx/edx-platform/language/ja_JP/)\n" "Language: ja_JP\n" @@ -86,7 +86,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -135,6 +135,7 @@ msgstr "削除" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -157,6 +158,7 @@ msgstr "アップãƒãƒ¼ãƒ‰ä¸" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -181,6 +183,7 @@ msgstr "ファイルをé¸æŠž" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "OK" @@ -736,7 +739,6 @@ msgstr "" #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "説明" @@ -783,6 +785,7 @@ msgstr "" #: cms/templates/js/show-textbook.underscore #: cms/templates/js/signatory-details.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Edit" msgstr "" @@ -1177,6 +1180,7 @@ msgstr "" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "次ã¸" @@ -1510,6 +1514,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/course-instructor-details.underscore #: cms/templates/js/signatory-details.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Title" msgstr "" @@ -2379,7 +2384,15 @@ msgid "Other" msgstr "ãã®ä»–" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx @@ -2387,20 +2400,23 @@ msgid "Details" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "æ出" +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2417,6 +2433,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2440,7 +2468,8 @@ msgstr "" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2620,6 +2649,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†è©¦è¡Œã—ã¦ãã ã•ã„。" +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "ã“ã®ãƒãƒ¼ãƒ を辞ã‚ã¾ã™ã‹ï¼Ÿ" @@ -3109,6 +3142,7 @@ msgid "There has been an error processing your survey." msgstr "アンケート調査処ç†ä¸ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚" #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -3125,6 +3159,7 @@ msgid "HTML preview of post" msgstr "" #: lms/static/js/customwmd.js +#: common/static/common/templates/discussion/templates.underscore msgid "Your question or idea (required)" msgstr "" @@ -5012,6 +5047,16 @@ msgstr "ã™ã¹ã¦ã‚’表示" msgid "Collapse All" msgstr "ã™ã¹ã¦ã‚’é–‰ã˜ã‚‹" +#: openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show More" +msgstr "" + +#: openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show Less" +msgstr "" + #: openedx/features/course_search/static/course_search/js/views/search_results_view.js msgid "{total_results} result" msgid_plural "{total_results} results" @@ -5154,6 +5199,10 @@ msgstr "ã¯ã„ã€ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªä¿®äº†è¨¼ã‚’編集ã—ã¾ã™" msgid "certificate" msgstr "修了証" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "修了証をè¨å®šã—ã¦ãã ã•ã„" @@ -5165,8 +5214,8 @@ msgid "You have not created any certificates yet." msgstr "ã¾ã 修了証を作æˆã—ã¦ã„ã¾ã›ã‚“。" #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "ç½²å一覧ã‹ã‚‰ \"<%= signatoryName %>\" を削除ã—ã¾ã™ã‹ï¼Ÿ" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5466,8 +5515,8 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -5645,7 +5694,7 @@ msgid "{selectedProvider} credentials saved" msgstr "" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" msgstr "" #: cms/static/js/views/edit_chapter.js @@ -6198,14 +6247,14 @@ msgstr "" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." -msgstr "組織åã€è¬›åº§ç•ªå·ã€course run欄ã®åˆè¨ˆæ–‡å—æ•°ã¯<%=limit%>æ–‡å—ã¾ã§ã§ã™ã€‚" +"fields cannot be more than <%- limit %> characters." +msgstr "" #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." -msgstr "組織åã€ãƒ©ã‚¤ãƒ–ラリコード欄ã®åˆè¨ˆæ–‡å—æ•°ã¯<%=limit%>æ–‡å—ã¾ã§ã§ã™ã€‚" +"more than <%- limit %> characters." +msgstr "" #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -6546,13 +6595,13 @@ msgid "Unscheduled" msgstr "未定" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "日付" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "å‰ã¸" @@ -6600,6 +6649,309 @@ msgstr "検索クリア" msgid "Search" msgstr "検索" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "æ出" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "å…¨ã¦ã®æŠ•ç¨¿" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "ディスカッション・ホーム" @@ -6656,10 +7008,6 @@ msgid "" "new, unread activity from posts you are following." msgstr "ã“ã®ãƒœãƒƒã‚¯ã‚¹ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹ã¨æ¯Žæ—¥ãƒ€ã‚¤ã‚¸ã‚§ã‚¹ãƒˆãƒ¡ãƒ¼ãƒ«ãŒå±Šãã¾ã™ã€‚ã‚ãªãŸãŒãƒ•ã‚©ãƒãƒ¼ã—ã¦ã„る投稿ã®æ–°ç€æƒ…å ±ã‚„æœªèªã®å‹•ãを知るã“ã¨ãŒã§ãã¾ã™ã€‚" -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "å…¨ã¦ã®æŠ•ç¨¿" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "ユーザーåã¾ãŸã¯ãƒ¡ãƒ¼ãƒ«" @@ -6894,6 +7242,10 @@ msgstr "å‚åŠ ã™ã‚‹ãƒãƒ¼ãƒ を探ã™ã®ã«ãŠå›°ã‚Šã§ã™ã‹ï¼Ÿ" msgid "Join Team" msgstr "ãƒãƒ¼ãƒ ã«å‚åŠ " +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "ãƒãƒ¼ãƒ 詳細" @@ -6978,96 +7330,6 @@ msgstr "サブセクション%(subsectionDisplayName)sを削除" msgid "Remove unit %(unitName)s" msgstr "ユニット%(unitName)sを削除" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "å˜ä½èªå®šå‡¦ç†ã‚’完了ã™ã‚‹ã«ã¯å¼•ã続ã%(display_name)sを見ã¦ãã ã•ã„。" - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"å˜ä½èªå®šã®æœ€çµ‚処ç†ã‚’ã™ã‚‹ãŸã‚ã«ã€%(display_name)sã§ã¯%(platform_name)så—講者ã«å˜ä½èªå®šç”³è«‹ã‚’æ出ã™ã‚‹ã‚ˆã†æ±‚ã‚ã¦ã„ã¾ã™ã€‚" - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "å˜ä½ã‚’ç²å¾—ã™ã‚‹" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "%(full_name)s様ã€ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ï¼%(course_name)sã«é–¢ã™ã‚‹ãŠæ”¯æ‰•ã„ã‚’å—ç†ã—ã¾ã—ãŸã€‚" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "ã“ã®ç”»é¢ã‚’記録用ã«å°åˆ·ã—ã¦ãã ã•ã„。ã“ã‚Œã¯é ˜åŽæ›¸ã«ãªã‚Šã¾ã™ã€‚åŒæ§˜ã®æƒ…å ±ã‚’ãƒ¡ãƒ¼ãƒ«ã§ã‚‚ãŠé€ã‚Šã—ã¦ã„ã¾ã™ã€‚" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "申込番å·" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "æ•°é‡" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "åˆè¨ˆ" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "注æ„ã—ã¦ãã ã•ã„" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "ç·šãŒå¼•ã„ã¦ã‚るアイテムã¯è¿”金ã•ã‚Œã¾ã—ãŸã€‚" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "請求先" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "é ˜åŽè¨¼ãªã—" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "ダッシュボードã¸ç§»å‹•" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" -"ã™ãã«æœ¬äººèªè¨¼ã‚’è¡Œã‚ãªã„å ´åˆã§ã‚‚ã€ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã§è¬›åº§ã‚’探ã™ã“ã¨ãŒã§ãã¾ã™ã€‚定期的ã«{platformName}ã‹ã‚‰æœ¬äººèªè¨¼ã‚’è¡Œã†ã‚ˆã†é€šçŸ¥ãŒã‚ã‚Šã¾ã™ã€‚" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "後ã§æœ¬äººèªè¨¼ã‚’è¡Œã„ã¾ã™ã‹ï¼Ÿ" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "ã„ã¾ã™ãèªè¨¼ã—よã†" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "'試験終了'ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹" @@ -7090,14 +7352,6 @@ msgid "" "before you select \"End My Exam\"." msgstr "å˜ä½ã‚’ç²å¾—ã™ã‚‹ã«ã¯ã€\"試験を終了ã™ã‚‹\"ã‚’é¸æŠžã™ã‚‹å‰ã«å„å•é¡Œã§\"æ出\"ã‚’é¸æŠžã—ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã‚“。" -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show More" -msgstr "" - -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show Less" -msgstr "" - #: lms/templates/courseware/proctored-exam-status.underscore msgid "Exam timer and end exam button" msgstr "" @@ -7204,8 +7458,8 @@ msgstr "ã‚ãªãŸã«ã¤ã„ã¦" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." -msgstr "以下ã®æƒ…å ±ã¯ã™ã§ã«ã‚ãªãŸã®{platform}ã®ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«ã«å…¥ã£ã¦ã„ã¾ã™ã€‚申込書ã«ä»¥ä¸‹ã®æƒ…å ±ã‚’å…¥ã‚Œã¾ã—ãŸã€‚" +"We've included it here for your application." +msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7233,6 +7487,10 @@ msgid "" "{course_name}! You can expect a response in 2-4 business days." msgstr "{course_name}ã®çµŒæ¸ˆæ´åŠ©ç”³è¾¼æ›¸ã‚’ã”æ出ã„ãŸã ãã€ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ï¼2-4å–¶æ¥æ—¥ä»¥å†…ã«è¿”ä¿¡ãŒå±Šãã¾ã™ã€‚" +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "ダッシュボードã¸ç§»å‹•" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "大é‡ã®ä¾‹å¤–" @@ -7573,14 +7831,6 @@ msgstr "" msgid "You can change sessions until {expiration_date}." msgstr "" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "アーカイブ済講座を見る" @@ -7795,7 +8045,27 @@ msgid "An error occurred. Please reload the page." msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã“ã®ç”»é¢ã‚’å†èªè¾¼ã—ã¦ãã ã•ã„。" #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -7994,17 +8264,13 @@ msgid "What You Need for Verification" msgstr "èªè¨¼ã«å¿…è¦ãªã‚‚ã®" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "ウェブカメラ" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8012,10 +8278,8 @@ msgid "Photo Identification" msgstr "写真ã«ã‚ˆã‚‹æœ¬äººç¢ºèª" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." -msgstr "åå‰ã¨å†™çœŸãŒè¨˜è¼‰ã•ã‚Œã¦ã„ã‚‹å…許証ã€ãƒ‘スãƒãƒ¼ãƒˆã¾ãŸã¯æ”¿åºœç™ºè¡Œã®èº«åˆ†è¨¼æ˜Žæ›¸ãŒå¿…è¦ã§ã™ã€‚" +msgid "You need a valid ID that contains your full name and photo." +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8040,14 +8304,10 @@ msgstr "é¡”ãŒå分ã«æ˜Žã‚‹ã„。" msgid "Your entire face fits inside the frame." msgstr "顔全体ãŒãƒ•ãƒ¬ãƒ¼ãƒ ã®ä¸ã«ç´ã¾ã£ã¦ã„る。" -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "顔写真ã¨IDã®å†™çœŸãŒä¸€è‡´ã—ã¦ã„る。" - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8064,14 +8324,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "%(platformName)s ã§ãªãœå†™çœŸãŒå¿…è¦ãªã®ã§ã—ょã†ã‹ï¼Ÿ" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"èªè¨¼æ‰‹ç¶šã®1ã¤ã¨ã—ã¦ã€é¡”写真ã¨æ”¿åºœç™ºè¡Œã®å†™çœŸä»˜ã身分証明書を撮影ã—ã¦ãã ã•ã„。我々ã®èªè¨¼ã‚µãƒ¼ãƒ“スãŒãれらを比較ã—ã¦ã€ã‚ãªãŸã®æœ¬äººç¢ºèªã‚’ã—ã¾ã™ã€‚" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8082,15 +8338,12 @@ msgstr "ã“ã®å†™çœŸã¯%(platformName)s ã§ã©ã®ã‚ˆã†ã«ä½¿ã‚れるã®ã§ã— #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"最高レベルã®ã‚»ã‚ュリティã§å†™çœŸã‚’æš—å·åŒ–ã—ã€èªè¨¼ã‚µãƒ¼ãƒ“スã¸é€ã‚Šã¾ã™ã€‚èªè¨¼æ‰‹ç¶šãŒå®Œäº†ã—ãŸå¾Œã¯ã€å†™çœŸã‚„æƒ…å ±ã‚’%(platformName)sã§ä¿å˜ã—ãŸã‚Šé–²è¦§ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8149,16 +8402,14 @@ msgid "Take a Photo of Your ID" msgstr "ã‚ãªãŸã®IDã®å†™çœŸã‚’撮影ã™ã‚‹" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." -msgstr "ウェブカメラを使ã£ã¦ã€ã‚ãªãŸã®IDã®å†™çœŸã‚’撮影ã—ã¦ãã ã•ã„。ãã®å†™çœŸã‚’ã‚ãªãŸã®é¡”写真ãŠã‚ˆã³ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«è¨å®šã•ã‚ŒãŸåå‰ã¨ç…§åˆã—ã¾ã™ã€‚" +msgid "Use your webcam to take a photo of your ID." +msgstr "" #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." -msgstr "æ°åã¨å†™çœŸä»˜ãã®IDãŒå¿…è¦ã§ã™ã€‚é‹è»¢å…許証ã€ãƒ‘スãƒãƒ¼ãƒˆã¾ãŸã¯æ”¿åºœç™ºè¡Œã®èº«åˆ†è¨¼æ˜Žæ›¸ãŒæœ‰åŠ¹ã§ã™ã€‚" +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." +msgstr "" #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8182,6 +8433,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8228,6 +8486,24 @@ msgstr "" msgid "Can we match the photo you took with the one on your ID?" msgstr "今回撮影ã—ãŸå†™çœŸã¨IDã®å†™çœŸã‚’ç…§åˆã—ã¦ã‚‚よã„ã§ã—ょã†ã‹ï¼Ÿ" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"èªè¨¼æ‰‹ç¶šã®1ã¤ã¨ã—ã¦ã€é¡”写真ã¨æ”¿åºœç™ºè¡Œã®å†™çœŸä»˜ã身分証明書を撮影ã—ã¦ãã ã•ã„。我々ã®èªè¨¼ã‚µãƒ¼ãƒ“スãŒãれらを比較ã—ã¦ã€ã‚ãªãŸã®æœ¬äººç¢ºèªã‚’ã—ã¾ã™ã€‚" + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"最高レベルã®ã‚»ã‚ュリティã§å†™çœŸã‚’æš—å·åŒ–ã—ã€èªè¨¼ã‚µãƒ¼ãƒ“スã¸é€ã‚Šã¾ã™ã€‚èªè¨¼æ‰‹ç¶šãŒå®Œäº†ã—ãŸå¾Œã¯ã€å†™çœŸã‚„æƒ…å ±ã‚’%(platformName)sã§ä¿å˜ã—ãŸã‚Šé–²è¦§ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。" + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "本講座ã®IDèªè¨¼ã«ãŠè¶Šã—ã„ãŸã ãã€ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™: {courseName}" @@ -8257,6 +8533,13 @@ msgid "" "and photo" msgstr "é‹è»¢å…許証ã€ãƒ‘スãƒãƒ¼ãƒˆã¾ãŸã¯æ”¿åºœç™ºè¡Œã®æ°åã¨å†™çœŸä»˜ã身分証明書" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "ウェブカメラ" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8344,6 +8627,11 @@ msgstr "修了証をアップグレードã™ã‚‹å‰ã«ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’有効 msgid "Check your email for an activation message." msgstr "有効化ã«é–¢ã™ã‚‹ãƒ¡ãƒ¼ãƒ«ã‚’確èªã—ã¦ãã ã•ã„。" +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "åˆè¨ˆ" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "{courseName}講座ã®Professional Certificate" @@ -8381,6 +8669,36 @@ msgstr "顔写真ãŠã‚ˆã³æ”¿åºœç™ºè¡Œã®å†™çœŸä»˜ãIDã®å†™çœŸã‚’撮るãŸã‚ msgid "Thank you! We have received your payment for {courseName}." msgstr "ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã—ãŸï¼ {courseName}講座ã®æ”¯æ‰•ã‚’å—é ˜ã—ã¾ã—ãŸã€‚" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "ã“ã®ç”»é¢ã‚’記録用ã«å°åˆ·ã—ã¦ãã ã•ã„。ã“ã‚Œã¯é ˜åŽæ›¸ã«ãªã‚Šã¾ã™ã€‚åŒæ§˜ã®æƒ…å ±ã‚’ãƒ¡ãƒ¼ãƒ«ã§ã‚‚ãŠé€ã‚Šã—ã¦ã„ã¾ã™ã€‚" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "申込番å·" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "æ•°é‡" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "注æ„ã—ã¦ãã ã•ã„" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "ç·šãŒå¼•ã„ã¦ã‚るアイテムã¯è¿”金ã•ã‚Œã¾ã—ãŸã€‚" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "請求先" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "é ˜åŽè¨¼ãªã—" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "次ã®ã‚¹ãƒ†ãƒƒãƒ—: 本人確èª" @@ -8410,6 +8728,10 @@ msgid "" msgstr "" "ã„ã¾ã™ã本人èªè¨¼ã‚’è¡Œã‚ãªãã¦ã‚‚ダッシュボードã§è¬›åº§ã‚’探ã™ã“ã¨ã¯ã§ãã¾ã™ã€‚定期的ã«%(platformName)sã‹ã‚‰æœ¬äººèªè¨¼ã‚’è¡Œã†ã‚ˆã†ã«é€šçŸ¥ãŒã‚ã‚Šã¾ã™ã€‚" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "後ã§æœ¬äººèªè¨¼ã‚’è¡Œã„ã¾ã™ã‹ï¼Ÿ" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "本人èªè¨¼æ‰‹ç¶šä¸" @@ -8418,10 +8740,9 @@ msgstr "本人èªè¨¼æ‰‹ç¶šä¸" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"ã‚ãªãŸã®æƒ…å ±ã‚’å—ã‘å–ã‚Šã€æœ¬äººèªè¨¼ä¸ã§ã™ã€‚èªè¨¼æ‰‹ç¶šãŒå®Œäº†ã—ã¾ã—ãŸã‚‰ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒè¡¨ç¤ºã•ã‚Œã¾ã™(通常1~2日以内)。ãã®é–“も講座コンテンツã«ã¯ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚" #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -8455,10 +8776,6 @@ msgstr "写真ã®å¿…è¦æ¡ä»¶: " msgid "Does the photo of you show your whole face?" msgstr "写真ã«ã‚ãªãŸã®é¡”全体ãŒå†™ã£ã¦ã„ã¾ã™ã‹ï¼Ÿ" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "身分証明書ã®å†™çœŸã¨ã‚ãªãŸã®å†™çœŸã¯ä¸€è‡´ã—ã¾ã™ã‹ï¼Ÿ" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "身分証明書ã®æ°åã¯èªã‚ã¾ã™ã‹ï¼Ÿ" @@ -9875,6 +10192,21 @@ msgstr "特別試験ã¨ã—ã¦è¨å®š" msgid "Exam Types" msgstr "試験タイプ" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "時間制é™ä»˜ã" @@ -10049,11 +10381,11 @@ msgid "Read more" msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" +msgid "No transcript uploaded." msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "No transcript uploaded." +msgid "Show transcripts ({totalTranscripts})" msgstr "" #: cms/templates/js/xblock-access-editor.underscore diff --git a/conf/locale/ka/LC_MESSAGES/django.mo b/conf/locale/ka/LC_MESSAGES/django.mo index 81480dbe6e0f99474f9541324f6b625b025b853f..53292435ef1109f7007e6db11c42bf432ecbef62 100644 Binary files a/conf/locale/ka/LC_MESSAGES/django.mo and b/conf/locale/ka/LC_MESSAGES/django.mo differ diff --git a/conf/locale/ka/LC_MESSAGES/django.po b/conf/locale/ka/LC_MESSAGES/django.po index 9ca69b7fb8aaac558e8c00bb34ec6f3ff1c82fff..bcb6776429e459e07408295c8a0af15c4122348e 100644 --- a/conf/locale/ka/LC_MESSAGES/django.po +++ b/conf/locale/ka/LC_MESSAGES/django.po @@ -60,7 +60,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed <waheed@edx.org>, 2019\n" "Language-Team: Georgian (https://www.transifex.com/open-edx/teams/6205/ka/)\n" @@ -69,7 +69,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -94,8 +94,8 @@ msgstr "მისáƒáƒ¦áƒ”ბი გáƒáƒ›áƒáƒªáƒ“áƒ" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "ერთეული" @@ -419,13 +419,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "áƒáƒœáƒ’áƒáƒ იში სáƒáƒ¯áƒáƒ რმáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლით '{username}' უკვე áƒáƒ სებáƒáƒ‘ს." +msgid "An account with the Email '{email}' already exists." +msgstr "áƒáƒœáƒ’áƒáƒ იში ელფáƒáƒ¡áƒ¢áƒ˜áƒ— '{email}' უკვე áƒáƒ სებáƒáƒ‘ს." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "áƒáƒœáƒ’áƒáƒ იში ელფáƒáƒ¡áƒ¢áƒ˜áƒ— '{email}' უკვე áƒáƒ სებáƒáƒ‘ს." +msgid "An account with the Public Username '{username}' already exists." +msgstr "áƒáƒœáƒ’áƒáƒ იში სáƒáƒ¯áƒáƒ რმáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლით '{username}' უკვე áƒáƒ სებáƒáƒ‘ს." #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2288,9 +2288,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -4206,12 +4206,12 @@ msgstr "" "შეიყვáƒáƒœáƒ”თ სწáƒáƒ ი áƒáƒœ მცდáƒáƒ ი. თუ სწáƒáƒ იáƒ, áƒáƒ›áƒáƒªáƒáƒœáƒ˜áƒ¡ მáƒáƒ“ულებზე პáƒáƒ¡áƒ£áƒ®áƒ”ბის გáƒáƒ’ზáƒáƒ•áƒœáƒ " "გáƒáƒœáƒ®áƒ˜áƒšáƒ£áƒšáƒ˜ იქნებრმისáƒáƒ¦áƒ”ბი გáƒáƒ›áƒáƒªáƒ“ების შეფáƒáƒ¡áƒ”ბის/მიღების áƒáƒšáƒ’áƒáƒ ითმში." -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "" @@ -4887,17 +4887,17 @@ msgstr "" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "დáƒáƒ®áƒ£áƒ ვáƒ" @@ -5837,55 +5837,6 @@ msgstr "" "{username} ({email})-ის მიერáƒáƒœáƒáƒ–ღáƒáƒ£áƒ ების მáƒáƒ—ხáƒáƒ•áƒœáƒ ინიცირებულიáƒ. áƒáƒ› " "მáƒáƒ—ხáƒáƒ•áƒœáƒ˜áƒ¡ სáƒáƒ›áƒáƒ თáƒáƒ•áƒáƒ“, გთხáƒáƒ•áƒ—, ეწვიეთ მისáƒáƒ›áƒáƒ თს(ებს) ქვემáƒáƒ—." -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "ქვითáƒáƒ ი" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "გáƒáƒ“áƒáƒ®áƒ“რვერმáƒáƒ®áƒ”რხდáƒ" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "პრáƒáƒ‘ლემის გáƒáƒ›áƒ ეს ტრáƒáƒœáƒ–áƒáƒ¥áƒªáƒ˜áƒ ვერგáƒáƒœáƒ®áƒáƒ ციელდáƒ. თáƒáƒœáƒ®áƒ áƒáƒ ჩáƒáƒ›áƒáƒ’ეáƒáƒ áƒáƒ—." - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" -"დáƒáƒ წმუნდით, რáƒáƒ› თქვენი ინფáƒáƒ მáƒáƒªáƒ˜áƒ სწáƒáƒ იáƒ, áƒáƒœ სცáƒáƒ“ეთ სხვრბáƒáƒ áƒáƒ—ი áƒáƒœ გáƒáƒ“áƒáƒ®áƒ“ის " -"სხვრმეთáƒáƒ“ი." - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" -"გáƒáƒ“áƒáƒ®áƒ“ის დáƒáƒ›áƒ£áƒ¨áƒ•áƒ”ბისáƒáƒ¡ დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრსისტემური შეცდáƒáƒ›áƒ. თáƒáƒœáƒ®áƒ áƒáƒ ჩáƒáƒ›áƒáƒ’ეáƒáƒ áƒáƒ—." - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "გთხáƒáƒ•áƒ—, მáƒáƒ˜áƒªáƒáƒ“áƒáƒ— რáƒáƒ›áƒ“ენიმე წუთი დრკვლáƒáƒ• სცáƒáƒ“áƒáƒ—." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "დáƒáƒ®áƒ›áƒáƒ ებისთვის დáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ დით {payment_support_link}." - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "თქვენი ქვითრის დáƒáƒ›áƒ£áƒ¨áƒ•áƒ”ბისáƒáƒ¡ დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრშეცდáƒáƒ›áƒ." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"დáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ დით {payment_support_link}-ს, თუ თქვენი პáƒáƒ თვის პáƒáƒœáƒ”ლზე თქვენი " -"კურსი áƒáƒ áƒáƒ ის მითითებული." - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "" @@ -5947,10 +5898,22 @@ msgstr "თქვენ áƒáƒ› კურსზე დáƒáƒ¨áƒ•áƒ”ბრáƒáƒ msgid "You do not have access to this course on a mobile device" msgstr "áƒáƒ› კურსზე თქვენ áƒáƒ გáƒáƒ¥áƒ•áƒ— დáƒáƒ¨áƒ•áƒ”ბრმáƒáƒ‘ილური მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ით" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "გáƒáƒœáƒáƒ®áƒšáƒ”ბრდáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებáƒáƒ›áƒ“ე" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -6612,9 +6575,8 @@ msgid "Good" msgstr "კáƒáƒ გიáƒ" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html @@ -6622,6 +6584,11 @@ msgstr "" msgid "View discussion" msgstr "დისკუსიის ნáƒáƒ®áƒ•áƒ" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6761,8 +6728,8 @@ msgid "Student" msgstr "სტუდენტი" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "პერსáƒáƒœáƒáƒšáƒ˜" @@ -6888,29 +6855,6 @@ msgstr "" msgid "Could not find problem with this location." msgstr "áƒáƒ› ლáƒáƒ™áƒáƒªáƒ˜áƒáƒ–ე პრáƒáƒ‘ლემრვერმáƒáƒ˜áƒ«áƒ”ბნáƒ." -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "áƒáƒœáƒ’áƒáƒ იშფáƒáƒ¥áƒ¢áƒ£áƒ ის ნáƒáƒ›áƒ”რი '{num}' áƒáƒ áƒáƒ სებáƒáƒ‘ს." - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "áƒáƒ› áƒáƒœáƒ’áƒáƒ იშფáƒáƒ¥áƒ¢áƒ£áƒ áƒáƒ¡áƒ—áƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ ებული ფáƒáƒ¡áƒ“áƒáƒ™áƒšáƒ”ბრუკვე გáƒáƒ£áƒ¥áƒ›áƒ”ბულიáƒ." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr " áƒáƒœáƒ’áƒáƒ იშფáƒáƒ¥áƒ¢áƒ£áƒ რნáƒáƒ›áƒ”რი {0} გáƒáƒ£áƒ¥áƒ›áƒ”ბულიáƒ." - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "ეს áƒáƒœáƒ’áƒáƒ იშფáƒáƒ¥áƒ¢áƒ£áƒ რუკვე áƒáƒ¥áƒ¢áƒ˜áƒ£áƒ იáƒ." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "{0} áƒáƒœáƒ’áƒáƒ იშფáƒáƒ¥áƒ¢áƒ£áƒ ის რეგისტრáƒáƒªáƒ˜áƒ˜áƒ¡ კáƒáƒ“ები ხელáƒáƒ®áƒšáƒ გáƒáƒáƒ¥áƒ¢áƒ˜áƒ£áƒ ებულიáƒ." - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "CourseID" @@ -6941,9 +6885,8 @@ msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის ID" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლი" @@ -7065,54 +7008,6 @@ msgstr "" "ფáƒáƒ˜áƒšáƒ˜ უნდრშეიცáƒáƒ•áƒ“ეს 'მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლის' სვეტს, 'ელფáƒáƒ¡áƒ¢áƒ˜áƒ¡' სვეტს áƒáƒœ " "áƒáƒ ივეს." -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "კუპáƒáƒœáƒ˜áƒ¡ კáƒáƒ“ი" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "კურსის Id" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% ფáƒáƒ¡áƒ“áƒáƒ™áƒšáƒ”ბáƒ" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "áƒáƒ¦áƒ¬áƒ”რáƒ" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "ვáƒáƒ“ის áƒáƒ›áƒáƒ¬áƒ£áƒ ვის თáƒáƒ იღი" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "áƒáƒ¥áƒ¢áƒ˜áƒ£áƒ იáƒ" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "უკáƒáƒœ დáƒáƒ‘რუნებული კáƒáƒ“ების დáƒáƒ—ვლáƒ" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "ფáƒáƒ¡áƒ“áƒáƒ™áƒšáƒ”ბული áƒáƒ“გილების სრული რáƒáƒáƒ“ენáƒáƒ‘áƒ" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "ფáƒáƒ¡áƒ“áƒáƒ™áƒšáƒ”ბული თáƒáƒœáƒ®áƒ˜áƒ¡ სრული áƒáƒ“ენáƒáƒ‘áƒ" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -7133,16 +7028,6 @@ msgstr "" msgid "proctored exam results" msgstr "" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "რáƒáƒáƒ“ენáƒáƒ‘ის áƒáƒ—წილáƒáƒ“ებში დáƒáƒ›áƒ£áƒ¨áƒáƒ•áƒ”ბრვერხერხდებáƒ" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" -"კურსის áƒáƒ áƒáƒ¡áƒ¬áƒáƒ ი კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ›áƒ ვერხერხდებრდáƒáƒ‘რუნების კáƒáƒ“ების " -"გენერირებáƒ." - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -7394,67 +7279,6 @@ msgstr "" "გáƒáƒ“áƒáƒáƒ›áƒáƒ¬áƒ›áƒ”თ სწáƒáƒ ირთუ áƒáƒ რსტუდენტის მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლი/ელფáƒáƒ¡áƒ¢áƒ დრმáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜" " კურსი დრკიდევ სცáƒáƒ“ეთ." -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "კუპáƒáƒœáƒ˜áƒ¡ id áƒáƒ ის „None“" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "კუპáƒáƒœáƒ˜ სáƒáƒ˜áƒ“ენტიფიკáƒáƒªáƒ˜áƒ კáƒáƒ“ით ({coupon_id}) áƒáƒ áƒáƒ სებáƒáƒ‘ს" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "კუპáƒáƒœáƒ˜áƒ¡ სáƒáƒ˜áƒ“ენტიფიკáƒáƒªáƒ˜áƒ კáƒáƒ“ით ({coupon_id}) უკვე áƒáƒ áƒáƒáƒ¥áƒ¢áƒ˜áƒ£áƒ იáƒ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "კუპáƒáƒœáƒ˜ სáƒáƒ˜áƒ“ენტიფიკáƒáƒªáƒ˜áƒ კáƒáƒ“ით ({coupon_id}) წáƒáƒ მáƒáƒ¢áƒ”ბით გáƒáƒœáƒáƒ®áƒšáƒ“áƒ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" -"({code}) კáƒáƒ“ი, რáƒáƒ›áƒ”ლიც თქვენ სცáƒáƒ“ეთ, უკვე გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნებრრáƒáƒ’áƒáƒ ც რეგისტრáƒáƒªáƒ˜áƒ˜áƒ¡ " -"კáƒáƒ“ი" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "გთხáƒáƒ•áƒ—, კუპáƒáƒœáƒ˜áƒ¡ ფáƒáƒ¡áƒ“áƒáƒ™áƒšáƒ”ბის მისáƒáƒ¦áƒ”ბáƒáƒ“ შეიყვáƒáƒœáƒáƒ— მთელი რიცხვი" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "" -"გთხáƒáƒ•áƒ—, კუპáƒáƒœáƒ˜áƒ¡ ფáƒáƒ¡áƒ“áƒáƒ™áƒšáƒ”ბის მნიშვნელáƒáƒ‘áƒáƒ¨áƒ˜ მიუთითáƒáƒ— 100-ის ტáƒáƒšáƒ˜ áƒáƒœ ნáƒáƒ™áƒšáƒ”ბი" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "გთხáƒáƒ•áƒ—, თáƒáƒ იღი შეიყვáƒáƒœáƒ”თ შემდეგ ფáƒáƒ მáƒáƒ¢áƒ¨áƒ˜: თვე/დღე/წელი" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "({code}) კáƒáƒ“ით კუპáƒáƒœáƒ˜áƒ¡ დáƒáƒ›áƒáƒ¢áƒ”ბრწáƒáƒ მáƒáƒ¢áƒ”ბით გáƒáƒœáƒ®áƒáƒ ციელდáƒ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "კუპáƒáƒœáƒ˜ კáƒáƒ“ით ({code}) áƒáƒ› კურსზე უკვე áƒáƒ სებáƒáƒ‘ს" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "კუპáƒáƒœáƒ˜áƒ¡ მáƒáƒ«áƒ˜áƒ”ბრვერმáƒáƒ®áƒ”რხდáƒ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "" -"({coupon_id}) იდენტიფიკáƒáƒ¢áƒáƒ ით კუპáƒáƒœáƒ˜áƒ¡ გáƒáƒœáƒáƒ®áƒšáƒ”ბრწáƒáƒ მáƒáƒ¢áƒ”ბით გáƒáƒœáƒ®áƒáƒ ციელდáƒ" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "ინსტრუქტáƒáƒ ი" @@ -7566,29 +7390,6 @@ msgstr "დáƒáƒ¡áƒ ულებულიáƒ" msgid "Incomplete" msgstr "áƒáƒ áƒáƒ¡áƒ ული" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "{course_name} კურსისთვის ჩáƒáƒ იცხვის კáƒáƒ“ი ({code}) ვერმáƒáƒ˜áƒ«áƒ”ბნáƒ." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "ჩáƒáƒ იცხვის კáƒáƒ“ი გáƒáƒ£áƒ¥áƒ›áƒ“áƒ. მისი გáƒáƒ›áƒáƒ§áƒ”ნებრáƒáƒ¦áƒáƒ შეიძლებáƒ." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "ჩáƒáƒ იცხვის áƒáƒ¦áƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ კáƒáƒ“ი მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜áƒ რáƒáƒ’áƒáƒ ც გáƒáƒ›áƒáƒ£áƒ§áƒ”ნებელი." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "ჩáƒáƒ იცხვის კáƒáƒ“ი áƒáƒ¦áƒ“გენილიáƒ." - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "ჩáƒáƒ იცხვის კáƒáƒ“ი ({code}) áƒáƒ სáƒáƒ“ გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნებáƒ." - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7996,8 +7797,8 @@ msgstr " ({total}-დáƒáƒœ)" #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "პრáƒáƒ’რáƒáƒ›áƒ”ბი" @@ -8195,12 +7996,12 @@ msgid "{mode_name} for course {course}" msgstr "{course} კურსის {mode_name} " #: lms/djangoapps/shoppingcart/models.py +#, python-brace-format msgid "" -"You can unenroll in the course and receive a full refund for 14 days after " -"the course start date. " +"To receive a refund you may unenroll from the course on your edX Dashboard " +"({dashboard_url}) up to 14 days after your payment or 14 days after your " +"course starts (up to six months after your payment).\n" msgstr "" -"შეგიძლიáƒáƒ— კურსზე ჩáƒáƒ იცხვის გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ. გáƒáƒ“áƒáƒ®áƒ“ილი თáƒáƒœáƒ®áƒ სრულáƒáƒ“ áƒáƒ’ინáƒáƒ–ღáƒáƒ£áƒ დებáƒáƒ— " -"კურსის დáƒáƒ¬áƒ§áƒ”ბის თáƒáƒ იღიდáƒáƒœ 14 დღის გáƒáƒœáƒ›áƒáƒ•áƒšáƒáƒ‘áƒáƒ¨áƒ˜." #: lms/djangoapps/shoppingcart/models.py #, python-brace-format @@ -8214,21 +8015,15 @@ msgstr "" #: lms/djangoapps/shoppingcart/models.py msgid "" "You can unenroll in the course and receive a full refund for 2 days after " -"the course start date. " +"the course start date.\n" msgstr "" -"შეგიძლიáƒáƒ— კურსზე რჩáƒáƒ იცხვის გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ. გáƒáƒ“áƒáƒ®áƒ“ილი თáƒáƒœáƒ®áƒ სრულáƒáƒ“ áƒáƒ’ინáƒáƒ–ღáƒáƒ£áƒ დებáƒáƒ—" -" კურსის დáƒáƒ¬áƒ§áƒ”ბიდáƒáƒœ 2 დღეში." #: lms/djangoapps/shoppingcart/models.py #, python-brace-format msgid "" -"{refund_reminder_msg}To receive your refund, contact {billing_email}. Please" -" include your order number in your email. Please do NOT include your credit " -"card information." +"{refund_reminder_msg}For help unenrolling, Please see How do I unenroll from" +" a course? ({how_to_unenroll_link}) in our edX HelpCenter." msgstr "" -"{refund_reminder_msg} áƒáƒœáƒáƒ–ღáƒáƒ£áƒ ების მისáƒáƒ¦áƒ”ბáƒáƒ“, დáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ დით " -"{billing_email}-ს. გთხáƒáƒ•áƒ— ელ-შეტყáƒáƒ‘ინებáƒáƒ¨áƒ˜ მიუთითეთ თქვენი შეკვეთის ნáƒáƒ›áƒ”რი " -"დრნუ შეიყვáƒáƒœáƒ— თქვენი სáƒáƒ™áƒ ედიტრბáƒáƒ áƒáƒ—ის მáƒáƒœáƒáƒªáƒ”მებს." #: lms/djangoapps/shoppingcart/models.py #, python-brace-format @@ -8740,6 +8535,15 @@ msgstr "სრული ღირებულებáƒ" msgid "Currency" msgstr "ვáƒáƒšáƒ£áƒ¢áƒ" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "áƒáƒ¦áƒ¬áƒ”რáƒ" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "კáƒáƒ›áƒ”ნტáƒáƒ ები" @@ -8887,14 +8691,6 @@ msgstr "თქვენ áƒáƒ გáƒáƒ¥áƒ•áƒ— áƒáƒ› გვერდის ნ msgid "View and regenerate certificates." msgstr "სერტიფიკáƒáƒ¢áƒ”ბის დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რებრდრხელáƒáƒ®áƒšáƒ გენერირებáƒ." -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "თáƒáƒœáƒ®áƒ˜áƒ¡ ხელით დáƒáƒ‘რუნებáƒ" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "უშუáƒáƒšáƒáƒ“ CyberSource-დáƒáƒœ მáƒáƒ—ხáƒáƒ•áƒœáƒ˜áƒšáƒ˜ თáƒáƒœáƒ®áƒ˜áƒ¡ დáƒáƒ‘რუნების მიდევნებáƒ." - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -8973,44 +8769,9 @@ msgstr "" msgid "User Disabled Successfully" msgstr "" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "ელფáƒáƒ¡áƒ¢áƒ˜áƒ¡ მისáƒáƒ›áƒáƒ თი" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "კურსის ID" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ ებელი ვერმáƒáƒ˜áƒ«áƒ”ბნáƒ" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "კურსი {course_id} áƒáƒ áƒáƒ ის áƒáƒœáƒáƒ–ღáƒáƒ£áƒ ების ფáƒáƒœáƒ¯áƒ ის მიღმáƒ." - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "კურსზე {course_id} {user}-ის შეკვეთრვერმáƒáƒ˜áƒ«áƒ”ბნáƒ" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ ებელი {user} გáƒáƒ იცხულირკურსიდáƒáƒœ {course_id}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "დáƒáƒ‘რუნებული თáƒáƒœáƒ®áƒ {cost} შეკვეთისთვის {order_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -9058,13 +8819,17 @@ msgid "The supplied course_id {course_id} is not valid." msgstr "მითითებული course_id {course_id} áƒáƒ áƒáƒ¡áƒ¬áƒáƒ იáƒ." #: lms/djangoapps/teams/views.py -msgid "You are already in a team in this course." -msgstr "თქვენ უკვე áƒáƒ› კურსის გუნდის წევრი ხáƒáƒ თ." +msgid "topic_id is required" +msgstr "" #: lms/djangoapps/teams/views.py msgid "You can't create a team in an instructor managed topic." msgstr "" +#: lms/djangoapps/teams/views.py +msgid "You are already in a team in this teamset." +msgstr "" + #: lms/djangoapps/teams/views.py msgid "teamset_id and team_id are mutually exclusive options." msgstr "" @@ -9629,8 +9394,8 @@ msgid "Allow" msgstr "დáƒáƒ¨áƒ•áƒ”ბáƒ" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "შეცდáƒáƒ›áƒ" @@ -10007,8 +9772,8 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "დáƒáƒœáƒáƒ თები" @@ -10041,11 +9806,10 @@ msgstr "" "სხვრსტáƒáƒ¢áƒ˜áƒ”ბშიც, რáƒáƒª შესáƒáƒ«áƒšáƒáƒ იყáƒáƒ¡ áƒáƒœ áƒáƒ იყáƒáƒ¡ მიზáƒáƒœáƒ¨áƒ”წáƒáƒœáƒ˜áƒšáƒ˜." #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -10434,6 +10198,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -10847,6 +10615,10 @@ msgstr "" msgid "Schedule start < course start" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "კურსის Id" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "ყველáƒ" @@ -10855,6 +10627,15 @@ msgstr "ყველáƒ" msgid "Experience" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "კურსის ID" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -11056,6 +10837,7 @@ msgid "" msgstr "" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "" @@ -11289,7 +11071,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -11316,8 +11097,8 @@ msgstr "" msgid "Success" msgstr "წáƒáƒ მáƒáƒ¢áƒ”ბáƒ" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "მáƒáƒ¥áƒ›áƒ”დებები" @@ -11484,6 +11265,14 @@ msgstr "" "თქვენი სისტემáƒáƒ¨áƒ˜ შესáƒáƒ¡áƒ•áƒšáƒ”ლი ინფáƒáƒ მáƒáƒªáƒ˜áƒ˜áƒ¡ მიღებისáƒáƒ¡ დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრშეცდáƒáƒ›áƒ. " "გთხáƒáƒ•áƒ—, გáƒáƒ›áƒáƒ’ვიგზáƒáƒ•áƒœáƒ”თ შეტყáƒáƒ‘ინებáƒ." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11497,6 +11286,15 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "შესვლის ძáƒáƒšáƒ˜áƒáƒœ ბევრი წáƒáƒ უმáƒáƒ¢áƒ”ბელი მცდელáƒáƒ‘áƒ. სცáƒáƒ“ეთ მáƒáƒ’ვიáƒáƒœáƒ”ბით." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11504,15 +11302,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "username@domain.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -11529,6 +11318,12 @@ msgstr "" msgid "Create Account" msgstr "" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "username@domain.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -11545,6 +11340,11 @@ msgstr "" "ელფáƒáƒ¡áƒ¢áƒ˜áƒ¡ მისáƒáƒ›áƒáƒ თზე მიბმული მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის áƒáƒœáƒ’áƒáƒ იშის პáƒáƒ áƒáƒšáƒ˜áƒ¡ áƒáƒ¦áƒ“გენრვერ" "ხერხდებáƒ." +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "პáƒáƒ áƒáƒšáƒ˜áƒ¡ გáƒáƒ“áƒáƒ§áƒ”ნებრვერმáƒáƒ®áƒ”რხდáƒ" @@ -11564,11 +11364,6 @@ msgid "" "created. {bold_start}{email}{bold_end} is now your primary login email." msgstr "" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "" @@ -11792,6 +11587,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "" @@ -11810,6 +11617,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "მნიშვნელáƒáƒ‘რáƒáƒ áƒáƒ ის სწáƒáƒ ი." @@ -12507,8 +12318,8 @@ msgstr "კურსი წáƒáƒ მáƒáƒ¢áƒ”ბით დáƒáƒ”ქსპáƒáƒ msgid "Vertical" msgstr "ვერტიკáƒáƒšáƒ£áƒ ი" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "გáƒáƒœáƒ§áƒáƒ¤áƒ˜áƒšáƒ”ბáƒ" @@ -12789,6 +12600,18 @@ msgstr "" msgid "Transcript Ready" msgstr "" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "" @@ -12986,14 +12809,14 @@ msgstr "კურსის ნáƒáƒ›áƒ”რი:" msgid "Course Run:" msgstr "" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "კურსები" @@ -13017,8 +12840,9 @@ msgstr "" msgid "Requirements" msgstr "მáƒáƒ—ხáƒáƒ•áƒœáƒ”ბი" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "დეტáƒáƒšáƒ”ბი" @@ -13070,15 +12894,15 @@ msgstr "" msgid "Choose Language" msgstr "áƒáƒ˜áƒ ჩიეთ ენáƒ" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "áƒáƒœáƒ’áƒáƒ იში" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -13150,8 +12974,8 @@ msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის მენიუ" msgid "Usermenu dropdown" msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის ჩáƒáƒ›áƒáƒ¡áƒáƒ¨áƒšáƒ”ლი მენიუ" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "გáƒáƒ¡áƒ•áƒšáƒ" @@ -13315,8 +13139,8 @@ msgstr "იწყებáƒ: {date}" msgid "View all Courses" msgstr "ყველრკურსის ნáƒáƒ®áƒ•áƒ" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "მáƒáƒ თვის დáƒáƒ¤áƒ" @@ -13335,8 +13159,8 @@ msgstr "თქვენ ჯერáƒáƒ ჩáƒáƒ იცხულხáƒáƒ თ #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "გáƒáƒ“áƒáƒ®áƒ”დეთ კურსებს" @@ -13354,7 +13178,7 @@ msgstr " შეცდáƒáƒ›áƒ”ბი კურსის ჩáƒáƒ¢áƒ•áƒ˜áƒ თვ msgid "Search Your Courses" msgstr "ეძიეთ თქვენი კურსები" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "სáƒáƒ«áƒ˜áƒ”ბრველის გáƒáƒ¬áƒ›áƒ”ნდáƒ" @@ -13379,7 +13203,7 @@ msgstr "კურსის შეტყáƒáƒ‘ინებების მიღ msgid "Save Settings" msgstr "პáƒáƒ áƒáƒ›áƒ”ტრების შენáƒáƒ®áƒ•áƒ" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -13389,9 +13213,87 @@ msgstr "პáƒáƒ áƒáƒ›áƒ”ტრების შენáƒáƒ®áƒ•áƒ" msgid "Unenroll" msgstr "ჩáƒáƒ იცხვის გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "ერთეულის ნáƒáƒ®áƒ•áƒ სტუდიáƒáƒ¨áƒ˜ " +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -13425,7 +13327,7 @@ msgstr "áƒáƒœáƒ’áƒáƒ იში áƒáƒ®áƒáƒšáƒ˜ ელფáƒáƒ¡áƒ¢áƒ˜áƒ¡ მი msgid "You should Register before trying to access the Unit" msgstr "სáƒáƒœáƒáƒ› ერთეულზე წვდáƒáƒ›áƒ˜áƒ¡ მიღებáƒáƒ¡ ეცდებით, უნდრდáƒáƒ ეგისტრირდეთ" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "" @@ -13529,7 +13431,7 @@ msgid "" "available on the {link_start}progress page{link_end}." msgstr "" -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "კურსის ძიებáƒ" @@ -13677,23 +13579,16 @@ msgstr "(გáƒáƒ¡áƒáƒáƒ®áƒšáƒ”ბლáƒáƒ“ გáƒáƒ“áƒáƒ¢áƒ•áƒ˜áƒ თეთ msgid "working" msgstr "დáƒáƒ›áƒ£áƒ¨áƒáƒ•áƒ”ბáƒ" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr " {platform_name} სერვერებზე დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრშეცდáƒáƒ›áƒ" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html -#: lms/templates/courseware/error-message.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"ვწუხვáƒáƒ თ, მáƒáƒ’რáƒáƒ› ეს მáƒáƒ“ული დრáƒáƒ”ბით მიუწვდáƒáƒ›áƒ”ლიáƒ. ჩვენი პერსáƒáƒœáƒáƒšáƒ˜ მუშáƒáƒáƒ‘ს მის" -" რáƒáƒª შეიძლებრსწრáƒáƒ¤ ჩáƒáƒ თვáƒáƒ–ე. გთხáƒáƒ•áƒ—, გáƒáƒ›áƒáƒ’ვიგზáƒáƒ•áƒœáƒáƒ— შეტყáƒáƒ‘ინებრ" -"{tech_support_email}-ზე დრგვáƒáƒªáƒœáƒáƒ‘áƒáƒ— ნებისმიერი პრáƒáƒ‘ლემის áƒáƒœ უბრáƒáƒšáƒáƒ“ " -"ტექნიკური გáƒáƒ£áƒ›áƒáƒ თáƒáƒáƒ‘ის შესáƒáƒ®áƒ”ბ." #: lms/templates/module-error.html msgid "Raw data:" @@ -13732,7 +13627,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "áƒáƒ®áƒšáƒ თქვენ ნáƒáƒ®áƒ£áƒšáƒáƒ‘თ კურსს, რáƒáƒ’áƒáƒ ც {i_start}{user_name}{i_end}." #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -13797,16 +13700,6 @@ msgstr "ელფáƒáƒ¡áƒ¢áƒ" msgid "Return To %s" msgstr "%s -ზე დáƒáƒ‘რუნებáƒ" -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "ხელáƒáƒ®áƒáƒšáƒ˜ გáƒáƒ›áƒáƒ¬áƒ”რრწáƒáƒ მáƒáƒ¢áƒ”ბით შესრულდáƒ!" @@ -13857,7 +13750,7 @@ msgstr "" msgid "Sequence" msgstr "" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -13988,18 +13881,18 @@ msgstr "" msgid "Reset Learner's Attempts to Zero" msgstr "მსმენელთრმცდელáƒáƒ‘ების ნულáƒáƒ›áƒ“ე ჩáƒáƒ›áƒáƒ§áƒ áƒ" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "მსმენელთრისტáƒáƒ იის მáƒáƒœáƒáƒªáƒ”მთრბáƒáƒ–ის წáƒáƒ¨áƒšáƒ" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "მáƒáƒ¡áƒ¬áƒáƒ•áƒšáƒ”თრმიერáƒáƒ¢áƒ•áƒ˜áƒ თული დáƒáƒ•áƒáƒšáƒ”ბების თáƒáƒ•áƒ˜áƒ“áƒáƒœ შეფáƒáƒ¡áƒ”ბრქულებით" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "ხელáƒáƒ®áƒšáƒ შეáƒáƒ¤áƒáƒ¡áƒ” მხáƒáƒšáƒáƒ“ ქულის გáƒáƒ£áƒ›áƒ¯áƒáƒ‘ესების შემთხვევáƒáƒ¨áƒ˜" @@ -14037,7 +13930,7 @@ msgstr "{course_number} სáƒáƒ®áƒ”ლმძღვáƒáƒœáƒ”ლáƒ" msgid "Textbook Navigation" msgstr " სáƒáƒ®áƒ”ლმძღვáƒáƒœáƒ”ლáƒáƒ¡ ნáƒáƒ•áƒ˜áƒ’áƒáƒªáƒ˜áƒ" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "გვერდი" @@ -14150,9 +14043,9 @@ msgstr "{current_page} გვერდი {total_pages}-დáƒáƒœ" msgid "Recent git load activity for {course_id}" msgstr " {course_id} ბáƒáƒšáƒ დრáƒáƒ˜áƒ¡ git შევსების áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒ‘áƒ" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Date" msgstr "თáƒáƒ იღი" @@ -14210,7 +14103,7 @@ msgstr "" "გáƒáƒ™áƒ”თებრáƒáƒ გიგულისხმიáƒáƒ—, {undo_link_start}შეგიძლიáƒáƒ— ხელáƒáƒ®áƒšáƒ " "გáƒáƒ›áƒáƒ˜áƒ¬áƒ”რáƒáƒ—{link_end}." -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "მáƒáƒ თვის დáƒáƒ¤áƒ:" @@ -14218,8 +14111,8 @@ msgstr "მáƒáƒ თვის დáƒáƒ¤áƒ:" msgid "More options" msgstr "" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "" @@ -15541,37 +15434,6 @@ msgstr "" msgid "About edX Certificates" msgstr "" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "შემáƒáƒ¬áƒ›áƒ”ბრგáƒáƒ£áƒ¥áƒ›áƒ“áƒ" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"თქვენი ტრáƒáƒœáƒ–áƒáƒ¥áƒªáƒ˜áƒ გáƒáƒ£áƒ¥áƒ›áƒ“áƒ. თუ ფიქრáƒáƒ‘თ, რáƒáƒ› წáƒáƒ მáƒáƒ˜áƒ¨áƒ•áƒ შეცდáƒáƒ›áƒ, დáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ დით " -"{email}." - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "შემáƒáƒ¬áƒ›áƒ”ბისáƒáƒ¡ დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრშეცდáƒáƒ›áƒ" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "შესყიდვის მáƒáƒœáƒáƒªáƒ”მების ჩáƒáƒ¢áƒ•áƒ˜áƒ თვáƒ..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "გთხáƒáƒ•áƒ—, დáƒáƒ”ლáƒáƒ“áƒáƒ— თქვენი შესყიდვის მáƒáƒœáƒáƒªáƒ”მებს áƒáƒ›áƒáƒ¦áƒ”ბáƒáƒ¡." - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -15796,28 +15658,25 @@ msgstr "{section_format} - {{date}}-მდე" msgid "This content is graded" msgstr "ეს შინáƒáƒáƒ სი შეფáƒáƒ¡áƒ”ბულიáƒ" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრშეცდáƒáƒ›áƒ. გთხáƒáƒ•áƒ— სცáƒáƒ“áƒáƒ— მáƒáƒ’ვიáƒáƒœáƒ”ბით." - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრშეცდáƒáƒ›áƒ. გთხáƒáƒ•áƒ— სცáƒáƒ“áƒáƒ— მáƒáƒ’ვიáƒáƒœáƒ”ბით." + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "თქვენ ჩáƒáƒ˜áƒ იცხეთ áƒáƒ› კურსზე" #: lms/templates/courseware/course_about.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: lms/templates/shoppingcart/registration_code_receipt.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "View Course" msgstr "იხილეთ კურსი" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "კურსი შევსებულიáƒ" @@ -15830,10 +15689,6 @@ msgstr "áƒáƒ› კურსზე ჩáƒáƒ იცხვრმხáƒáƒšáƒáƒ“ msgid "Enrollment is Closed" msgstr "ჩáƒáƒ იცხვრდáƒáƒ¡áƒ ულებულიáƒ" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "" @@ -15959,6 +15814,13 @@ msgstr "კურსის დáƒáƒ›áƒ®áƒ›áƒáƒ ე მáƒáƒ¡áƒáƒšáƒ" msgid "Courseware" msgstr "შინáƒáƒáƒ სი" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "კურსის ძებნáƒ" @@ -15987,7 +15849,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -15995,8 +15857,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" +msgstr "" + +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -16049,8 +15914,9 @@ msgid "Welcome to {course_title}!" msgstr "" #: lms/templates/courseware/info.html -#: lms/templates/dashboard/_dashboard_course_listing.html +#: lms/templates/dashboard/_dashboard_course_resume.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html +#: themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html msgid "Resume Course" msgstr "კურსზე დáƒáƒ‘რუნებáƒ" @@ -16670,10 +16536,8 @@ msgstr "თქვენ წáƒáƒ áƒáƒ“გინეთ დáƒáƒ¡áƒáƒ“áƒáƒ¡áƒ¢ #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" -"რáƒáƒ“ესáƒáƒª დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ების პრáƒáƒªáƒ”სი დáƒáƒ¡áƒ ულდებრმიიღებთ შეტყáƒáƒ‘ინებáƒáƒ¡ თქვენს მáƒáƒ თვის " -"დáƒáƒ¤áƒáƒ–ე (სáƒáƒ¨áƒ£áƒáƒšáƒáƒ“ 1-2 დღეში)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -16683,11 +16547,8 @@ msgstr "თქვენი მიმდინáƒáƒ ე დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" -"თქვენ წáƒáƒ áƒáƒ“გინეთ თáƒáƒ•áƒ˜áƒ“áƒáƒœ დáƒáƒ¡áƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებელი ინფáƒáƒ მáƒáƒªáƒ˜áƒ. რáƒáƒ“ესáƒáƒª დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ების " -"პრáƒáƒªáƒ”სი დáƒáƒ¡áƒ ულდებრმიიღებთ შეტყáƒáƒ‘ინებáƒáƒ¡ თქვენს მáƒáƒ თვის დáƒáƒ¤áƒáƒ–ე (სáƒáƒ¨áƒ£áƒáƒšáƒáƒ“ " -"1-2დღეში)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -17414,150 +17275,6 @@ msgid "" "verification process on your dashboard." msgstr "" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "გმáƒáƒ“ლáƒáƒ‘თ {course_name}-ზე ჩრიცხვების შეძენისთვის." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"{currency_symbol}{total_price}-ის áƒáƒœáƒ’áƒáƒ იშფáƒáƒ¥áƒ¢áƒ£áƒ რთáƒáƒœáƒ“áƒáƒ თულიáƒ. გáƒáƒ“áƒáƒ®áƒ“რ" -"გáƒáƒœáƒ®áƒáƒ ციელდებრქვითრის მიხედვით. ინფáƒáƒ მáƒáƒªáƒ˜áƒáƒ¡ გáƒáƒ“áƒáƒ®áƒ“ის მეთáƒáƒ“ებზე ნáƒáƒ®áƒáƒ•áƒ— " -"áƒáƒœáƒ’áƒáƒ იშფáƒáƒ¥áƒ¢áƒ£áƒ áƒáƒ¨áƒ˜." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -".csv ფáƒáƒ˜áƒšáƒ˜, რáƒáƒ›áƒ”ლშიც ჩáƒáƒ›áƒáƒ—ვლილირთქვენი ჩáƒáƒ იცხვის კáƒáƒ“ები, თáƒáƒœáƒ“áƒáƒ თულიáƒ. " -"შეგიძლიáƒáƒ— გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნáƒáƒ— ქვემáƒáƒ— მáƒáƒªáƒ”მული შეტყáƒáƒ‘ინების ნიმუში თქვენი " -"სტუდენტებისთვის ჩერიცხვის კáƒáƒ“ების დáƒáƒ¡áƒáƒ’ზáƒáƒ•áƒœáƒáƒ“. თითáƒáƒ”ულმრსტუდენტმრჩáƒáƒ იცხვის" -" ცáƒáƒšáƒ™áƒ”ული კáƒáƒ“ი უნდრგáƒáƒ›áƒáƒ˜áƒ§áƒ”ნáƒáƒ¡." - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"გმáƒáƒ“ლáƒáƒ‘თ,\n" -"{platform_name}-ის გუნდი" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "ძვირფáƒáƒ¡áƒ [[Name]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"ჩვენ მáƒáƒ’áƒáƒ¬áƒáƒ“ეთ კურსის ჩáƒáƒ იცხვის კáƒáƒ“ი {course_name}-ზე. კურსზე ჩáƒáƒ¡áƒáƒ იცხáƒáƒ“ " -"დáƒáƒáƒ¬áƒ™áƒáƒžáƒ£áƒœáƒ”თ შემდეგ ბმულს:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "HTML ბმული თáƒáƒœáƒ“áƒáƒ თული CSV ფáƒáƒ˜áƒšáƒ˜áƒ“áƒáƒœ" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"ჩáƒáƒ იცხვის შემდეგ თქვენს სტუდენტურმáƒáƒ თვის დáƒáƒ¤áƒáƒ–ე დáƒáƒ˜áƒœáƒáƒ®áƒáƒ•áƒ— კურსს. კურსის " -"მáƒáƒ¡áƒáƒšáƒ”ბის ნáƒáƒ®áƒ•áƒáƒ¡ კურსის დáƒáƒ¬áƒ§áƒ”ბის თáƒáƒ იღის შემდეგ შეძლებთ." - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"პáƒáƒ¢áƒ˜áƒ•áƒ˜áƒ¡áƒªáƒ”მით,\n" -"[[Your Signature]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "áƒáƒœáƒ’áƒáƒ იშფáƒáƒ¥áƒ¢áƒ£áƒ áƒ" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "თáƒáƒ იღი: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "áƒáƒœáƒ’áƒáƒ იშფáƒáƒ¥áƒ¢áƒ£áƒ ის ნáƒáƒ›áƒ”რი: {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "პირáƒáƒ‘ები: გáƒáƒ“áƒáƒ®áƒ“რმიღებისთáƒáƒœáƒáƒ•áƒ”" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "გáƒáƒ“áƒáƒ®áƒ“ის ვáƒáƒ“áƒ: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "გáƒáƒ“áƒáƒ¡áƒáƒ®áƒ“ელი áƒáƒœáƒ’áƒáƒ იში:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის დáƒáƒ›áƒáƒ¬áƒ›áƒ”ბის ნáƒáƒ›áƒ”რი: {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "ნáƒáƒ¨áƒ—ი: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "კურსი: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"ფáƒáƒ¡áƒ˜: {currency_symbol}{course_price} რáƒáƒáƒ“ენáƒáƒ‘áƒ: {quantity} შუáƒáƒšáƒ”დური " -"ჯáƒáƒ›áƒ˜: {currency_symbol}{sub_total} ფáƒáƒ¡áƒ“áƒáƒ™áƒšáƒ”ბáƒ: {currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "ჯáƒáƒ›áƒ˜: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "გáƒáƒ“áƒáƒ®áƒ“ის ინსტრუქციები" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"თუ áƒáƒ მივიღებთ გáƒáƒ“áƒáƒ®áƒ“áƒáƒ¡, მáƒáƒ¡áƒ¬áƒáƒ•áƒšáƒ”ების ჩáƒáƒ იცხვები რáƒáƒ›áƒ”იც áƒáƒ› კáƒáƒ“ებს იყენებს, " -"გáƒáƒ£áƒ¥áƒ›áƒ“ებრდრმსმენელები ვერშეძლებენ კურსის მáƒáƒ¡áƒáƒšáƒ”ბზე წვდáƒáƒ›áƒáƒ¡. ყველრ" -"შესყიდვრსáƒáƒ‘áƒáƒšáƒáƒáƒ. დáƒáƒ›áƒáƒ¢áƒ”ბითი ინფáƒáƒ მáƒáƒªáƒ˜áƒ˜áƒ¡áƒ—ვის იხილეთ {site_name}-ის " -"გáƒáƒ£áƒ¥áƒ›áƒ”ბის პáƒáƒšáƒ˜áƒ¢áƒ˜áƒ™áƒ." - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "კითხვებით გáƒáƒ“áƒáƒ®áƒ“ის შესáƒáƒ®áƒ”ბ დáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ დით {contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -17763,8 +17480,8 @@ msgstr "მიმáƒáƒ თეთ ფინáƒáƒœáƒ¡áƒ£áƒ მხáƒáƒ დáƒáƒ #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} მთáƒáƒ•áƒáƒ ი გვერდი" @@ -17787,19 +17504,11 @@ msgstr "" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "სისტემური áƒáƒ“მინისტრáƒáƒ¢áƒáƒ ი" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "სáƒáƒ§áƒ˜áƒ“ლების კáƒáƒšáƒáƒ—ი" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "" @@ -17836,6 +17545,12 @@ msgstr "კუპáƒáƒœáƒ˜áƒ¡ კáƒáƒ“ის დáƒáƒ›áƒáƒ¢áƒ”ბáƒ" msgid "Enter information about the coupon code below." msgstr "ქვემáƒáƒ— შეიყვáƒáƒœáƒ”თ ინფáƒáƒ მáƒáƒªáƒ˜áƒ კუპáƒáƒœáƒ˜áƒ¡ კáƒáƒ“ზე." +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "კუპáƒáƒœáƒ˜áƒ¡ კáƒáƒ“ი" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "ფáƒáƒ¡áƒ“áƒáƒ™áƒšáƒ”ბის პრáƒáƒªáƒ”ნტი" @@ -18454,6 +18169,11 @@ msgstr "ჩáƒáƒ›áƒáƒ¢áƒ•áƒ˜áƒ თეთ კუპáƒáƒœáƒ˜áƒ¡ კáƒáƒ“ებ msgid "Coupon Codes" msgstr "კუპáƒáƒœáƒ˜áƒ¡ კáƒáƒ“ები" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "ვáƒáƒ“ის áƒáƒ›áƒáƒ¬áƒ£áƒ ვის თáƒáƒ იღი" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "კუპáƒáƒœáƒ˜ (%)" @@ -19823,6 +19543,10 @@ msgstr "áƒáƒ გáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡ შესყიდვáƒ" msgid "Purchase order number (if any)" msgstr "შესყიდვის შეკვეთის ნáƒáƒ›áƒ”რი (áƒáƒ¡áƒ”თის áƒáƒ სებáƒáƒ‘ის შემთხვევáƒáƒ¨áƒ˜)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "ელფáƒáƒ¡áƒ¢áƒ˜áƒ¡ მისáƒáƒ›áƒáƒ თი" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "email@example.com" @@ -20143,6 +19867,10 @@ msgid_plural "" msgstr[0] "{course_names} წáƒáƒ˜áƒ¨áƒáƒšáƒ რáƒáƒ“გáƒáƒœ ჩáƒáƒ იცხვის პერიáƒáƒ“ი დáƒáƒ˜áƒ®áƒ£áƒ áƒ." msgstr[1] "{course_names} წáƒáƒ˜áƒ¨áƒáƒšáƒ რáƒáƒ“გáƒáƒœ ჩáƒáƒ იცხვის პერიáƒáƒ“ი დáƒáƒ˜áƒ®áƒ£áƒ áƒ." +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "სáƒáƒ§áƒ˜áƒ“ლების კáƒáƒšáƒáƒ—ი" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "ყდის ფáƒáƒ¢áƒáƒ¡áƒ£áƒ áƒáƒ—ი" @@ -20229,12 +19957,8 @@ msgstr "დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებáƒ" #: lms/templates/static_templates/404.html msgid "" "The page that you were looking for was not found. Go back to the " -"{link_start}homepage{link_end} or let us know about any pages that may have " -"been moved at {email}." +"{link_start}homepage{link_end} ." msgstr "" -"გვერდი რáƒáƒ›áƒ”ლსáƒáƒª ეძებდით ვერმáƒáƒ˜áƒ«áƒ”ბნáƒ. დáƒáƒ£áƒ‘რუნდით {link_start}-ის მთáƒáƒ•áƒáƒ " -"გვერდს{link_end} áƒáƒœ გვáƒáƒªáƒœáƒáƒ‘ეთ ნებისმიერი გვერდის შესáƒáƒ®áƒ”ბ რáƒáƒ›áƒ”ლიც შესáƒáƒ«áƒšáƒáƒ " -"გáƒáƒ“áƒáƒ•áƒ˜áƒ“რ{email}-ზე." #: lms/templates/static_templates/about.html #: lms/templates/static_templates/blog.html @@ -20285,23 +20009,15 @@ msgstr "áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ {platform_name}-ის სერვერები #: lms/templates/static_templates/server-overloaded.html msgid "" "Our staff is currently working to get the site back up as soon as possible. " -"Please email us at {tech_support_email} to report any problems or downtime." msgstr "" -"ჩვენი პერსáƒáƒœáƒáƒšáƒ˜ áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ მუშáƒáƒáƒ‘ს რáƒáƒª შეიძლებრსწრáƒáƒ¤áƒáƒ“ მáƒáƒ˜áƒžáƒáƒ•áƒáƒ¡ სáƒáƒ˜áƒ¢áƒ˜áƒ¡ " -"მხáƒáƒ დáƒáƒáƒ”რáƒ. გთხáƒáƒ•áƒ—, შეგვáƒáƒ¢áƒ§áƒáƒ‘ინáƒáƒ— {tech_support_email}-ზე ნებისმიერ" -"პრáƒáƒ‘ლემáƒáƒ¡áƒ—áƒáƒœ áƒáƒœ ტექნიკურგáƒáƒ£áƒ›áƒáƒ თáƒáƒáƒ‘áƒáƒ¡áƒ—áƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ ებით." #: lms/templates/static_templates/server-error.html msgid "There has been a 500 error on the {platform_name} servers" msgstr " 500 შეცდáƒáƒ›áƒ დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრ{platform_name}-ის სერვერებზე" #: lms/templates/static_templates/server-error.html -msgid "" -"Please wait a few seconds and then reload the page. If the problem persists," -" please email us at {email}." +msgid "Please wait a few seconds and then reload the page." msgstr "" -"გთხáƒáƒ•áƒ—, დáƒáƒ”ლáƒáƒ“ეთ რáƒáƒ›áƒ“ენიმე წáƒáƒ›áƒ˜ დრგáƒáƒ“áƒáƒ¢áƒ•áƒ˜áƒ თეთ გვერდი. თუ პრáƒáƒ‘ლემრ" -"გáƒáƒœáƒ›áƒ”რáƒáƒ“áƒ, გთხáƒáƒ•áƒ— შეგვáƒáƒ¢áƒ§áƒáƒ‘ინეთ {email}-ზე." #: lms/templates/static_templates/server-overloaded.html msgid "Currently the {platform_name} servers are overloaded" @@ -20369,46 +20085,6 @@ msgstr "" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "áƒáƒ› შეკვეთის თáƒáƒœáƒ®áƒ˜áƒ¡ დáƒáƒ‘რუნებáƒ:" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "შეკვეთის Id:" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "ჩáƒáƒ იცხვáƒ:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "ჩáƒáƒ იცხული" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "áƒáƒ›áƒáƒ იცხული" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "ღირებულებáƒ:" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "სერტიფიკáƒáƒ¢áƒ˜áƒ¡ სტáƒáƒ¢áƒ£áƒ¡áƒ˜:" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "შეკვეთის სტáƒáƒ¢áƒ£áƒ¡áƒ˜:" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "დáƒáƒ¡áƒ ულებული დრáƒ:" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "დრáƒáƒ˜áƒ¡ áƒáƒœáƒáƒ–ღáƒáƒ£áƒ ების მáƒáƒ—ხáƒáƒ•áƒœáƒ:" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის კვლევრ" @@ -20561,11 +20237,8 @@ msgstr "ვინáƒáƒáƒ‘ის დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებáƒ" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" -"თქვენ უკვე გáƒáƒáƒ’ზáƒáƒ•áƒœáƒ”თ ინფáƒáƒ მáƒáƒªáƒ˜áƒ დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებáƒáƒ–ე. რáƒáƒ“ესáƒáƒª დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ების პრáƒáƒªáƒ”სი" -" დáƒáƒ¡áƒ ულდებáƒ, თქვენს მáƒáƒ თვის დáƒáƒ¤áƒáƒ–ე გáƒáƒ›áƒáƒ©áƒœáƒ“ებრშეტყáƒáƒ‘ინებრ(ჩვეულებრივ 1-2 " -"დღეში). " #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -20780,6 +20453,10 @@ msgstr "" msgid "Get started on what's next: " msgstr "" +#: openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html +msgid "Show More" +msgstr "" + #: openedx/features/course_search/templates/course_search/course-search-fragment.html msgid "Search Results" msgstr "" @@ -21247,12 +20924,8 @@ msgid "The page that you were looking for was not found." msgstr "გვერდი, რáƒáƒ›áƒ”ლსáƒáƒª ეძებდით, ვერმáƒáƒ˜áƒ«áƒ”ბნáƒ." #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" -"დáƒáƒ‘რუნდით {homepage}-ზე áƒáƒœ გვáƒáƒªáƒœáƒáƒ‘ეთ ნებისმიერი გვერდის შესáƒáƒ®áƒ”ბ, რáƒáƒ›áƒ”ლიც " -"გáƒáƒ“áƒáƒáƒ“გილებულირ{email}-ზე." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -21278,12 +20951,6 @@ msgstr "" "შეცდáƒáƒ›áƒ áƒáƒ¦áƒ იცხულიáƒ. ჩვენი თáƒáƒœáƒáƒ›áƒ¨áƒ áƒáƒ›áƒšáƒ”ბი მის შეძლებისდáƒáƒ’ვáƒáƒ áƒáƒ“ მáƒáƒ™áƒšáƒ” დრáƒáƒ¨áƒ˜ " "áƒáƒ¦áƒ›áƒáƒ¤áƒ®áƒ•áƒ áƒáƒ–ე მუშáƒáƒáƒ‘ენ." -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "" -"პრáƒáƒ‘ლემის გáƒáƒœáƒ›áƒ”áƒáƒ ების შემთხვევáƒáƒ¨áƒ˜, გთხáƒáƒ•áƒ—, დáƒáƒ’ვიკáƒáƒ•áƒ¨áƒ˜áƒ დეთ ელფáƒáƒ¡áƒ¢áƒáƒ–ე " -"{email_link}." - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "" @@ -21973,14 +21640,8 @@ msgstr "თქვენს მიერმáƒáƒ—ხáƒáƒ•áƒœáƒ˜áƒšáƒ˜ გვე #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" -"ვწუხვáƒáƒ თ, გვერდი {studio_name}, რáƒáƒ›áƒ”ლსáƒáƒª ეძებთ, ვერმáƒáƒ˜áƒ«áƒ”ბნáƒ. შესáƒáƒ«áƒšáƒáƒ, " -"გსურთ დáƒáƒ‘რუნდეთ {studio_name}-ის მáƒáƒ თვის პáƒáƒœáƒ”ლზე დრხელáƒáƒ®áƒšáƒ სცáƒáƒ“áƒáƒ—. წვდáƒáƒ›áƒáƒ–ე" -" პრáƒáƒ‘ლემის გáƒáƒœáƒ›áƒ”áƒáƒ ების შემთხვევáƒáƒ¨áƒ˜, გთხáƒáƒ•áƒ— {link_start}დáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ დით " -"{studio_name} მხáƒáƒ დáƒáƒáƒ”რის გუნდს{link_end} დრáƒáƒ¦áƒ›áƒáƒ’იჩენთ დáƒáƒ®áƒ›áƒáƒ ებáƒáƒ¡." #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -21990,15 +21651,8 @@ msgstr "დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრსერვერის შეცდრmsgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" -"ვწუხვáƒáƒ თ, სერვერზე წáƒáƒ მáƒáƒ¥áƒ›áƒœáƒ˜áƒšáƒ˜ პრáƒáƒ‘ლემის გáƒáƒ›áƒ თქვენი ბáƒáƒšáƒ მáƒáƒ—ხáƒáƒ•áƒœáƒ˜áƒ¡ " -"დáƒáƒ›áƒ£áƒ¨áƒáƒ•áƒ”ბრვერმáƒáƒ®áƒ”რხდáƒ. შესáƒáƒ«áƒšáƒáƒ თქვენ გსურთ {studio_name}-ის მáƒáƒ თვის " -"პáƒáƒœáƒ”ლში დáƒáƒ‘რუნებრáƒáƒœ თქვენი მáƒáƒ—ხáƒáƒ•áƒœáƒ˜áƒ¡ გáƒáƒ›áƒ”áƒáƒ ებáƒ. წვდáƒáƒ›áƒáƒ–ე პრáƒáƒ‘ლემის " -"გáƒáƒ›áƒ”áƒáƒ ების შემთხვევáƒáƒ¨áƒ˜, გთხáƒáƒ•áƒ— {link_start}დუკáƒáƒ•áƒ¨áƒ˜áƒ დეთ {studio_name} " -"მხáƒáƒ დáƒáƒáƒ”რის გუნდს{link_end}." #: cms/templates/error.html msgid "Back to dashboard" @@ -25320,8 +24974,8 @@ msgstr "%(file)s შეიცვáƒáƒšáƒ გáƒáƒœáƒáƒ®áƒšáƒ”ბული ვ msgid "%(file)s has been saved." msgstr "%(file)s შენáƒáƒ®áƒ£áƒšáƒ˜áƒ." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "გáƒáƒ›áƒáƒ¡áƒáƒ®áƒ£áƒšáƒ”ბები" @@ -25514,8 +25168,8 @@ msgstr "" msgid "Search..." msgstr "" -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "" diff --git a/conf/locale/ka/LC_MESSAGES/djangojs.mo b/conf/locale/ka/LC_MESSAGES/djangojs.mo index eec1d7ab5c56f238bb849d8913f51203768fa9f5..a6cc4222ba7d6cad1f6c6f8334dd87c020fb8704 100644 Binary files a/conf/locale/ka/LC_MESSAGES/djangojs.mo and b/conf/locale/ka/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/ka/LC_MESSAGES/djangojs.po b/conf/locale/ka/LC_MESSAGES/djangojs.po index ad1b4902806c7b5612085a3c709569a1cbea1221..424375eca8796642e32e2ec3856162ec9d36857b 100644 --- a/conf/locale/ka/LC_MESSAGES/djangojs.po +++ b/conf/locale/ka/LC_MESSAGES/djangojs.po @@ -56,8 +56,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-05 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Georgian (http://www.transifex.com/open-edx/edx-platform/language/ka/)\n" "Language: ka\n" @@ -65,7 +65,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -114,6 +114,7 @@ msgstr "წáƒáƒ¨áƒšáƒ" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -136,6 +137,7 @@ msgstr "áƒáƒ¢áƒ•áƒ˜áƒ თვáƒ" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -160,6 +162,7 @@ msgstr "ფáƒáƒ˜áƒšáƒ˜áƒ¡ áƒáƒ ჩევáƒ" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "დიáƒáƒ®" @@ -721,7 +724,6 @@ msgstr "" #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "áƒáƒ¦áƒ¬áƒ”რáƒ" @@ -768,6 +770,7 @@ msgstr "" #: cms/templates/js/show-textbook.underscore #: cms/templates/js/signatory-details.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Edit" msgstr "" @@ -1162,6 +1165,7 @@ msgstr "" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "მáƒáƒ›áƒ“ევნáƒ" @@ -1495,6 +1499,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/course-instructor-details.underscore #: cms/templates/js/signatory-details.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Title" msgstr "" @@ -2384,7 +2389,15 @@ msgid "Other" msgstr "სხვáƒ" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx @@ -2392,20 +2405,23 @@ msgid "Details" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "გáƒáƒ’ზáƒáƒ•áƒœáƒ" +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2422,6 +2438,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2445,7 +2473,8 @@ msgstr "" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2628,6 +2657,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრშეცდáƒáƒ›áƒ. კიდევ სცáƒáƒ“ეთ." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "ტáƒáƒ•áƒ”ბთ áƒáƒ› გუნდს?" @@ -3139,6 +3172,7 @@ msgid "There has been an error processing your survey." msgstr "თქვენი კვლევის დáƒáƒ›áƒ£áƒ¨áƒáƒ•áƒ”ბისáƒáƒ¡ მáƒáƒ®áƒ“რშეცდáƒáƒ›áƒ." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -3155,6 +3189,7 @@ msgid "HTML preview of post" msgstr "" #: lms/static/js/customwmd.js +#: common/static/common/templates/discussion/templates.underscore msgid "Your question or idea (required)" msgstr "" @@ -5147,6 +5182,16 @@ msgstr "ყველáƒáƒ¡ გáƒáƒ®áƒ¡áƒœáƒ" msgid "Collapse All" msgstr "ყველáƒáƒ¡ áƒáƒ™áƒ”ცვáƒ" +#: openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show More" +msgstr "" + +#: openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js +#: lms/templates/courseware/proctored-exam-status.underscore +msgid "Show Less" +msgstr "" + #: openedx/features/course_search/static/course_search/js/views/search_results_view.js msgid "{total_results} result" msgid_plural "{total_results} results" @@ -5289,6 +5334,10 @@ msgstr "დიáƒáƒ®, áƒáƒ¥áƒ¢áƒ˜áƒ£áƒ სერტიფიკáƒáƒ¢áƒ–ე msgid "certificate" msgstr "სერტიფიკáƒáƒ¢áƒ˜" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "სერტიფიკáƒáƒ¢áƒ˜áƒ¡ მáƒáƒ›áƒ–áƒáƒ“ებáƒ" @@ -5300,8 +5349,8 @@ msgid "You have not created any certificates yet." msgstr "ჯერჯერáƒáƒ‘ით სერტიფიკáƒáƒ¢áƒ˜ áƒáƒ შეგიქმნიáƒáƒ—." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "áƒáƒ›áƒáƒ˜áƒ¦áƒ”თ <%= signatoryName %>\" ხელმáƒáƒ›áƒ¬áƒ”რთრსიიდáƒáƒœ?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5611,8 +5660,8 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -5791,7 +5840,7 @@ msgid "{selectedProvider} credentials saved" msgstr "" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" msgstr "" #: cms/static/js/views/edit_chapter.js @@ -6360,18 +6409,14 @@ msgstr "" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" -"áƒáƒ გáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡, კურსის ნáƒáƒ›áƒ ისრდრკურსის მსვლელáƒáƒ‘ის ველის სáƒáƒ”რთრსიგრძე ვერ" -"იქნებრ<%=limit%> სიმბáƒáƒšáƒáƒ–ე მეტი." #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" -"áƒáƒ გáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡áƒ დრბიბლიáƒáƒ—ეკის კáƒáƒ“ის ველის სáƒáƒ”რთრსიგრძე áƒáƒ უნდრáƒáƒ¦áƒ”მáƒáƒ¢áƒ”ბáƒáƒ“ეს " -"<%=limit%> სიმბáƒáƒšáƒáƒ¡." #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -6710,13 +6755,13 @@ msgid "Unscheduled" msgstr "გáƒáƒ¨áƒ•áƒ”ბის თáƒáƒ იღი მითითებული áƒáƒ áƒáƒ" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "თáƒáƒ იღი" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "წინáƒ" @@ -6764,6 +6809,310 @@ msgstr "სáƒáƒ«áƒ˜áƒ”ბრველის გáƒáƒ¬áƒ›áƒ”ნდáƒ" msgid "Search" msgstr "ძიებáƒ" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "გáƒáƒ’ზáƒáƒ•áƒœáƒ" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "დისკუსიის მთáƒáƒ•áƒáƒ ი გვერდი" @@ -6823,10 +7172,6 @@ msgstr "" " მიერმიდევნებულ თემებში áƒáƒ®áƒáƒš კáƒáƒ›áƒ”ნტáƒáƒ ებსრდრწáƒáƒ£áƒ™áƒ˜áƒ—ხáƒáƒ• შეტყáƒáƒ‘ინებებს " "გáƒáƒ”ცნáƒáƒ‘ით." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის სáƒáƒ®áƒ”ლი áƒáƒœ ელფáƒáƒ¡áƒ¢áƒ" @@ -7067,6 +7412,10 @@ msgstr "" msgid "Join Team" msgstr "გუნდში გáƒáƒ¬áƒ”ვრიáƒáƒœáƒ”ბáƒ" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "გუნდის დეტáƒáƒšáƒ”ბი" @@ -7153,105 +7502,6 @@ msgstr "áƒáƒ›áƒáƒ˜áƒ¦áƒ”თ ქვეგáƒáƒœáƒ§áƒáƒ¤áƒ˜áƒšáƒ”ბრ%(subse msgid "Remove unit %(unitName)s" msgstr "წáƒáƒ¨áƒáƒšáƒ”თ მáƒáƒ“ული %(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" -"კრედიტების áƒáƒ¡áƒáƒ¦áƒ”ბáƒáƒ“, თქვენ მáƒáƒ˜áƒœáƒª გáƒáƒ˜áƒ დებáƒáƒ— %(display_name)s ვებ-სáƒáƒ˜áƒ¢áƒ˜áƒ¡ " -"მáƒáƒœáƒáƒ®áƒ£áƒšáƒ”ბáƒ." - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"კურსის კრედიტების მáƒáƒ¡áƒáƒžáƒáƒ•áƒ”ბლáƒáƒ“, %(display_name)s ითხáƒáƒ•áƒ¡, რáƒáƒ› " -"%(platform_name)s მსმენელებმრკრედიტის მáƒáƒ—ხáƒáƒ•áƒœáƒ გáƒáƒ’ზáƒáƒ•áƒœáƒáƒœ." - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "კრედიტის მიღებáƒ" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" -"მáƒáƒ“ლáƒáƒ‘რ%(full_name)s! ჩვენ მივიღეთ თქვენი გáƒáƒ“áƒáƒ®áƒ“რკურსისთვის " -"„%(course_name)s“." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"გთხáƒáƒ•áƒ— áƒáƒ›áƒáƒ‘ეáƒáƒ“áƒáƒ— თქვენი ჩáƒáƒœáƒáƒ¬áƒ”რების ეს გვერდი. ის áƒáƒ¡áƒ ულებს ქვითრის ფუნქციáƒáƒ¡." -" თქვენ áƒáƒ¡áƒ”ვე მიიღებთ ელფáƒáƒ¡áƒ¢áƒ˜áƒ¡ შეტყáƒáƒ‘ინებáƒáƒ¡ იგივე ინფáƒáƒ მáƒáƒªáƒ˜áƒ˜áƒ—." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "შეკვეთის ნáƒáƒ›áƒ”რი" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "რáƒáƒáƒ“ენáƒáƒ‘áƒ" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "სულ" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "გთხáƒáƒ•áƒ—, გáƒáƒ˜áƒ—ვáƒáƒšáƒ˜áƒ¡áƒ¬áƒ˜áƒœáƒáƒ—" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "გáƒáƒ“áƒáƒ®áƒáƒ–ულ ერთეულებში გáƒáƒ“áƒáƒ®áƒ“ილი თáƒáƒœáƒ®áƒ დáƒáƒ‘რუნებულიáƒ." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "გáƒáƒ“áƒáƒ”რიცხáƒ" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "ქვითáƒáƒ ი ხელმისáƒáƒ¬áƒ•áƒ“áƒáƒ›áƒ˜ áƒáƒ áƒáƒ ის" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "სáƒáƒ›áƒ£áƒ¨áƒáƒ დáƒáƒ¤áƒáƒ–ე დáƒáƒ‘რუნებáƒ" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" -"თუ თქვენ áƒáƒ დáƒáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებთ თქვენს ვინáƒáƒáƒ‘áƒáƒ¡, მáƒáƒ˜áƒœáƒª შეძლებთ კურსის მáƒáƒ«áƒ˜áƒ”ბáƒáƒ¡ " -"სáƒáƒ›áƒ£áƒ¨áƒáƒ დáƒáƒ¤áƒáƒ–ე. პერიáƒáƒ“ულáƒáƒ“ თქვენ მიიღებთ შეხსენებáƒáƒ¡, რáƒáƒ› {platformName} " -"ითხáƒáƒ•áƒ¡ პირáƒáƒ•áƒœáƒ”ბის იდენტიფიკáƒáƒªáƒ˜áƒáƒ¡." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "გსურთ, თქვენი პირáƒáƒ•áƒœáƒ”ბრმáƒáƒ’ვიáƒáƒœáƒ”ბით დáƒáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒáƒ—?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებáƒ" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "ყველრგáƒáƒ›áƒáƒªáƒ“ის დáƒáƒ¡áƒ ულებულáƒáƒ“ მáƒáƒœáƒ˜áƒ¨áƒ•áƒœáƒ" @@ -7276,14 +7526,6 @@ msgstr "" "áƒáƒ›áƒáƒªáƒáƒœáƒ”ბში კრდიტების მისáƒáƒ¦áƒ”ბáƒáƒ“, უნდრáƒáƒ˜áƒ ჩიáƒáƒ— „გáƒáƒ’ზáƒáƒ•áƒœáƒâ€œ ყáƒáƒ•áƒ”ლი სáƒáƒ™áƒ˜áƒ—ხისთვის," " ვიდრე „ჩემი გáƒáƒ›áƒáƒªáƒ“ის დáƒáƒ¡áƒ ულებáƒáƒ¡â€œ áƒáƒ˜áƒ ჩევთ." -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show More" -msgstr "" - -#: lms/templates/courseware/proctored-exam-status.underscore -msgid "Show Less" -msgstr "" - #: lms/templates/courseware/proctored-exam-status.underscore msgid "Exam timer and end exam button" msgstr "" @@ -7389,10 +7631,8 @@ msgstr "თქვენ შესáƒáƒ®áƒ”ბ" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" -"შემდეგი ინფáƒáƒ მáƒáƒªáƒ˜áƒ უკვე áƒáƒ ის თქვენი {platform} პრáƒáƒ¤áƒ˜áƒšáƒ˜áƒ¡ ნáƒáƒ¬áƒ˜áƒšáƒ˜. ჩვენ უკვე " -"შევიტáƒáƒœáƒ”თ ის თქვენს áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒáƒ¨áƒ˜." #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7422,6 +7662,10 @@ msgstr "" "გმáƒáƒ“ლáƒáƒ‘თ, რáƒáƒ› გáƒáƒ’ზáƒáƒ•áƒœáƒ”თ ფინáƒáƒœáƒ¡áƒ£áƒ ი დáƒáƒ®áƒ›áƒáƒ ების áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ {course_name} " "კურსისთვის! პáƒáƒ¡áƒ£áƒ®áƒ¡ 2-4 სáƒáƒ›áƒ£áƒ¨áƒáƒ დღის გáƒáƒœáƒ›áƒáƒ•áƒšáƒáƒ‘áƒáƒ¨áƒ˜ მიიღებთ." +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "სáƒáƒ›áƒ£áƒ¨áƒáƒ დáƒáƒ¤áƒáƒ–ე დáƒáƒ‘რუნებáƒ" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "მთელი რიგი გáƒáƒ›áƒáƒœáƒáƒ™áƒšáƒ˜áƒ¡áƒ”ბი" @@ -7781,14 +8025,6 @@ msgstr "" msgid "You can change sessions until {expiration_date}." msgstr "" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "დáƒáƒáƒ ქივებული კურსის ნáƒáƒ®áƒ•áƒ" @@ -8006,7 +8242,27 @@ msgid "An error occurred. Please reload the page." msgstr "დáƒáƒ¤áƒ˜áƒ¥áƒ¡áƒ˜áƒ დრშეცდáƒáƒ›áƒ. გთხáƒáƒ•áƒ— გáƒáƒ“áƒáƒ¢áƒ•áƒ˜áƒ თáƒáƒ— გვერდი." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -8216,17 +8472,13 @@ msgid "What You Need for Verification" msgstr "რრáƒáƒ ის სáƒáƒáƒ˜áƒ რდáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებისთვის" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "ვერბკáƒáƒ›áƒ”რáƒ" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8234,12 +8486,8 @@ msgid "Photo Identification" msgstr "ფáƒáƒ¢áƒáƒ¡ იდენტიფიცირებáƒ" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"დáƒáƒ’áƒáƒ˜áƒ დებáƒáƒ— მáƒáƒ თვის მáƒáƒ¬áƒ›áƒáƒ‘áƒ, პáƒáƒ¡áƒžáƒáƒ ტი, áƒáƒœ სáƒáƒ®áƒ”ლმწიფáƒáƒ¡ მიერგáƒáƒªáƒ”მული " -"პირáƒáƒ“áƒáƒ‘ის მáƒáƒ¬áƒ›áƒáƒ‘áƒ, რáƒáƒ›áƒ”ლშიც მითითებული იქნებრთქვენი სáƒáƒ®áƒ”ლი დრფáƒáƒ¢áƒ." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8264,14 +8512,10 @@ msgstr "თქვენი სáƒáƒ®áƒ” კáƒáƒ გáƒáƒ“ áƒáƒ ის გრmsgid "Your entire face fits inside the frame." msgstr "თქვენი სáƒáƒ®áƒ” ჩáƒáƒ ჩáƒáƒ¨áƒ˜ სრულáƒáƒ“ ჩáƒáƒœáƒ¡." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "თქვენი ფáƒáƒ¢áƒ ემთხვევრპირáƒáƒ“áƒáƒ‘ის მáƒáƒ¬áƒ›áƒáƒ‘ის ფáƒáƒ¢áƒáƒ¡." - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8288,17 +8532,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "რისთვის სáƒáƒ˜áƒ დებრ%(platformName)s-ს ჩემი ფáƒáƒ¢áƒ?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"რáƒáƒ’áƒáƒ ც პირáƒáƒ•áƒœáƒ”ბის დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ების პრáƒáƒªáƒ”სის ნáƒáƒ¬áƒ˜áƒšáƒ˜, თქვენ იღებთ რáƒáƒ’áƒáƒ ც სáƒáƒ™áƒ£áƒ—áƒáƒ " -"პáƒáƒ ტრეტს, áƒáƒ¡áƒ”ვე სáƒáƒ®áƒ”ლმწიფრუწყებების გáƒáƒªáƒ”მულ ფáƒáƒ¢áƒáƒ¡áƒ£áƒ áƒáƒ—იáƒáƒœ დáƒáƒ™áƒ£áƒ›áƒ”ნტს. ჩვენი " -"áƒáƒ•áƒ¢áƒáƒ იზáƒáƒªáƒ˜áƒ˜áƒ¡ სერვისი პირáƒáƒ•áƒœáƒ”ბის დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებáƒáƒ¡ გáƒáƒ“áƒáƒ¦áƒ”ბული ფáƒáƒ¢áƒáƒ¡áƒ დრპირáƒáƒ“áƒáƒ‘ის " -"დáƒáƒ›áƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებელი მáƒáƒ¬áƒ›áƒáƒ‘ის ფáƒáƒ¢áƒáƒ¡ შედáƒáƒ ებით áƒáƒ®áƒ“ენს." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8309,18 +8546,12 @@ msgstr "რáƒáƒ¡ უკეთებს %(platformName)s áƒáƒ› ფáƒáƒ¢áƒáƒ” #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"ჩვენ ვიყენებთ უსáƒáƒ¤áƒ თხáƒáƒ”ბის უმáƒáƒ¦áƒšáƒ”ს დáƒáƒœáƒ”ს, რáƒáƒ›áƒ”ლიც დáƒáƒ¨áƒ˜áƒ¤áƒ áƒáƒ•áƒ¡ თქვენს ფáƒáƒ¢áƒáƒ¡ დრ" -"ჩვენ áƒáƒ•áƒ¢áƒáƒ იზáƒáƒªáƒ˜áƒ˜áƒ¡ სერვისში გáƒáƒœáƒ¡áƒáƒ®áƒ˜áƒšáƒ•áƒ”ლáƒáƒ“ გáƒáƒ“áƒáƒ’ზáƒáƒ•áƒœáƒ˜áƒ¡. თქვენი ფáƒáƒ¢áƒ დრ" -"ინფáƒáƒ მáƒáƒªáƒ˜áƒ áƒáƒ შეინáƒáƒ®áƒ”ბრდრდáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ების პრáƒáƒªáƒ”დურის დáƒáƒ¡áƒ ულების შემდეგ " -"%(platformName)s-ზე áƒáƒ სáƒáƒ“ გáƒáƒ›áƒáƒ©áƒœáƒ“ებáƒ." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8379,21 +8610,14 @@ msgid "Take a Photo of Your ID" msgstr "გáƒáƒ“áƒáƒ£áƒ¦áƒ”თ ფáƒáƒ¢áƒ თქვენს პირáƒáƒ“áƒáƒ‘ის მáƒáƒ¬áƒ›áƒáƒ‘áƒáƒ¡" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"პირáƒáƒ“áƒáƒ‘ის მáƒáƒ¬áƒ›áƒáƒ‘ის ფáƒáƒ¢áƒáƒ¡ გáƒáƒ“áƒáƒ¡áƒáƒ¦áƒ”ბáƒáƒ“ გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნეთ თქვენი ვებკáƒáƒ›áƒ”რáƒ. ჩვენ მáƒáƒ¡ " -"თქვენს სáƒáƒ®áƒ”ლსრდრთქვენს áƒáƒœáƒ’áƒáƒ იშში მითითებულ სáƒáƒ®áƒ”ლს შევáƒáƒ“áƒáƒ ებთ." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"თქვენ დáƒáƒ’áƒáƒ˜áƒ დებáƒáƒ— პირáƒáƒ“áƒáƒ‘ის მáƒáƒ¬áƒ›áƒáƒ‘áƒ, რáƒáƒ›áƒ”ლშიც მითითებულირთქვენი სáƒáƒ®áƒ”ლი დრ" -"ფáƒáƒ¢áƒ. მისáƒáƒ¦áƒ”ბირსáƒáƒ®áƒ”ლმწიფრუწყებების გáƒáƒªáƒ”მული ნებისმიერი სáƒáƒ‘უთი. მáƒáƒ— შáƒáƒ ის " -"მáƒáƒ თვის მáƒáƒ¬áƒ›áƒáƒ‘áƒ, პáƒáƒ¡áƒžáƒáƒ ტი დრსხვáƒ." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8419,6 +8643,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8469,6 +8700,30 @@ msgstr "" "შეიძლებრშევáƒáƒ“áƒáƒ áƒáƒ— თქვენი გáƒáƒ“áƒáƒ¦áƒ”ბული ფáƒáƒ¢áƒ თქვენ პირáƒáƒ“áƒáƒ‘ის მáƒáƒ¬áƒ›áƒáƒ‘áƒáƒ–ე áƒáƒ სებულ " "ფáƒáƒ¢áƒáƒ¡?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"რáƒáƒ’áƒáƒ ც პირáƒáƒ•áƒœáƒ”ბის დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ების პრáƒáƒªáƒ”სის ნáƒáƒ¬áƒ˜áƒšáƒ˜, თქვენ იღებთ რáƒáƒ’áƒáƒ ც სáƒáƒ™áƒ£áƒ—áƒáƒ " +"პáƒáƒ ტრეტს, áƒáƒ¡áƒ”ვე სáƒáƒ®áƒ”ლმწიფრუწყებების გáƒáƒªáƒ”მულ ფáƒáƒ¢áƒáƒ¡áƒ£áƒ áƒáƒ—იáƒáƒœ დáƒáƒ™áƒ£áƒ›áƒ”ნტს. ჩვენი " +"áƒáƒ•áƒ¢áƒáƒ იზáƒáƒªáƒ˜áƒ˜áƒ¡ სერვისი პირáƒáƒ•áƒœáƒ”ბის დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებáƒáƒ¡ გáƒáƒ“áƒáƒ¦áƒ”ბული ფáƒáƒ¢áƒáƒ¡áƒ დრპირáƒáƒ“áƒáƒ‘ის " +"დáƒáƒ›áƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებელი მáƒáƒ¬áƒ›áƒáƒ‘ის ფáƒáƒ¢áƒáƒ¡ შედáƒáƒ ებით áƒáƒ®áƒ“ენს." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"ჩვენ ვიყენებთ უსáƒáƒ¤áƒ თხáƒáƒ”ბის უმáƒáƒ¦áƒšáƒ”ს დáƒáƒœáƒ”ს, რáƒáƒ›áƒ”ლიც დáƒáƒ¨áƒ˜áƒ¤áƒ áƒáƒ•áƒ¡ თქვენს ფáƒáƒ¢áƒáƒ¡ დრ" +"ჩვენ áƒáƒ•áƒ¢áƒáƒ იზáƒáƒªáƒ˜áƒ˜áƒ¡ სერვისში გáƒáƒœáƒ¡áƒáƒ®áƒ˜áƒšáƒ•áƒ”ლáƒáƒ“ გáƒáƒ“áƒáƒ’ზáƒáƒ•áƒœáƒ˜áƒ¡. თქვენი ფáƒáƒ¢áƒ დრ" +"ინფáƒáƒ მáƒáƒªáƒ˜áƒ áƒáƒ შეინáƒáƒ®áƒ”ბრდრდáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ების პრáƒáƒªáƒ”დურის დáƒáƒ¡áƒ ულების შემდეგ " +"%(platformName)s-ზე áƒáƒ სáƒáƒ“ გáƒáƒ›áƒáƒ©áƒœáƒ“ებáƒ." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -8504,6 +8759,13 @@ msgstr "" "მáƒáƒ თვის მáƒáƒ¬áƒ›áƒáƒ‘áƒ, პáƒáƒ¡áƒžáƒáƒ ტი, áƒáƒœ სáƒáƒ®áƒ”ლმწიფáƒáƒ¡ გáƒáƒªáƒ”მული პირáƒáƒ“áƒáƒ‘ის დáƒáƒ›áƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებელი" " სáƒáƒ‘უთი თქვენი სáƒáƒ®áƒ”ლითრდრფáƒáƒ¢áƒáƒ¡áƒ£áƒ áƒáƒ—ით" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "ვერბკáƒáƒ›áƒ”რáƒ" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8608,6 +8870,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒªáƒ˜áƒ˜áƒ¡ შეტყáƒáƒ‘ინების სáƒáƒœáƒáƒ®áƒáƒ•áƒáƒ“ გáƒáƒ“áƒáƒáƒ›áƒáƒ¬áƒ›áƒ”თ თქვენი ელფáƒáƒ¡áƒ¢áƒ." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "სულ" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "„{courseName}“ კურსის პრáƒáƒ¤áƒ”სიული სერთიფიკáƒáƒ¢áƒ˜" @@ -8653,6 +8920,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "გმáƒáƒ“ლáƒáƒ‘თ! ჩვენ მივიღეთ თქვენი გáƒáƒ“áƒáƒ®áƒ“რკურსისთვის: {courseName}." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"გთხáƒáƒ•áƒ— áƒáƒ›áƒáƒ‘ეáƒáƒ“áƒáƒ— თქვენი ჩáƒáƒœáƒáƒ¬áƒ”რების ეს გვერდი. ის áƒáƒ¡áƒ ულებს ქვითრის ფუნქციáƒáƒ¡." +" თქვენ áƒáƒ¡áƒ”ვე მიიღებთ ელფáƒáƒ¡áƒ¢áƒ˜áƒ¡ შეტყáƒáƒ‘ინებáƒáƒ¡ იგივე ინფáƒáƒ მáƒáƒªáƒ˜áƒ˜áƒ—." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "შეკვეთის ნáƒáƒ›áƒ”რი" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "რáƒáƒáƒ“ენáƒáƒ‘áƒ" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "გთხáƒáƒ•áƒ—, გáƒáƒ˜áƒ—ვáƒáƒšáƒ˜áƒ¡áƒ¬áƒ˜áƒœáƒáƒ—" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "გáƒáƒ“áƒáƒ®áƒáƒ–ულ ერთეულებში გáƒáƒ“áƒáƒ®áƒ“ილი თáƒáƒœáƒ®áƒ დáƒáƒ‘რუნებულიáƒ." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "გáƒáƒ“áƒáƒ”რიცხáƒ" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "ქვითáƒáƒ ი ხელმისáƒáƒ¬áƒ•áƒ“áƒáƒ›áƒ˜ áƒáƒ áƒáƒ ის" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "შემდეგი სáƒáƒ¤áƒ”ხური: თქვენი პირáƒáƒ•áƒœáƒ”ბის დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებáƒ" @@ -8688,6 +8987,10 @@ msgstr "" "სáƒáƒ›áƒ£áƒ¨áƒáƒ დáƒáƒ¤áƒáƒ–ე. პერიáƒáƒ“ულáƒáƒ“ თქვენ მიიღებთ შეხსენებáƒáƒ¡, რáƒáƒ› %(platformName)s " "ითხáƒáƒ•áƒ¡ პირáƒáƒ•áƒœáƒ”ბის იდენტიფიკáƒáƒªáƒ˜áƒáƒ¡." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "გსურთ, თქვენი პირáƒáƒ•áƒœáƒ”ბრმáƒáƒ’ვიáƒáƒœáƒ”ბით დáƒáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒáƒ—?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "მიმდინáƒáƒ ეáƒáƒ‘ს ვინáƒáƒáƒ‘ის გáƒáƒ“áƒáƒ›áƒáƒ¬áƒ›áƒ”ბáƒ" @@ -8696,13 +8999,9 @@ msgstr "მიმდინáƒáƒ ეáƒáƒ‘ს ვინáƒáƒáƒ‘ის გáƒáƒ“ msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"ჩვენ მივიღეთ თქვენი ინფáƒáƒ მáƒáƒªáƒ˜áƒ დრვáƒáƒ®áƒ“ენთ თქვენი ვინáƒáƒáƒ‘ის დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ ებáƒáƒ¡. " -"გáƒáƒ“áƒáƒ›áƒáƒ¬áƒ›áƒ”ბის პრáƒáƒªáƒ”სის დáƒáƒ¡áƒ ულების შემდეგ, სáƒáƒ›áƒáƒ თáƒáƒ• დáƒáƒ¤áƒáƒ–ე შეტყáƒáƒ‘ინებრ" -"გáƒáƒ›áƒáƒ©áƒœáƒ“ებრ(ჩეულებრივ 1-2 დღეში). მáƒáƒœáƒáƒ›áƒ“ე კი, თქვენ კვლáƒáƒ• გექნებáƒáƒ— წვდáƒáƒ›áƒ " -"კურსის ყველრმáƒáƒ¡áƒáƒšáƒáƒ–ე." #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -8738,10 +9037,6 @@ msgstr "ფáƒáƒ¢áƒáƒ¡ მáƒáƒ®áƒáƒ•áƒœáƒ”ბი:" msgid "Does the photo of you show your whole face?" msgstr "ჩáƒáƒœáƒ¡ თუ áƒáƒ რფáƒáƒ¢áƒáƒ–ე თქვენი სáƒáƒ®áƒ” სრულáƒáƒ“?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "ემთხვევრთუ áƒáƒ რთქვენი ფáƒáƒ¢áƒ თქვენი ID-ის ფáƒáƒ¢áƒáƒ¡." - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "იკითხებრთუ áƒáƒ რთქვენს ID-ზე áƒáƒ სებული სáƒáƒ®áƒ”ლი ?" @@ -10215,6 +10510,21 @@ msgstr "სპეციáƒáƒšáƒ£áƒ გáƒáƒ›áƒáƒªáƒ“áƒáƒ“ დáƒáƒ§áƒ”ნე msgid "Exam Types" msgstr "გáƒáƒ›áƒáƒªáƒ“ის ტიპები" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "დრáƒáƒ˜áƒ—ი" @@ -10402,11 +10712,11 @@ msgid "Read more" msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" +msgid "No transcript uploaded." msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "No transcript uploaded." +msgid "Show transcripts ({totalTranscripts})" msgstr "" #: cms/templates/js/xblock-access-editor.underscore diff --git a/conf/locale/pl/LC_MESSAGES/django.mo b/conf/locale/pl/LC_MESSAGES/django.mo index 14b8cdb50bdf649de4c9b3be67dc6953ae42281e..ef9b384c38c63941b20822fbcee4c3e4d378178b 100644 Binary files a/conf/locale/pl/LC_MESSAGES/django.mo and b/conf/locale/pl/LC_MESSAGES/django.mo differ diff --git a/conf/locale/pl/LC_MESSAGES/django.po b/conf/locale/pl/LC_MESSAGES/django.po index 275519eff216de028bee2b0fdb4d0d4124d5c4ad..5ec4adad1741085886a2c9b50fb944363284cdcd 100644 --- a/conf/locale/pl/LC_MESSAGES/django.po +++ b/conf/locale/pl/LC_MESSAGES/django.po @@ -21,7 +21,7 @@ # Michael Drozd <michael.alex.drozd@gmail.com>, 2016 # MichaÅ‚ KoÅ‚odziej <M.Kolodziej@stud.elka.pw.edu.pl>, 2016 # MichaÅ‚ Szkutnik <michal7x7@o2.pl>, 2015 -# Cairath, 2014 +# 2cdc55bf3a20ff25d939c7db7de19147_3ae98f5, 2014 # Ned Batchelder <ned@edx.org>, 2017 # PaweÅ‚ Marchewka <mamior@o2.pl>, 2014 # Radek <d.exax@hotmail.com>, 2015 @@ -61,15 +61,15 @@ # Jaroslaw Lukawski <sekretariat@kmti.uz.zgora.pl>, 2014 # Kamil Magryta <gryxon@gmail.com>, 2015 # Jaroslaw Lukawski <sekretariat@kmti.uz.zgora.pl>, 2014 -# Lazarus Zamenhof <inactive+lazarus_zamenhof@transifex.com>, 2014 +# a64592d83cf839ec74a351ae18cc2d2e_cee44e9 <56b7ddfd39a966524c1a849ff758782f_139437>, 2014 # lucek <lucjan.kierczak@gmail.com>, 2014 # Magdalena JarosiÅ„ska <m.jarosinska@stud.elka.pw.edu.pl>, 2015 # mateusz2238 <mateusz2238@outlook.com>, 2014 # Mateusz <blue90pl@gmail.com>, 2014 # MichaÅ‚ Szkutnik <michal7x7@o2.pl>, 2015 -# Cairath, 2014 +# 2cdc55bf3a20ff25d939c7db7de19147_3ae98f5, 2014 # Radek <d.exax@hotmail.com>, 2014-2015 -# rutek <inactive+rutek@transifex.com>, 2014 +# e63c7c8176237aadfd7c181dfcb19125_0d2a2cf <2b9ee820ae00a56bd0783458d267b6f2_166252>, 2014 # Sarina Canelake <sarina@edx.org>, 2015 # Sebastian <foobarbaz@gazeta.pl>, 2014 # Jaroslaw Lukawski <sekretariat@kmti.uz.zgora.pl>, 2014 @@ -81,7 +81,7 @@ # # Translators: # Adam Banasiak <adam@cku.elblag.pl>, 2015 -# Adam Banasiak <inactive+adamba@transifex.com>, 2014 +# be8238a6a200ce133e6c46360471eb91_d2fb582 <ff48a1e86ce9f4cd3956f7438592f7c5_237459>, 2014 # Adrian Budasz <adrianbudasz@gmail.com>, 2015 # Bart Fischer (Archimedesign) <info@archimedesign.co.uk>, 2015 # Bartosz MuczyÅ„ski <b.muczynski@gmail.com>, 2015 @@ -93,7 +93,7 @@ # Jaroslaw Lukawski <sekretariat@kmti.uz.zgora.pl>, 2014 # Magdalena JarosiÅ„ska <m.jarosinska@stud.elka.pw.edu.pl>, 2015-2016 # Mateusz <blue90pl@gmail.com>, 2014 -# Cairath, 2014 +# 2cdc55bf3a20ff25d939c7db7de19147_3ae98f5, 2014 # Sebastian <foobarbaz@gazeta.pl>, 2014 # Jaroslaw Lukawski <sekretariat@kmti.uz.zgora.pl>, 2014 # #-#-#-#-# wiki.po (edx-platform) #-#-#-#-# @@ -110,7 +110,7 @@ # mateusz2238 <mateusz2238@outlook.com>, 2014 # Mateusz <blue90pl@gmail.com>, 2014 # AlinaG <musicalpreschool@hotmail.com>, 2014 -# Cairath, 2014 +# 2cdc55bf3a20ff25d939c7db7de19147_3ae98f5, 2014 # Piotr JaÅ„czuk <piotr.janczuk@gmail.com>, 2015 # Radek <d.exax@hotmail.com>, 2014 # #-#-#-#-# edx_proctoring_proctortrack.po (0.1a) #-#-#-#-# @@ -126,7 +126,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed <waheed@edx.org>, 2019\n" "Language-Team: Polish (https://www.transifex.com/open-edx/teams/6205/pl/)\n" @@ -135,7 +135,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -160,8 +160,8 @@ msgstr "Egzamin wstÄ™pny" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "Ekran" @@ -486,13 +486,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "Istnieje już konto o nazwie użytkownika '{username}'." +msgid "An account with the Email '{email}' already exists." +msgstr "Istnieje już konto z adresem e-mail '{email}'." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "Istnieje już konto z adresem e-mail '{email}'." +msgid "An account with the Public Username '{username}' already exists." +msgstr "Istnieje już konto o nazwie użytkownika '{username}'." #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2437,9 +2437,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -4398,12 +4398,12 @@ msgstr "" "ćwiczenia z tego moduÅ‚u bÄ™dÄ… brane pod uwagÄ™ przez algorytm oceniajÄ…cy " "egzamin wstÄ™pny." -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "Grupy Å›cieżki kursu" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "Partycja do segmentowania studentów wedÅ‚ug Å›cieżki kursu" @@ -5081,17 +5081,17 @@ msgstr "" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "Zamknij" @@ -6044,56 +6044,6 @@ msgstr "" "{username} ({email}). W celu rozpatrzenia wniosku kliknij w poniższy " "odnoÅ›nik(i)." -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "Rachunek" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "PÅ‚atność nieudana" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "WystÄ…piÅ‚ problem z transakcjÄ…, Nie zostaÅ‚eÅ› obciążony żadnÄ… kwotÄ…." - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" -"Upewnij siÄ™, że twoje dane sÄ… poprawne, albo spróbuj dokonać opÅ‚aty innym " -"Å›rodkiem pÅ‚atnoÅ›ci." - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" -"W trakcie przetwarzania pÅ‚atnoÅ›ci wystÄ…piÅ‚ bÅ‚Ä…d systemu. Nie zostaÅ‚eÅ› " -"obciążony żadnÄ… kwotÄ…." - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "ProszÄ™ odczekać kilka minut i spróbować ponownie." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "Aby uzyskać pomoc, skontaktuj siÄ™ na {payment_support_link}." - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "WystÄ…piÅ‚ bÅ‚Ä…d w trakcie generowania twojego rachunku." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"Jeżeli kurs nie pojawi siÄ™ na twoim pulpicie, skontaktuj siÄ™ na " -"{payment_support_link}." - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "Uzyskać certyfikat" @@ -6158,11 +6108,23 @@ msgstr "Nie posiadasz dostÄ™pu do tego kursu." msgid "You do not have access to this course on a mobile device" msgstr "Nie posiadasz dostÄ™pu do tego kursu na urzÄ…dzeniu mobilnym." +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "ZmieÅ„ tryb kursu do poziomu potwierdzonego" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -6837,9 +6799,8 @@ msgid "Good" msgstr "Dobrze" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html @@ -6847,6 +6808,11 @@ msgstr "" msgid "View discussion" msgstr "WyÅ›wietl dyskusjÄ™" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6990,8 +6956,8 @@ msgid "Student" msgstr "Student" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "Kadra" @@ -7120,29 +7086,6 @@ msgstr "odpowiedzi na ćwiczenie" msgid "Could not find problem with this location." msgstr "Nie udaÅ‚o siÄ™ odnaleźć ćwiczenia pod wskazanym adresem." -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "Rachunek o numerze '{num}' nie istnieje." - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "Transakcja powiÄ…zana z tym rachunkiem zostaÅ‚a już unieważniona." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "Rachunek o numerze {0} zostaÅ‚ unieważniony." - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "Ten rachunek jest już aktywny." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "Kody rejestracyjne dla rachunku {0} zostaÅ‚y reaktywowane." - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "Identyfikator kursu" @@ -7173,9 +7116,8 @@ msgstr "Identyfikator użytkownika" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "Nazwa użytkownika" @@ -7295,54 +7237,6 @@ msgstr "Plik musi zawierać kolumnÄ™ \"kohorta\" obejmujÄ…cÄ… nazwy kohort." msgid "The file must contain a 'username' column, an 'email' column, or both." msgstr "Plik musi zawierać kolumnÄ™ 'użytkownik', kolumnÄ™ 'e-mail' lub obie." -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "Kod promocyjny" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "Identyfikator kursu" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% rabatu" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "Opis" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "Data ważnoÅ›ci" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "Jest aktywny" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "Liczba wykorzystaÅ„ kodu" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "Suma zrabatowanych miejsc" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "ÅÄ…czna kwota zrabatowania" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -7363,16 +7257,6 @@ msgstr "ankieta" msgid "proctored exam results" msgstr "wyniki egzaminu nadzorowanego" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "Nie można przedstawić sumy jako uÅ‚amek dziesiÄ™tny" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" -"Nie można wygenerować kodów rejestracyjnych ze wzglÄ™du na bÅ‚Ä™dnÄ… " -"konfiguracjÄ™ kursu." - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -7621,66 +7505,6 @@ msgstr "" "sprawdzić, czy para nazwa użytkownika / adres e-mail oraz identyfikator " "kursu sÄ… poprawne, a nastÄ™pnie spróbować ponownie." -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "brak identyfikatora kodu" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "kod o identyfikatorze ({coupon_id}) nie istnieje" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "kud o identyfikatorze ({coupon_id}) jest już nieaktywny" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "kod o identyfikatorze ({coupon_id}) zostaÅ‚ pomyÅ›lnie zaktualizowany" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" -"Kod ({code}), który próbowaÅ‚eÅ› zmienić, znajduje siÄ™ już w użyciu jako kod " -"rejestracyjny." - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "ProszÄ™ podać wartość zniżkowÄ… kodu promocyjnego jako liczbÄ™ caÅ‚kowitÄ…" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "" -"ProszÄ™ podać wartość zniżkowÄ… kodu promocyjnego mniejszÄ… lub równÄ… 100" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "ProszÄ™ podać datÄ™ w formacie dzieÅ„/miesiÄ…c/rok" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "kod o identyfikatorze ({code}) zostaÅ‚ dodany pomyÅ›lnie" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "kod o identyfikatorze ({code}) już istnieje dla tego kursu" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "nie odnaleziono identyfikatora kodu" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "kod o identyfikatorze ({coupon_id}) zostaÅ‚ pomyÅ›lnie zaktualizowany" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "ProwadzÄ…cy" @@ -7796,30 +7620,6 @@ msgstr "UkoÅ„czone" msgid "Incomplete" msgstr "NieukoÅ„czone" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "" -"Kod rejestracyjny ({code}) nie zostaÅ‚ odnaleziony dla kursu {course_name}." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "Kod rejestracyjny zostaÅ‚ anulowany. Nie można go użyć." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "Kod rejestracyjny zostaÅ‚ oznaczony jako niewykorzystany." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "Kod rejestracyjny zostaÅ‚ przywrócony." - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "Nie użyto kodu rejestracyjnego ({code})." - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -8234,8 +8034,8 @@ msgstr "(spoÅ›ród {total})" #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Programy" @@ -8888,6 +8688,15 @@ msgstr "Cena caÅ‚kowita" msgid "Currency" msgstr "Waluta" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "Opis" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "Komentarze" @@ -9033,14 +8842,6 @@ msgstr "Nie posiadasz uprawnieÅ„ do przeglÄ…dania tej strony. " msgid "View and regenerate certificates." msgstr "Zobacz i odnów certyfikaty." -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "Manualny zwrot pieniÄ™dzy" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "Åšledź zwroty przetworzone bezpoÅ›rednio przez operatora pÅ‚atnoÅ›ci." - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -9119,44 +8920,9 @@ msgstr "" msgid "User Disabled Successfully" msgstr "" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "Adres e-mail" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "Identyfikator kursu" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "Nie znaleziono użytkownika" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "Kurs {course_id} nie przekroczyÅ‚ okienka dostÄ™pnoÅ›ci zwrotów." - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "Nie znaleziono zamówienia użytkownika {user} dla kursu {course_id}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "Wypisano studenta {user} z kursu {course_id}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "Zwrócono {cost} z zamówienia numer {order_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -9780,8 +9546,8 @@ msgid "Allow" msgstr "Zezwól" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "BÅ‚Ä…d" @@ -10174,8 +9940,8 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "ZaÅ‚Ä…czniki" @@ -10213,11 +9979,10 @@ msgstr "" "innych artykuÅ‚ach, co może być korzyÅ›ciÄ… lub wadÄ…." #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -10637,6 +10402,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -11051,6 +10820,10 @@ msgstr "" msgid "Schedule start < course start" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "Identyfikator kursu" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "Wszystko" @@ -11059,6 +10832,15 @@ msgstr "Wszystko" msgid "Experience" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "Identyfikator kursu" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -11262,6 +11044,7 @@ msgid "" msgstr "" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "" @@ -11500,7 +11283,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -11527,8 +11309,8 @@ msgstr "" msgid "Success" msgstr "Zrobione" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "CzynnoÅ›ci" @@ -11699,6 +11481,14 @@ msgstr "" "WystÄ…piÅ‚ bÅ‚Ä…d w trakcie uzyskiwania twoich danych do logowania. Skontaktuj " "siÄ™ z pomocÄ… technicznÄ…." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11712,6 +11502,15 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "Zbyt wiele nieudanych prób logowania. Spróbuj ponownie później." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11719,15 +11518,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "uzytkownik@domena.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -11743,6 +11533,12 @@ msgstr "Adres e-mail, którego użyÅ‚eÅ› podczas rejestracji w {platform_name}" msgid "Create Account" msgstr "Utwórz konto" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "uzytkownik@domena.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -11759,6 +11555,11 @@ msgstr "" "Nie można zresetować hasÅ‚a do konta użytkownika powiÄ…zanego z tym adresem " "e-mail." +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "Zresetowanie hasÅ‚a nie powiodÅ‚o siÄ™" @@ -11778,11 +11579,6 @@ msgid "" "created. {bold_start}{email}{bold_end} is now your primary login email." msgstr "" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "" @@ -12017,6 +11813,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "Automat: wÅ‚Ä…czony" @@ -12035,6 +11843,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "NieprawidÅ‚owa wartość." @@ -12749,8 +12561,8 @@ msgstr "Kurs pomyÅ›lnie wyeksportowany do repozytorium git" msgid "Vertical" msgstr "Pionowy" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "RozdziaÅ‚" @@ -13031,6 +12843,18 @@ msgstr "Trwa generowanie transkrypcji" msgid "Transcript Ready" msgstr "Transkrypcja gotowa" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "Wymagany jest plik obrazka." @@ -13183,8 +13007,8 @@ msgstr "Treść" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "Ustawienia" @@ -13232,14 +13056,14 @@ msgstr "Numer kursu:" msgid "Course Run:" msgstr "Edycja kursu:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "Kursy" @@ -13263,8 +13087,9 @@ msgstr "ProwadzÄ…cy" msgid "Requirements" msgstr "Wymagania" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "Szczegóły" @@ -13318,15 +13143,15 @@ msgstr "" msgid "Choose Language" msgstr "Wybierz jÄ™zyk" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "Konto" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -13399,8 +13224,8 @@ msgstr "Menu użytkownika" msgid "Usermenu dropdown" msgstr "Rozwijane menu" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "Wyloguj siÄ™" @@ -13570,8 +13395,8 @@ msgstr "RozpoczÄ™cie: {date}" msgid "View all Courses" msgstr "WyÅ›wietl wszystkie kursy" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "Pulpit" @@ -13590,8 +13415,8 @@ msgstr "Nie uczestniczysz jeszcze w żadnym kursie..." #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "PrzeglÄ…daj kursy" @@ -13609,7 +13434,7 @@ msgstr "BÅ‚Ä™dy wczytywania kursu" msgid "Search Your Courses" msgstr "Przeszukaj swoje kursy" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "Wyczyść wyszukiwanie" @@ -13634,7 +13459,7 @@ msgstr "ChcÄ™ otrzymywać powiadomienia e-mail z kursu" msgid "Save Settings" msgstr "Zapisz ustawienia" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -13644,9 +13469,87 @@ msgstr "Zapisz ustawienia" msgid "Unenroll" msgstr "Wypisz siÄ™ " -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "WyÅ›wietl ekran w Studio" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -13681,7 +13584,7 @@ msgstr "Konto ze wskazanym nowym adresem e-mail już istnieje." msgid "You should Register before trying to access the Unit" msgstr "Przed przystÄ…pieniem do lekcji musisz siÄ™ zarejestrować" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "Zapisz siÄ™" @@ -13790,7 +13693,7 @@ msgstr "" "{line_break}JeÅ›li ukoÅ„czyÅ‚eÅ› to zadanie, twoja ocena jest dostÄ™pna " "{link_start}w dzienniku postÄ™pów{link_end}." -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "Szukaj kursu" @@ -13941,21 +13844,16 @@ msgstr "(przeÅ‚aduj stronÄ™, aby odÅ›wieżyć)" msgid "working" msgstr "dziaÅ‚am" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "WystÄ…piÅ‚ bÅ‚Ä…d na serwerach platformy {platform_name}" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"Przepraszamy, ten moduÅ‚ jest chwilowo niedostÄ™pny. Nasi technicy pracujÄ… nad" -" jak najszybszym rozwiÄ…zaniem problemu. W celu zgÅ‚aszania wystÄ™pujÄ…cych " -"problemów prosimy o e-mail na adres {tech_support_email}." #: lms/templates/module-error.html msgid "Raw data:" @@ -13994,7 +13892,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "PrzeglÄ…dasz teraz kurs jako {i_start}{user_name}{i_end}." #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -14063,28 +13969,6 @@ msgstr "E-mail" msgid "Return To %s" msgstr "Wróć do %s" -#: lms/templates/reset_deadlines_banner.html -msgid "It looks like you've missed some important deadlines. Visit " -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "edx.org" -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid " to reset your deadlines and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "Wznowienie subskrypcji zakoÅ„czone powodzeniem!" @@ -14135,7 +14019,7 @@ msgstr "" msgid "Sequence" msgstr "Sekwencja" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -14266,18 +14150,18 @@ msgstr "Ocena (wyÅ‚Ä…cznie do nadpisania)" msgid "Reset Learner's Attempts to Zero" msgstr "Zresetuj do zera próby studenta" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "UsuÅ„ stan studenta" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "OceÅ„ ponownie pracÄ™ studenta" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "OceÅ„ ponownie tylko w przypadku poprawy oceny" @@ -14315,7 +14199,7 @@ msgstr "PodrÄ™cznik kursu {course_number}" msgid "Textbook Navigation" msgstr "Poruszanie siÄ™ po podrÄ™czniku" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "Strona" @@ -14428,9 +14312,9 @@ msgstr "Strona {current_page} z {total_pages}" msgid "Recent git load activity for {course_id}" msgstr "Ostatnia czynność wczytywania git dla kursu {course_id}" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -14490,7 +14374,7 @@ msgstr "" "Jeżeli nie chciaÅ‚eÅ› wyÅ‚Ä…czyć subskrypcji, {undo_link_start}możesz jÄ… " "wznowić{link_end}." -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "Pulpit dla:" @@ -14498,8 +14382,8 @@ msgstr "Pulpit dla:" msgid "More options" msgstr "WiÄ™cej opcji" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "WiÄ™cej opcji" @@ -15740,37 +15624,6 @@ msgstr "" msgid "About edX Certificates" msgstr "" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "Zamówienie anulowane" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"Twoja transakcja zostaÅ‚a anulowana. JeÅ›li uważasz, że doszÅ‚o do bÅ‚Ä™du, " -"skontaktuj siÄ™ na {email}." - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "BÅ‚Ä…d transakcji" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "Wczytywanie danych zamówienia..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "ProszÄ™ poczekać aż pobierzemy szczegóły zamówienia." - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -15992,14 +15845,14 @@ msgstr "{section_format} - termin koÅ„cowy: {{date}}" msgid "This content is graded" msgstr "Ta zawartość podlega ocenie" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "WystÄ…piÅ‚ bÅ‚Ä…d. Spróbuj ponownie później." - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "WystÄ…piÅ‚ bÅ‚Ä…d. Spróbuj ponownie później." + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "JesteÅ› zapisany na ten kurs" @@ -16011,10 +15864,6 @@ msgstr "JesteÅ› zapisany na ten kurs" msgid "View Course" msgstr "WyÅ›wietl kurs" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "Lista uczestników jest już peÅ‚na" @@ -16027,10 +15876,6 @@ msgstr "Rekrutacja do tego kursu jest wyÅ‚Ä…cznie na zaproszenia" msgid "Enrollment is Closed" msgstr "Rekrutacja jest zamkniÄ™ta" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "" @@ -16157,6 +16002,13 @@ msgstr "NarzÄ™dzia kursu" msgid "Courseware" msgstr "TreÅ›ci szkoleniowe" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "Przeszukaj kurs" @@ -16187,7 +16039,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -16195,14 +16047,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" msgstr "" -#: lms/templates/courseware/error-message.html -msgid "" -"We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible." +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -16896,10 +16745,8 @@ msgstr "Informacje do celów weryfikacyjnych zostaÅ‚y przez ciebie zÅ‚ożone." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" -"Po zakoÅ„czeniu czynnoÅ›ci weryfikacyjnych otrzymasz wiadomość na swój pulpit " -"studenta (zwykle w ciÄ…gu 1-2 dni)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -16909,11 +16756,8 @@ msgstr "Twoja obecna weryfikacja tożsamoÅ›ci wkrótce wygaÅ›nie!" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" -"Informacje do celów weryfikacyjnych zostaÅ‚y przez ciebie zÅ‚ożone. Po " -"zakoÅ„czeniu czynnoÅ›ci weryfikacyjnych otrzymasz wiadomość na swój pulpit " -"studenta (zwykle w ciÄ…gu 1-2 dni)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -17650,151 +17494,6 @@ msgid "" "verification process on your dashboard." msgstr "" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "DziÄ™kujemy za zakup kodów dostÄ™pu do kursu {course_name}." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"ZaÅ‚Ä…czamy rachunek na kwotÄ™ {total_price}{currency_symbol}. PÅ‚atnoÅ›ci należy" -" dokonać natychmiast. Informacje o dostÄ™pnych metodach pÅ‚atnoÅ›ci znajdziesz " -"na rachunku." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -"W zaÅ‚Ä…czeniu znajduje siÄ™ plik .csv z kodami rejestracyjnymi do kursów. " -"Możesz użyć poniższego szablonu e-mail, aby porozsyÅ‚ać kody studentom. Każdy" -" student musi użyć oddzielnego kodu." - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"DziÄ™kujemy,\n" -"Zespół {platform_name}" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "Witaj [[Name]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"Mamy dla ciebie kod rejestracyjny na kurs {course_name}. Aby siÄ™ zapisać na " -"kurs, przejdź pod poniższy adres:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "Link HTML z zaÅ‚Ä…czonego pliku CSV" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"Po zapisaniu siÄ™, zobaczysz kurs na swoim pulpicie studenta. DostÄ™p do " -"materiałów kursowych otrzymasz po jego rozpoczÄ™ciu." - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"Z poważaniem,\n" -"[[Your Signature]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "RACHUNEK" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "Data: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "Numer rachunku: {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "Warunki: pÅ‚atny po otrzymaniu" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "PÅ‚atny do: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "Odbiorca rachunku:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "Numer referencyjny klienta: {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "Kwota do zapÅ‚aty: {sale_price} {currency_symbol}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "Kurs: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"Kwota: {course_price}{currency_symbol} Ilość: {quantity} Cena jedn: " -"{sub_total}{currency_symbol} Rabat: {discount}{currency_symbol}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "Suma: {sale_price}{currency_symbol}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "Instrukcja zapÅ‚aty" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"W przypadku nieuregulowania opÅ‚aty, udziaÅ‚ w kursie studenta, który użyÅ‚ " -"danego kodu rejestracyjnego, zostanie anulowany. Wszystkie opÅ‚aty majÄ… " -"charakter ostateczny. Aby uzyskać wiÄ™cej informacji, proszÄ™ odwiedzić stronÄ™" -" polityki zwrotów {site_name}." - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "" -"W razie pytaÅ„ dotyczÄ…cych pÅ‚atnoÅ›ci, proszÄ™ skontaktować siÄ™ z nami na " -"{contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -18000,8 +17699,8 @@ msgstr "Aplikuj po wsparcie finansowe" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "Strona główna {platform_name}" @@ -18024,19 +17723,11 @@ msgstr "" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "Sysadmin" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "Koszyk" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "" @@ -18073,6 +17764,12 @@ msgstr "Dodaj kod promocyjny" msgid "Enter information about the coupon code below." msgstr "Wprowadź informacjÄ™ na temat kodu promocyjnego." +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "Kod promocyjny" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "Rabat procentowy" @@ -18688,6 +18385,11 @@ msgstr "Pobierz kody promocyjne" msgid "Coupon Codes" msgstr "Kody promocyjne" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "Data wygaÅ›niÄ™cia" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "Rabat (%)" @@ -20060,6 +19762,10 @@ msgstr "Nazwa nabywcy" msgid "Purchase order number (if any)" msgstr "Numer zamówienia (opcjonalny)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "Adres e-mail" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "email@example.com" @@ -20391,6 +20097,10 @@ msgstr[2] "" msgstr[3] "" "Kursy {course_names} zostaÅ‚y usuniÄ™te, gdyż wygasÅ‚y okresy ich trwania." +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "Koszyk" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "Główny obrazek" @@ -20610,46 +20320,6 @@ msgstr "" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "Zamiar zwrotu pieniÄ™dzy za zamówienie:" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "Identyfikator zamówienia:" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "Uczestnictwo:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "uczestniczÄ…cy" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "nieuczestniczÄ…cy" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "Koszt:" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "Status certyfikacji:" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "Status zamówienia:" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "Czas zrealizowania:" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "Data żądania zwrotu:" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "Ankieta użytkownika" @@ -20804,11 +20474,8 @@ msgstr "Potwierdzenie tożsamoÅ›ci" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" -"Informacje do celów weryfikacyjnych zostaÅ‚y przez ciebie zÅ‚ożone. Po " -"zakoÅ„czeniu czynnoÅ›ci weryfikacyjnych otrzymasz wiadomość na swój pulpit " -"studenta (zwykle w ciÄ…gu 1-2 dni)." #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -21401,8 +21068,8 @@ msgid "Already registered?" msgstr "JesteÅ› już zarejestrowany/a?" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "Zaloguj siÄ™" @@ -21520,12 +21187,8 @@ msgid "The page that you were looking for was not found." msgstr "Szukana strona nie zostaÅ‚a odnaleziona." #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" -"Wróć do strony głównej {homepage} lub poinformuj nas o nieaktywnych " -"stronach: {email}." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -21551,10 +21214,6 @@ msgstr "" "BÅ‚Ä…d zostaÅ‚ odnotowany i nasz zespół pracuje nad jak najszybszym " "rozwiÄ…zaniem problemu." -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "JeÅ›li problem nie ustÄ…pi, prosimy o kontakt: {email_link}." - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "Polityka dostÄ™pnoÅ›ci Studio" @@ -22252,14 +21911,8 @@ msgstr "Strona której szukasz nie zostaÅ‚a odnaleziona" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" -"Przepraszamy. Nie nie udaÅ‚o siÄ™ odnaleźć strony {studio_name}, której " -"szukasz. Możesz wrócić na stronÄ™ głównÄ… {studio_name} i spróbować ponownie. " -"W razie dalszych problemów z dostÄ™pem do okreÅ›lonych treÅ›ci, skorzystaj z " -"{link_start} pomocy {studio_name} {link_end}." #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -22269,14 +21922,8 @@ msgstr "Serwer napotkaÅ‚ bÅ‚Ä…d" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" -"Przepraszamy. WystÄ…piÅ‚ bÅ‚Ä…d serwera w trakcie próby przetworzenia twojego " -"żądania. Zalecamy powrót do pulpitu {studio_name} lub podjÄ™cie kolejnej " -"próby. W razie dalszych problemów z dostÄ™pem do okreÅ›lonych treÅ›ci, " -"skorzystaj z {link_start} pomocy {studio_name} {link_end}." #: cms/templates/error.html msgid "Back to dashboard" @@ -25662,8 +25309,8 @@ msgstr "%(file)s zostaÅ‚ zmieniony do wersji #%(revision)d" msgid "%(file)s has been saved." msgstr "%(file)s zostaÅ‚ zapisany." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "Obrazy" @@ -25857,8 +25504,8 @@ msgstr "" msgid "Search..." msgstr "Szukaj..." -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "" diff --git a/conf/locale/pl/LC_MESSAGES/djangojs.mo b/conf/locale/pl/LC_MESSAGES/djangojs.mo index 3faf4d3a368e8639bf4c634b7d6b6d1eda05a052..1ee6ab62b3e04c4fed2128e0fd6ec7c99e669e67 100644 Binary files a/conf/locale/pl/LC_MESSAGES/djangojs.mo and b/conf/locale/pl/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/pl/LC_MESSAGES/djangojs.po b/conf/locale/pl/LC_MESSAGES/djangojs.po index e58025d912cfdd4274b25acde3b64dc11da06ca6..f20cf917bf1351f4dafc4511148502a302f09688 100644 --- a/conf/locale/pl/LC_MESSAGES/djangojs.po +++ b/conf/locale/pl/LC_MESSAGES/djangojs.po @@ -23,7 +23,7 @@ # Mateusz <blue90pl@gmail.com>, 2014 # MichaÅ‚ Szkutnik <michal7x7@o2.pl>, 2015 # Monika Biskupska <monika.biskupska@nask.pl>, 2019 -# Cairath, 2014 +# 2cdc55bf3a20ff25d939c7db7de19147_3ae98f5, 2014 # Ola Kleniewska <anyzeklove@gmail.com>, 2016 # Piotr JaÅ„czuk <piotr.janczuk@gmail.com>, 2015 # Radek <d.exax@hotmail.com>, 2015 @@ -47,7 +47,7 @@ # Jaroslaw Lukawski <sekretariat@kmti.uz.zgora.pl>, 2014 # Magdalena JarosiÅ„ska <m.jarosinska@stud.elka.pw.edu.pl>, 2015 # Mateusz <blue90pl@gmail.com>, 2014 -# Cairath, 2014 +# 2cdc55bf3a20ff25d939c7db7de19147_3ae98f5, 2014 # Ned Batchelder <ned@edx.org>, 2017 # Sebastian <foobarbaz@gazeta.pl>, 2014 # Jaroslaw Lukawski <sekretariat@kmti.uz.zgora.pl>, 2014 @@ -95,8 +95,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-18 18:51+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Polish (http://www.transifex.com/open-edx/edx-platform/language/pl/)\n" "Language: pl\n" @@ -104,7 +104,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -153,6 +153,7 @@ msgstr "UsuÅ„" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -175,6 +176,7 @@ msgstr "PrzesyÅ‚anie" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -199,6 +201,7 @@ msgstr "Wybierz plik" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "OK" @@ -772,7 +775,6 @@ msgstr "" #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Opis" @@ -819,6 +821,7 @@ msgstr "" #: cms/templates/js/show-textbook.underscore #: cms/templates/js/signatory-details.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Edit" msgstr "" @@ -1213,6 +1216,7 @@ msgstr "" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "NastÄ™pny" @@ -1546,6 +1550,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/course-instructor-details.underscore #: cms/templates/js/signatory-details.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Title" msgstr "" @@ -2482,7 +2487,15 @@ msgid "Other" msgstr "Inne" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx @@ -2490,20 +2503,23 @@ msgid "Details" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "WyÅ›lij" +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2520,6 +2536,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2543,7 +2571,8 @@ msgstr "" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2727,6 +2756,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "WystÄ…piÅ‚ bÅ‚Ä…d. Spróbuj ponownie." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "OpuÅ›cić ten zespół?" @@ -3269,6 +3302,7 @@ msgid "There has been an error processing your survey." msgstr "WystÄ…piÅ‚ bÅ‚Ä…d w trakcie przetwarzania twojej ankiety." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -3285,6 +3319,7 @@ msgid "HTML preview of post" msgstr "" #: lms/static/js/customwmd.js +#: common/static/common/templates/discussion/templates.underscore msgid "Your question or idea (required)" msgstr "" @@ -5521,6 +5556,10 @@ msgstr "Tak, pozwól na edycjÄ™ aktywnego certyfikatu." msgid "certificate" msgstr "certyfikat" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Przygotuj certyfikat" @@ -5532,8 +5571,8 @@ msgid "You have not created any certificates yet." msgstr "Nie stworzyÅ‚eÅ› jeszcze żadnych certyfikatów." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "Usunąć \"<%= signatoryName %>\" z listy sygnatariuszy?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5841,8 +5880,8 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -6027,7 +6066,7 @@ msgid "{selectedProvider} credentials saved" msgstr "Dane {selectedProvider} zapisane" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" msgstr "" #: cms/static/js/views/edit_chapter.js @@ -6608,18 +6647,14 @@ msgstr "" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" -"ÅÄ…czna dÅ‚ugość nazwy organizacji, numeru kursu i edycji kursu nie może " -"przekroczyć <%=limit%> znaków." #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" -"ÅÄ…czna dÅ‚ugość pól nazwy organizacji i kodu biblioteki nie może przekroczyć " -"<%=limit%> znaków." #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -6968,13 +7003,13 @@ msgid "Unscheduled" msgstr "Niezaplanowany" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Data" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Poprzedni" @@ -7022,6 +7057,312 @@ msgstr "Wyczyść wyszukiwanie" msgid "Search" msgstr "Szukaj" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "WyÅ›lij" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "Wszystkie wpisy" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "Strona główna dyskusji" @@ -7080,10 +7421,6 @@ msgstr "" "Zaznacz to pole, aby raz dziennie otrzymywać zbiorczy e-mail z " "aktualnoÅ›ciami i nowymi wpisami w tematach, które Å›ledzisz." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "Wszystkie wpisy" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "nazwa użytkownika lub adres e-mail" @@ -7323,6 +7660,10 @@ msgstr "Masz problem ze znalezieniem zespoÅ‚u?" msgid "Join Team" msgstr "DoÅ‚Ä…cz do zespoÅ‚u" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "O zespole" @@ -7409,106 +7750,6 @@ msgstr "UsuÅ„ lekcjÄ™ %(subsectionDisplayName)s" msgid "Remove unit %(unitName)s" msgstr "UsuÅ„ ekran %(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" -"Wciąż musisz odwiedzić stronÄ™ %(display_name)s w celu dopeÅ‚nienia " -"formalnoÅ›ci zwiÄ…zanych z przyznaniem punktów edukacyjnych." - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"W celu sfinalizowania procesu przyznawania punktów edukacyjnych, " -"%(display_name)s wymaga od studentów %(platform_name)s przesÅ‚ania zgÅ‚oszenia" -" żądania przyznania punktów." - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Odbierz punkty" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" -"DziÄ™kujemy, %(full_name)s! OtrzymaliÅ›my twojÄ… opÅ‚atÄ™ za %(course_name)s." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"ProszÄ™ zapisać lub wydrukować tÄ™ stronÄ™, gdyż sÅ‚uży ona za rachunek. Ten sam" -" rachunek otrzymasz również drogÄ… poczty elektronicznej." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "Nr zamówienia" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Ilość" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Suma" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Uwaga" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "Za wykreÅ›lone elementy nastÄ…piÅ‚ zwrot pieniÄ™dzy." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Nabywca:" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Brak dostÄ™pnego pokwitowania" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Przejdź do pulpitu" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" -"JeÅ›li nie potwierdzisz swojej tożsamoÅ›ci już teraz, wciąż możesz " -"uczestniczyć w kursie z poziomu pulpitu studenta. BÄ™dziesz otrzymywać " -"cykliczne powiadomienia od {platformName} z proÅ›bÄ… o poddanie siÄ™ " -"weryfikacji tożsamoÅ›ci." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "Czy chcesz potwierdzić swojÄ… tożsamość później?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Potwierdź teraz" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Oznacz egzamin jako ukoÅ„czony" @@ -7640,10 +7881,8 @@ msgstr "O tobie" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" -"Poniższe informacje sÄ… częściÄ… twojego profilu w {platform}. ZaÅ‚Ä…czyliÅ›my je" -" jako element twojego zgÅ‚oszenia." #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7673,6 +7912,10 @@ msgstr "" "DziÄ™kujemy za twoje zgÅ‚oszenie do wsparcia finansowego dla kursu " "{course_name}. Możesz spodziewać siÄ™ odpowiedzi w ciÄ…gu 2-4 dni roboczych." +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Przejdź do pulpitu" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "Masowe wyjÄ…tki" @@ -8037,14 +8280,6 @@ msgstr "Nie możesz już dokonać zmiany sesji kursu." msgid "You can change sessions until {expiration_date}." msgstr "Możesz dokonać zmiany sesji kursu do dn. {expiration_date}." -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "Ocena koÅ„cowa" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "z kursu {courseName}" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "WyÅ›wietl zarchiwizowany kurs" @@ -8267,7 +8502,27 @@ msgid "An error occurred. Please reload the page." msgstr "WystÄ…piÅ‚ bÅ‚Ä…d. ProszÄ™ odÅ›wieżyć stronÄ™." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -8479,17 +8734,13 @@ msgid "What You Need for Verification" msgstr "Czego potrzebujesz do potwierdzenia tożsamoÅ›ci" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Kamerka internetowa" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8497,12 +8748,8 @@ msgid "Photo Identification" msgstr "Identyfikacja zdjÄ™cia" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"Potrzebujesz dowodu osobistego, paszportu lub innego oficjalnego dokumentu " -"tożsamoÅ›ci ze zdjÄ™ciem i twoim nazwiskiem." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8527,14 +8774,10 @@ msgstr "Twoja twarz jest dobrze oÅ›wietlona." msgid "Your entire face fits inside the frame." msgstr "CaÅ‚a twoja twarz znajduje siÄ™ w ramie zdjÄ™cia." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "ZdjÄ™cie twojej twarzy odpowiada temu z dokumentu tożsamoÅ›ci." - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8551,17 +8794,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Dlaczego %(platformName)s potrzebuje mojego zdjÄ™cia?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"W ramach czynnoÅ›ci potwierdzania tożsamoÅ›ci, wykonujesz zdjÄ™cie swojej " -"twarzy oraz dokumentu tożsamoÅ›ci ze zdjÄ™ciem. Nasz zespół autoryzacyjny " -"potwierdzi twojÄ… tożsamość porównujÄ…c Å›wieżo zrobione zdjÄ™cie ze zdjÄ™ciem z " -"twojego dokumentu." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8572,18 +8808,12 @@ msgstr "W jaki sposób %(platformName)s dba o bezpieczeÅ„stwo danych?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"Używamy najwyższych dostÄ™pnych poziomów bezpieczeÅ„stwa w celu szyfrowania " -"zdjęć i przesyÅ‚ania ich do sprawdzenia. Po zakoÅ„czeniu czynnoÅ›ci " -"weryfikacyjnych, twoje zdjÄ™cia i dane z dokumentu nie sÄ… zapisywane ani " -"widoczne gdziekolwiek na Å‚amach %(platformName)s." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8642,22 +8872,14 @@ msgid "Take a Photo of Your ID" msgstr "Wykonaj zdjÄ™cie swojego dokumentu tożsamoÅ›ci" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"Użyj kamerki internetowej, aby zrobić zdjÄ™cie swojego dokumentu tożsamoÅ›ci. " -"Porównamy to zdjÄ™cie ze zdjÄ™ciem twojej twarzy oraz zweryfikujemy dane " -"osobowe." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Potrzebujesz dokumentu tożsamoÅ›ci ze zdjÄ™ciem i danymi osobowymi. " -"Zaakceptujemy dowód osobisty, paszport, prawo jazdy lub inny oficjalny " -"dokument." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8683,6 +8905,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8735,6 +8964,30 @@ msgstr "" "Czy uda nam siÄ™ porównać wykonane przez ciebie zdjÄ™cie z tym z twojego " "dokumentu?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"W ramach czynnoÅ›ci potwierdzania tożsamoÅ›ci, wykonujesz zdjÄ™cie swojej " +"twarzy oraz dokumentu tożsamoÅ›ci ze zdjÄ™ciem. Nasz zespół autoryzacyjny " +"potwierdzi twojÄ… tożsamość porównujÄ…c Å›wieżo zrobione zdjÄ™cie ze zdjÄ™ciem z " +"twojego dokumentu." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"Używamy najwyższych dostÄ™pnych poziomów bezpieczeÅ„stwa w celu szyfrowania " +"zdjęć i przesyÅ‚ania ich do sprawdzenia. Po zakoÅ„czeniu czynnoÅ›ci " +"weryfikacyjnych, twoje zdjÄ™cia i dane z dokumentu nie sÄ… zapisywane ani " +"widoczne gdziekolwiek na Å‚amach %(platformName)s." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -8770,6 +9023,13 @@ msgstr "" "Dowód osobisty, prawo jazdy, paszport lub inny dokument tożsamoÅ›ci " "zawierajÄ…cy twoje zdjÄ™cie oraz imiÄ™ i nazwisko." +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Kamerka internetowa" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8873,6 +9133,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "Sprawdź pocztÄ™ e-mail i odszukać wiadomość aktywacyjnÄ…." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Suma" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "Certyfikat Edukacji Specjalistycznej kursu {courseName}" @@ -8918,6 +9183,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "DziÄ™kujemy! OtrzymaliÅ›my twojÄ… opÅ‚atÄ™ za kurs {courseName}." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"ProszÄ™ zapisać lub wydrukować tÄ™ stronÄ™, gdyż sÅ‚uży ona za rachunek. Ten sam" +" rachunek otrzymasz również drogÄ… poczty elektronicznej." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "Nr zamówienia" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Ilość" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Uwaga" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "Za wykreÅ›lone elementy nastÄ…piÅ‚ zwrot pieniÄ™dzy." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Nabywca:" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Brak dostÄ™pnego pokwitowania" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "NastÄ™pny krok: potwierdź swojÄ… tożsamość" @@ -8954,6 +9251,10 @@ msgstr "" "cykliczne powiadomienia od %(platformName)s z proÅ›bÄ… o poddanie siÄ™ " "weryfikacji tożsamoÅ›ci." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "Czy chcesz potwierdzić swojÄ… tożsamość później?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "Potwierdzenie tożsamoÅ›ci w toku" @@ -8962,13 +9263,9 @@ msgstr "Potwierdzenie tożsamoÅ›ci w toku" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"OtrzymaliÅ›my twoje dane i sprawdzimy je by potwierdzić twojÄ… tożsamość. Na " -"swoim pulpicie studenta znajdziesz wiadomość gdy proces weryfikacyjny " -"zostanie zakoÅ„czony (zwykle w ciÄ…gu 1-2 dni). W miÄ™dzyczasie możesz bez " -"przeszkód korzystać ze wszystkich materiałów kursowych." #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -9004,10 +9301,6 @@ msgstr "Wymagania wobec zdjęć:" msgid "Does the photo of you show your whole face?" msgstr "Czy na zdjÄ™ciu widać caÅ‚Ä… twojÄ… twarz?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "Czy zdjÄ™cie twojej twarzy odpowiada temu z dokumentu tożsamoÅ›ci?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "Czy da siÄ™ odczytać imiÄ™ i nazwisko z dokumentu tożsamoÅ›ci?" @@ -10519,6 +10812,21 @@ msgstr "Ustaw jako egzamin specjalny" msgid "Exam Types" msgstr "Typy egzaminów" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Z limitem czasu" @@ -10722,14 +11030,14 @@ msgstr "" msgid "Read more" msgstr "Czytaj dalej" -#: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" -msgstr "WyÅ›wietl transkrypcje ({totalTranscripts})" - #: cms/templates/js/video-transcripts.underscore msgid "No transcript uploaded." msgstr "Nie przesÅ‚ano transkrypcji." +#: cms/templates/js/video-transcripts.underscore +msgid "Show transcripts ({totalTranscripts})" +msgstr "WyÅ›wietl transkrypcje ({totalTranscripts})" + #: cms/templates/js/xblock-access-editor.underscore msgid "Set Access" msgstr "Ustal dostÄ™p" diff --git a/conf/locale/pt_BR/LC_MESSAGES/djangojs.mo b/conf/locale/pt_BR/LC_MESSAGES/djangojs.mo index d49470515f7a5e77adf5949455d92c982887e56b..792d506e5e2520f8d4348e5d990540602e640197 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 7c626640347fb522b3cf8d902bdfc5ce5a6d83b5..accf63d3bcba4160941114c9fb996353034bd494 100644 --- a/conf/locale/pt_BR/LC_MESSAGES/djangojs.po +++ b/conf/locale/pt_BR/LC_MESSAGES/djangojs.po @@ -13,12 +13,12 @@ # Andrei Bosco Bezerra Torres <andreibosco@gmail.com>, 2013 # Angela Amaro <angelasimei@gmail.com>, 2016 # brk0_0, 2013 -# brunojm <inactive+brunojm@transifex.com>, 2014 -# brunojm <inactive+brunojm@transifex.com>, 2014 -# brunojm <inactive+brunojm@transifex.com>, 2014 +# 754e3b4535c42482e9d79823c604dedb_998e2fc <7e9e8733acd656dd73e747b19e4fe9b4_1809>, 2014 +# 754e3b4535c42482e9d79823c604dedb_998e2fc <7e9e8733acd656dd73e747b19e4fe9b4_1809>, 2014 +# 754e3b4535c42482e9d79823c604dedb_998e2fc <7e9e8733acd656dd73e747b19e4fe9b4_1809>, 2014 # Bruno Marques <brunojmbq@gmail.com>, 2019 -# Bruno Sette <inactive+BrunoSette@transifex.com>, 2015 -# Bruno Sette <inactive+BrunoSette@transifex.com>, 2015 +# 0281eea346bccd642f86fb3f8f246263_27228e8 <a68031c06893a19cfe23a2c7a30eb91c_260934>, 2015 +# 0281eea346bccd642f86fb3f8f246263_27228e8 <a68031c06893a19cfe23a2c7a30eb91c_260934>, 2015 # Cleomir Waiczyk <w.cleomir@gmail.com>, 2015 # rqllira <contato@raquellira.com>, 2014 # Cristiano Oliveira <cristoliv@gmail.com>, 2014 @@ -39,7 +39,7 @@ # javiercencig <javier@jecnet.com.br>, 2014 # javiercencig <javier@jecnet.com.br>, 2014 # Jefferson Floyd Conz, 2014 -# Jefferson Floyd Conz, 2014 +# 696c22ebb4383944463b186ef9bcc83a_301220f, 2014 # Kaio VinÃcius Vilerá <kaiovilera@gmail.com>, 2016 # Kayo Leone Dias Perim <kayo_2008_@hotmail.com>, 2014 # Kevin Grist <kgrist@localconcept.com>, 2014 @@ -48,8 +48,8 @@ # Leonardo Lehnemann <lehneman@gmail.com>, 2014 # LucasPPires <lucaspylespires@hotmail.com>, 2014 # LucasPPires <lucaspylespires@hotmail.com>, 2014 -# Lulatini <inactive+Lulatini@transifex.com>, 2014 -# Lulatini <inactive+Lulatini@transifex.com>, 2014 +# 65971a0953e55f53f5475a3fa483ec89_9b4f7df <c1633493954e537617ecd67b590e3d56_202429>, 2014 +# 65971a0953e55f53f5475a3fa483ec89_9b4f7df <c1633493954e537617ecd67b590e3d56_202429>, 2014 # MaÃta Medeiros e Silva <moliveira.maita@gmail.com>, 2015 # Marcelo Soares Souza <marcelo@libertais.org>, 2014 # Marcelo Soares Souza <marcelo@libertais.org>, 2014 @@ -101,12 +101,12 @@ # Antonio Henrique Dianin <antoniohdianin@hotmail.com>, 2015 # brk0_0, 2013 # Bruno Horphoz <horphoz@gmail.com>, 2014 -# brunojm <inactive+brunojm@transifex.com>, 2014 +# 754e3b4535c42482e9d79823c604dedb_998e2fc <7e9e8733acd656dd73e747b19e4fe9b4_1809>, 2014 # Caio Kalil Gragnani <caio.gragnani@gmail.com>, 2015 # Cleomir Waiczyk <w.cleomir@gmail.com>, 2015 # Daniel Linhares <danielinhares@gmail.com>, 2014 # Deusilene Sousa Matos <deusymatos@gmail.com>, 2015 -# Diego Rabatone Oliveira <diraol@diraol.eng.br>, 2015 +# Diego Rabatone Oliveira <transifex@diraol.eng.br>, 2015 # Douglas Reginatto <dreginatto@yahoo.com.br>, 2016 # Edgar Aparecido Pereira de Melo <edgarapmelo@gmail.com>, 2014 # Eduardo Barasal Morales <emorales@nic.br>, 2017 @@ -125,7 +125,7 @@ # Leonardo Flores Zambaldi <fzleonardo@gmail.com>, 2014 # Leonardo Lehnemann <lehneman@gmail.com>, 2014 # LucasPPires <lucaspylespires@hotmail.com>, 2014 -# Luiz Penedo <inactive+luiz.penedo@transifex.com>, 2015 +# edf2562ed7f957c9db5fa43524c002dc_d650b64 <d2dacee5528ef7f329f2d27d3d767062_261832>, 2015 # Marco Túlio Pires <mtrpires@outlook.com>, 2014 # Mike Job <mikejobrn@gmail.com>, 2015 # Monica Farias <monifar.tp@gmail.com>, 2015-2016 @@ -138,10 +138,11 @@ # RaÃssa Teles Bicock <raissa.bicock@gmail.com>, 2015 # RenataBarboza, 2013 # Renata Barboza, 2014-2016 +# Rodrigo Rocha <prof.rodrigorocha@yahoo.com>, 2020 # Sarina Canelake <sarina@edx.org>, 2014 # Siderlan Santos <siderlan.santos@gmail.com>, 2015 # Stefania Trabucchi <stefania.trabucchi@abstract-technology.de>, 2019 -# Thiago Perrotta <inactive+thiagowfx@transifex.com>, 2014 +# e05a6f0c527312287ac027cf3d3a35f5_685166c <0e3f187c36e42a887ffaef9a9e407417_190443>, 2014 # Victor Hochgreb de Freitas <victorhochgreb@gmail.com>, 2015 # Vinicius Ferreira de Souza <vinicius.fk9@gmail.com>, 2016 # William Bellinazo Roca <williambr_1331@hotmail.com>, 2016 @@ -168,25 +169,25 @@ # Anderson Franca <anderson.frca@gmail.com>, 2017 # Andrea Z. Bitencourt <azbitencourt@gmail.com>, 2015 # Angela Amaro <angelasimei@gmail.com>, 2016 -# Bruno Sette <inactive+BrunoSette@transifex.com>, 2015 +# 0281eea346bccd642f86fb3f8f246263_27228e8 <a68031c06893a19cfe23a2c7a30eb91c_260934>, 2015 # Cleomir Waiczyk <w.cleomir@gmail.com>, 2015 # Edgar Aparecido Pereira de Melo <edgarapmelo@gmail.com>, 2014 # Eduardo Barasal Morales <emorales@nic.br>, 2017 # Fabiano Nunes <fabianofnunes@gmail.com>, 2016 # Fabio Eis <fabio@fabioeis.com>, 2016 -# Felipe Lube de Bragança <inactive+felubra@transifex.com>, 2015 +# b42485a36dcfdd00e325e4e0a3703395_f289b96 <b7894f796c2b44908123638fb5b52c63_262264>, 2015 # Fernando Nunes <fernubr@gmail.com>, 2015 # Francisco Cantarutti <francisco.cantarutti@sisqualis.com.br>, 2014 # Francisco Ventura <fra.ventura@gmail.com>, 2015 # G <glaucogm@ufpr.br>, 2014 -# Guilherme Henrique Spiller <inactive+guispiller@transifex.com>, 2015 +# 24ee4117159a8d7b075e8539bbb7c6de_b1253aa <a2be32db0cdc5cc222c84ce21aae4d51_327905>, 2015 # Gustavo Bertoli, 2015 # Hudson Martins <p4p4l3gu4x@gmail.com>, 2015 # Jaqueline Knebel Wildner <jaquelinewildner@gmail.com>, 2015 # Leonardo Flores Zambaldi <fzleonardo@gmail.com>, 2014 # Luan Benavenuto dos Santos <luanbenavenuto@outlook.com>, 2015 # Lucas Oliveira Silva <lucas_sem@hotmail.com>, 2014 -# Lulatini <inactive+Lulatini@transifex.com>, 2015 +# 65971a0953e55f53f5475a3fa483ec89_9b4f7df <c1633493954e537617ecd67b590e3d56_202429>, 2015 # Marcos Paulo Castilho Costa <hospitaldomicro2@yahoo.com.br>, 2019 # Matheus Gomes Correia, 2017 # MaurÃcio Gonçalves Melara Camargo <mauriciogmc@gmail.com>, 2015 @@ -197,7 +198,7 @@ # Sergio Silva <sergiohrs@gmail.com>, 2016 # sgtmarciosilva <sgtmarciosilva@ibest.com.br>, 2015 # Thiago Perrotta <tbperrotta@gmail.com>, 2016 -# Thiago Perrotta <inactive+thiagowfx@transifex.com>, 2014 +# e05a6f0c527312287ac027cf3d3a35f5_685166c <0e3f187c36e42a887ffaef9a9e407417_190443>, 2014 # Victor Hochgreb <victorfeec@gmail.com>, 2015 # Victor Hochgreb de Freitas <victorhochgreb@gmail.com>, 2015 # Victor Oliveira <victor@codebit.com.br>, 2016 @@ -210,15 +211,15 @@ # # Translators: # Angela Amaro <angelasimei@gmail.com>, 2016 -# Bruno Sette <inactive+BrunoSette@transifex.com>, 2015 +# 0281eea346bccd642f86fb3f8f246263_27228e8 <a68031c06893a19cfe23a2c7a30eb91c_260934>, 2015 # Cleomir Waiczyk <w.cleomir@gmail.com>, 2015 # Edgar Aparecido Pereira de Melo <edgarapmelo@gmail.com>, 2014 # aivuk <e@vaz.io>, 2014 # Fabio Eis <fabio@fabioeis.com>, 2016 # Fernando Nunes <fernubr@gmail.com>, 2015 -# Jefferson Floyd Conz, 2014 +# 696c22ebb4383944463b186ef9bcc83a_301220f, 2014 # Leonardo Lehnemann <lehneman@gmail.com>, 2014 -# Luiz Marques <inactive+luizcardineli@transifex.com>, 2015 +# e519a39286619fcc31783727fc0c3a54_b2af932 <58deda3d0248d9eb70768f899a029b59_269074>, 2015 # Magaly Munik da Rocha, 2014 # Marco Túlio Pires <mtrpires@outlook.com>, 2014 # Mariana Jó de Souza <mariana.jsouza@gmail.com>, 2015 @@ -233,6 +234,7 @@ # Renato Monteiro da Silva <renato_city@yahoo.com.br>, 2019 # Ricardo Pietrobon <pietr007@gmail.com>, 2014 # Rodrigo Mozelli <romozelli@outlook.com>, 2016 +# Rodrigo Rocha <prof.rodrigorocha@yahoo.com>, 2020 # Victor Hochgreb <victorfeec@gmail.com>, 2015 # Victor Hochgreb de Freitas <victorhochgreb@gmail.com>, 2015 # Willian Pascoal <willianpascoal@protonmail.com>, 2016 @@ -240,8 +242,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/open-edx/edx-platform/language/pt_BR/)\n" "Language: pt_BR\n" @@ -249,7 +251,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -298,6 +300,7 @@ msgstr "Apagar" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -320,6 +323,7 @@ msgstr "Carregando" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -903,7 +907,6 @@ msgstr "" #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Descrição" @@ -950,6 +953,7 @@ msgstr "" #: cms/templates/js/show-textbook.underscore #: cms/templates/js/signatory-details.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Edit" msgstr "" @@ -1344,6 +1348,7 @@ msgstr "" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Próximo" @@ -1677,6 +1682,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/course-instructor-details.underscore #: cms/templates/js/signatory-details.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Title" msgstr "" @@ -2561,7 +2567,15 @@ msgid "Other" msgstr "Outro" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx @@ -2569,20 +2583,23 @@ msgid "Details" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Enviar" +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2599,6 +2616,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2622,7 +2651,8 @@ msgstr "" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2804,6 +2834,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "Ocorreu um erro. Tente novamente." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Sair desta equipe?" @@ -3298,6 +3332,7 @@ msgid "There has been an error processing your survey." msgstr "Ocorreu um erro ao processar a sua enquete." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -3314,6 +3349,7 @@ msgid "HTML preview of post" msgstr "" #: lms/static/js/customwmd.js +#: common/static/common/templates/discussion/templates.underscore msgid "Your question or idea (required)" msgstr "" @@ -5405,6 +5441,10 @@ msgstr "Sim, permita a edição para este certificado" msgid "certificate" msgstr "certificado" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Emita seu certificado" @@ -5416,8 +5456,8 @@ msgid "You have not created any certificates yet." msgstr "Você ainda não criou um certificado." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "Apagar \"<%= signatoryName %>\" da lista de emissores?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5726,8 +5766,8 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -5907,7 +5947,7 @@ msgid "{selectedProvider} credentials saved" msgstr "" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" msgstr "" #: cms/static/js/views/edit_chapter.js @@ -6469,18 +6509,14 @@ msgstr "" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" -"Os campos comprimento total da Organização, número do curso e funcionamento " -"do curso não podem exceder <%=limit%> caracteres. " #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" -"Os campos comprimento combinando da Organização e código da biblioteca não " -"podem ultrapassar <%=limit%> caracteres. " #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -6826,13 +6862,13 @@ msgid "Unscheduled" msgstr "Não agendado" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Data" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Anterior" @@ -6880,6 +6916,310 @@ msgstr "Limpar pesquisa" msgid "Search" msgstr "Busca" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Enviar" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "" @@ -6938,10 +7278,6 @@ msgstr "" "Marque esta alternativa para receber um e-mail uma vez por dia com um resumo" " das novidades das publicações não lidas as quais você segue." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "usuário ou email" @@ -7180,6 +7516,10 @@ msgstr "Você está com problemas para encontrar uma equipe para fazer parte ?" msgid "Join Team" msgstr "Participe da Equipe" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "Detalhes da equipe" @@ -7264,100 +7604,6 @@ msgstr "Remover subseção %(subsectionDisplayName)s" msgid "Remove unit %(unitName)s" msgstr "Remover unidade %(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" -"Você ainda precisa visitar o site %(display_name)s para completar o processo" -" de crédito." - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"Para finalizar os créditos do curso, %(display_name)s exige que os alunos " -"%(platform_name)s enviem uma solicitação de créditos. " - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Obter Crédito" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"Por favor, imprima esta página para seu controle; ela serve como recibo. " -"Você também receberá um e-mail com as mesmas informações. " - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "Número do pedido" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Quantidade" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Total" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Por favor observe" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "Itens riscados tiveram seu valor reembolsado" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Cobrar a" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Recibo não disponÃvel" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Ir para a Página Inicial" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "Deseja confirmar sua identidade mais tarde?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Verifique agora" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Marcar avaliação como completa" @@ -7485,10 +7731,8 @@ msgstr "Sobre Você" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" -"As informações a seguir já fazem parte do seu perfil {platform}. Nós as " -"incluÃmos aqui para seu pedido." #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7518,6 +7762,10 @@ msgstr "" "Agradecemos por nos enviar o seu pedido de assistência financeira para " "{course_name}! Você pode esperar uma resposta entre 2-4 dias úteis." +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Ir para a Página Inicial" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "Exceções em massa" @@ -7868,14 +8116,6 @@ msgstr "" msgid "You can change sessions until {expiration_date}." msgstr "" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "" @@ -8091,7 +8331,27 @@ msgid "An error occurred. Please reload the page." msgstr "Um erro ocorreu. Por favor, recarregue a página." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -8296,17 +8556,13 @@ msgid "What You Need for Verification" msgstr "O que é necessário para verificação" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Webcam" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8314,12 +8570,8 @@ msgid "Photo Identification" msgstr "Identificação pela foto" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"Você precisa de uma carteira de habilitação, passaporte ou outra " -"identificação emitida pelo governo que possua o seu nome e foto." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8344,14 +8596,10 @@ msgstr "Seu rosto está bem iluminado." msgid "Your entire face fits inside the frame." msgstr "Seu rosto inteiro cabe dentro do quadro." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "A foto do seu rosto corresponde à foto no seu documento." - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8368,17 +8616,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Por que %(platformName)s precisa da minha foto?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"Como parte do processo de verificação, você irá tirar uma foto tanto do seu " -"rosto como de uma foto de documento oficial. Nosso serviço de autorização " -"confirma sua identidade ao comparar a foto que você tira com a foto no seu " -"documento." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8389,18 +8630,12 @@ msgstr "O que %(platformName)s faz com esta foto?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"Nós usamos os mais altos nÃveis de segurança disponÃveis para encriptar sua " -"foto e enviá-la para no serviço de autorização para análise. Informações " -"sobre você e sua foto não são salvas ou visÃveis em qualquer lugar em " -"%(platformName)s depois que o processo de verificação é completado." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8459,21 +8694,14 @@ msgid "Take a Photo of Your ID" msgstr "Tire uma foto do seu documento de identidade" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"Use a webcam para tirar uma foto do seu documento. Nós vamos conferir esta " -"foto com a foto do seu rosto e o nome na sua conta." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Você precisa de um documento com o seu nome e foto. Uma carteira de " -"motorista, passaporte ou outro documento emitido pelo governo são " -"aceitáveis." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8498,6 +8726,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8550,6 +8785,30 @@ msgstr "" "Podemos comparar a foto que você tirou com a do seu documento de " "identificação?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"Como parte do processo de verificação, você irá tirar uma foto tanto do seu " +"rosto como de uma foto de documento oficial. Nosso serviço de autorização " +"confirma sua identidade ao comparar a foto que você tira com a foto no seu " +"documento." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"Nós usamos os mais altos nÃveis de segurança disponÃveis para encriptar sua " +"foto e enviá-la para no serviço de autorização para análise. Informações " +"sobre você e sua foto não são salvas ou visÃveis em qualquer lugar em " +"%(platformName)s depois que o processo de verificação é completado." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -8583,6 +8842,13 @@ msgstr "" "Uma carteira de motorista, um passaporte ou outro documento de identidade " "oficial com o seu nome e foto" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Webcam" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8680,6 +8946,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "Verifique o e-mail recebido com uma mensagem de ativação." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Total" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "" @@ -8724,6 +8995,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"Por favor, imprima esta página para seu controle; ela serve como recibo. " +"Você também receberá um e-mail com as mesmas informações. " + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "Número do pedido" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Quantidade" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Por favor observe" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "Itens riscados tiveram seu valor reembolsado" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Cobrar a" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Recibo não disponÃvel" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "Próximo passo: confirme a sua identidade" @@ -8759,6 +9062,10 @@ msgstr "" "curso pelo seu painel de controle. Você vai receber lembretes periódicos de " "%(platformName)s para verificar a sua identidade." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "Deseja confirmar sua identidade mais tarde?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "Verificação de Identificação em Progresso" @@ -8767,13 +9074,9 @@ msgstr "Verificação de Identificação em Progresso" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"Recebemos as suas informações e estamos verificando a sua identificação. " -"Você receberá uma mensagem em seu painel de controle quando o processo de " -"verificação estiver concluÃdo (normalmente entre 1-2 dias). Enquanto isso, " -"você ainda pode acessar a todo o conteúdo do curso." #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -8809,10 +9112,6 @@ msgstr "Requisitos da foto:" msgid "Does the photo of you show your whole face?" msgstr "A sua foto escolhida exibe todo o seu rosto?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "A foto a seguir é a mesma foto de sua identidade?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "O seu nome é legÃvel em seu documento?" @@ -10250,6 +10549,21 @@ msgstr "" msgid "Exam Types" msgstr "" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Cronometrado" @@ -10437,11 +10751,11 @@ msgid "Read more" msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" +msgid "No transcript uploaded." msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "No transcript uploaded." +msgid "Show transcripts ({totalTranscripts})" msgstr "" #: cms/templates/js/xblock-access-editor.underscore diff --git a/conf/locale/rtl/LC_MESSAGES/django.mo b/conf/locale/rtl/LC_MESSAGES/django.mo index b12b192071995ca5096f318a32a5de6fd6d22618..b93d6c3ffb17f0e0fca9406e8105455c5578eaca 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 91d44fd9d0e5ca9038d8f8c1475116b4f1a69fc7..1547a35f0e31181e60bc1593f5099e8e4866640f 100644 --- a/conf/locale/rtl/LC_MESSAGES/django.po +++ b/conf/locale/rtl/LC_MESSAGES/django.po @@ -38,8 +38,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:53+0000\n" -"PO-Revision-Date: 2020-04-12 20:53:38.526475\n" +"POT-Creation-Date: 2020-06-21 20:50+0000\n" +"PO-Revision-Date: 2020-06-21 20:50:24.457974\n" "Last-Translator: \n" "Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n" "Language: rtl\n" @@ -47,7 +47,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (0.1a) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -72,8 +72,8 @@ msgstr "ثرÙقشرذث ثطشو" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "عرهÙ" @@ -406,13 +406,13 @@ msgstr "عسثق صهÙا Ùاهس ثوشهم يخثسر'٠ثطهس٠هر سغ #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "شر شذذخعر٠صهÙا Ùاث Øعزمهذ عسثقرشوث '{username}' شمقثشيغ ثطهسÙس." +msgid "An account with the Email '{email}' already exists." +msgstr "شر شذذخعر٠صهÙا Ùاث ثوشهم '{email}' شمقثشيغ ثطهسÙس." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "شر شذذخعر٠صهÙا Ùاث ثوشهم '{email}' شمقثشيغ ثطهسÙس." +msgid "An account with the Public Username '{username}' already exists." +msgstr "شر شذذخعر٠صهÙا Ùاث Øعزمهذ عسثقرشوث '{username}' شمقثشيغ ثطهسÙس." #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2135,7 +2135,7 @@ msgstr "شمصشغس" msgid "Never" msgstr "رثدثق" -#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/capa_base.py lms/templates/courseware/dates.html msgid "Past Due" msgstr "Øشس٠يعث" @@ -2325,9 +2325,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -4255,12 +4255,12 @@ msgstr "" "ثرÙثق Ùقعث خق بشمسث. هب Ùقعث, شرسصثق سعزوهسسهخرس بخق Øقخزمثو وخيعمثس صهمم زث" " ذخرسهيثقثي هر Ùاث ثرÙقشرذث ثطشو سذخقهرل/لشÙهرل شملخقهÙاو." -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "ثرقخمموثر٠Ùقشذن لقخعØس" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "ØشقÙÙ‡Ùهخر بخق سثلوثرÙهرل عسثقس زغ ثرقخمموثر٠Ùقشذن" @@ -4931,17 +4931,17 @@ msgstr "عرمخذن شذذخعرÙ" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "ذمخسث" @@ -5916,56 +5916,6 @@ msgstr "" "Ø´ قثبعري قثضعثس٠اشس زثثر هرهÙهشÙثي بخق {username} ({email}). ÙØ® Øقخذثسس " "Ùاهس قثضعثسÙ, Øمثشسث دهسه٠Ùاث مهرن(س) زثمخص." -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "قثذثهØÙ" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "Øشغوثر٠بشهمثي" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "Ùاثقث صشس Ø´ Øقخزمثو صهÙا Ùاهس ÙقشرسشذÙهخر. غخع اشدث رخ٠زثثر ذاشقلثي." - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" -"وشنث سعقث غخعق هربخقوشÙهخر هس ذخققثذÙ, خق Ùقغ شلشهر صهÙا Ø´ يهببثقثر٠ذشقي خق" -" شرخÙاثق بخقو خب ØشغوثرÙ." - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" -"Ø´ سغسÙثو ثققخق خذذعققثي صاهمث Øقخذثسسهرل غخعق ØشغوثرÙ. غخع اشدث رخ٠زثثر " -"ذاشقلثي." - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "Øمثشسث صشه٠ش بثص وهرعÙثس شري Ùاثر Ùقغ شلشهر." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "بخق اثمØ, ذخرÙشذ٠{payment_support_link}." - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "شر ثققخق خذذعققثي صاهمث ذقثشÙهرل غخعق قثذثهØÙ." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"هب غخعق ذخعقسث يخثس رخ٠شØØثشق خر غخعق يشسازخشقي, ذخرÙشذ٠" -"{payment_support_link}." - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "ثشقر Ø´ ذثقÙهبهذشÙØ«" @@ -6028,11 +5978,23 @@ msgstr "غخع يخ رخ٠اشدث شذذثسس ÙØ® Ùاهس ذخعقسث" msgid "You do not have access to this course on a mobile device" msgstr "غخع يخ رخ٠اشدث شذذثسس ÙØ® Ùاهس ذخعقسث خر Ø´ وخزهمث يثدهذث" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "غخع وعس٠زث ثرقخممثي هر Ùاث ذخعقسث" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "غخع وعس٠زث مخللثي هر ÙØ® سثث Ùاهس ذخعقسث" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "عØلقشيث ÙØ® دثقهبهثي" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "بهرشرذهشم شسسهسÙشرذث" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "شسسهلروثرÙ" @@ -6052,6 +6014,11 @@ msgstr "{relative} شلخ - {absolute}" msgid "in {relative} - {absolute}" msgstr "هر {relative} - {absolute}" +#: lms/djangoapps/courseware/date_summary.py +#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py +msgid "Enrollment Date" +msgstr "ثرقخمموثر٠يشÙØ«" + #: lms/djangoapps/courseware/date_summary.py msgid "Course Starts" msgstr "ذخعقسث سÙشقÙس" @@ -6721,16 +6688,20 @@ msgid "Good" msgstr "لخخي" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" -msgstr "%(comment_username)s قثØمهثي ÙØ® <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" +msgstr "%(comment_username)s قثØمهثي ÙØ®" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt msgid "View discussion" msgstr "دهثص يهسذعسسهخر" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "%(comment_username)s قثØمهثي ÙØ® <b>%(thread_title)s</b>:" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6866,8 +6837,8 @@ msgid "Student" msgstr "سÙعيثرÙ" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "سÙشبب" @@ -6997,29 +6968,6 @@ msgstr "Øقخزمثو قثسØخرسثس" msgid "Could not find problem with this location." msgstr "ذخعمي رخ٠بهري Øقخزمثو صهÙا Ùاهس مخذشÙهخر." -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "هردخهذث رعوزثق '{num}' يخثس رخ٠ثطهسÙ." - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "Ùاث سشمث شسسخذهشÙثي صهÙا Ùاهس هردخهذث اشس شمقثشيغ زثثر هردشمهيشÙثي." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "هردخهذث رعوزثق {0} اشس زثثر هردشمهيشÙثي." - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "Ùاهس هردخهذث هس شمقثشيغ شذÙهدث." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "Ùاث قثلهسÙقشÙهخر ذخيثس بخق هردخهذث {0} اشدث زثثر قث-شذÙهدشÙثي." - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "ذخعقسثهي" @@ -7050,9 +6998,8 @@ msgstr "عسثق هي" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "عسثقرشوث" @@ -7173,54 +7120,6 @@ msgid "The file must contain a 'username' column, an 'email' column, or both." msgstr "" "Ùاث بهمث وعس٠ذخرÙشهر Ø´ 'عسثقرشوث' ذخمعور, شر 'ثوشهم' ذخمعور, خق زخÙا." -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "ذخعØخر ذخيث" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "ذخعقسث هي" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% يهسذخعرÙ" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "يثسذقهØÙهخر" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "ثطØهقشÙهخر يشÙØ«" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "هس شذÙهدث" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "ذخيث قثيثثوثي ذخعرÙ" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "ÙØ®Ùشم يهسذخعرÙثي سثشÙس" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "ÙØ®Ùشم يهسذخعرÙثي شوخعرÙ" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -7241,14 +7140,6 @@ msgstr "سعقدثغ" msgid "proctored exam results" msgstr "ØقخذÙخقثي ثطشو قثسعمÙس" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "ذخعمي رخ٠Øشقسث شوخعر٠شس Ø´ يثذهوشم" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "عرشزمث ÙØ® لثرثقشÙØ« قثيثثو ذخيثس زثذشعسث خب ذخعقسث وهسذخربهلعقشÙهخر." - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -7489,65 +7380,6 @@ msgstr "" "نهريمغ دثقهبغ سÙعيثر٠عسثقرشوث/ثوشهم شري Ùاث سثمثذÙثي ذخعقسث شقث ذخققثذ٠شري" " Ùقغ شلشهر." -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "ذخعØخر هي هس رخرث" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "ذخعØخر صهÙا Ùاث ذخعØخر هي ({coupon_id}) يخثسرخÙثطهسÙ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "ذخعØخر صهÙا Ùاث ذخعØخر هي ({coupon_id}) هس شمقثشيغ هرشذÙهدث" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "ذخعØخر صهÙا Ùاث ذخعØخر هي ({coupon_id}) عØيشÙثي سعذذثسسبعممغ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" -"Ùاث ذخيث ({code}) Ùاش٠غخع اشدث Ùقهثي ÙØ® يثبهرث هس شمقثشيغ هر عسث شس Ø´ " -"قثلهسÙقشÙهخر ذخيث" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "Øمثشسث ثرÙثق Ùاث هرÙثلثق دشمعث بخق ذخعØخر يهسذخعرÙ" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "Øمثشسث ثرÙثق Ùاث ذخعØخر يهسذخعر٠دشمعث مثسس Ùاشر خق ثضعشم ÙØ® 100" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "Øمثشسث ثرÙثق Ùاث يشÙØ« هر Ùاهس بخقوش٠ه-Ø« وخرÙا/يشغ/غثشق" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "ذخعØخر صهÙا Ùاث ذخعØخر ذخيث ({code}) شييثي سعذذثسسبعممغ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "ذخعØخر صهÙا Ùاث ذخعØخر ذخيث ({code}) شمقثشيغ ثطهسÙس بخق Ùاهس ذخعقسث" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "ذخعØخر هي رخ٠بخعري" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "ذخعØخر صهÙا Ùاث ذخعØخر هي ({coupon_id}) عØيشÙثي سعذذثسسبعممغ" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "هرسÙقعذÙخق" @@ -7658,30 +7490,6 @@ msgstr "ذخوØمثÙØ«" msgid "Incomplete" msgstr "هرذخوØمثÙØ«" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "" -"Ùاث ثرقخمموثر٠ذخيث ({code}) صشس رخ٠بخعري بخق Ùاث {course_name} ذخعقسث." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "Ùاهس ثرقخمموثر٠ذخيث اشس زثثر ذشرذثمثي. ه٠ذشر رخ مخرلثق زث عسثي." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "Ùاهس ثرقخمموثر٠ذخيث اشس زثثر وشقنثي شس عرعسثي." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "Ùاث ثرقخمموثر٠ذخيث اشس زثثر قثسÙخقثي." - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "Ùاث قثيثوØÙهخر يخثس رخ٠ثطهس٠شلشهرس٠ثرقخمموثر٠ذخيث ({code})." - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7879,10 +7687,6 @@ msgstr "ÙÙ‡Ùمث" msgid "Year of Birth" msgstr "غثشق خب زهقÙا" -#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py -msgid "Enrollment Date" -msgstr "ثرقخمموثر٠يشÙØ«" - #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py msgid "Currently Enrolled" msgstr "ذعققثرÙمغ ثرقخممثي" @@ -8084,8 +7888,8 @@ msgstr " (خع٠خب {total})" #: lms/djangoapps/learner_dashboard/programs.py #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Øقخلقشوس" @@ -8847,6 +8651,15 @@ msgstr "ÙØ®Ùشم ذخسÙ" msgid "Currency" msgstr "ذعققثرذغ" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "يثسذقهØÙهخر" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "ذخووثرÙس" @@ -8993,14 +8806,6 @@ msgstr "غخع يخ رخ٠اشدث Øثقوهسسهخر ÙØ® دهثص Ùاهس msgid "View and regenerate certificates." msgstr "دهثص شري قثلثرثقشÙØ« ذثقÙهبهذشÙثس." -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "وشرعشم قثبعري" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "Ùقشذن قثبعريس هسسعثي يهقثذÙمغ Ùاقخعلا ذغزثقسخعقذث." - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -9079,44 +8884,9 @@ msgstr "عسثق ثرشزمثي سعذذثسسبعممغ" msgid "User Disabled Successfully" msgstr "عسثق يهسشزمثي سعذذثسسبعممغ" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "ثوشهم شييقثسس" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "ذخعقسث هي" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "عسثق رخ٠بخعري" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "ذخعقسث {course_id} رخ٠Øشس٠Ùاث قثبعري صهريخص." - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "رخ خقيثق بخعري بخق {user} هر ذخعقسث {course_id}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "عرثرقخممثي {user} بقخو {course_id}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "قثبعريثي {cost} بخق خقيثق هي {order_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "غخع وعس٠ذخوØمثÙØ« Ø´ سعقدثغ" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -9801,8 +9571,8 @@ msgid "Allow" msgstr "شممخص" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "ثققخق" @@ -10206,8 +9976,8 @@ msgstr "" " اثمØ." #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "Ø´ÙÙشذاوثرÙس" @@ -10245,11 +10015,10 @@ msgstr "" "خر Ø®Ùاثق شقÙهذمثس صاهذا وشغ خق وشغ رخ٠زث Ø´ لخخي Ùاهرل." #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -10695,6 +10464,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "ذخربهلعقشÙهخر وشغ رخ٠زث سØثذهبهثي ش٠وخقث Ùاشر خرث مثدثم ش٠خرذث." +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "مثشقرهرل سثضعثرذثس" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "شيوهرهسÙثق عسثقس شري شعÙاخق ذخرÙثرÙ" @@ -11114,6 +10887,10 @@ msgstr "نرخصر ثققخق ذشسث" msgid "Schedule start < course start" msgstr "سذاثيعمث سÙشق٠< ذخعقسث سÙشقÙ" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "ذخعقسث هي" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "شمم" @@ -11122,6 +10899,15 @@ msgstr "شمم" msgid "Experience" msgstr "ثطØثقهثرذث" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "ذخعقسث هي" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -11364,6 +11150,7 @@ msgstr "" "زغ %(user_schedule_upgrade_deadline_time)s." #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "عØلقشيث رخص" @@ -11613,7 +11400,6 @@ msgstr "" "زمشرن." #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -11642,8 +11428,8 @@ msgid "Success" msgstr "سعذذثسس" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "شذÙهخرس" @@ -11826,6 +11612,17 @@ msgstr "قثلهسÙثق" msgid "There was an error receiving your login information. Please email us." msgstr "Ùاثقث صشس شر ثققخق قثذثهدهرل غخعق مخلهر هربخقوشÙهخر. Øمثشسث ثوشهم عس." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" +"ÙØ® ØقخÙثذ٠غخعق شذذخعرÙ, هْس زثثر ÙثوØخقشقهمغ مخذنثي. Ùقغ شلشهر هر " +"{locked_out_period} وهرعÙثس.{li_start}ÙØ® زث خر Ùاث سشبث سهيث, غخع ذشر قثسث٠" +"غخعق Øشسسصخقي {link_start}اثقث{link_end} زثبخقث غخع Ùقغ شلشهر." + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11843,6 +11640,19 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "Ùخخ وشرغ بشهمثي مخلهر Ø´ÙÙثوØÙس. Ùقغ شلشهر مشÙثق." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" +"ثوشهم خق Øشسسصخقي هس هرذخققثذÙ.{li_start}غخع اشدث {remaining_attempts} وخقث " +"سهلر-هر Ø´ÙÙثوØÙس زثبخقث غخعق شذذخعر٠هس ÙثوØخقشقهمغ " +"مخذنثي.{li_end}{li_start}هب غخع'دث بخقلخÙÙثر غخعق Øشسسصخقي, ذمهذن " +"{link_start}اثقث{link_end} ÙØ® قثسثÙ.{li_end}" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11852,15 +11662,6 @@ msgstr "" "شس {allowed_domain} عسثق, غخع وعس٠مخلهر صهÙا غخعق {allowed_domain} " "{link_start}{provider} شذذخعرÙ{link_end}." -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "عسثقرشوث@يخوشهر.ذخو" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -11876,6 +11677,12 @@ msgstr "Ùاث ثوشهم شييقثسس غخع عسثي ÙØ® قثلهسÙثق msgid "Create Account" msgstr "ذقثشÙØ« شذذخعرÙ" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "عسثقرشوث@يخوشهر.ذخو" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -11892,6 +11699,12 @@ msgstr "" "Ùاث عسثق شذذخعر٠شسسخذهشÙثي صهÙا Ùاهس Ø«-وشهم شييقثسس ذشررخ٠قثسث٠Ùاث " "Øشسسصخقي." +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" +"غخعق Øقثدهخعس قثضعثس٠هس هر Øقخلقثسس, Øمثشسث Ùقغ شلشهر هر Ø´ بثص وخوثرÙس." + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "Øشسسصخقي قثسث٠عرسعذذثسسبعم" @@ -11913,12 +11726,6 @@ msgstr "" "{html_start}Øشسسصخقي ذقثشÙهخر ذخوØمثÙØ«{html_end}غخعق Øشسسصخقي اشس زثثر " "ذقثشÙثي. {bold_start}{email}{bold_end} هس رخص غخعق Øقهوشقغ مخلهر ثوشهم." -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" -"غخعق Øقثدهخعس قثضعثس٠هس هر Øقخلقثسس, Øمثشسث Ùقغ شلشهر هر Ø´ بثص وخوثرÙس." - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "سخوث ثققخق خذذعقثي يعقهرل Øشسسصخقي ذاشرلث. Øمثشسث Ùقغ شلشهر" @@ -12159,6 +11966,18 @@ msgid "" msgstr "" "عسثقرشوث ذقثشÙثي بخق دهيثخ ØÙ‡Øثمهرث هرÙثلقشÙهخر, Ø«.Ù„. دثيش_سثقدهذث_عسثق." +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "خشعÙا ذمهثر٠رشوث خب دثو سثقدهذث." + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "دهيثخ ثرذخيث وشرشلثق Ø´ØÙ‡ عقم." + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "عسثقرشوث ذقثشÙثي بخق دثو هرÙثلقشÙهخر, Ø«.Ù„. دثو_سثقدهذث_عسثق." + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "بخقذث خر" @@ -12179,6 +11998,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "Ùاهس ذخرÙثر٠هس خرمغ شذذثسسهزمث ÙØ® ثرقخممثي مثشقرثقس. " +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "Ùاث شزخع٠وث بهثمي وعس٠زث ش٠وخس٠{} ذاشقشذÙثقس مخرل." + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "Ùاهس دشمعث هس هردشمهي." @@ -12953,8 +12776,8 @@ msgid "Vertical" msgstr "دثقÙهذشم" #: cms/djangoapps/contentstore/views/helpers.py -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "سثذÙهخر" @@ -13234,6 +13057,18 @@ msgstr "ÙقشرسذقهØÙهخر هر Øقخلقثسس" msgid "Transcript Ready" msgstr "ÙقشرسذقهØ٠قثشيغ" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "ØشقÙهشم بشهمعقث" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "ÙقشرسذقهØ٠بشهمثي" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "شر هوشلث بهمث هس قثضعهقثي." @@ -13385,8 +13220,8 @@ msgstr "ذخرÙثرÙ" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "سثÙÙهرلس" @@ -13434,14 +13269,14 @@ msgstr "ذخعقسث رعوزثق:" msgid "Course Run:" msgstr "ذخعقسث قعر:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "ذخعقسثس" @@ -13465,8 +13300,9 @@ msgstr "هرسÙقعذÙخقس" msgid "Requirements" msgstr "قثضعهقثوثرÙس" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "يثÙشهمس" @@ -13522,15 +13358,15 @@ msgstr "" msgid "Choose Language" msgstr "ذاخخسث مشرلعشلث" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "شذذخعرÙ" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -13602,8 +13438,8 @@ msgstr "عسثقوثرع" msgid "Usermenu dropdown" msgstr "عسثقوثرع يقخØيخصر" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "سهلر خعÙ" @@ -13775,8 +13611,8 @@ msgstr "سÙشقÙس: {date}" msgid "View all Courses" msgstr "دهثص شمم ذخعقسثس" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "يشسازخشقي" @@ -13795,8 +13631,8 @@ msgstr "غخع شقث رخ٠ثرقخممثي هر شرغ ذخعقسثس غثÙ. #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "ثطØمخقث ذخعقسثس" @@ -13814,7 +13650,7 @@ msgstr "ذخعقسث-مخشيهرل ثققخقس" msgid "Search Your Courses" msgstr "سثشقذا غخعق ذخعقسثس" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "ذمثشق سثشقذا" @@ -13839,7 +13675,7 @@ msgstr "قثذثهدث ذخعقسث ثوشهمس" msgid "Save Settings" msgstr "سشدث سثÙÙهرلس" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -13849,9 +13685,110 @@ msgstr "سشدث سثÙÙهرلس" msgid "Unenroll" msgstr "عرثرقخمم" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "دهثص عره٠هر سÙعيهخ" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" +"ه٠مخخنس مهنث غخع وهسسثي سخوث هوØخقÙشر٠يثشيمهرثس زشسثي خر خعق سعللثسÙثي " +"سذاثيعمث. " + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" +"ÙØ® Ù†Ø«Ø«Ø ØºØ®Ø¹Ù‚Ø³Ø«Ù…Ø¨ خر Ùقشذن, غخع ذشر عØيشÙØ« Ùاهس سذاثيعمث شري ساهب٠Ùاث Øشس٠" +"يعث شسسهلروثرÙس هرÙØ® Ùاث بعÙعقث زغ دهسهÙهرل " + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" +" يخر'٠صخققغ—غخع صخر'٠مخسث شرغ خب Ùاث Øقخلقثسس غخع'دث وشيث صاثر غخع ساهب٠" +"غخعق يعث يشÙثس." + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" +"ه٠مخخنس مهنث غخع وهسسثي سخوث هوØخقÙشر٠يثشيمهرثس زشسثي خر خعق سعللثسÙثي " +"سذاثيعمث." + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" +"ÙØ® Ù†Ø«Ø«Ø ØºØ®Ø¹Ù‚Ø³Ø«Ù…Ø¨ خر Ùقشذن, غخع ذشر عØيشÙØ« Ùاهس سذاثيعمث شري ساهب٠Ùاث Øشس٠" +"يعث شسسهلروثرÙس هرÙØ® Ùاث بعÙعقث. يخر'٠صخققغ—غخع صخر'٠مخسث شرغ خب Ùاث " +"Øقخلقثسس غخع'دث وشيث صاثر غخع ساهب٠غخعق يعث يشÙثس." + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "ساهب٠يعث يشÙثس" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "غخع شقث شعيهÙهرل Ùاهس ذخعقسث," + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" +" صاهذا وثشرس Ùاش٠غخع شقث عرشزمث ÙØ® ØشقÙهذهØØ´ÙØ« هر لقشيثي شسسهلروثرÙس." + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" +" ه٠مخخنس مهنث غخع وهسسثي سخوث هوØخقÙشر٠يثشيمهرثس زشسثي خر خعق سعللثسÙثي " +"سذاثيعمث. لقشيثي شسسهلروثرÙس شري سذاثيعمث شيتعسÙوثر٠شقث شدشهمشزمث ÙØ® " +"دثقهبهثي Ùقشذن مثشقرثقس." + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" +" ه٠مخخنس مهنث غخع وهسسثي سخوث هوØخقÙشر٠يثشيمهرثس زشسثي خر خعق سعللثسÙثي " +"سذاثيعمث. ÙØ® ذخوØمثÙØ« لقشيثي شسسهلروثرÙس شس Øشق٠خب Ùاهس ذخعقسث شري ساهب٠" +"Ùاث Øشس٠يعث شسسهلروثرÙس هرÙØ® Ùاث بعÙعقث, غخع ذشر عØلقشيث Ùخيشغ." + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "عØلقشيث ÙØ® ساهب٠يعث يشÙثس" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "لقشيثي شسسهلروثرÙس شقث شدشهمشزمث ÙØ® دثقهبهثي Ùقشذن مثشقرثقس." + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" +" ÙØ® ذخوØمثÙØ« لقشيثي شسسهلروثرÙس شس Øشق٠خب Ùاهس ذخعقسث, غخع ذشر عØلقشيث " +"Ùخيشغ." + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "صث'دث زعهم٠ش سعللثسÙثي سذاثيعمث ÙØ® Ø§Ø«Ù…Ø ØºØ®Ø¹ سÙشغ خر Ùقشذن." + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" +"زع٠يخر'٠صخققغ—هÙ'س بمثطهزمث سخ غخع ذشر مثشقر ش٠غخعق خصر Øشذث. هب غخع " +"اشØØثر ÙØ® بشمم زثاهري خر خعق سعللثسÙثي يشÙثس, غخع'مم زث شزمث ÙØ® شيتعس٠Ùاثو " +"ÙØ® Ù†Ø«Ø«Ø ØºØ®Ø¹Ù‚Ø³Ø«Ù…Ø¨ خر Ùقشذن." #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -13884,7 +13821,7 @@ msgstr "شر شذذخعر٠صهÙا Ùاث رثص Ø«-وشهم شييقثسس Ø´ msgid "You should Register before trying to access the Unit" msgstr "غخع ساخعمي قثلهسÙثق زثبخقث Ùقغهرل ÙØ® شذذثسس Ùاث عرهÙ" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "ثرقخمم" @@ -13992,7 +13929,7 @@ msgstr "" "شدشهمشزمث.{line_break}هب غخع اشدث ذخوØمثÙثي Ùاهس شسسهلروثرÙ, غخعق لقشيث هس " "شدشهمشزمث خر Ùاث {link_start}Øقخلقثسس Øشلث{link_end}." -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "سثشقذا بخق Ø´ ذخعقسث" @@ -14137,21 +14074,18 @@ msgstr "(قثمخشي غخعق Øشلث ÙØ® قثبقثسا)" msgid "working" msgstr "صخقنهرل" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "Ùاثقث اشس زثثر شر ثققخق خر Ùاث {platform_name} سثقدثقس" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" "صث'قث سخققغ, Ùاهس وخيعمث هس ÙثوØخقشقهمغ عرشدشهمشزمث. خعق سÙشبب هس صخقنهرل ÙØ®" -" بهط ه٠شس سخخر شس Øخسسهزمث. Øمثشسث ثوشهم عس Ø´Ù {tech_support_email} ÙØ® " -"قثØخق٠شرغ Øقخزمثوس خق يخصرÙهوث." +" بهط ه٠شس سخخر شس Øخسسهزمث. " #: lms/templates/module-error.html msgid "Raw data:" @@ -14190,8 +14124,16 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "غخع شقث رخص دهثصهرل Ùاث ذخعقسث شس {i_start}{user_name}{i_end}." #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" -msgstr "دهثص Ùاهس عره٠هر Ùاث رثص ثطØثقهثرذث" +msgid "View in the new experience" +msgstr "دهثص هر Ùاث رثص ثطØثقهثرذث" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "دهثص هر سÙعيهخ" + +#: lms/templates/preview_menu.html +msgid "View in Insights" +msgstr "دهثص هر هرسهلاÙس" #: lms/templates/problem.html msgid "You have used {num_used} of {num_total} attempt" @@ -14257,30 +14199,6 @@ msgstr "Ø«-وشهم" msgid "Return To %s" msgstr "قثÙعقر ÙØ® %s" -#: lms/templates/reset_deadlines_banner.html -msgid "It looks like you've missed some important deadlines. Visit " -msgstr "ه٠مخخنس مهنث غخع'دث وهسسثي سخوث هوØخقÙشر٠يثشيمهرثس. دهسه٠" - -#: lms/templates/reset_deadlines_banner.html -msgid "edx.org" -msgstr "ثيط.خقل" - -#: lms/templates/reset_deadlines_banner.html -msgid " to reset your deadlines and get started today." -msgstr " ÙØ® قثسث٠غخعق يثشيمهرثس شري لث٠سÙشقÙثي Ùخيشغ." - -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" -"ه٠مخخنس مهنث غخع'دث وهسسثي سخوث هوØخقÙشر٠يثشيمهرثس. قثسث٠غخعق يثشيمهرثس " -"شري لث٠سÙشقÙثي Ùخيشغ." - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "قثسث٠وغ يثشيمهرثس" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "قث-سعزسذقهزث سعذذثسسبعم!" @@ -14333,7 +14251,7 @@ msgstr "رثطÙ" msgid "Sequence" msgstr "سثضعثرذث" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "ذخوØمثÙثي" @@ -14464,18 +14382,18 @@ msgstr "سذخقث (بخق خدثققهيث خرمغ)" msgid "Reset Learner's Attempts to Zero" msgstr "قثسث٠مثشقرثق'س Ø´ÙÙثوØÙس ÙØ® ظثقخ" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "يثمثÙØ« مثشقرثق'س سÙØ´ÙØ«" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "قثسذخقث مثشقرثق'س سعزوهسسهخر" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "قثسذخقث خرمغ هب سذخقث هوØقخدثس" @@ -14513,7 +14431,7 @@ msgstr "{course_number} ÙثطÙزخخن" msgid "Textbook Navigation" msgstr "ÙثطÙزخخن رشدهلشÙهخر" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "Øشلث" @@ -14626,9 +14544,9 @@ msgstr "Øشلث {current_page} خب {total_pages}" msgid "Recent git load activity for {course_id}" msgstr "قثذثر٠له٠مخشي شذÙهدهÙغ بخق {course_id}" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -14687,7 +14605,7 @@ msgstr "" "غخع وشغ {dashboard_link_start}قثÙعقر ÙØ® غخعق يشسازخشقي{link_end}. هب غخع يهي" " رخ٠وثشر ÙØ® يخ Ùاهس, {undo_link_start}غخع ذشر قث-سعزسذقهزث{link_end}." -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "يشسازخشقي بخق:" @@ -14695,8 +14613,8 @@ msgstr "يشسازخشقي بخق:" msgid "More options" msgstr "وخقث Ø®ØÙهخرس" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "وخقث Ø®ØÙهخرس" @@ -16191,40 +16109,6 @@ msgstr "" msgid "About edX Certificates" msgstr "شزخع٠ثيط ذثقÙهبهذشÙثس" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "ذاثذنخع٠ذشرذثممثي" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"غخعق ÙقشرسشذÙهخر اشس زثثر ذشرذثممثي. هب غخع بثثم شر ثققخق اشس خذذعققثي, " -"ذخرÙشذ٠{email}." - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "ذاثذنخع٠ثققخق" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" -"شر ثققخق اشس خذذعققثي صهÙا غخعق ØشغوثرÙ. {b_start}غخع اشدث رخ٠زثثر " -"ذاشقلثي.{b_end} Øمثشسث Ùقغ ÙØ® سعزوه٠غخعق Øشغوثر٠شلشهر. هب Ùاهس Øقخزمثو " -"ØثقسهسÙس, ذخرÙشذ٠{email}." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "مخشيهرل خقيثق يشÙØ´..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "Øمثشسث صشه٠صاهمث صث قثÙقهثدث غخعق خقيثق يثÙشهمس." - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -16462,15 +16346,15 @@ msgstr "{section_format} يعث {{date}}" msgid "This content is graded" msgstr "Ùاهس ذخرÙثر٠هس لقشيثي" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "شر ثققخق خذذعققثي. Øمثشسث Ùقغ شلشهر مشÙثق." - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" "شر ثققخق اشس خذذعققثي. Øمثشسث ثرسعقث Ùاش٠غخع شقث مخللثي هر ÙØ® ثرقخمم." +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "شر ثققخق خذذعققثي. Øمثشسث Ùقغ شلشهر مشÙثق." + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "غخع شقث ثرقخممثي هر Ùاهس ذخعقسث" @@ -16482,10 +16366,6 @@ msgstr "غخع شقث ثرقخممثي هر Ùاهس ذخعقسث" msgid "View Course" msgstr "دهثص ذخعقسث" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "Ùاهس ذخعقسث هس هر غخعق {start_cart_link}ذشقÙ{end_cart_link}." - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "ذخعقسث هس بعمم" @@ -16498,10 +16378,6 @@ msgstr "ثرقخمموثر٠هر Ùاهس ذخعقسث هس زغ هردهÙØ´Ù msgid "Enrollment is Closed" msgstr "ثرقخمموثر٠هس ذمخسثي" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "شيي {course_name} ÙØ® ذشق٠{start_span}({price} عسي){end_span}" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "ثرقخمم رخص" @@ -16625,6 +16501,15 @@ msgstr "ذخعقسث عÙهمهÙهثس" msgid "Courseware" msgstr "ذخعقسثصشقث" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" +"صث'قث سخققغ, Ùاهس وخيعمث هس ÙثوØخقشقهمغ عرشدشهمشزمث. خعق سÙشبب هس صخقنهرل ÙØ®" +" بهط ه٠شس سخخر شس Øخسسهزمث." + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "ذخعقسث سثشقذا" @@ -16655,26 +16540,20 @@ msgid "Important Dates" msgstr "هوØخقÙشر٠يشÙثس" #: lms/templates/courseware/dates.html -msgid "Due Today" -msgstr "يعث Ùخيشغ" +msgid "Today" +msgstr "Ùخيشغ" #: lms/templates/courseware/dates.html msgid "Verified Only" msgstr "دثقهبهثي خرمغ" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." -msgstr "" -"{a_start}عØلقشيث{a_end}{space}ÙØ® Ø´ دثقهبهثي ذثقÙهبهذشÙØ« بخق بعمم شذذثسس." +msgid "Due Next" +msgstr "يعث رثطÙ" -#: lms/templates/courseware/error-message.html -msgid "" -"We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible." -msgstr "" -"صث'قث سخققغ, Ùاهس وخيعمث هس ÙثوØخقشقهمغ عرشدشهمشزمث. خعق سÙشبب هس صخقنهرل ÙØ®" -" بهط ه٠شس سخخر شس Øخسسهزمث." +#: lms/templates/courseware/dates.html +msgid "Not yet released" +msgstr "رخ٠غث٠قثمثشسثي" #: lms/templates/courseware/gradebook.html msgid "Gradebook" @@ -17364,10 +17243,10 @@ msgstr "غخع اشدث سعزوهÙÙثي غخعق دثقهبهذشÙهخر Ù‡ #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" "غخع صهمم سثث Ø´ وثسسشلث خر غخعق يشسازخشقي صاثر Ùاث دثقهبهذشÙهخر Øقخذثسس هس " -"ذخوØمثÙØ« (عسعشممغ صهÙاهر 1-2 يشغس)." +"ذخوØمثÙØ« (عسعشممغ صهÙاهر 5-7 يشغس)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -17377,11 +17256,11 @@ msgstr "غخعق ذعققثر٠دثقهبهذشÙهخر صهمم ثطØهقث msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" "غخع اشدث سعزوهÙÙثي غخعق قثدثقهبهذشÙهخر هربخقوشÙهخر. غخع صهمم سثث Ø´ وثسسشلث " "خر غخعق يشسازخشقي صاثر Ùاث دثقهبهذشÙهخر Øقخذثسس هس ذخوØمثÙØ« (عسعشممغ صهÙاهر " -"1-2 يشغس)." +"5-7 يشغس)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -18131,149 +18010,6 @@ msgstr "" "غخعق دثقهبهذشÙهخر صشس سعذذثسسبعم.غخع ذشر شمسخ ذاثذن Ùاث سÙØ´Ùعس خب Ùاث " "دثقهبهذشÙهخر Øقخذثسس خر غخعق يشسازخشقي." -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "Ùاشرن غخع بخق Øعقذاشسهرل ثرقخمموثرÙس هر {course_name}." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"شر هردخهذث بخق {currency_symbol}{total_price} هس Ø´ÙÙشذاثي. Øشغوثر٠هس يعث " -"عØخر قثذثهØÙ. غخع ذشر بهري هربخقوشÙهخر شزخع٠Øشغوثر٠وثÙاخيس خر Ùاث هردخهذث." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -"Ø´ .ذسد بهمث Ùاش٠مهسÙس غخعق ثرقخمموثر٠ذخيثس هس Ø´ÙÙشذاثي. غخع ذشر عسث Ùاث " -"ثوشهم ÙثوØمشÙØ« زثمخص ÙØ® يهسÙقهزعÙØ« ثرقخمموثر٠ذخيثس ÙØ® غخعق سÙعيثرÙس. ثشذا " -"سÙعيثر٠وعس٠عسث Ø´ سثØشقشÙØ« ثرقخمموثر٠ذخيث." - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"Ùاشرنس,\n" -"Ùاث {platform_name} Ùثشو" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "يثشق [[رشوث]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"صث اشدث Øقخدهيثي Ø´ ذخعقسث ثرقخمموثر٠ذخيث بخق غخع هر {course_name}. ÙØ® " -"ثرقخمم هر Ùاث ذخعقسث, ذمهذن Ùاث بخممخصهرل مهرن:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "اÙوم مهرن بقخو Ùاث Ø´ÙÙشذاثي ذسد بهمث" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"شبÙثق غخع ثرقخمم, غخع ذشر سثث Ùاث ذخعقسث خر غخعق سÙعيثر٠يشسازخشقي. غخع ذشر " -"سثث ذخعقسث وشÙثقهشمس شبÙثق Ùاث ذخعقسث سÙشق٠يشÙØ«." - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"سهرذثقثمغ,\n" -"[[غخعق سهلرشÙعقث]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "هردخهذث" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "يشÙØ«: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "هردخهذث رخ: {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "Ùثقوس: يعث عØخر قثذثهØÙ" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "يعث يشÙØ«: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "زهمم ÙØ®:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "ذعسÙخوثق قثبثقثرذث رعوزثق: {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "زشمشرذث يعث: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "ذخعقسث: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"Øقهذث: {currency_symbol}{course_price} ضعشرÙÙ‡Ùغ: {quantity} " -"سعز-ÙØ®Ùشم: {currency_symbol}{sub_total} يهسذخعرÙ: " -"{currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "ÙØ®Ùشم: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "Øشغوثر٠هرسÙقعذÙهخرس" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"هب صث يخ رخ٠قثذثهدث ØشغوثرÙ, Ùاث مثشقرثق ثرقخمموثرÙس Ùاش٠عسث Ùاثسث ذخيثس " -"صهمم زث ذشرذثمثي شري مثشقرثقس صهمم رخ٠زث شزمث ÙØ® شذذثسس ذخعقسث وشÙثقهشمس. " -"شمم Øعقذاشسثس شقث بهرشم. بخق وخقث هربخقوشÙهخر, سثث Ùاث {site_name} " -"ذشرذثممشÙهخر Øخمهذغ." - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "بخق Øشغوثر٠ضعثسÙهخرس, ذخرÙشذ٠{contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -18475,8 +18211,8 @@ msgstr "Ø´ØØمغ بخق بهرشرذهشم شسسهسÙشرذث" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} اخوث Øشلث" @@ -18499,19 +18235,11 @@ msgstr "يهسذخدثق رثص" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "سغسشيوهر" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "ساخØØهرل ذشقÙ" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "سعØØمثوثرÙشم مهرنس" @@ -18548,6 +18276,12 @@ msgstr "شيي ذخعØخر ذخيث" msgid "Enter information about the coupon code below." msgstr "ثرÙثق هربخقوشÙهخر شزخع٠Ùاث ذخعØخر ذخيث زثمخص." +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "ذخعØخر ذخيث" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "يهسذخعر٠ØثقذثرÙشلث" @@ -19157,6 +18891,11 @@ msgstr "يخصرمخشي ذخعØخر ذخيثس" msgid "Coupon Codes" msgstr "ذخعØخر ذخيثس" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "ثطØهقشÙهخر يشÙØ«" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "ذخعØخر (%)" @@ -20551,6 +20290,10 @@ msgstr "Øعقذاشسهرل خقلشرهظشÙهخر" msgid "Purchase order number (if any)" msgstr "Øعقذاشسث خقيثق رعوزثق (هب شرغ)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "ثوشهم شييقثسس" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "ثوشهم@ثطشوØمث.ذخو" @@ -20868,6 +20611,10 @@ msgstr[0] "" msgstr[1] "" "{course_names} اشدث زثثر قثوخدثي زثذشعسث Ùاث ثرقخمموثر٠Øثقهخي اشس ذمخسثي." +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "ساخØØهرل ذشقÙ" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "ذخدثق هوشلث" @@ -21092,46 +20839,6 @@ msgstr "سÙعيثر٠سعØØخقÙ: وشرشلث عسثق" msgid "Program Enrollments Inspector" msgstr "Øقخلقشو ثرقخمموثرÙس هرسØثذÙخق" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "شزخع٠ÙØ® قثبعري Ùاهس خقيثق:" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "خقيثق هي:" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "ثرقخمموثرÙ:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "ثرقخممثي" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "عرثرقخممثي" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "ذخسÙ:" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "ذثقÙهبهذشÙثهÙثو سÙØ´Ùعس:" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "خقيثق سÙØ´Ùعس:" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "بعمبهممثي Ùهوث:" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "قثبعري قثضعثس٠Ùهوث:" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "عسثق سعقدثغ" @@ -21285,11 +20992,11 @@ msgstr "هيثرÙÙ‡Ùغ دثقهبهذشÙهخر" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" "غخع اشدث شمقثشيغ سعزوهÙÙثي غخعق دثقهبهذشÙهخر هربخقوشÙهخر. غخع صهمم سثث Ø´ " "وثسسشلث خر غخعق يشسازخشقي صاثر Ùاث دثقهبهذشÙهخر Øقخذثسس هس ذخوØمثÙØ« (عسعشممغ" -" صهÙاهر 1-2 يشغس)." +" صهÙاهر 5-7 يشغس)." #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -21898,8 +21605,8 @@ msgid "Already registered?" msgstr "شمقثشيغ قثلهسÙثقثي?" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "مخل هر" @@ -22015,12 +21722,8 @@ msgid "The page that you were looking for was not found." msgstr "Ùاث Øشلث Ùاش٠غخع صثقث مخخنهرل بخق صشس رخ٠بخعري." #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." -msgstr "" -"لخ زشذن ÙØ® Ùاث {homepage} خق مث٠عس نرخص شزخع٠شرغ Øشلثس Ùاش٠وشغ اشدث زثثر " -"وخدثي Ø´Ù {email}." +msgid "Go back to the {homepage}." +msgstr "لخ زشذن ÙØ® Ùاث {homepage}." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -22046,10 +21749,6 @@ msgstr "" "صث'دث مخللثي Ùاث ثققخق شري خعق سÙشبب هس ذعققثرÙمغ صخقنهرل ÙØ® قثسخمدث Ùاهس " "ثققخق شس سخخر شس Øخسسهزمث." -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "هب Ùاث Øقخزمثو ØثقسهسÙس, Øمثشسث ثوشهم عس Ø´Ù {email_link}." - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "سÙعيهخ شذذثسسهزهمهÙغ Øخمهذغ" @@ -22742,14 +22441,10 @@ msgstr "Ùاث Øشلث غخع قثضعثسÙثي Øشلث ذشررخ٠زث ب #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" "صث'قث سخققغ. صث ذخعمير'٠بهري Ùاث {studio_name} Øشلث غخع'قث مخخنهرل بخق. غخع" -" وشغ صشر٠ÙØ® قثÙعقر ÙØ® Ùاث {studio_name} يشسازخشقي شري Ùقغ شلشهر. هب غخع شقث" -" سÙهمم اشدهرل Øقخزمثوس شذذثسسهرل Ùاهرلس, Øمثشسث بثثم بقثث ÙØ® " -"{link_start}ذخرÙشذ٠{studio_name} سعØØخقÙ{link_end} بخق بعقÙاثق اثمØ." +" وشغ صشر٠ÙØ® قثÙعقر ÙØ® Ùاث {studio_name} يشسازخشقي شري Ùقغ شلشهر." #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -22759,15 +22454,11 @@ msgstr "Ùاث سثقدثق ثرذخعرÙثقثي شر ثققخق" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" "صث'قث سخققغ. Ùاثقث صشس Ø´ Øقخزمثو صهÙا Ùاث سثقدثق صاهمث Ùقغهرل ÙØ® Øقخذثسس " "غخعق مشس٠قثضعثسÙ. غخع وشغ صشر٠ÙØ® قثÙعقر ÙØ® Ùاث {studio_name} يشسازخشقي خق " -"Ùقغ Ùاهس قثضعثس٠شلشهر. هب غخع شقث سÙهمم اشدهرل Øقخزمثوس شذذثسسهرل Ùاهرلس, " -"Øمثشسث بثثم بقثث ÙØ® {link_start}ذخرÙشذ٠{studio_name} سعØØخقÙ{link_end} بخق " -"بعقÙاثق اثمØ." +"Ùقغ Ùاهس قثضعثس٠شلشهر." #: cms/templates/error.html msgid "Back to dashboard" @@ -26126,8 +25817,8 @@ msgstr "%(file)s اشس زثثر ذاشرلثي ÙØ® قثدهسهخر #%(revisio msgid "%(file)s has been saved." msgstr "%(file)s اشس زثثر سشدثي." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "هوشلثس" @@ -26332,8 +26023,8 @@ msgstr "ذمثشق رخÙهبهذشÙهخرس مهسÙ" msgid "Search..." msgstr "سثشقذا..." -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "سهلر عØ" diff --git a/conf/locale/rtl/LC_MESSAGES/djangojs.mo b/conf/locale/rtl/LC_MESSAGES/djangojs.mo index 3694b1f20a52e5eb0b64e4b96fda02665c859256..e96fa6e9d729ad42c1edabbfceebeb87dfe6bd94 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 f64dc57ef41ff38a934cf991ae05c8152600d2bc..680c3d61b442aba0feac4bbf3e1b73db5462b8ec 100644 --- a/conf/locale/rtl/LC_MESSAGES/djangojs.po +++ b/conf/locale/rtl/LC_MESSAGES/djangojs.po @@ -32,8 +32,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:53+0000\n" -"PO-Revision-Date: 2020-04-12 20:53:38.541186\n" +"POT-Creation-Date: 2020-06-21 20:50+0000\n" +"PO-Revision-Date: 2020-06-21 20:50:24.441486\n" "Last-Translator: \n" "Language-Team: openedx-translation <openedx-translation@googlegroups.com>\n" "Language: rtl\n" @@ -41,7 +41,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -77,6 +77,7 @@ msgstr "سشدهرل" #: cms/templates/js/signatory-editor.underscore #: cms/templates/js/video-transcripts.underscore #: cms/templates/js/xblock-outline.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Delete" msgstr "يثمثÙØ«" @@ -105,6 +106,7 @@ msgstr "يثمثÙØ«" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -127,6 +129,7 @@ msgstr "عØمخشيهرل" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -156,6 +159,7 @@ msgstr "ذاخخسث بهمث" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "خن" @@ -746,7 +750,6 @@ msgstr "يثمثÙØ« Ùشزمث" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "يثسذقهØÙهخر" @@ -793,6 +796,7 @@ msgstr "ثيه٠اÙوم" #: cms/templates/js/show-textbook.underscore #: cms/templates/js/signatory-details.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Edit" msgstr "ثيهÙ" @@ -1195,6 +1199,7 @@ msgstr "رثص صهريخص" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "رثطÙ" @@ -1544,6 +1549,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/course-instructor-details.underscore #: cms/templates/js/signatory-details.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Title" msgstr "ÙÙ‡Ùمث" @@ -2018,6 +2024,7 @@ msgid "Your request could not be processed. Refresh the page and try again." msgstr "غخعق قثضعثس٠ذخعمي رخ٠زث Øقخذثسسثي. قثبقثسا Ùاث Øشلث شري Ùقغ شلشهر." #: common/static/common/js/discussion/utils.js +#: common/static/common/templates/discussion/templates.underscore msgid "…" msgstr "…" @@ -2217,6 +2224,7 @@ msgid "Your post will be discarded." msgstr "غخعق Øخس٠صهمم زث يهسذشقيثي." #: common/static/common/js/discussion/views/response_comment_show_view.js +#: common/static/common/templates/discussion/templates.underscore msgid "anonymous" msgstr "شرخرغوخعس" @@ -2480,31 +2488,44 @@ msgid "Other" msgstr "Ø®Ùاثق" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" -msgstr "صاش٠ذشر صث Ø§Ø«Ù…Ø ØºØ®Ø¹ صهÙا, {username}?" +msgid "Course Discussion Forum" +msgstr "ذخعقسث يهسذعسسهخر بخقعو" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." +msgstr "" +"صاهمث خعق سعØØخق٠Ùثشو هس اشØØغ ÙØ® شسسهس٠صهÙا Ùاث ثيط ØمشÙبخقو, Ùاث ذخعقسث " +"سÙشبب اشس Ùاث ثطØثقÙهسث بخق سØثذهبهذ شسسهلروثر٠ضعثسÙهخرس, لقشيهرل خق Ùاث " +"ØقخØثق Øقخذثيعقثس هر ثشذا ذخعقسث. Øمثشسث Øخس٠شمم ذخعقسث قثمشÙثي ضعثسÙهخرس " +"صهÙاهر Ùاث يهسذعسسهخر بخقعو صاثقث Ùاث ذخعقسث سÙشبب ذشر يهقثذÙمغ قثسØخري." #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Details" msgstr "يثÙشهمس" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" -msgstr "Ùاث وخقث غخع Ùثمم عس, Ùاث وخقث ضعهذنمغ شري اثمØبعممغ صث ذشر قثسØخري!" +msgid "the more quickly and helpfully we can respond!" +msgstr "Ùاث وخقث ضعهذنمغ شري اثمØبعممغ صث ذشر قثسØخري!" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "سعزوهÙ" +msgid "Create Support Ticket" +msgstr "ذقثشÙØ« سعØØخق٠ÙهذنثÙ" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "صاش٠ذشر صث Ø§Ø«Ù…Ø ØºØ®Ø¹ صهÙا, {username}?" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "سهلر هر ÙØ® {platform} سخ صث ذشر Ø§Ø«Ù…Ø ØºØ®Ø¹ زثÙÙثق." #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." -msgstr "" -"هب غخع شقث عرشزمث ÙØ® شذذثسس غخعق شذذخعر٠ذخرÙشذ٠عس دهش ثوشهم عسهرل {email}." +msgid "Need help logging in?" +msgstr "رثثي Ø§Ø«Ù…Ø Ù…Ø®Ù„Ù„Ù‡Ø±Ù„ هر?" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "" @@ -2522,6 +2543,22 @@ msgstr "سثمثذ٠ش سعزتثذ٠بخق غخعق سعØØخق٠قثضعث msgid "Enter some details for your support request." msgstr "ثرÙثق سخوث يثÙشهمس بخق غخعق سعØØخق٠قثضعثسÙ." +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" +"يعث ÙØ® Ùاث قثذثر٠هرذقثشسث هر هرÙثقثس٠هر خرمهرث ثيعذشÙهخر شري ثيط, صث شقث " +"ذعققثرÙمغ ثطØثقهثرذهرل شر عرعسعشممغ اهلا دخمعوث خب سعØØخق٠قثضعثسÙس. صث " +"Ø´ØØقثذهشÙØ« غخعق ØØ´Ùهثرذث شس صث صخقن ÙØ® قثدهثص ثشذا قثضعثسÙ. Øمثشسث ذاثذن Ùاث" +" " + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr " شس وشرغ ضعثسÙهخرس وشغ اشدث شمقثشيغ زثثر شرسصثقثي." + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2545,9 +2582,11 @@ msgstr "لخ ÙØ® {platform} اخوث" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" -"Ùاشرن غخع بخق سعزوهÙÙهرل Ø´ قثضعثسÙ! صث صهمم ذخرÙشذ٠غخع صهÙاهر 24 اخعقس." +"Ùاشرن غخع بخق سعزوهÙÙهرل Ø´ قثضعثسÙ! صث Ø´ØØقثذهشÙØ« غخعق ØØ´Ùهثرذث صاهمث صث " +"صخقن ÙØ® قثدهثص غخعق قثضعثسÙ." #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx msgid "Cancel upload" @@ -2733,6 +2772,10 @@ msgstr "دهثص {span_start} {team_name} {span_end}" msgid "An error occurred. Try again." msgstr "شر ثققخق خذذعققثي. Ùقغ شلشهر." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "رخ شسسهلروثرÙس بخق Ùثشو" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "مثشدث Ùاهس Ùثشو?" @@ -3267,6 +3310,7 @@ msgid "There has been an error processing your survey." msgstr "Ùاثقث اشس زثثر شر ثققخق Øقخذثسسهرل غخعق سعقدثغ." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -3283,6 +3327,7 @@ msgid "HTML preview of post" msgstr "اÙوم Øقثدهثص خب ØخسÙ" #: lms/static/js/customwmd.js +#: common/static/common/templates/discussion/templates.underscore msgid "Your question or idea (required)" msgstr "غخعق ضعثسÙهخر خق هيثش (قثضعهقثي)" @@ -5507,6 +5552,10 @@ msgstr "غثس, شممخص ثيهÙس ÙØ® Ùاث شذÙهدث ذثقÙهبهذ msgid "certificate" msgstr "ذثقÙهبهذشÙØ«" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "يثشذÙهدشÙهرل" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Ø³Ø«Ù Ø¹Ø ØºØ®Ø¹Ù‚ ذثقÙهبهذشÙØ«" @@ -5518,8 +5567,8 @@ msgid "You have not created any certificates yet." msgstr "غخع اشدث رخ٠ذقثشÙثي شرغ ذثقÙهبهذشÙثس غثÙ." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "يثمثÙØ« \"<%= signatoryName %>\" بقخو Ùاث مهس٠خب سهلرشÙخقهثس?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "يثمثÙØ« \"<%- signatoryName %>\" بقخو Ùاث مهس٠خب سهلرشÙخقهثس?" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5571,6 +5620,7 @@ msgstr "" #: cms/static/js/factories/manage_users.js #: cms/static/js/factories/manage_users_lib.js +#: common/static/common/templates/discussion/templates.underscore msgid "Staff" msgstr "سÙشبب" @@ -5825,11 +5875,11 @@ msgstr "شمم ذاشØÙثقس وعس٠اشدث Ø´ رشوث شري شسسثÙ" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" -"خرمغ <%= fileTypes %> بهمثس ذشر زث عØمخشيثي. Øمثشسث سثمثذ٠ش بهمث ثريهرل هر " -"<%= fileExtensions %> ÙØ® عØمخشي." +"خرمغ <%- fileTypes %> بهمثس ذشر زث عØمخشيثي. Øمثشسث سثمثذ٠ش بهمث ثريهرل هر " +"<%- (fileExtensions) %> ÙØ® عØمخشي." #: cms/static/js/models/uploads.js #: lms/templates/student_account/hinted_login.underscore @@ -6010,8 +6060,8 @@ msgid "{selectedProvider} credentials saved" msgstr "{selectedProvider} ذقثيثرÙهشمس سشدثي" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" -msgstr "عØمخشي Ø´ رثص Øيب ÙØ® “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" +msgstr "عØمخشي Ø´ رثص Øيب ÙØ® “<%- name %>â€" #: cms/static/js/views/edit_chapter.js msgid "Please select a PDF file to upload." @@ -6615,18 +6665,18 @@ msgstr "صث'قث سخققغ, Ùاثقث صشس شر ثققخق" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" "Ùاث ذخوزهرثي مثرلÙا خب Ùاث خقلشرهظشÙهخر, ذخعقسث رعوزثق, شري ذخعقسث قعر " -"بهثميس ذشررخ٠زث وخقث Ùاشر <%=limit%> ذاشقشذÙثقس." +"بهثميس ذشررخ٠زث وخقث Ùاشر <%- limit %> ذاشقشذÙثقس." #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" "Ùاث ذخوزهرثي مثرلÙا خب Ùاث خقلشرهظشÙهخر شري مهزقشقغ ذخيث بهثميس ذشررخ٠زث " -"وخقث Ùاشر <%=limit%> ذاشقشذÙثقس." +"وخقث Ùاشر <%- limit %> ذاشقشذÙثقس." #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -6988,13 +7038,13 @@ msgid "Unscheduled" msgstr "عرسذاثيعمثي" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "يشÙØ«" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Øقثدهخعس" @@ -7042,6 +7092,317 @@ msgstr "ذمثشق سثشقذا" msgid "Search" msgstr "سثشقذا" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "شيي Ø´ قثسØخرسث" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "Ùاهس Ùاقثشي هس ذمخسثي." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "شيي Ø´ قثسØخرسث:" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "سعزوهÙ" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "يهسذعسسهخر ØخسÙثي %(time_ago)s زغ %(author)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "ضعثسÙهخر ØخسÙثي %(time_ago)s زغ %(author)s" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "Øهررثي" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "قثØخقÙثي" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "ذمخسثي" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "قثمشÙثي ÙØ®: %(courseware_title_linked)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "Ùاهس Øخس٠هس دهسهزمث خرمغ ÙØ® %(group_name)s." + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "Ùاهس Øخس٠هس دهسهزمث ÙØ® ثدثقغخرث." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "ثيهÙهرل ØخسÙ" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" +"شيي Ø´ ذمثشق شري يثسذقهØÙهدث ÙÙ‡Ùمث ÙØ® ثرذخعقشلث ØشقÙهذهØØ´Ùهخر. (قثضعهقثي)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "ثيه٠غخعق Øخس٠زثمخص." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "عØيشÙØ« ØخسÙ" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "ساخص ذخووثر٠(%(num_comments)s)" +msgstr[1] "ساخص ذخووثرÙس (%(num_comments)s)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "شيي Ø´ ذخووثرÙ" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "وشقنثي شس شرسصثق %(time_ago)s زغ %(user)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "وشقنثي شس شرسصثق %(time_ago)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "ثريخقسثي %(time_ago)s زغ %(user)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "ثريخقسثي %(time_ago)s" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "ثيهÙهرل قثسØخرسث" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "عØيشÙØ« قثسØخرسث" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "ØخسÙثي %(time_ago)s زغ %(author)s" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "ثيهÙهرل ذخووثرÙ" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "عØيشÙØ« ذخووثرÙ" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "يهسذعسسهخر" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "شرسصثقثي ضعثسÙهخر" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "عرشرسصثقثي ضعثسÙهخر" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "بخممخصهرل" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "ذخووعرهÙغ ÙØ´" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "{unread_comments_count} رثص" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" +"%(comments_count)s %(span_sr_open)sذخووثرÙس (%(unread_comments_count)s " +"عرقثشي ذخووثرÙس)%(span_close)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "%(comments_count)s %(span_sr_open)sذخووثرÙس %(span_close)s" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "شيي Ø´ ØخسÙ" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "دهسهزمث ÙØ®" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" +"يهسذعسسهخر شيوهرس, وخيثقشÙخقس, شري Ùشس ذشر وشنث Ùاثهق ØخسÙس دهسهزمث ÙØ® شمم " +"سÙعيثرÙس خق سØثذهبغ Ø´ سهرلمث لقخعØ." + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "شمم لقخعØس" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "بخممخص Ùاهس ØخسÙ" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "Øخس٠شرخرغوخعسمغ" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "Øخس٠شرخرغوخعسمغ ÙØ® ذمشسسوشÙثس" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "ثققخق ØخسÙهرل غخعق وثسسشلث." + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "Ùاهس Øخس٠صهمم زث دهسهزمث خرمغ ÙØ® %(group_name)s." + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "Ùاهس Øخس٠صهمم زث دهسهزمث ÙØ® ثدثقغخرث." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "ÙØ®Øهذ شقثش" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "شيي غخعق Øخس٠ÙØ® Ø´ قثمثدشر٠ÙØ®Øهذ ÙØ® Ø§Ø«Ù…Ø Ø®Ùاثقس بهري Ù‡Ù. (قثضعهقثي)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "(ذخووعرهÙغ ÙØ´)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "(سÙشبب)" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "شمم ØخسÙس" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "قثÙعقر ÙØ® شمم ØخسÙس" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "دهثص يهسذعسسهخر" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "مخشي وخقث" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "Øخس٠ÙغØØ«" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" +"ضعثسÙهخرس قشهسث هسسعثس Ùاش٠رثثي شرسصثقس. يهسذعسسهخرس ساشقث هيثشس شري سÙشق٠" +"ذخردثقسشÙهخرس. (قثضعهقثي)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "ضعثسÙهخر" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "يهسذعسسهخر" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "ثريخقسث" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "عرثريخقسث" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "وشقن شس شرسصثق" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "عروشقن شس شرسصثق" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "بخممخص" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "عربخممخص" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "دخÙØ« بخق Ùاهس ØخسÙ," + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "قثØخق٠شزعسث" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "قثØخقÙ" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "عرقثØخقÙ" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "Øهر" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "عرØهر" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "Ø®Øثر" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "يهسذعسسهخر اخوث" @@ -7100,10 +7461,6 @@ msgstr "" "ذاثذن Ùاهس زخط ÙØ® قثذثهدث شر ثوشهم يهلثس٠خرذث Ø´ يشغ رخÙهبغهرل غخع شزخع٠" "رثص, عرقثشي شذÙهدهÙغ بقخو ØخسÙس غخع شقث بخممخصهرل." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "شمم ØخسÙس" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "عسثقرشوث خق ثوشهم" @@ -7342,6 +7699,10 @@ msgstr "شقث غخع اشدهرل Ùقخعزمث بهريهرل Ø´ Ùثشو Ù msgid "Join Team" msgstr "تخهر Ùثشو" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "Ùثشو شسسهلروثرÙس" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "Ùثشو يثÙشهمس" @@ -7428,104 +7789,6 @@ msgstr "قثوخدث سعزسثذÙهخر %(subsectionDisplayName)s" msgid "Remove unit %(unitName)s" msgstr "قثوخدث عره٠%(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" -"غخع سÙهمم رثثي ÙØ® دهسه٠Ùاث %(display_name)s صثزسهÙØ« ÙØ® ذخوØمثÙØ« Ùاث ذقثيه٠" -"Øقخذثسس." - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"ÙØ® بهرشمهظث ذخعقسث ذقثيهÙ, %(display_name)s قثضعهقثس %(platform_name)s " -"مثشقرثقس ÙØ® سعزوه٠ش ذقثيه٠قثضعثسÙ." - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "لث٠ذقثيهÙ" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" -"Ùاشرن غخع %(full_name)s! صث اشدث قثذثهدثي غخعق Øشغوثر٠بخق %(course_name)s." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"Øمثشسث Øقهر٠Ùاهس Øشلث بخق غخعق قثذخقيس; ه٠سثقدثس شس غخعق قثذثهØÙ. غخع صهمم" -" شمسخ قثذثهدث شر ثوشهم صهÙا Ùاث سشوث هربخقوشÙهخر." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "خقيثق رخ." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "شوخعرÙ" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "ÙØ®Ùشم" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Øمثشسث رخÙØ«" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "ذقخسسثي خع٠هÙثوس اشدث زثثر قثبعريثي." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "زهممثي ÙØ®" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "رخ قثذثهØ٠شدشهمشزمث" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "لخ ÙØ® يشسازخشقي" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" -"هب غخع يخر'٠دثقهبغ غخعق هيثرÙÙ‡Ùغ رخص, غخع ذشر سÙهمم ثطØمخقث غخعق ذخعقسث " -"بقخو غخعق يشسازخشقي. غخع صهمم قثذثهدث Øثقهخيهذ قثوهريثقس بقخو {platformName}" -" ÙØ® دثقهبغ غخعق هيثرÙÙ‡Ùغ." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "صشر٠ÙØ® ذخربهقو غخعق هيثرÙÙ‡Ùغ مشÙثق?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "دثقهبغ رخص" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "وشقن ثطشو شس ذخوØمثÙثي" @@ -7657,10 +7920,10 @@ msgstr "شزخع٠غخع" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" "Ùاث بخممخصهرل هربخقوشÙهخر هس شمقثشيغ Ø´ Øشق٠خب غخعق {platform} Øقخبهمث. " -"صث\\'دث هرذمعيثي ه٠اثقث بخق غخعق Ø´ØØمهذشÙهخر." +"صث'دث هرذمعيثي ه٠اثقث بخق غخعق Ø´ØØمهذشÙهخر." #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7690,6 +7953,10 @@ msgstr "" "Ùاشرن غخع بخق سعزوهÙÙهرل غخعق بهرشرذهشم شسسهسÙشرذث Ø´ØØمهذشÙهخر بخق " "{course_name}! غخع ذشر ثطØثذ٠ش قثسØخرسث هر 2-4 زعسهرثسس يشغس." +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "لخ ÙØ® يشسازخشقي" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "زعمن ثطذثØÙهخرس" @@ -8050,14 +8317,6 @@ msgstr "غخع ذشر رخ مخرلثق ذاشرلث سثسسهخرس." msgid "You can change sessions until {expiration_date}." msgstr "غخع ذشر ذاشرلث سثسسهخرس عرÙهم {expiration_date}." -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "بهرشم لقشيث" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "بخق {courseName}" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "دهثص شقذاهدثي ذخعقسث" @@ -8282,8 +8541,28 @@ msgid "An error occurred. Please reload the page." msgstr "شر ثققخق خذذعققثي. Øمثشسث قثمخشي Ùاث Øشلث." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" -msgstr "رثثي Ø§Ø«Ù…Ø Ù…Ø®Ù„Ù„Ù‡Ø±Ù„ هر?" +msgid "Need help signing in?" +msgstr "رثثي Ø§Ø«Ù…Ø Ø³Ù‡Ù„Ø±Ù‡Ø±Ù„ هر?" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "بخقلخ٠وغ Øشسسصخقي" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "Ø®Ùاثق سهلر-هر هسسعثس" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "سهلر هر صهÙا غخعق ذخوØشرغ خق سذاخخم" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "رثثي Ø®Ùاثق Ø§Ø«Ù…Ø Ø³Ù‡Ù„Ø±Ù‡Ø±Ù„ هر?" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" +msgstr "ذقثشÙØ« شر شذذخعرÙ" #: lms/templates/student_account/hinted_login.underscore #: lms/templates/student_account/login.underscore @@ -8493,32 +8772,24 @@ msgid "What You Need for Verification" msgstr "صاش٠غخع رثثي بخق دثقهبهذشÙهخر" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "صثزذشو" +msgid "Device with Camera" +msgstr "يثدهذث صهÙا ذشوثقش" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" -"غخع رثثي Ø´ ذخوØعÙثق خق ذثمم Øاخرث Ùاش٠اشس Ø´ صثزذشو. صاثر غخع قثذثهدث Ø´ " -"زقخصسثق ØقخوØÙ, وشنث سعقث Ùاش٠غخع شممخص شذذثسس ÙØ® Ùاث ذشوثقش." +"غخع رثثي Ø´ يثدهذث Ùاش٠اشس Ø´ صثزذشو. هب غخع قثذثهدث Ø´ زقخصسثق ØقخوØ٠بخق " +"شذذثسس ÙØ® غخعق ذشوثقش, Øمثشسث وشنث سعقث ÙØ® ذمهذن 'شممخص'." #: lms/templates/verify_student/face_photo_step.underscore msgid "Photo Identification" msgstr "ØاخÙØ® هيثرÙهبهذشÙهخر" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." -msgstr "" -"غخع رثثي Ø´ يقهدثق'س مهذثرسث, ØشسسØخقÙ, خق Ø®Ùاثق لخدثقروثرÙ-هسسعثي هي Ùاش٠" -"اشس غخعق رشوث شري ØاخÙØ®." +msgid "You need a valid ID that contains your full name and photo." +msgstr "غخع رثثي Ø´ دشمهي هي Ùاش٠ذخرÙشهرس غخعق بعمم رشوث شري ØاخÙØ®." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8545,17 +8816,13 @@ msgstr "غخعق بشذث هس صثمم-مهÙ." msgid "Your entire face fits inside the frame." msgstr "غخعق ثرÙهقث بشذث بهÙس هرسهيث Ùاث بقشوث." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "Ùاث ØاخÙØ® خب غخعق بشذث وشÙذاثس Ùاث ØاخÙØ® خر غخعق هي." - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" -"ÙØ® عسث Ùاث ذعققثر٠ØاخÙØ®, سثمثذ٠Ùاث Ùشنث ØاخÙØ® زعÙÙخر {icon}. ÙØ® Ùشنث " -"شرخÙاثق ØاخÙØ®, سثمثذ٠Ùاث قثÙشنث ØاخÙØ® زعÙÙخر {icon}." +"ÙØ® Ùشنث Ùاث ØاخÙØ® خب غخعق بشذث, ذمهذن خر Ùاث ذشوثقش زعÙÙخر {icon}. هب غخع " +"رثثي ÙØ® Ùقغ شلشهر, ذمهذن 'قثÙشنث ØاخÙØ®'." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8571,16 +8838,12 @@ msgid "Why does %(platformName)s need my photo?" msgstr "صاغ يخثس %(platformName)s رثثي وغ ØاخÙØ®?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"شس Øشق٠خب Ùاث دثقهبهذشÙهخر Øقخذثسس, غخع Ùشنث Ø´ ØاخÙØ® خب زخÙا غخعق بشذث شري " -"Ø´ لخدثقروثرÙ-هسسعثي ØاخÙØ® هي. خعق شعÙاخقهظشÙهخر سثقدهذث ذخربهقوس غخعق " -"هيثرÙÙ‡Ùغ زغ ذخوØشقهرل Ùاث ØاخÙØ® غخع Ùشنث صهÙا Ùاث ØاخÙØ® خر غخعق هي." +"صث عسث غخعق دثقهبهذشÙهخر ØاخÙخس ÙØ® ذخربهقو غخعق هيثرÙÙ‡Ùغ شري ثرسعقث Ùاث " +"دشمهيهÙغ خب غخعق ذثقÙهبهذشÙØ«." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8591,18 +8854,15 @@ msgstr "صاش٠يخثس %(platformName)s يخ صهÙا Ùاهس ØاخÙØ®?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"صث عسث Ùاث اهلاثس٠مثدثمس خب سثذعقهÙغ شدشهمشزمث ÙØ® ثرذقغØ٠غخعق ØاخÙØ® شري " -"سثري Ù‡Ù ÙØ® خعق شعÙاخقهظشÙهخر سثقدهذث بخق قثدهثص. غخعق ØاخÙØ® شري هربخقوشÙهخر " -"شقث رخ٠سشدثي خق دهسهزمث شرغصاثقث خر %(platformName)s شبÙثق Ùاث دثقهبهذشÙهخر" -" Øقخذثسس هس ذخوØمثÙØ«." +"صث سثذعقثمغ ثرذقغØ٠غخعق ØاخÙØ® شري سثري Ù‡Ù ÙØ® خعق شعÙاخقهظشÙهخر سثقدهذث بخق " +"قثدهثص. غخعق ØاخÙØ® شري هربخقوشÙهخر شقث رخ٠سشدثي خق دهسهزمث شرغصاثقث خر " +"%(platformName)s شبÙثق Ùاث دثقهبهذشÙهخر Øقخذثسس هس ذخوØمثÙØ«." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8676,20 +8936,16 @@ msgid "Take a Photo of Your ID" msgstr "Ùشنث Ø´ ØاخÙØ® خب غخعق هي" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." -msgstr "" -"عسث غخعق صثزذشو ÙØ® Ùشنث Ø´ ØاخÙØ® خب غخعق هي. صث صهمم وشÙذا Ùاهس ØاخÙØ® صهÙا " -"Ùاث ØاخÙØ® خب غخعق بشذث شري Ùاث رشوث خر غخعق شذذخعرÙ." +msgid "Use your webcam to take a photo of your ID." +msgstr "عسث غخعق صثزذشو ÙØ® Ùشنث Ø´ ØاخÙØ® خب غخعق هي." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"غخع رثثي شر هي صهÙا غخعق رشوث شري ØاخÙØ®. Ø´ يقهدثق'س مهذثرسث, ØشسسØخقÙ, خق " -"Ø®Ùاثق لخدثقروثرÙ-هسسعثي هيس شقث شمم شذذثØÙشزمث." +"غخع رثثي شر هي صهÙا غخعق رشوث شري ØاخÙØ®. Ø´ يقهدثق'س مهذثرسث, ØشسسØخقÙ, خق هي" +" شقث شمم شذذثØÙشزمث." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8713,6 +8969,16 @@ msgstr "خرذث هر ØخسهÙهخر, عسث Ùاث Ùشنث ØاخÙØ® زع٠msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "عسث Ùاث قثÙشنث ØاخÙØ® زعÙÙخر هب غخع شقث رخ٠Øمثشسثي صهÙا غخعق ØاخÙØ®" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" +"شس Øشق٠خب Ùاث دثقهبهذشÙهخر Øقخذثسس, غخع Ùشنث Ø´ ØاخÙØ® خب زخÙا غخعق بشذث شري " +"Ø´ ØاخÙØ® هي. خعق شعÙاخقهظشÙهخر سثقدهذث ذخربهقوس غخعق هيثرÙÙ‡Ùغ زغ ذخوØشقهرل " +"Ùاث ØاخÙØ® غخع Ùشنث صهÙا Ùاث ØاخÙØ® خر غخعق هي." + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8769,6 +9035,29 @@ msgstr "" msgid "Can we match the photo you took with the one on your ID?" msgstr "ذشر صث وشÙذا Ùاث ØاخÙØ® غخع Ùخخن صهÙا Ùاث خرث خر غخعق هي?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"شس Øشق٠خب Ùاث دثقهبهذشÙهخر Øقخذثسس, غخع Ùشنث Ø´ ØاخÙØ® خب زخÙا غخعق بشذث شري " +"Ø´ لخدثقروثرÙ-هسسعثي ØاخÙØ® هي. خعق شعÙاخقهظشÙهخر سثقدهذث ذخربهقوس غخعق " +"هيثرÙÙ‡Ùغ زغ ذخوØشقهرل Ùاث ØاخÙØ® غخع Ùشنث صهÙا Ùاث ØاخÙØ® خر غخعق هي." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"صث عسث Ùاث اهلاثس٠مثدثمس خب سثذعقهÙغ شدشهمشزمث ÙØ® ثرذقغØ٠غخعق ØاخÙØ® شري " +"سثري Ù‡Ù ÙØ® خعق شعÙاخقهظشÙهخر سثقدهذث بخق قثدهثص. غخعق ØاخÙØ® شري هربخقوشÙهخر " +"شقث رخ٠سشدثي خق دهسهزمث شرغصاثقث خر %(platformName)s شبÙثق Ùاث دثقهبهذشÙهخر" +" Øقخذثسس هس ذخوØمثÙØ«." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "Ùاشرنس بخق قثÙعقرهرل ÙØ® دثقهبغ غخعق هي هر: {courseName}" @@ -8802,6 +9091,13 @@ msgstr "" "Ø´ يقهدثق'س مهذثرسث, ØشسسØخقÙ, خق Ø®Ùاثق لخدثقروثرÙ-هسسعثي هي صهÙا غخعق رشوث " "شري ØاخÙØ®" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "صثزذشو" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8903,6 +9199,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "ذاثذن غخعق ثوشهم بخق شر شذÙهدشÙهخر وثسسشلث." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "ÙØ®Ùشم" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "Øقخبثسسهخرشم ذثقÙهبهذشÙØ« بخق {courseName}" @@ -8945,6 +9246,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "Ùاشرن غخع! صث اشدث قثذثهدثي غخعق Øشغوثر٠بخق {courseName}." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"Øمثشسث Øقهر٠Ùاهس Øشلث بخق غخعق قثذخقيس; ه٠سثقدثس شس غخعق قثذثهØÙ. غخع صهمم" +" شمسخ قثذثهدث شر ثوشهم صهÙا Ùاث سشوث هربخقوشÙهخر." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "خقيثق رخ." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "شوخعرÙ" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Øمثشسث رخÙØ«" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "ذقخسسثي خع٠هÙثوس اشدث زثثر قثبعريثي." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "زهممثي ÙØ®" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "رخ قثذثهØ٠شدشهمشزمث" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "رثط٠سÙØ«Ø: ذخربهقو غخعق هيثرÙÙ‡Ùغ" @@ -8980,6 +9313,10 @@ msgstr "" "بقخو غخعق يشسازخشقي. غخع صهمم قثذثهدث Øثقهخيهذ قثوهريثقس بقخو " "%(platformName)s ÙØ® دثقهبغ غخعق هيثرÙÙ‡Ùغ." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "صشر٠ÙØ® ذخربهقو غخعق هيثرÙÙ‡Ùغ مشÙثق?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "هيثرÙÙ‡Ùغ دثقهبهذشÙهخر هر Øقخلقثسس" @@ -8988,12 +9325,12 @@ msgstr "هيثرÙÙ‡Ùغ دثقهبهذشÙهخر هر Øقخلقثسس" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" "صث اشدث قثذثهدثي غخعق هربخقوشÙهخر شري شقث دثقهبغهرل غخعق هيثرÙÙ‡Ùغ. غخع صهمم " "سثث Ø´ وثسسشلث خر غخعق يشسازخشقي صاثر Ùاث دثقهبهذشÙهخر Øقخذثسس هس ذخوØمثÙØ« " -"(عسعشممغ صهÙاهر 1-2 يشغس). هر Ùاث وثشرÙهوث, غخع ذشر سÙهمم شذذثسس شمم " +"(عسعشممغ صهÙاهر 5-7 يشغس). هر Ùاث وثشرÙهوث, غخع ذشر سÙهمم شذذثسس شمم " "شدشهمشزمث ذخعقسث ذخرÙثرÙ." #: lms/templates/verify_student/reverify_success_step.underscore @@ -9030,10 +9367,6 @@ msgstr "ØاخÙØ® قثضعهقثوثرÙس:" msgid "Does the photo of you show your whole face?" msgstr "يخثس Ùاث ØاخÙØ® خب غخع ساخص غخعق صاخمث بشذث?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "يخثس Ùاث ØاخÙØ® خب غخع وشÙذا غخعق هي ØاخÙØ®?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "هس غخعق رشوث خر غخعق هي قثشيشزمث?" @@ -10539,6 +10872,28 @@ msgstr "سث٠شس Ø´ سØثذهشم ثطشو" msgid "Exam Types" msgstr "ثطشو ÙغØثس" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" +"Ùاهس سعزسثذÙهخر صشس قثمثشسثي ÙØ® مثشقرثقس شس Ø´ سØثذهشم ثطشو, زع٠صشس قثدثقÙثي" +" زشذن ÙØ® Ø´ زشسهذ ثطشو. غخع وشغ رخ٠ذخربهلعقث ه٠شس Ø´ سØثذهشم ثطشو رخص. " +"ذخرÙشذ٠ثيط سعØØخق٠بخق شسسهسÙشرذث." + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" +"Ùاهس سØثذهشم ثطشو اشس زثثر قثمثشسثي ÙØ® مثشقرثقس. غخع وشغ رخ٠ذخردثق٠ه٠ÙØ® " +"شرخÙاثق ÙغØØ« خب سØثذهشم ثطشو. غخع وشغ قثدثق٠Ùاهس سعزسثذÙهخر زشذن ÙØ® زثهرل Ø´" +" زشسهذ ثطشو زغ سثمثذÙهرل 'رخرث', زع٠غخع صهمم رخ٠زث شزمث ÙØ® ذخربهلعقث ه٠شس" +" Ø´ سØثذهشم ثطشو هر Ùاث بعÙعقث." + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Ùهوثي" @@ -10741,14 +11096,14 @@ msgstr "" msgid "Read more" msgstr "قثشي وخقث" -#: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" -msgstr "ساخص ÙقشرسذقهØÙس ({totalTranscripts})" - #: cms/templates/js/video-transcripts.underscore msgid "No transcript uploaded." msgstr "رخ ÙقشرسذقهØ٠عØمخشيثي." +#: cms/templates/js/video-transcripts.underscore +msgid "Show transcripts ({totalTranscripts})" +msgstr "ساخص ÙقشرسذقهØÙس ({totalTranscripts})" + #: cms/templates/js/xblock-access-editor.underscore msgid "Set Access" msgstr "سث٠شذذثسس" diff --git a/conf/locale/ru/LC_MESSAGES/djangojs.mo b/conf/locale/ru/LC_MESSAGES/djangojs.mo index 3c5692fde7b62839fd989c656bab6a2fe6dabad0..191c3da9d17f763b25c6ee1e88927cbe30327dfc 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 11a274eb76f8a28040425c9f003d9ae5016f18f7..dcbf9b0a2ef1795adb165dfb80ee68f92df571f1 100644 --- a/conf/locale/ru/LC_MESSAGES/djangojs.po +++ b/conf/locale/ru/LC_MESSAGES/djangojs.po @@ -13,7 +13,7 @@ # Alexey Yuriev <yurievac@gmail.com>, 2018 # AndyZ <Andrey.Zakhvatov@gmail.com>, 2014 # AndyZ <Andrey.Zakhvatov@gmail.com>, 2014 -# Ðндрей Сандлер <inactive+asandler@transifex.com>, 2013 +# 80dca42de6d6f19a9206ebd06d0c9cb9_4216643 <e5580e6e1f445efa0c4f3eb584b99765_116976>, 2013 # Danil Moskovoy <tenrius@gmail.com>, 2013 # DariaTkacheva <d.i.tkacheva@gmail.com>, 2014 # dfxedx <ah532@ya.ru>, 2014 @@ -61,8 +61,8 @@ # YummyTranslations Edx <yummytranslations.edx@gmail.com>, 2015 # Pavel Zamyshliaev, 2014 # Ðндрей ГуÑев <gaussgss@gmail.com>, 2018 -# Ðндрей Сандлер <inactive+asandler@transifex.com>, 2013 -# Ðндрей Сандлер <inactive+asandler@transifex.com>, 2013 +# 80dca42de6d6f19a9206ebd06d0c9cb9_4216643 <e5580e6e1f445efa0c4f3eb584b99765_116976>, 2013 +# 80dca42de6d6f19a9206ebd06d0c9cb9_4216643 <e5580e6e1f445efa0c4f3eb584b99765_116976>, 2013 # Евгений Козлов <eudjin@gmail.com>, 2014 # Ðичик Дмитрий Валерьевич <dmi.nichik@gmail.com>, 2013 # ОкÑана Ли <okcanochka.lee@list.ru>, 2016 @@ -78,7 +78,7 @@ # Alexandr Kosharny <acosarnii@gmail.com>, 2016 # AndyZ <Andrey.Zakhvatov@gmail.com>, 2014 # AndyZ <Andrey.Zakhvatov@gmail.com>, 2014 -# Ðндрей Сандлер <inactive+asandler@transifex.com>, 2013 +# 80dca42de6d6f19a9206ebd06d0c9cb9_4216643 <e5580e6e1f445efa0c4f3eb584b99765_116976>, 2013 # Danil Moskovoy <tenrius@gmail.com>, 2013 # Dmitri Polevoi <polevaiabrest@gmail.com>, 2014 # Дмитрий Ошкало <dmitry.oshkalo@gmail.com>, 2015 @@ -104,7 +104,7 @@ # Volodia Bickov <1@ja2t.ru>, 2020 # Weyedide <weyedide@gmail.com>, 2014-2016 # Yana Malinovskaya <y.malinovskaya@itransition.com>, 2014 -# Ðндрей Сандлер <inactive+asandler@transifex.com>, 2013 +# 80dca42de6d6f19a9206ebd06d0c9cb9_4216643 <e5580e6e1f445efa0c4f3eb584b99765_116976>, 2013 # Ðичик Дмитрий Валерьевич <dmi.nichik@gmail.com>, 2013 # Павел Жилкин, 2018-2019 # #-#-#-#-# djangojs-account-settings-view.po (0.1a) #-#-#-#-# @@ -179,16 +179,16 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" -"PO-Revision-Date: 2020-04-11 16:25+0000\n" -"Last-Translator: Volodia Bickov <1@ja2t.ru>\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" +"Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Russian (http://www.transifex.com/open-edx/edx-platform/language/ru/)\n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -237,6 +237,7 @@ msgstr "Удалить" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -259,6 +260,7 @@ msgstr "Загрузка" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -288,6 +290,7 @@ msgstr "Выберите файл" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "ОК" @@ -892,7 +895,6 @@ msgstr "Удалить таблицу" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "ОпиÑание" @@ -1332,6 +1334,7 @@ msgstr "Ðовое окно" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Вперёд" @@ -2646,7 +2649,15 @@ msgid "Other" msgstr "Другое" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx @@ -2654,21 +2665,23 @@ msgid "Details" msgstr "ПодробноÑти" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Отправить" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2687,6 +2700,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2710,7 +2735,8 @@ msgstr "Перейти {platform} Домой" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2894,6 +2920,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "Произошла ошибка. Попробуйте ещё раз." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Выйти из ÑоÑтава команды?" @@ -3424,6 +3454,7 @@ msgid "There has been an error processing your survey." msgstr "Произошла ошибка при обработке обзора" #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -5638,6 +5669,10 @@ msgstr "Да, разрешить редактирование активного msgid "certificate" msgstr "Ñертификат" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "ÐаÑтройте Ñвой Ñертификат" @@ -5649,8 +5684,8 @@ msgid "You have not created any certificates yet." msgstr "Ð’Ñ‹ ещё не Ñоздали ни одного Ñертификата." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "Удалить «<%= signatoryName %>» из ÑпиÑка предÑтавителей?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5958,8 +5993,8 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -6144,7 +6179,7 @@ msgid "{selectedProvider} credentials saved" msgstr "" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" msgstr "" #: cms/static/js/views/edit_chapter.js @@ -6725,18 +6760,14 @@ msgstr "" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" -"Ð¡Ð¾Ð²Ð¾ÐºÑƒÐ¿Ð½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° Ð½Ð°Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ð¸, номера и периода Ð¿Ñ€Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ ÐºÑƒÑ€Ñа" -" не должна превышать <%=limit%> Ñимволов." #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" -"Ð¡Ð¾Ð²Ð¾ÐºÑƒÐ¿Ð½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° кода организации и библиотеки не может превышать <%=limit%>" -" Ñимволов." #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -7078,13 +7109,13 @@ msgid "Unscheduled" msgstr "Дата выпуÑка не задана" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Дата" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Ðазад" @@ -7132,6 +7163,312 @@ msgstr "ОчиÑтить поиÑк" msgid "Search" msgstr "ПоиÑк" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Отправить" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "Ð’Ñе темы" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "Ð“Ð»Ð°Ð²Ð½Ð°Ñ Ñтраница обÑуждениÑ" @@ -7190,10 +7527,6 @@ msgstr "" "ПоÑтавьте галочку, чтобы ежедневно получать обзор новых непрочитанных " "комментариев и ответов на ÑообщениÑ, которые вы отÑлеживаете." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "Ð’Ñе темы" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ Ñлектронный адреÑ" @@ -7432,6 +7765,10 @@ msgstr "Ðе можете найти Ñебе команду?" msgid "Join Team" msgstr "ПриÑоединитьÑÑ Ðº команде" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "О команде" @@ -7518,102 +7855,6 @@ msgstr "Удалить подраздел %(subsectionDisplayName)s" msgid "Remove unit %(unitName)s" msgstr "Удалить блок %(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "Вам нужно поÑетить %(display_name)s веб-Ñайт Ð´Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¿Ð¾ÐºÑƒÐ¿ÐºÐ¸." - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"Чтобы получить зачётные единицы, %(display_name)s от %(platform_name)s " -"Ñлушатель должен подать запроÑ." - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Получить зачёт" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "СпаÑибо, %(full_name)s! Ваш платёж за ÐºÑƒÑ€Ñ %(course_name)s принÑÑ‚." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"Ðта Ñтраница – ваша ÐºÐ²Ð¸Ñ‚Ð°Ð½Ñ†Ð¸Ñ Ð¾Ð± оплате. Рекомендуем раÑпечатать её. Ð’Ñ‹ " -"также получите Ñлектронное Ñообщение Ñ Ñтой информацией." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "Заказ â„–" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Сумма" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Итого" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Обратите внимание!" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "Платежи за вычеркнутые пункты возвращены." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Счёт на имÑ" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Ðет квитанции об оплате" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Перейти к панели управлениÑ" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" -"ЕÑли вы не подтвердите Ñвою личноÑÑ‚ÑŒ ÑейчаÑ, вы вÑÑ‘ равно Ñможете получить " -"доÑтуп к курÑу через панель управлениÑ. Ð’Ñ‹ периодичеÑки будете получать " -"Ð½Ð°Ð¿Ð¾Ð¼Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾ необходимоÑти Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð»Ð¸Ñ‡Ð½Ð¾Ñти от платформы " -"«{platformName}»." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "Хотите подтвердить данные позже?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Подтвердить" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Отметить Ñкзамен, как завершённый" @@ -7746,9 +7987,8 @@ msgstr "О ваÑ" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" -"Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ ÑƒÐ¶Ðµ ÑвлÑетÑÑ Ñ‡Ð°Ñтью вашего Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ Ð½Ð° {platform}." #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7778,6 +8018,10 @@ msgstr "" "Благодарим Ð²Ð°Ñ Ð·Ð° подачу заÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð½Ð° грант по курÑу {course_name}! Ð’Ñ‹ " "получите ответ через 2-4 рабочих днÑ." +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Перейти к панели управлениÑ" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "МаÑÑовые иÑключениÑ" @@ -8152,14 +8396,6 @@ msgstr "" msgid "You can change sessions until {expiration_date}." msgstr "" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "ПоÑмотреть ÐºÑƒÑ€Ñ Ð¸Ð· архива" @@ -8385,7 +8621,27 @@ msgid "An error occurred. Please reload the page." msgstr "Произошла ошибка. Перезагрузите Ñтраницу." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -8590,17 +8846,13 @@ msgid "What You Need for Verification" msgstr "Что нужно Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð»Ð¸Ñ‡Ð½Ð¾Ñти" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Веб-камера" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8608,12 +8860,8 @@ msgid "Photo Identification" msgstr "Документ Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸ÐµÐ¹" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"Вам требуютÑÑ Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÑкие права, паÑпорт или иной гоÑударÑтвенный документ," -" в котором еÑÑ‚ÑŒ ваше Ð¸Ð¼Ñ Ð¸ фотографиÑ." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8638,14 +8886,10 @@ msgstr "Ваше лицо хорошо оÑвещено." msgid "Your entire face fits inside the frame." msgstr "Ваше лицо полноÑтью помещаетÑÑ Ð² рамку." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "Фото вашего лица ÑоответÑтвует фото в вашем документе." - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8662,18 +8906,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Зачем %(platformName)s нужна Ð¼Ð¾Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ñ?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"Ð’ рамках процеÑÑа проверки вы должны предоÑтавить вашу фотографию и " -"фотографию вашего удоÑÑ‚Ð¾Ð²ÐµÑ€ÐµÐ½Ð¸Ñ Ð»Ð¸Ñ‡Ð½Ð¾Ñти Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸ÐµÐ¹: паÑпорта, " -"ÑтуденчеÑкого или ученичеÑкого билет.а Ðаша Ñлужба авторизации подтверждает " -"вашу личноÑÑ‚ÑŒ путём ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ¹ фотографии Ñ Ñ„Ð¾Ñ‚Ð¾ на удоÑтоверении " -"личноÑти." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8684,18 +8920,12 @@ msgstr "Ð”Ð»Ñ Ñ‡ÐµÐ³Ð¾ %(platformName)s нужен Ñтот Ñнимок?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"Мы иÑпользуем Ñамый выÑокий уровень защищённоÑти Ð´Ð»Ñ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ фото " -"и отправки его на наш ÑÐµÑ€Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸. Ваша Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ñ Ð¸ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð½Ðµ " -"ÑохранÑетÑÑ Ð¸ недоÑтупна нигде на платформе «%(platformName)s» поÑле того, " -"как процеÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ будет завершён." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8754,22 +8984,14 @@ msgid "Take a Photo of Your ID" msgstr "Сделайте Ñнимок документа, удоÑтоверÑющего вашу личноÑÑ‚ÑŒ" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"ПользуÑÑÑŒ веб-камерой, Ñделайте Ñнимок Ñвоего удоÑÑ‚Ð¾Ð²ÐµÑ€ÐµÐ½Ð¸Ñ Ð»Ð¸Ñ‡Ð½Ð¾Ñти. Мы " -"ÑопоÑтавим Ñтот Ñнимок Ñо Ñнимком вашего лица и именем в вашей учётной " -"запиÑи." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Вам потребуетÑÑ ÑƒÐ´Ð¾Ñтоверение личноÑти Ñ Ð²Ð°ÑˆÐ¸Ð¼ именем и фотографией. " -"Подойдёт водительÑкое удоÑтоверение, паÑпорт или другой документ " -"гоÑударÑтвенного образца." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8793,6 +9015,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8843,6 +9072,31 @@ msgid "Can we match the photo you took with the one on your ID?" msgstr "" "Можем ли мы ÑопоÑтавить Ñнимок, Ñделанный вами, Ñ Ñ„Ð¾Ñ‚Ð¾ в вашем документе?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"Ð’ рамках процеÑÑа проверки вы должны предоÑтавить вашу фотографию и " +"фотографию вашего удоÑÑ‚Ð¾Ð²ÐµÑ€ÐµÐ½Ð¸Ñ Ð»Ð¸Ñ‡Ð½Ð¾Ñти Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸ÐµÐ¹: паÑпорта, " +"ÑтуденчеÑкого или ученичеÑкого билет.а Ðаша Ñлужба авторизации подтверждает " +"вашу личноÑÑ‚ÑŒ путём ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð²Ð°ÑˆÐµÐ¹ фотографии Ñ Ñ„Ð¾Ñ‚Ð¾ на удоÑтоверении " +"личноÑти." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"Мы иÑпользуем Ñамый выÑокий уровень защищённоÑти Ð´Ð»Ñ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ фото " +"и отправки его на наш ÑÐµÑ€Ð²Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸. Ваша Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ñ Ð¸ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð½Ðµ " +"ÑохранÑетÑÑ Ð¸ недоÑтупна нигде на платформе «%(platformName)s» поÑле того, " +"как процеÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ будет завершён." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "Благодарим за подтверждение личноÑти на курÑе: {courseName}" @@ -8876,6 +9130,13 @@ msgstr "" "ВодительÑкое удоÑтоверение, паÑпорт или другой документ гоÑударÑтвенного " "образца Ñ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ именем и фотографией" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Веб-камера" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8980,6 +9241,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "ПожалуйÑта, проверьте почту – вам отправлена ÑÑылка Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ð¸." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Итого" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "Сертификат о повышении квалификации {courseName}" @@ -9025,6 +9291,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "Благодарим ВаÑ! Ваш платёж за ÐºÑƒÑ€Ñ {courseName} принÑÑ‚." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"Ðта Ñтраница – ваша ÐºÐ²Ð¸Ñ‚Ð°Ð½Ñ†Ð¸Ñ Ð¾Ð± оплате. Рекомендуем раÑпечатать её. Ð’Ñ‹ " +"также получите Ñлектронное Ñообщение Ñ Ñтой информацией." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "Заказ â„–" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Сумма" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Обратите внимание!" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "Платежи за вычеркнутые пункты возвращены." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Счёт на имÑ" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Ðет квитанции об оплате" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "Далее: подтвердите подлинноÑÑ‚ÑŒ данных" @@ -9060,6 +9358,10 @@ msgstr "" "через панель управлениÑ. Ð’Ñ‹ периодичеÑки будете получать Ð½Ð°Ð¿Ð¾Ð¼Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾ " "необходимоÑти Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð»Ð¸Ñ‡Ð½Ð¾Ñти от платформы «%(platformName)s»." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "Хотите подтвердить данные позже?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "Данные отправлены на проверку" @@ -9068,13 +9370,9 @@ msgstr "Данные отправлены на проверку" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"Мы получили ваши данные и обработаем их в ближайшее Ð²Ñ€ÐµÐ¼Ñ (1-2 днÑ). Как " -"только они будут подтверждены, на вашей панели ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ÑвитÑÑ " -"оповещение. Обратите внимание, что до Ñтого момента вам будут доÑтупны вÑе " -"учебные материалы." #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -9110,11 +9408,6 @@ msgstr "Ð¢Ñ€ÐµÐ±Ð¾Ð²Ð°Ð½Ð¸Ñ Ðº фотографии:" msgid "Does the photo of you show your whole face?" msgstr "Видно ли на фотографии ваше лицо целиком?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "" -"СопоÑтавима ли Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ñ Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸ÐµÐ¹ в вашем удоÑтоверении личноÑти?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "Чётко ли отображаетÑÑ Ð²Ð°ÑˆÐµ Ð¸Ð¼Ñ Ð² вашем удоÑтоверении личноÑти?" @@ -10620,6 +10913,21 @@ msgstr "УÑтановить в качеÑтве контрольного иÑп msgid "Exam Types" msgstr "Типы Ñкзамена" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Ограничен по времени" @@ -10815,11 +11123,11 @@ msgid "Read more" msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" +msgid "No transcript uploaded." msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "No transcript uploaded." +msgid "Show transcripts ({totalTranscripts})" msgstr "" #: cms/templates/js/xblock-access-editor.underscore diff --git a/conf/locale/sw_KE/LC_MESSAGES/django.mo b/conf/locale/sw_KE/LC_MESSAGES/django.mo index 29e1a012292e369bd01db9c6aef5551aa979ce2e..c4c9d7aa00397cc5093f46016f36bb2e85eb7b3e 100644 Binary files a/conf/locale/sw_KE/LC_MESSAGES/django.mo and b/conf/locale/sw_KE/LC_MESSAGES/django.mo differ diff --git a/conf/locale/sw_KE/LC_MESSAGES/django.po b/conf/locale/sw_KE/LC_MESSAGES/django.po index 16f5de8f5b814000cc6ef01bf227c03ba4ab9ad2..69ef5957e1e03bc4f15ceaaf80a3bab37eac3297 100644 --- a/conf/locale/sw_KE/LC_MESSAGES/django.po +++ b/conf/locale/sw_KE/LC_MESSAGES/django.po @@ -85,7 +85,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed <waheed@edx.org>, 2019\n" "Language-Team: Swahili (Kenya) (https://www.transifex.com/open-edx/teams/6205/sw_KE/)\n" @@ -94,7 +94,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -119,8 +119,8 @@ msgstr "Mtihani wa Kujiunga na masomo" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "Kitengo" @@ -444,13 +444,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "Akaunti yenye Jina la Mtumiaji {username} tayari ipo." +msgid "An account with the Email '{email}' already exists." +msgstr "Akaunti yenye anwani ya barua pepe '{email}' tayari ipo." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "Akaunti yenye anwani ya barua pepe '{email}' tayari ipo." +msgid "An account with the Public Username '{username}' already exists." +msgstr "Akaunti yenye Jina la Mtumiaji {username} tayari ipo." #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2105,7 +2105,7 @@ msgstr "Daima" msgid "Never" msgstr "Kamwe" -#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/capa_base.py lms/templates/courseware/dates.html msgid "Past Due" msgstr "" @@ -2277,9 +2277,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -3989,12 +3989,12 @@ msgid "" " considered in the Entrance Exam scoring/gating algorithm." msgstr "" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "Makundi ya Uandikishwaji" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "Ugawaji watumiaji kwenye makundi kwa kutumia njia ya uandikishaji" @@ -4587,17 +4587,17 @@ msgstr "" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "Funga" @@ -5477,52 +5477,6 @@ msgid "" "this request, please visit the link(s) below." msgstr "" -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "Risiti" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "Malipo Hayakufaulu" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "" - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"Kama kozi yako haitokezi kwenye dashibodi yako, wasiliana na " -"{payment_support_link}." - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "" @@ -5585,10 +5539,22 @@ msgstr "Huna fursa ya kupata kozi hii" msgid "You do not have access to this course on a mobile device" msgstr "Huna fursa ya kupata kozi hii kwenye simu ya mkononi" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "Boresha Uthibitishe" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -5608,6 +5574,11 @@ msgstr "" msgid "in {relative} - {absolute}" msgstr "" +#: lms/djangoapps/courseware/date_summary.py +#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py +msgid "Enrollment Date" +msgstr "Tarehe ya Usajili" + #: lms/djangoapps/courseware/date_summary.py msgid "Course Starts" msgstr "Kozi Inaanza" @@ -6236,9 +6207,8 @@ msgid "Good" msgstr "Vizuri" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html @@ -6246,6 +6216,11 @@ msgstr "" msgid "View discussion" msgstr "" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6382,8 +6357,8 @@ msgstr "Walimu wa Kozi" msgid "Student" msgstr "Mwanafunzi" -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "Mfanyakazi" @@ -6499,29 +6474,6 @@ msgstr "" msgid "Could not find problem with this location." msgstr "" -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "" - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "Kitambulisho cha Kozi" @@ -6548,9 +6500,8 @@ msgstr "" msgid "User ID" msgstr "KItambulisho cha Mtumiaji" -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "'Jina la mtumiaji'" @@ -6663,50 +6614,6 @@ msgstr "" msgid "The file must contain a 'username' column, an 'email' column, or both." msgstr "" -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "Namba ya Kuponi" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "Kitambulisho cha Kozi" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "" - -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "Maelezo" - -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "Tarehe ya Kumalizika/Kutofaa" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "Ina Tumika / Iko Hai" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -6727,16 +6634,6 @@ msgstr "" msgid "proctored exam results" msgstr "" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" -"Haiwezi kuzalisha vificho vya kukomboa kwa sababu ya mpangilio kombo wa " -"kozi." - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -6957,63 +6854,6 @@ msgstr "" " jina analotumia mwanfunzi/barua pepe na kozi iliyochaguliwa kama viko " "sahihi na jaribu tena." -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "kuponi ikiwa na kificho cha kuponi ({code}) tayari ipo katika kozi" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "" @@ -7124,30 +6964,6 @@ msgstr "" msgid "Incomplete" msgstr "Haijakamilika" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "" -"Kificho cha usajili ({code}) hakikupatikana kwa kozi hii {course_name} ." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "" - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "" - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7335,10 +7151,6 @@ msgstr "Kichwa cha makala" msgid "Year of Birth" msgstr "Mwaka wa Kuzaliwa" -#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py -msgid "Enrollment Date" -msgstr "Tarehe ya Usajili" - #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py msgid "Currently Enrolled" msgstr "" @@ -7536,8 +7348,8 @@ msgstr "" #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Programu" @@ -8171,6 +7983,14 @@ msgstr "Jumla ya Gharama" msgid "Currency" msgstr "Sarafu" +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "Maelezo" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "Maoni" @@ -8318,15 +8138,6 @@ msgstr "Huna ruhusa kutizama ukurasa huu." msgid "View and regenerate certificates." msgstr "Tizama na uzalishe upya vyeti." -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "Malipo ya fedha kwa Mkono" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "" -"Fuatilia marejesho ya fedha yaliyotolewa moja kwa moja kupitia CyberAsili." - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -8405,43 +8216,8 @@ msgstr "" msgid "User Disabled Successfully" msgstr "" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "Anwani Barua pepe" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "Kitambulisho cha Kozi" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "Mtumiaji hapatikani" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "Kozi {course_id} haikupita dirisha la marejesho ya malipo." - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "Hakuna uagizaji uliopatikana kwa {user} katika kozi {course_id}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "Usajili uliotenguliwa {user} kutoka kwa {course_id}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" msgstr "" #: lms/djangoapps/teams/models.py @@ -9065,8 +8841,8 @@ msgid "Allow" msgstr "Ruhusu" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "Hitilafu" @@ -9433,8 +9209,8 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "Viambatisho" @@ -9466,11 +9242,10 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -9864,6 +9639,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -10255,6 +10034,10 @@ msgstr "" msgid "Schedule start < course start" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "Kitambulisho cha Kozi" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "" @@ -10263,6 +10046,15 @@ msgstr "" msgid "Experience" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "Kitambulisho cha Kozi" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -10463,6 +10255,7 @@ msgid "" msgstr "" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "" @@ -10696,7 +10489,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -10723,8 +10515,8 @@ msgstr "" msgid "Success" msgstr "Mafanikio" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "Matendo" @@ -10891,6 +10683,14 @@ msgstr "" "Kulikuwa na hitilafu kupokea taarifa ya kuingia kwako mtandaoni. Tafadhali " "tutumie barua pepe." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -10906,6 +10706,15 @@ msgstr "" "Majaribio mengi ya kuingia mtandaoni hayakufaulu. Tafadhali jaribu tena " "baadae." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -10913,15 +10722,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "jina la mtumiaji@domain.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -10937,6 +10737,12 @@ msgstr "Anwani ya barua pepe uliyotumia kujisajili na{platform_name}" msgid "Create Account" msgstr "" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "jina la mtumiaji@domain.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -10953,6 +10759,11 @@ msgstr "" "Akaunti ya mtumiaji inayohusiana na anwani ya barua pepe hii haiwezi kuunda " "upya nywila." +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "Uwekaji upya wa nywila haukufaulu " @@ -10972,11 +10783,6 @@ msgid "" "created. {bold_start}{email}{bold_end} is now your primary login email." msgstr "" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "" @@ -11211,6 +11017,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "" @@ -11229,6 +11047,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "Namba hii ni batili." @@ -11922,8 +11744,8 @@ msgstr "Kozi imefanikiwa kutumwa kwenye hazina ya Git" msgid "Vertical" msgstr "Wima" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "Kifungu" @@ -12199,6 +12021,18 @@ msgstr "" msgid "Transcript Ready" msgstr "" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "" @@ -12396,14 +12230,14 @@ msgstr "Namba ya Kozi:" msgid "Course Run:" msgstr "Uendeshaji wa Fanni:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "Kozi" @@ -12427,8 +12261,9 @@ msgstr "Wakufunzi" msgid "Requirements" msgstr "Yanayohitajika" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "Utondoti" @@ -12480,15 +12315,15 @@ msgstr "" msgid "Choose Language" msgstr "Chagua Lugha" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "Akaunti" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -12560,8 +12395,8 @@ msgstr "Menyu ya mtumiaji" msgid "Usermenu dropdown" msgstr "Alama inayoangalia chini menyu ya mtumiaji" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "Toka Mtandaoni" @@ -12723,8 +12558,8 @@ msgstr "Kuanza: {date}" msgid "View all Courses" msgstr "Angalia Kozi zote" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "Dashibodi" @@ -12743,8 +12578,8 @@ msgstr "Bado haujasajiliwa katika kozi yoyote." #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "Tafuta kozi" @@ -12762,7 +12597,7 @@ msgstr "Hitilafu za upakiaji kozi" msgid "Search Your Courses" msgstr "Tafuta Kozi Zako" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "Futa utautaji" @@ -12787,7 +12622,7 @@ msgstr "Pokea barua pepe za kozi" msgid "Save Settings" msgstr "Hifadhi mitegesho" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -12797,9 +12632,87 @@ msgstr "Hifadhi mitegesho" msgid "Unenroll" msgstr "Tengua usajili" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "Tazama Kitengo ndani ya Studio" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -12832,7 +12745,7 @@ msgstr "Akaunti yenye anwani mpya ya barua pepe tayari ipo." msgid "You should Register before trying to access the Unit" msgstr "Unastahili Ujiandikishe kabla kujaribu kuifikia 'Sura/Mada'" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "Sajili" @@ -12942,7 +12855,7 @@ msgstr "" "umekamilisha kazi hii daraja lako la ufaulu linapatikana {link_start} kurasa" " endelevu {link_end}" -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "Tafuta \"kozi\"" @@ -13090,21 +13003,16 @@ msgstr "(fungua upya ukurasa wako kuonesha tena)" msgid "working" msgstr "inafanya kazi" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "Kumekuwa na hitilafu kwenye seva za {platform_name}" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"Tunasikitika, moduli hii haipatikani kwa sasa. Mwalimu wetu anashughulika " -"kurekebisha haraka iwezekanavyo. Tafadhali tutumie barua pepe kupitia " -"{tech_support_email} kutuarifu tatizo lolote au wakati mtandao ukiwa chini." #: lms/templates/module-error.html msgid "Raw data:" @@ -13143,7 +13051,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "Sasa Unaangalia kozi kama{i_start}{user_name}{i_end}." #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -13210,28 +13126,6 @@ msgstr "Barua pepe" msgid "Return To %s" msgstr "Rudi Kwenye %s" -#: lms/templates/reset_deadlines_banner.html -msgid "It looks like you've missed some important deadlines. Visit " -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "edx.org" -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid " to reset your deadlines and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "Kujiunga upya kumefaulu!" @@ -13282,7 +13176,7 @@ msgstr "" msgid "Sequence" msgstr "Mfululizo" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -13413,18 +13307,18 @@ msgstr "" msgid "Reset Learner's Attempts to Zero" msgstr "Futa majaribio ya mwanafunzi yawe sifuri" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "Futa Hali ya Mwanafunzi" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "Weka upya alama za Uwasilisho wa Mwanafunzi " -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "Weka upya alama kama zimekuwa bora" @@ -13462,7 +13356,7 @@ msgstr "Kitabu cha kiada {course_number} " msgid "Textbook Navigation" msgstr "Uabiri wa 'Kitabu cha kiada'" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "Ukurasa" @@ -13573,9 +13467,9 @@ msgstr "Ukurasa {current_page} wa {total_pages}" msgid "Recent git load activity for {course_id}" msgstr "Shughuli za git za upakiaji wa {course_id}" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Date" msgstr "Tarehe" @@ -13633,7 +13527,7 @@ msgstr "" " hukumaanisha kufanya hivi, {undo_link_start}unaweza kujiandikisha " "upya{link_end}. " -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "Dashibodi kwa ajili ya:" @@ -13641,8 +13535,8 @@ msgstr "Dashibodi kwa ajili ya:" msgid "More options" msgstr "Machaguzi zaidi" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "" @@ -14950,37 +14844,6 @@ msgstr "" msgid "About edX Certificates" msgstr "" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "Utokaji Batilisha" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"Muamala wako umebatilishwa. Ukihisi kuna hitilafu iliyotokea, wasiliana na " -"{email}. " - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "Hitilafu ya Utokaji" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "Upakiaji wa maelezo ya uagizishaji" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "Tafadhali subiri tukiwa tunarudisha uagizaji wako." - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -15201,14 +15064,14 @@ msgstr "{section_format} inatazamiwa {{date}}" msgid "This content is graded" msgstr "Maudhui haya yamepangwa kwenye madaraja" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "Hitilafu imetokea. Tafadhali jaribu tena baadae." - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "Hitilafu imetokea. Tafadhali jaribu tena baadae." + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "Umesajiliwa katika kozi hii" @@ -15220,10 +15083,6 @@ msgstr "Umesajiliwa katika kozi hii" msgid "View Course" msgstr "Angalia Kozi" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "Kozi imejaa wanafunzi" @@ -15236,10 +15095,6 @@ msgstr "Usajili katika kozi hii ni kwa ukaribisho pekee" msgid "Enrollment is Closed" msgstr "Usajili Umefungwa" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "" @@ -15363,6 +15218,13 @@ msgstr "Utumizi wa Kozi" msgid "Courseware" msgstr "Maudhui ya kozi" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "Utafutaji Kozi" @@ -15393,7 +15255,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -15401,14 +15263,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" msgstr "" -#: lms/templates/courseware/error-message.html -msgid "" -"We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible." +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -16080,10 +15939,8 @@ msgstr "Umewasilisha taarifa za uhakiki wako." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" -"Utaona ujumbe kwenye dashbodi yako baada ya utaratibu wa kuhakiki kukamilika" -" (mara nyingi ndani ya siku 1-2 )." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -16093,10 +15950,8 @@ msgstr "Muda wa uhakiki wako wa sasa utaisha hivi karibuni!" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" -"Umewasilisha taarifa za uhakiki wako. Utaona ujumbe kwenye dashbodi yako " -"baada ya utaratibu wa kuhakiki kukamilika (mara nyingi ndani ya siku 1-2 )." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -16820,149 +16675,6 @@ msgid "" "verification process on your dashboard." msgstr "" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "Asante kwa kununua usajili kwenye {course_name}." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"Bili kwa ajili ya {currency_symbol}{total_price} imeambatanishwa. Malipo " -"yatafanyika baada ya upokeaji. Unaweza kupata maelezo kuhusu njia za malipo " -"kwenye bili" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -"Faili ya CSV inayo orodhesha namba za usajili wako imeshikanishwa. Unaweza " -"kutumia kigezo cha barua pepe hapo chini kusambaza namba za usajili kwa " -"wanafunzi wako. Kila mwanafunzi lazima utumie namba ya usajili " -"kilichotengwa." - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"Asante,\n" -"Timu {platform_name} " - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "Mpendwa [[Jina]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"Tumekupa kificho cha usajili wa kozi kwa ajili ya {course_name}. Kusajili " -"katika kozi, bofya kiungo-wavuti kifuatacho:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "Uunganishi kutoka kwa faili ya CSV ilioshikanishwa wa HTML" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"Ukishajisajili, unaweza kuona kozi kwenye dashibodi ya mwanafunzi wako. " -"Unaweza kuona zana za kozi baada ya tarehe ya kuanza kozi." - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"Wako Mwaminifu,\n" -"[[Sahihi Yako]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "ANKARA" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "Tarehe: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "Bili No: {invoice_number} " - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "Masharti: Malipo Ni Unapopokea Bidhaa ulizo Agizia." - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "Tarehe ya Mwisho: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "Bili inalipwa kwa:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "Namba Itakayo Ashiria Mteja: {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "Mwisho kulipa Baki ya Malipo ni: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "Kozi: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"Bei: {currency_symbol}{course_price} Kiasi: {quantity} Jumla-Ndogo: " -"{currency_symbol}{sub_total} Punguzo: {currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "Jumla: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "Maelezo ya Malipo" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"Tusipo pokea malipo, usajili wa wanafunzi unaotumia namba hizi utafutwa na " -"wanafunzi hawataweza kufikia nyenzo za kozi. Ununuzi wote unafanyika mwisho." -" Kwa habari zaidi, ona {site_name} kanuni za ufutaji. " - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "Kwa maswali ya jinsi ya kulipa, wasiliana {contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -17166,8 +16878,8 @@ msgstr "Tuma maombi ya Msaada wa Fedha" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "Ukurasa wa mwanzo {platform_name} " @@ -17190,19 +16902,11 @@ msgstr "" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "Msimamizi wa mfumo" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "Gari la kufanyia Ununuzi" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "" @@ -17239,6 +16943,12 @@ msgstr "Ongeza Namba ya Kuponi" msgid "Enter information about the coupon code below." msgstr "Ingiza taarifa kuhusu namba ya kuponi hapo chini." +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "Namba ya Kuponi" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "Asilimia ya Punguzo" @@ -17833,6 +17543,11 @@ msgstr "Pakua Namba za Kuponi" msgid "Coupon Codes" msgstr "Tambulizi ya Koponi" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "Tarehe ya Kumalizika/Kutofaa" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "Kuponi (%)" @@ -19200,6 +18915,10 @@ msgstr "Mjumuiko wa manunuzi" msgid "Purchase order number (if any)" msgstr "Nambari ya manunuzii (kama ipo)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "Anwani Barua pepe" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "barua pepe@mfano.com" @@ -19515,6 +19234,10 @@ msgid_plural "" msgstr[0] "{course_names} imeondolewa kwa sababu muda wa kusajili umefungwa." msgstr[1] "{course_names} zimeondolewa kwa sababu muda ya kusajili umefungwa." +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "Gari la kufanyia Ununuzi" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "Jalada la Picha" @@ -19734,46 +19457,6 @@ msgstr "" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "Kuhusu kurejesha malipo ya hili agizo:" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "Namba ya Agizo:" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "Usajili:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "sajiliwa" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "haijasajiliwa" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "Gharama:" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "Hali ya Cheti cha bidhaa:" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "Hali ilivyo ya Uagizaji:" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "Muda Uliotimizwa:" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "Muda wa maombi ya kurejesha malipo:" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "Utafiti wa Mtumiaji" @@ -19927,10 +19610,8 @@ msgstr "'Uthibitisho' wa Kitambulisho" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" -"Tayari umetoa taarifa za uthibitisho. Utaona ujumbe kwenye skrini yako " -"taratibu za uthibitishozikikamilika (kawaida ndani ya siku 1-2)" #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -20623,12 +20304,8 @@ msgid "The page that you were looking for was not found." msgstr "Ukurasa uliokuwa ukitafuta haukupatikana." #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" -"Rudi nyuma kwenye {homepage} au tujulishe kuhusu ukurasa wowote ambao " -"umewekwa kwenye {email}." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -20654,11 +20331,6 @@ msgstr "" "Tumetambua hitlafu na mfanyakazi wetu anashughulikia kutatua hitlafu hii " "haraka iwezekanavyo." -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "" -"Kama tatizo linaendelea, tafadhali tutumie barua pepe kupitia {email_link}." - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "" @@ -21310,9 +20982,7 @@ msgstr "Ukurasa Ulioomba Haupatikani" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" #: cms/templates/error.html @@ -21323,9 +20993,7 @@ msgstr "Seva Ilipata Hitlafu" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" #: cms/templates/error.html @@ -24415,8 +24083,8 @@ msgstr "%(file)s yamebadilishwa kuwa marudio namba #%(revision)d" msgid "%(file)s has been saved." msgstr "%(file)s yamehifadhiwa." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "Picha" @@ -24610,8 +24278,8 @@ msgstr "" msgid "Search..." msgstr "" -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "" diff --git a/conf/locale/sw_KE/LC_MESSAGES/djangojs.mo b/conf/locale/sw_KE/LC_MESSAGES/djangojs.mo index a6c4991654e72cedd75702926dc47912bfa9216c..58bff090ad5bd29d3a13367e69c9b332d1196e58 100644 Binary files a/conf/locale/sw_KE/LC_MESSAGES/djangojs.mo and b/conf/locale/sw_KE/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/sw_KE/LC_MESSAGES/djangojs.po b/conf/locale/sw_KE/LC_MESSAGES/djangojs.po index cd38c289c4d6447e3584c6e3e80c1571ddb4faef..b7e59e4a0d3324b976d00546adcdbe530bbfd0f4 100644 --- a/conf/locale/sw_KE/LC_MESSAGES/djangojs.po +++ b/conf/locale/sw_KE/LC_MESSAGES/djangojs.po @@ -71,8 +71,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Swahili (Kenya) (http://www.transifex.com/open-edx/edx-platform/language/sw_KE/)\n" "Language: sw_KE\n" @@ -80,7 +80,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -129,6 +129,7 @@ msgstr "Futa" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -151,6 +152,7 @@ msgstr "Pakia ujumbe" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -175,6 +177,7 @@ msgstr "Chagua Faili" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "Sawa" @@ -736,7 +739,6 @@ msgstr "" #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Maelezo" @@ -783,6 +785,7 @@ msgstr "" #: cms/templates/js/show-textbook.underscore #: cms/templates/js/signatory-details.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Edit" msgstr "" @@ -1177,6 +1180,7 @@ msgstr "" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Inayofuata" @@ -1510,6 +1514,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/course-instructor-details.underscore #: cms/templates/js/signatory-details.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Title" msgstr "" @@ -2421,7 +2426,15 @@ msgid "Other" msgstr "Nyingine" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx @@ -2429,20 +2442,23 @@ msgid "Details" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Wasilisha " +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2459,6 +2475,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2482,7 +2510,8 @@ msgstr "" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2664,6 +2693,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "Hitilafu imetokea. Jaribu tena." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Ondoka kwenye hii timu?" @@ -3195,6 +3228,7 @@ msgid "There has been an error processing your survey." msgstr "" #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -3211,6 +3245,7 @@ msgid "HTML preview of post" msgstr "" #: lms/static/js/customwmd.js +#: common/static/common/templates/discussion/templates.underscore msgid "Your question or idea (required)" msgstr "" @@ -5301,6 +5336,10 @@ msgstr "Ndiyo, ruhusu kuhariri Hati inayofanya kazi" msgid "certificate" msgstr "cheti" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Tengeneza cheti chako" @@ -5312,8 +5351,8 @@ msgid "You have not created any certificates yet." msgstr "Bado hujatengeneza cheti chochote." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "Futa \\\"<%= signatoryName %>\\\" kutoka kwenye orodha ya waweka sahihi?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5619,8 +5658,8 @@ msgstr "" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -5796,7 +5835,7 @@ msgid "{selectedProvider} credentials saved" msgstr "" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" msgstr "" #: cms/static/js/views/edit_chapter.js @@ -6361,13 +6400,13 @@ msgstr "" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" #: cms/static/js/views/utils/move_xblock_utils.js @@ -6706,13 +6745,13 @@ msgid "Unscheduled" msgstr "Haijapangiwa" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Tarehe" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Iliopita" @@ -6760,6 +6799,310 @@ msgstr "Futa utafutaji" msgid "Search" msgstr "Tafuta" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Wasilisha " + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "'Machapisho' Yote" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "Majadiliano Mwanzo" @@ -6818,10 +7161,6 @@ msgstr "" "Angalia kisanduku hii kupokea barua pepe mara moja kwa siku kukujulisha " "kuhusu makala mapya ambayo hayajasomwa kwenye nguzo uzifuatiliazo." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "'Machapisho' Yote" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "jina la mtumiaji au barua pepe" @@ -7055,6 +7394,10 @@ msgstr "Je, unashindwa kupata timu ya kujiunga?" msgid "Join Team" msgstr "'Jiunge na Timu'" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "Taarifa za \"Timu\"" @@ -7139,96 +7482,6 @@ msgstr "" msgid "Remove unit %(unitName)s" msgstr "Ondoa Sura ya %(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "Asante %(full_name)s! Tumepokea malipo yako kwa %(course_name)s." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"Tafadhali chapisha huu ukurasa wa kumbukumbu yako; inajihifadhi kama risiti." -" Pia utapokea barua pepe yenye taarifa sawa." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "'Idadi' ya Mahitaji." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Kiasi" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Jumla" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Tafadhali Zingatia" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Bili kwa" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Hakuna risiti inayopatikana" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Nenda kwenye 'Dashibodi'" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "Unataka kuhakiki kitambulisho chako baadae?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "'Thibitisha Sasa'" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Usahihishaji wa Mtihani 'umekamilika'" @@ -7356,7 +7609,7 @@ msgstr "Kuhusu Wewe" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore @@ -7385,6 +7638,10 @@ msgid "" "{course_name}! You can expect a response in 2-4 business days." msgstr "" +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Nenda kwenye 'Dashibodi'" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "" @@ -7733,14 +7990,6 @@ msgstr "" msgid "You can change sessions until {expiration_date}." msgstr "" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "Angalia Kozi Zilizohifadhiwa" @@ -7960,7 +8209,27 @@ msgid "An error occurred. Please reload the page." msgstr "Hitilafu imetokea. Tafadhali pakia upya ukurasa." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -8166,17 +8435,13 @@ msgid "What You Need for Verification" msgstr "Unachohitaji kwenye Uthibitisho" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Kamera ya wavuti" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8184,12 +8449,8 @@ msgid "Photo Identification" msgstr "Kitambulisho cha Picha" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"Unahitaji leseni ya udereva, pasipoti, au Kitambulisho kingine cha serikali " -"ambacho kina jina lako na picha. " #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8214,14 +8475,10 @@ msgstr "Uso wako umemulikwa vizuri." msgid "Your entire face fits inside the frame." msgstr "Uso wako wote umetoshea kwenye fremu." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "Picha yako inaendana na picha ya iliyopo kwenye Kitambulisho chako." - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8238,17 +8495,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Kwanini unahitaji %(platformName)s picha yangu?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"Kama sehemu ya mchakakto wa uhakiki, unapiga picha ya sura yako na " -"kitambulisho kilichoidhinishwa na serikali. Huduma . Mamlaka ya uthibitisho " -"wa huduma zetu utathibitisha kitambulisho kwa kulinganisha picha uliyopiga " -"na picha ya Kitambulisho chako." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8259,18 +8509,12 @@ msgstr "Tuifanyie nini %(platformName)s hii picha?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"Tunatumia viwango vya juu kabisa vya kiusalama vilivyopo kwa ajili ya " -"kuificha picha yako na kuituma kwenye huduma yetu ya kuidhinisha kwa ajili " -"ya kuikagua Picha yako na taarifa hazihifadhiwi au kuonekana popote kwenye " -"%(platformName)s baada ya shughuli za uhakiki kukamilika." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8329,21 +8573,14 @@ msgid "Take a Photo of Your ID" msgstr "Piga picha ya Kitambulisho chako" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"Tumia kamera yako ya wavuti kupiga picha ya Kitambulisho chako. " -"Tutalinganisha picha hii na picha ya sura yako pamoja na jina kwenye akaunti" -" yako." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Unahitaji Kitambulisho chenye jina lako na picha. Leseni ya udereva, " -"pasipoti, au Vitambulisho vyengine vilivyotolewa na serikali vinakubalika." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8367,6 +8604,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8416,6 +8660,30 @@ msgid "Can we match the photo you took with the one on your ID?" msgstr "" "Je tunaweza kulinganisha picha yako na iliyopo kwenye Kitambulisho chako?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"Kama sehemu ya mchakakto wa uhakiki, unapiga picha ya sura yako na " +"kitambulisho kilichoidhinishwa na serikali. Huduma . Mamlaka ya uthibitisho " +"wa huduma zetu utathibitisha kitambulisho kwa kulinganisha picha uliyopiga " +"na picha ya Kitambulisho chako." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"Tunatumia viwango vya juu kabisa vya kiusalama vilivyopo kwa ajili ya " +"kuificha picha yako na kuituma kwenye huduma yetu ya kuidhinisha kwa ajili " +"ya kuikagua Picha yako na taarifa hazihifadhiwi au kuonekana popote kwenye " +"%(platformName)s baada ya shughuli za uhakiki kukamilika." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -8450,6 +8718,13 @@ msgstr "" "Leseni ya udereva, 'pasipoti', au Kitambulisho kingine chochote cha " "kiserikali kilicho na jina lako na picha yako " +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Kamera ya wavuti" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8552,6 +8827,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "Angalia barua pepe yako kwa ajili ya ujumbe uliowezeshwa." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Jumla" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "Cheti cha Taaluma kwa ajili ya {courseName}" @@ -8595,6 +8875,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "Asante! Tume pokea malipo yako ya {courseName}." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"Tafadhali chapisha huu ukurasa wa kumbukumbu yako; inajihifadhi kama risiti." +" Pia utapokea barua pepe yenye taarifa sawa." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "'Idadi' ya Mahitaji." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Kiasi" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Tafadhali Zingatia" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Bili kwa" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Hakuna risiti inayopatikana" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "Hatua Inayofuata: Thibitisha kitambulisho chako" @@ -8630,6 +8942,10 @@ msgstr "" " kozi yako kupitia Dashboard yako. Utapokea ujumbe wa kukumbusha mara kwa " "mara kutoka %(platformName)s kuhakiki kitambulisho chako." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "Unataka kuhakiki kitambulisho chako baadae?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "Uthibitisho wa Kitambulisho Unaendelea" @@ -8638,12 +8954,9 @@ msgstr "Uthibitisho wa Kitambulisho Unaendelea" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"Tumepokea taarifa zako na tunahakiki kitambulisho chako. Utaona ujumbe " -"kwenye dashibodi yako wakati mchakato wa uhakiki ukikamilika (kawaida kama " -"siku 1-2). Kwa sasa hivi, unaweza kupata maudhui yote ya kozi." #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -8679,10 +8992,6 @@ msgstr "Picha zinazohitajika:" msgid "Does the photo of you show your whole face?" msgstr "Je picha yako inaonesha sura yako yote?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "Je picha yako inaendana na Picha kwenye Kitambulisho chako?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "Je jina lako kwenye Kitambulisho chako linasomeka?" @@ -10154,6 +10463,21 @@ msgstr "Andaa kama Mtihani Maalum" msgid "Exam Types" msgstr "Aina za Mitihani" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "" @@ -10333,11 +10657,11 @@ msgid "Read more" msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" +msgid "No transcript uploaded." msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "No transcript uploaded." +msgid "Show transcripts ({totalTranscripts})" msgstr "" #: cms/templates/js/xblock-access-editor.underscore diff --git a/conf/locale/tr_TR/LC_MESSAGES/django.mo b/conf/locale/tr_TR/LC_MESSAGES/django.mo index 1b8140e1bc7743033455c596ab60391a1a684f9f..bcbb1c5061d9657fb1f6896af9d1d391e6361696 100644 Binary files a/conf/locale/tr_TR/LC_MESSAGES/django.mo and b/conf/locale/tr_TR/LC_MESSAGES/django.mo differ diff --git a/conf/locale/tr_TR/LC_MESSAGES/django.po b/conf/locale/tr_TR/LC_MESSAGES/django.po index 1b1b864e56ce82cd267716567953dfcfb63eefeb..b5c7fb64f74631425098f47730f0fe22e218c6e0 100644 --- a/conf/locale/tr_TR/LC_MESSAGES/django.po +++ b/conf/locale/tr_TR/LC_MESSAGES/django.po @@ -24,14 +24,14 @@ # msare <mervesareakin@gmail.com>, 2014 # salih <salihh.demirr@gmail.com>, 2019 # ElektrikAkar <volkan.kumtepeli@gmail.com>, 2014 -# iron_man <inactive+iron_man@transifex.com>, 2014 +# ca47f5bf05c27c3888896d9870e257ad_00aad6f <5addf4166015f6e11583e89fe2c53975_164880>, 2014 # #-#-#-#-# django-studio.po (edx-platform) #-#-#-#-# # edX community translations have been downloaded from Turkish (Turkey) (http://www.transifex.com/open-edx/edx-platform/language/tr_TR/). # Copyright (C) 2020 EdX # This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE. # # Translators: -# Ali Işıngör <ali@artistanbul.io>, 2017-2019 +# Ali Işıngör <ali@artistanbul.io>, 2017-2020 # ali selek <aliselek01@gmail.com>, 2015 # baris <brscvs@gmail.com>, 2013 # Burak Özalp <realburq@gmail.com>, 2013 @@ -78,7 +78,7 @@ # Onur Bektas <mustafaonurbektas@gmail.com>, 2013 # Pelin Çılgın <pelincilgin@hotmail.com>, 2015 # ElektrikAkar <volkan.kumtepeli@gmail.com>, 2014 -# iron_man <inactive+iron_man@transifex.com>, 2014 +# ca47f5bf05c27c3888896d9870e257ad_00aad6f <5addf4166015f6e11583e89fe2c53975_164880>, 2014 # #-#-#-#-# mako-studio.po (edx-platform) #-#-#-#-# # edX community translations have been downloaded from Turkish (Turkey) (http://www.transifex.com/open-edx/edx-platform/language/tr_TR/) # Copyright (C) 2020 edX @@ -129,7 +129,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Ali Işıngör <ali@artistanbul.io>, 2019\n" "Language-Team: Turkish (Turkey) (https://www.transifex.com/open-edx/teams/6205/tr_TR/)\n" @@ -138,7 +138,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -163,8 +163,8 @@ msgstr "GiriÅŸ Sınavı" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "Ãœnite" @@ -493,13 +493,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "Bu kullanıcı '{username}' adı ile zaten mevcut." +msgid "An account with the Email '{email}' already exists." +msgstr "Bu '{email}' e-posta adresine ait bir hesap zaten bulunmaktadır." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "Bu '{email}' e-posta adresine ait bir hesap zaten bulunmaktadır." +msgid "An account with the Public Username '{username}' already exists." +msgstr "Bu kullanıcı '{username}' adı ile zaten mevcut." #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2187,7 +2187,7 @@ msgstr "Her Zaman" msgid "Never" msgstr "Asla" -#: common/lib/xmodule/xmodule/capa_base.py +#: common/lib/xmodule/xmodule/capa_base.py lms/templates/courseware/dates.html msgid "Past Due" msgstr "Zaman Aşımına UÄŸramış" @@ -2380,9 +2380,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -4294,12 +4294,12 @@ msgstr "" "girilmiÅŸse, problem modülleri için olan cevap gönderimleri GiriÅŸ Sınavı " "scoring/gating algoritmasında kabul edilecektir." -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "Kayıtlanma Yolu Grupları" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "Kullanıcıları kayıtlanma yollarına göre ayrıştırma için bölümleme" @@ -4973,17 +4973,17 @@ msgstr "Hesap Kilidini Aç" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "Kapa" @@ -5929,57 +5929,6 @@ msgstr "" "{username} ({email}) kullanıcısı için geri ödeme isteÄŸi baÅŸlatıldı. Bu " "isteÄŸi iÅŸleme koymak için, lütfen aÅŸağıdaki baÄŸlantı(ları) ziyaret edin." -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "Fatura" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "Ödeme BaÅŸarısız" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "" -"Bu iÅŸlem ile ilgili bir sorun vardı. Sizden bir ödeme tahsil edilmedi." - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" -"Bilgilerinizin doÄŸru olduÄŸundan emin olun ya da farklı bir kart ile tekrar " -"deneyin veya baÅŸka bir ödeme yolu seçin." - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" -"Ödemeniz iÅŸlenirken bir sistem hatası meydana geldi. Sizden bir ödeme tahsil" -" edilmedi." - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "Lütfen bir kaç dakika bekledikten sonra tekrar deneyin." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "Yardım için, {payment_support_link} ile iletiÅŸime geçin." - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "Faturanızı oluÅŸtururken bir hata meydana geldi." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"EÄŸer dersiniz panelinizde görünmüyorsa, {payment_support_link} ile iletiÅŸime" -" geçin." - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "Bir sertifika kazanın" @@ -6042,11 +5991,23 @@ msgstr "Bu ders için eriÅŸime sahip deÄŸilsiniz" msgid "You do not have access to this course on a mobile device" msgstr "Bu ders için mobil cihazlardan eriÅŸime sahip deÄŸilsiniz" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "Onaylanmışa Yükselt" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "Görev" @@ -6066,6 +6027,11 @@ msgstr "{relative} önce - {absolute}" msgid "in {relative} - {absolute}" msgstr "{absolute} üzerinden {relative}" +#: lms/djangoapps/courseware/date_summary.py +#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py +msgid "Enrollment Date" +msgstr "Kayıt Tarihi" + #: lms/djangoapps/courseware/date_summary.py msgid "Course Starts" msgstr "Ders BaÅŸlangıcı" @@ -6734,16 +6700,20 @@ msgid "Good" msgstr "Ä°yi" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" -msgstr "%(comment_username)s <b>%(thread_title)s</b> baÅŸlığına cevap yazdı:" +msgid "%(comment_username)s replied to" +msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt msgid "View discussion" msgstr "Tartışmayı görüntüle" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "%(comment_username)s <b>%(thread_title)s</b> baÅŸlığına cevap yazdı:" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6883,8 +6853,8 @@ msgid "Student" msgstr "Öğrenci" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "Personel" @@ -7010,29 +6980,6 @@ msgstr "problem cevapları" msgid "Could not find problem with this location." msgstr "Bu yerde sorun bulunamadı." -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "Fatura numarası '{num}' bulunmuyor. " - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "Bu fatura ile ilgili satış zaten geçersiz hale getirilmiÅŸ." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "Fatura numarası {0} geçersiz hale getirildi. " - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "Bu fatura zaten aktif." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "Fatura {0} için kayıt kodları yeniden aktive edildi." - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "DersNo" @@ -7063,9 +7010,8 @@ msgstr "Kullanıcı No" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "Kullanıcı adı" @@ -7188,54 +7134,6 @@ msgstr "" "Dosyada bir 'kullanıcı adı' sütunu, bir 'e-posta' sütunu ya da iki sütun " "birden bulunmalıdır." -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "Kupon Kodu" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "Ders No" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% Indirim" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "Tanımlama" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "BitiÅŸ Tarihi" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "Aktif mi" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "Kullanılan Kod Sayısı" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "Toplam Ä°ndirimli Yerler" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "Toplam Ä°ndirim Miktarı" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -7256,15 +7154,6 @@ msgstr "anket" msgid "proctored exam results" msgstr "gözetmenli sınav sonuçları" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "Ondalıklı deÄŸer okunamadı. " - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" -"Dersin yanlış yapılandırılmasından dolayı kurtarma kodu oluÅŸturulamıyor." - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -7510,65 +7399,6 @@ msgstr "" "öğrencinin kullanıcı adı/e-posta adresi ile seçilen dersi doÄŸrulayın ve " "yeniden deneyin." -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "kupon No Yok" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "({coupon_id}) kimlikli kupon bulunmuyor." - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr " ({coupon_id}) kimlikli kupon halihazırda aktif deÄŸil." - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "({coupon_id}) kimlikli kupon baÅŸarıyla güncellendi" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" -"Tanımlamaya çalıştığınız kod ({code}) halihazırda kayıt kodu olarak " -"kullanılıyor. " - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "Lütfen Kupon Ä°ndirimi için Tamsayı DeÄŸerini Girin" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "Lütfen Kupon Ä°ndirim DeÄŸerini 100'e eÅŸit ya da az olarak girin." - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "Lütfen tarihi ÅŸu formatta girin: ay/gün/yıl" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "({code}) kodlu kupon baÅŸarıyla eklendi" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "({code}) kodlu kupon bu ders için zaten mevcut" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "kupon no bulunamadı" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "({coupon_id}) kimlikli kupon baÅŸarıyla güncellendi" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "EÄŸitmen" @@ -7680,29 +7510,6 @@ msgstr "Tamamlanmış" msgid "Incomplete" msgstr "Eksik" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "{course_name} dersi için kayıtlanma kodu ({code}) bulunamadı. " - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "Bu kayıtlanma kodu iptal edilmiÅŸ. Bu kod artık kullanılamaz." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "Bu kayıtlanma kodu kullanılmamış olarak iÅŸaretlenmiÅŸ." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "Kayıtlanma kodu sıfırlanmış." - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "({code}) kayıtlanma koduna karşılık bir kullanım bulunmuyor." - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7899,10 +7706,6 @@ msgstr "BaÅŸlık" msgid "Year of Birth" msgstr "DoÄŸum Yılı" -#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py -msgid "Enrollment Date" -msgstr "Kayıt Tarihi" - #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py msgid "Currently Enrolled" msgstr "Güncel Kayıtlanan Sayısı" @@ -8106,8 +7909,8 @@ msgstr "({total} içinde)" #: lms/djangoapps/learner_dashboard/programs.py #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Programlar" @@ -8860,6 +8663,15 @@ msgstr "Toplam Maliyet" msgid "Currency" msgstr "Para" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "Tanımlama" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "Yorumlar" @@ -9007,14 +8819,6 @@ msgstr "Bu sayfayı görmek için yetkiniz yok." msgid "View and regenerate certificates." msgstr "Sertifikaları görüntüle ve yeniden oluÅŸtur" -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "Elle Iade" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "Ä°adeler doÄŸrudan CyberSource tarafından düzenlenir." - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -9093,44 +8897,9 @@ msgstr "Kullanıcı BaÅŸarıyla EtkinleÅŸtirildi" msgid "User Disabled Successfully" msgstr "Kullanıcı BaÅŸarıyla Devre Dışı Bırakıldı" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "E-posta Adresi" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "Ders No" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "Kullanıcı bulunamadı." - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "{course_id} dersi için iade süresi aralığı sürüyor." - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "{course_id} dersinde {user} için bir sipariÅŸ bulunamadı. " - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "{course_id} dersinden {user} kullanıcısının kaydı silindi" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "KimliÄŸi {order_id} olan sipariÅŸ için {cost} iade edildi." +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -9816,8 +9585,8 @@ msgid "Allow" msgstr "Ä°zin ver" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "Hata" @@ -10217,8 +9986,8 @@ msgstr "" "%(start_link)sipuçları%(end_link)ssayfasına bakın." #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "Ekler" @@ -10256,11 +10025,10 @@ msgstr "" "yüklendiÄŸi makaleler için olduÄŸundan, kullanımı uygun olmayabilir." #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -10676,6 +10444,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "Aynı anda bir seviyeden daha fazla yapılandırma tanımlanamaz." +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -11082,6 +10854,10 @@ msgstr "Bilinen Hata Durumu" msgid "Schedule start < course start" msgstr "Takvim baÅŸlangıcı < ders baÅŸlangıcı" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "Ders No" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "Tümü" @@ -11090,6 +10866,15 @@ msgstr "Tümü" msgid "Experience" msgstr "Deneyim" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "Ders No" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -11314,6 +11099,7 @@ msgstr "" "edinebilirsiniz." #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "Åžimdi yükselt" @@ -11551,7 +11337,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -11580,8 +11365,8 @@ msgid "Success" msgstr "BaÅŸarı" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "Eylemler" @@ -11759,6 +11544,14 @@ msgid "There was an error receiving your login information. Please email us." msgstr "" "GiriÅŸ bilgilerinizi alırken bir hata oluÅŸtu. Lütfen bize e-posta atın." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11772,6 +11565,15 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "Fazla sayıda hatalı giriÅŸ. Lütfen daha sonra tekrar deneyin." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11779,15 +11581,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "mehmet@siteadi.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -11804,6 +11597,12 @@ msgstr "" msgid "Create Account" msgstr "Hesap OluÅŸtur" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "mehmet@siteadi.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -11820,6 +11619,11 @@ msgstr "" "Bu e-posta adresi ile iliÅŸkili kullanıcı hesabı parolasını sıfırlamak mümkün" " deÄŸil." +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "Parola sıfırlama iÅŸlemi baÅŸarısız" @@ -11842,11 +11646,6 @@ msgstr "" "oluÅŸturuldu.{bold_start}{email}{bold_end} artık birincil giriÅŸ e-posta " "adresiniz." -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "" @@ -12088,6 +11887,18 @@ msgstr "" "Video Pipeline Entegrasyonu için oluÅŸturulan kullanıcı adı, örn. " "veda_service_user." +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "Açmaya Zorla" @@ -12106,6 +11917,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "DeÄŸer geçersiz." @@ -12836,8 +12651,8 @@ msgid "Vertical" msgstr "Dikey" #: cms/djangoapps/contentstore/views/helpers.py -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "Bölüm" @@ -13119,6 +12934,18 @@ msgstr "Altyazı Hazırlanıyor" msgid "Transcript Ready" msgstr "Altyazı Hazır" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "Kısmi Arıza" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "Altyazı Çalıştırılamadı" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "Bir görüntü dosyası gerekli." @@ -13272,8 +13099,8 @@ msgstr "İçerik" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "Ayarlar" @@ -13321,14 +13148,14 @@ msgstr "Ders Numarası:" msgid "Course Run:" msgstr "Ders Zamanı:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "Dersler" @@ -13352,8 +13179,9 @@ msgstr "EÄŸitmenler" msgid "Requirements" msgstr "Gereklilikler" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "Ayrıntılar" @@ -13409,15 +13237,15 @@ msgstr "" msgid "Choose Language" msgstr "Dil Seçin" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "Hesap" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -13489,8 +13317,8 @@ msgstr "Kullanıcı menüsü" msgid "Usermenu dropdown" msgstr "Kullanıcı açılır menüsü" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "Çıkış Yap" @@ -13658,8 +13486,8 @@ msgstr "BaÅŸlama Tarihi: {date}" msgid "View all Courses" msgstr "Tüm Dersleri Görüntüle" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "Ana Panel" @@ -13678,8 +13506,8 @@ msgstr "Henüz bir derse kayıt olmadınız." #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "Dersleri keÅŸfedin" @@ -13697,7 +13525,7 @@ msgstr "Ders-yükleme hataları" msgid "Search Your Courses" msgstr "Derslerimde Ara" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "Aramayı Temizle" @@ -13722,7 +13550,7 @@ msgstr "Ders e-postalarını al" msgid "Save Settings" msgstr "Ayarları Kaydet" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -13732,9 +13560,87 @@ msgstr "Ayarları Kaydet" msgid "Unenroll" msgstr "Kaydı iptal et" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "Studio'da Ãœnite Görüntüle" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -13767,7 +13673,7 @@ msgstr "Yeni e-posta adresiyle baÄŸlantılı bir hesap zaten mevcut." msgid "You should Register before trying to access the Unit" msgstr "Ãœniteye eriÅŸmeyi denemeden önce Kayıt olmalısınız" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "Kaydol" @@ -13875,7 +13781,7 @@ msgstr "" "görevi tamamladıysanız, notunuz {link_start}ilerleme sayfasında{link_end} " "gösterilecek." -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "Bir ders ara" @@ -14018,21 +13924,16 @@ msgstr "(yenilemek için sayfanızı yeniden yükleyin)" msgid "working" msgstr "çalışıyor" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "{platform_name} sunucularında hata meydana geldi" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"Ãœzgünüz, bu modül geçici olarak devre dışı. Ekibimiz sorunu bir an önce " -"çözmek için çalışıyor. Lütfen sorunları ve aksama süresini " -"{tech_support_email} adresine rapor edin." #: lms/templates/module-error.html msgid "Raw data:" @@ -14071,7 +13972,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "Dersi {i_start}{user_name}{i_end} kullanıcısı olarak inceliyorsunuz." #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -14138,28 +14047,6 @@ msgstr "E-posta" msgid "Return To %s" msgstr "%s e Geri Dön" -#: lms/templates/reset_deadlines_banner.html -msgid "It looks like you've missed some important deadlines. Visit " -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "edx.org" -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid " to reset your deadlines and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "Yeniden Abonelik BaÅŸarılı!" @@ -14212,7 +14099,7 @@ msgstr "Sonraki" msgid "Sequence" msgstr "Sıralı" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "Tamamlandı" @@ -14343,18 +14230,18 @@ msgstr "Not (yalnızca geçersizleÅŸtirmek için)" msgid "Reset Learner's Attempts to Zero" msgstr "Öğrencinin Deneme Sayısını Sıfırla" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "Öğrencinin Durumunu Sil" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "Öğrencinin Cevaplarını Yeniden Notlandır" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "Sadece Not Yükselecekse Yeniden Puanla" @@ -14392,7 +14279,7 @@ msgstr "{course_number} Ders kitabı" msgid "Textbook Navigation" msgstr "Ders kitabı Navigasyonu" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "Sayfa" @@ -14503,9 +14390,9 @@ msgstr "{total_pages} sayfanın {current_page}. sayfası" msgid "Recent git load activity for {course_id}" msgstr "{course_id} dersi için son git yükleme faaliyeti" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -14564,7 +14451,7 @@ msgstr "" "{dashboard_link_start}panelinize dönebilirsiniz{link_end}. EÄŸer bunu yapmak " "istemediyseniz, {undo_link_start}yeniden abone olabilirsiniz{link_end}." -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "Panel:" @@ -14572,8 +14459,8 @@ msgstr "Panel:" msgid "More options" msgstr "Daha fazla seçenek" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "Daha Fazla Seçenek" @@ -15825,37 +15712,6 @@ msgstr "" msgid "About edX Certificates" msgstr "edX Sertifikaları Hakkında" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "Ödeme Ä°ptal Edildi" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" -"Ä°ÅŸleminiz iptal edildi. EÄŸer hata bir hata oluÅŸtuÄŸunu düşünüyorsanız, " -"{email} ile iletiÅŸime geçin. " - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "Ödeme yeri Hatası" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "SipariÅŸ Verisi Yükleniyor..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "Lütfen sipariÅŸinizle ilgili detaylar hazırlanırken bekleyin." - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -16076,14 +15932,14 @@ msgstr "{section_format} son tarihi {{date}}" msgid "This content is graded" msgstr "Bu içerik puanlandı" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "Bir hata oluÅŸtu. Lütfen daha sonra tekrar deneyin" - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "Bir hata oluÅŸtu. Lütfen daha sonra tekrar deneyin" + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "Bu derse kaydoldunuz" @@ -16095,10 +15951,6 @@ msgstr "Bu derse kaydoldunuz" msgid "View Course" msgstr "Derse Gözat" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "Bu ders sizin {start_cart_link}alışveriÅŸ sepetinizde{end_cart_link}." - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "Ders Dolu" @@ -16111,10 +15963,6 @@ msgstr "Bu derse sadece davet ile kayıtlanılır" msgid "Enrollment is Closed" msgstr "Kayıtlanma Kapalıdır" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "Hemen Kaydol" @@ -16238,6 +16086,13 @@ msgstr "Ders Uygulamaları" msgid "Courseware" msgstr "Ders İçerikleri" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "Ders Ara" @@ -16266,22 +16121,19 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" -msgstr "" +msgid "Today" +msgstr "Bugün" #: lms/templates/courseware/dates.html msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" msgstr "" -#: lms/templates/courseware/error-message.html -msgid "" -"We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible." +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -16967,10 +16819,8 @@ msgstr "DoÄŸrulama bilgilerinizi gönderdiniz." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" -"DoÄŸrulama süreci tamamlandığında panelinizde bir ileti göreceksiniz " -"(genellikle 1-2 gün içerisinde)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -16980,11 +16830,8 @@ msgstr "Mevcut doÄŸrulamanızın süresi yakında sona erecek!" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" -"Yeniden doÄŸrulama bilgilerinizi gönderdiniz. DoÄŸrulama süreciniz " -"tamamlandığında panelinizde bir ileti göreceksiniz (genellikle 1-2 gün " -"içerisinde)." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -17725,148 +17572,6 @@ msgstr "" "e-postayı size göndereceÄŸiz. DoÄŸrulama iÅŸleminin durumunu kendi panelinizden" " kontrol edebilirsiniz." -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "{course_name} içinde kayıtları satın aldığınız için teÅŸekkür ederiz." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" -"{currency_symbol}{total_price} için bir fatura eklendi. Ödeme faturanın son " -"günüdür. Fatura üzerinde ödeme methotları hakkında bilgi alabilirsiniz." - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" -"Kayıt kodlarınızı listeleyen bir .csv dosyası eklendi. AÅŸağıdaki e-posta " -"ÅŸablonunu, kayıt kodlarını öğrencilerinize dağıtmak için kullanabilirsiniz. " -"Her bir öğrenci ayrı bir kayıt kodu kullanmalıdır." - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"TeÅŸekkürler,\n" -"{platform_name} Takımı" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "Sayın [[Name]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" -"{course_name} dersinde sizin için ders kayıt kodu saÄŸladık. Derse kaydolmak " -"için, aÅŸağıdaki baÄŸlantıya tıklayın:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "Ekli CSV dosyasındaki HTML baÄŸlantısı" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" -"Derse kayıtlandıktan sonra, Öğrenci Panonuzda dersi görebilirsiniz. Ders " -"materyallerini ise dersin baÅŸlama tarihinden itibaren görebilirsiniz." - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"Saygılarımla,\n" -"[[Your Signature]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "FATURA" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "Tarih: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "Fatura No: {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "Vade: Fatura Ä°brazında" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "Son Tarih: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "Fatura edilecek:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "Müşteri Referans Numarası: {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "Bakiye: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "Ders: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"Fiyat: {currency_symbol}{course_price} Miktar: {quantity} Toplam: " -"{currency_symbol}{sub_total} Ä°ndirim: {currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "Toplam: {sale_price}{currency_symbol}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "Ödeme Yönergeleri" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"EÄŸer ödeme almazsak, bu kodları kullanan öğrenci kayıtları iptal olacak ve " -"öğrenciler ders materyallerine giriÅŸ yapamayacak. Tüm satın almalar sona " -"ermiÅŸtir. Daha fazla bilgi için, {site_name} iptal politikasını inceleyin." - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "" -"Ödemeyle ilgili sorularınız için {contact_email} ile iletiÅŸime geçiniz" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -18070,8 +17775,8 @@ msgstr "Mali Yardım için BaÅŸvurun" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} Ana Sayfa" @@ -18094,19 +17799,11 @@ msgstr "Dersleri KeÅŸfet" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "Sistem Yöneticisi" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "AlışveriÅŸ Sepeti" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "Ek BaÄŸlantılar" @@ -18143,6 +17840,12 @@ msgstr "Kupon Kodu Ekle" msgid "Enter information about the coupon code below." msgstr "AÅŸağıdaki kupon kodu bilgilerini girin." +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "Kupon Kodu" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "Ä°ndirim Yüzdesi" @@ -18739,6 +18442,11 @@ msgstr "Kupon Kodu Ä°ndir" msgid "Coupon Codes" msgstr "Kupon Kodu" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "BitiÅŸ Tarihi" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "Kupon (%)" @@ -19388,7 +19096,7 @@ msgstr "Tartışma Yöneticisi Ekle" #: lms/templates/instructor/instructor_dashboard_2/membership.html msgid "Course Data Researcher" -msgstr "" +msgstr "Ders Veri AraÅŸtırmacısı" #: lms/templates/instructor/instructor_dashboard_2/membership.html msgid "Course Data Researchers can access the data download tab." @@ -20108,6 +19816,10 @@ msgstr "Satınalma organizasyonu" msgid "Purchase order number (if any)" msgstr " SipariÅŸ numarası satın alma(varsa)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "E-posta Adresi" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "eposta@siteadi.com" @@ -20420,6 +20132,10 @@ msgid_plural "" msgstr[0] "" msgstr[1] "{course_names} kaldırıldı çünkü kayıt dönemi kapandı." +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "AlışveriÅŸ Sepeti" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "Kapak Resmi" @@ -20638,46 +20354,6 @@ msgstr "Öğrenci DesteÄŸi: Kullanıcı Yönet" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "Bu sipariÅŸin iadesi hakkında:" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "SipariÅŸ KimliÄŸi:" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "Kayıtlanma:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "kayıtlandı" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "kayıtlanılmamış" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "Maliyet:" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "Sertifika Öğe Durumu:" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "SipariÅŸ Durumu:" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "Tamamlanma Süresi:" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "Ä°ade Talep Zamanı:" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "Kullanıcı Anketi" @@ -20828,11 +20504,8 @@ msgstr "Kimlik DoÄŸrulama" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" -"Daha önceden doÄŸrulama bilgilerinizi kaydetmiÅŸ görünüyorsunuz. DoÄŸrulama " -"süreciniz tamamlandığında panelinizde bir ileti göreceksiniz (genellikle 1-2" -" gün içerisinde)." #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -21062,7 +20735,7 @@ msgstr "" #: openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html msgid "Show More" -msgstr "" +msgstr "Daha Fazla Göster" #: openedx/features/course_search/templates/course_search/course-search-fragment.html msgid "Search Results" @@ -21444,8 +21117,8 @@ msgid "Already registered?" msgstr "Zaten kayıtlı mısın?" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "GiriÅŸ yap" @@ -21563,12 +21236,8 @@ msgid "The page that you were looking for was not found." msgstr "Aradığınız sayfa bulunamadı." #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" -"{homepage} adresine geri dönün veya taşınmış sayfayı {email} adresine " -"bildirin." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -21594,10 +21263,6 @@ msgstr "" "Bir hata tespit ettik ve hatayı bir an önce düzeltmek için üzerinde " "çalışıyoruz." -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "EÄŸer sorun tekrar ederse, {email_link} adresine e-posta atınız." - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "Studio EriÅŸilebilirlik Politikası" @@ -22294,14 +21959,8 @@ msgstr "Aradığınız sayfa bulunamadı" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" -"Ãœzgünüz, aradığınız {studio_name} sayfasını bulamadık. {studio_name} " -"paneline dönüp tekrar deneyebilirsiniz. EÄŸer sorun devam ediyorsa " -"{link_start}{studio_name} destek ekibiyle iletiÅŸime geçerek{link_end} daha " -"fazla yardım alabilirsiniz." #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -22311,14 +21970,8 @@ msgstr "Sunucu bir Hatayla KarşılaÅŸtı" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" -"Ãœzgünüz. Son isteÄŸinizi yaparken bir problem oluÅŸtu. {studio_name} ana " -"paneline dönerek bunu tekrar deneyiniz. Hala problem yaşıyorsanız Lütfen " -"yardım için {link_start}{studio_name} yardım grubu{link_end} ile iletiÅŸime " -"geçin." #: cms/templates/error.html msgid "Back to dashboard" @@ -25667,8 +25320,8 @@ msgstr "%(file)s #%(revision)d revizyonuna deÄŸiÅŸtirildi. " msgid "%(file)s has been saved." msgstr "%(file)s dosyası kaydedildi." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "Görseller" @@ -25871,8 +25524,8 @@ msgstr "Bildirim listesini temizle" msgid "Search..." msgstr "Ara..." -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "Kayıt ol" diff --git a/conf/locale/tr_TR/LC_MESSAGES/djangojs.mo b/conf/locale/tr_TR/LC_MESSAGES/djangojs.mo index 1fae4654f00487f16588232aa34342d153be3703..cb90f9619b4c55fc6736141e2666db054ceb241e 100644 Binary files a/conf/locale/tr_TR/LC_MESSAGES/djangojs.mo and b/conf/locale/tr_TR/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/tr_TR/LC_MESSAGES/djangojs.po b/conf/locale/tr_TR/LC_MESSAGES/djangojs.po index 9a7fb13df6735e32d9215446ba1886830b307df2..27db74ddb6229f0c7edbebd391d55d111f26fc85 100644 --- a/conf/locale/tr_TR/LC_MESSAGES/djangojs.po +++ b/conf/locale/tr_TR/LC_MESSAGES/djangojs.po @@ -50,7 +50,7 @@ # Kubilay <kubilayinceoren10@gmail.com>, 2015 # msare <mervesareakin@gmail.com>, 2014 # Onur Bektas <mustafaonurbektas@gmail.com>, 2013 -# serd@r <inactive+serince@transifex.com>, 2015 +# 169685c64da20f8565d5bb4b5fa14388_0122c8a <d6cdb6a8d55668108fbee6af67afa0d1_255939>, 2015 # umit.dogan <umitgri@gmail.com>, 2014 # ElektrikAkar <volkan.kumtepeli@gmail.com>, 2014 # #-#-#-#-# djangojs-account-settings-view.po (0.1a) #-#-#-#-# @@ -107,16 +107,16 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" -"PO-Revision-Date: 2020-02-20 16:22+0000\n" -"Last-Translator: Ali Işıngör <ali@artistanbul.io>\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" +"Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Turkish (Turkey) (http://www.transifex.com/open-edx/edx-platform/language/tr_TR/)\n" "Language: tr_TR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -152,6 +152,7 @@ msgstr "Kaydediliyor" #: cms/templates/js/signatory-editor.underscore #: cms/templates/js/video-transcripts.underscore #: cms/templates/js/xblock-outline.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Delete" msgstr "Sil" @@ -180,6 +181,7 @@ msgstr "Sil" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -202,6 +204,7 @@ msgstr "Yüklüyor" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -231,6 +234,7 @@ msgstr "Dosya Seç" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "Tamam" @@ -823,7 +827,6 @@ msgstr "Tabloyu sil" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Açıklama" @@ -870,6 +873,7 @@ msgstr "HTML düzenle" #: cms/templates/js/show-textbook.underscore #: cms/templates/js/signatory-details.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Edit" msgstr "Düzenle" @@ -1272,6 +1276,7 @@ msgstr "Yeni pencere" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Sonraki" @@ -1621,6 +1626,7 @@ msgstr "" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/course-instructor-details.underscore #: cms/templates/js/signatory-details.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Title" msgstr "BaÅŸlık" @@ -2099,6 +2105,7 @@ msgid "Your request could not be processed. Refresh the page and try again." msgstr "Ä°steÄŸiniz iÅŸlenemiyor. Tekrar denemek için sayfayı yeniden yükleyin." #: common/static/common/js/discussion/utils.js +#: common/static/common/templates/discussion/templates.underscore msgid "…" msgstr "..." @@ -2303,6 +2310,7 @@ msgid "Your post will be discarded." msgstr "Gönderiniz çıkartılacaktır." #: common/static/common/js/discussion/views/response_comment_show_view.js +#: common/static/common/templates/discussion/templates.underscore msgid "anonymous" msgstr "anonim" @@ -2565,23 +2573,32 @@ msgid "Other" msgstr "DiÄŸer" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" -msgstr "Sana nasıl yardımcı olabiliriz, {username}?" +msgid "Course Discussion Forum" +msgstr "Ders Tartışma Forumu" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Details" msgstr "Ayrıntılar" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" -"Bize ne kadar çok ayrıntı verirseniz, size o kadar hızlı ve faydalı bir " -"ÅŸekilde cevap verebiliriz!" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Gönder" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "Sana nasıl yardımcı olabiliriz, {username}?" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." @@ -2590,11 +2607,8 @@ msgstr "" "saÄŸlayabilirsiniz." #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." -msgstr "" -"Hesabınıza ulaÅŸamıyorsanız bizimle {email} e-posta adresi üzerinden " -"iletiÅŸime geçebilirsiniz." +msgid "Need help logging in?" +msgstr "Oturum açmak için yardıma mı ihtiyacınız var?" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "" @@ -2612,6 +2626,18 @@ msgstr "Destek talebiniz için bir konu seçin." msgid "Enter some details for your support request." msgstr "Destek talebinize dair ayrıntıları girin." +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2636,10 +2662,9 @@ msgstr "{platform} Anasayfasına Git" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" -"Bize talebinizi ilettiÄŸiniz için teÅŸekkür ederiz! Size 24 saat içinde geri " -"döneceÄŸiz." #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx msgid "Cancel upload" @@ -2824,6 +2849,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "Bir hata oluÅŸtu. Tekrar deneyin." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Bu takımdan ayrıl?" @@ -3349,6 +3378,7 @@ msgid "There has been an error processing your survey." msgstr "Anketinizi iÅŸlerken hata oluÅŸtu." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -3365,6 +3395,7 @@ msgid "HTML preview of post" msgstr "Gönderinin HTML önizlemesi" #: lms/static/js/customwmd.js +#: common/static/common/templates/discussion/templates.underscore msgid "Your question or idea (required)" msgstr "Sorunuz veya fikriniz (gerekli)" @@ -3420,6 +3451,8 @@ msgid "" "Unable to determine whether we should give you a refund because of System " "Error. Please try again later." msgstr "" +"Åžu anda Sistem Hatasından dolayı geri ödeme verip veremeyeceÄŸimizi " +"saptayamıyoruz. Lütfen daha sonra tekrar deneyiniz." #: lms/static/js/discovery/views/search_form.js #, javascript-format @@ -5395,10 +5428,12 @@ msgstr "Tümünü Aç" msgid "Collapse All" msgstr "Tümünü Kapa" +#: openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js #: lms/templates/courseware/proctored-exam-status.underscore msgid "Show More" msgstr "Daha Fazla Göster" +#: openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js #: lms/templates/courseware/proctored-exam-status.underscore msgid "Show Less" msgstr "Daha Az Göster" @@ -5555,6 +5590,10 @@ msgstr "Evet, etkinleÅŸtirilmiÅŸ Sertifikayı düzenlemeye izin ver" msgid "certificate" msgstr "sertifika" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Sertifikanızı kurun" @@ -5566,8 +5605,8 @@ msgid "You have not created any certificates yet." msgstr "Henüz bir sertifika oluÅŸturmadınız." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "Ä°mza sahipleri listesinden \"<%= signatoryName %>\" sil?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5619,6 +5658,7 @@ msgstr "" #: cms/static/js/factories/manage_users.js #: cms/static/js/factories/manage_users_lib.js +#: common/static/common/templates/discussion/templates.underscore msgid "Staff" msgstr "Personel" @@ -5876,11 +5916,9 @@ msgstr "Tüm bölümlerin bir adı ve varlığı olmalı" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" -"Sadece <%= fileTypes %> dosya uzantılarını yükleyebilirsiniz. Lütfen sonunda" -" <%= fileExtensions %> uzantısı olan bir dosya yükleyin." #: cms/static/js/models/uploads.js #: lms/templates/student_account/hinted_login.underscore @@ -6064,8 +6102,8 @@ msgid "{selectedProvider} credentials saved" msgstr "" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" -msgstr " Åžu konuma “<%= name %>†yeni bir PDF dosyası yükle" +msgid "Upload a new PDF to “<%- name %>â€" +msgstr "" #: cms/static/js/views/edit_chapter.js msgid "Please select a PDF file to upload." @@ -6666,18 +6704,14 @@ msgstr "Özür dileriz, bir hata oluÅŸtu" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" -"Organizasyonun birleÅŸik boyutu, ders sayısı, ve ders alanları <%=limit%> " -"karakterden fazla olamaz." #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" -"Organizasyonun birleÅŸik boyutu ve kütüphane kodu alanları <%=limit%> " -"karakterden fazla olamaz." #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -7029,13 +7063,13 @@ msgid "Unscheduled" msgstr "Planlanmamış" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Tarih" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Önceki" @@ -7083,6 +7117,311 @@ msgstr "Aramayı Temizle" msgid "Search" msgstr "Ara" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "Bir Cevap Ekle" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "Bu ileti dizisi kapandı." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "Bir cevap ekle:" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Gönder" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "Ä°ÅŸaretli" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "Rapor edildi" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "Kapatıldı" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "Ä°lgili: %(courseware_title_linked)s" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "Bu gönderi herkese açıktır" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "Ä°leti düzenleniyor" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" +"Katılıma teÅŸvik etmek için açık ve tanıtıcı bir baÅŸlık ekle. (Gerekli)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "Ä°letinizi aÅŸağıda düzenleyin." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "Ä°leti güncelle" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "Bir yorum ekleyin" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "Cevap düzenleniyor" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "Cevabı güncelle" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "%(author)s tarafından %(time_ago)s önce gönderildi" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "Yorum deÄŸiÅŸtiriliyor" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "Yorumu güncelle" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "tartışma" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "soru cevaplandı" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "cevaplanmayan soru" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "Takip ediliyor" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "Topluluk Öğretim Elemanı" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "{unread_comments_count} yeni" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "Ä°leti Ekle" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "Görünecek kiÅŸiler" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "Bütün Gruplar" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "bu iletiyi takip et" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "isimsiz olarak ileti yolla" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "Bu ileti herkese görünür olacak." + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "BaÅŸlık alanı" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "(Topluluk Öğretim Elemanı)" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "(Personel)" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "Tüm Gönderiler" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "Tartışmayı görüntüle" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "Daha fazla yükle" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "Gönderi türü" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "Soru" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "Forum" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "Destekle" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "Destekleme" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "Cevap olarak Ä°ÅŸaretle" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "Cevap iÅŸaretini Kaldır" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "Takip et" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "Takibi bırak" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "Bu ileti için oyla," + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "Kötü kullanımı bildir" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "Raporla" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "Bildirme" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "Ä°ÅŸaretle" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "Ä°ÅŸareti kaldır" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "Aç" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "Tartışma Anasayfası" @@ -7141,10 +7480,6 @@ msgstr "" "Takip ettiÄŸiniz gönderilerdeki yeni ve okunmamış etkinlikler hakkında günde " "bir kez etkinlik özeti almak için bu kutucuÄŸu iÅŸaretleyin." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "Tüm Gönderiler" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "kullanıcı adı veya e-posta" @@ -7366,7 +7701,7 @@ msgstr "" #: lms/djangoapps/teams/static/teams/templates/manage.underscore msgid "Assign Team Memberships" -msgstr "" +msgstr "Takım Ãœyeliklerini Belirle" #: lms/djangoapps/teams/static/teams/templates/manage.underscore msgid "Upload Memberships" @@ -7384,6 +7719,10 @@ msgstr "Katılacak bir takım bulmada sorun mu yaşıyorsunuz?" msgid "Join Team" msgstr "Takıma Katıl" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "Takım Detayları" @@ -7470,104 +7809,6 @@ msgstr "Altbölümü kaldır %(subsectionDisplayName)s" msgid "Remove unit %(unitName)s" msgstr "Birimi kaldır %(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" -"Sizin hala daha kredi iÅŸlemini tamamlamak için %(display_name)s websitesine " -"ziyaret etmeniz gerekmektedir." - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" -"Ders kredisini sonlandırmak için, %(display_name)s, kredi talebini yüklemek " -"için %(platform_name)s öğrencilerini gerektirir." - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Kredi Al" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" -"%(course_name)s dersi için ödemenizi aldık. TeÅŸekkürler %(full_name)s!" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"Lütfen kayıtlarınız için bu sayfanın çıktısını fatura olarak alın. Aynı " -"bilgileri içeren bir de e-posta alacaksınız." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "SipariÅŸ No." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Miktar" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Toplam" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Lütfen Bildirin" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "Ãœzerinde çarpı iÅŸareti öğeler iade edilmiÅŸtir." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Faturalandı" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Fatura bulunamadı" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Ana Panele Git" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" -"Åžu an kimliÄŸinizi onaylamasanız da, dersinize hâlâ panelinizden " -"ulaÅŸabilirsiniz. KimliÄŸinizi onaylamanız için, {platformName} size düzenli " -"bildirimler gönderecek." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "KimliÄŸinizi daha sonra mı doÄŸrulamak istersiniz?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Åžimdi DoÄŸrula" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Sınavı Tamamlandı Olarak Ä°ÅŸaretle" @@ -7695,10 +7936,8 @@ msgstr "Hakkınızda" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" -"AÅŸağıdaki bilgiler profilinizde mevcut {platform} bulunuyor. BaÅŸvurunuz için" -" buraya ekledik." #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7728,6 +7967,10 @@ msgstr "" "{course_name} için mali yardım baÅŸvurunuzu gönderdiÄŸiniz için teÅŸekkürler ! " "2-4 iÅŸ günü içerisinde size geri döneceÄŸiz. " +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Ana Panele Git" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "Toplu Ä°stisnalar" @@ -8089,14 +8332,6 @@ msgstr "Artık oturum deÄŸiÅŸtiremezsiniz." msgid "You can change sessions until {expiration_date}." msgstr "{expiration_date} tarihine kadar oturumları deÄŸiÅŸtirebilirsiniz" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "Final Notu" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "{courseName} için" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "ArÅŸivlenmiÅŸ Dersleri Görüntüle" @@ -8181,7 +8416,7 @@ msgstr "Yeni Programları KeÅŸfedin" #: lms/templates/verify_student/enrollment_confirmation_step.underscore msgid "Course" msgid_plural "Courses" -msgstr[0] "" +msgstr[0] "Ders" msgstr[1] "Dersler" #: lms/templates/learner_dashboard/program_card.underscore @@ -8281,7 +8516,7 @@ msgstr "Derslerinizi bitirdikçe, burada listelenmiÅŸ halde göreceksiniz." #: lms/templates/learner_dashboard/program_details_view.underscore msgid "" "Complete courses on your schedule to ensure you stand out in your field!" -msgstr "" +msgstr "Alanınızda öne çıkmanızı saÄŸlamak için derslerinizi tamamlayın!" #: lms/templates/learner_dashboard/program_header_view.underscore msgid "{organization}\\'s logo" @@ -8316,8 +8551,28 @@ msgid "An error occurred. Please reload the page." msgstr "Bir hata oluÅŸtu. Lütfen sayfayı tekrar yükleyin." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" -msgstr "Oturum açmak için yardıma mı ihtiyacınız var?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" +msgstr "" #: lms/templates/student_account/hinted_login.underscore #: lms/templates/student_account/login.underscore @@ -8521,17 +8776,13 @@ msgid "What You Need for Verification" msgstr "DoÄŸrulama İçin Gerekenler" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Web Kamera" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8539,12 +8790,8 @@ msgid "Photo Identification" msgstr "FotoÄŸraflı Kimlik" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"Adınızı ve fotoÄŸrafınızı içeren bir ehliyet, pasaport veya diÄŸer devlet " -"tarafından verilen kimliÄŸe ihtiyacınız var." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8569,14 +8816,10 @@ msgstr "Yüzünüz iyi ışıklandırılmış olmalı." msgid "Your entire face fits inside the frame." msgstr "Yüzünüzün tamamı çerçeve içerisine sığmalı." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "FotoÄŸrafınız, kimlik kartınızdaki ile uygun olmalı." - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8593,17 +8836,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Niçin %(platformName)s benim fotoÄŸrafıma gerek duyuyor?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"DoÄŸrulama sürecinin bir parçası olarak hem yüzünüzün fotÄŸrafını hem de " -"devlet tarafından verilmiÅŸ fotoÄŸraflı kimliÄŸinizin fotoÄŸrafını çekmelisiniz." -" Yetkilendirme hizmetimiz çekmiÅŸ olduÄŸunuz fotoÄŸrafınızı kimlik fotoÄŸrafınız" -" ile karşılaÅŸtırararak kimliÄŸinizi doÄŸrular." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8614,18 +8850,12 @@ msgstr "%(platformName)s bu fotoÄŸraf ile ne yapar?" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"FotoÄŸrafınızı ÅŸifrelemek ve inceleme için yetkilendirme hizmetimize " -"göndermek için uygun olan en yüksek seviyede güvenliÄŸi kullanıyoruz. " -"FotoÄŸrafınız ve bilgileriniz kaydedilmez ve doÄŸrulama süreci tamamlandıktan " -"sonra %(platformName)s üzerinde hiçbir yerde görülmez." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8684,21 +8914,14 @@ msgid "Take a Photo of Your ID" msgstr "KimliÄŸinizin FotoÄŸrafını Çekin" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"KimliÄŸinizin fotoÄŸrafını çekmek için web kameranızı kullanın. Biz bu " -"fotoÄŸrafınızı kimliÄŸiniz üzerindeki fotoÄŸraf ile eÅŸleÅŸtireceÄŸiz." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Adınızı ve fotoÄŸrafınızı içeren bir kimliÄŸe ihtiyacınız vardır. Bir ehliyet," -" pasaport veya diÄŸer hükümet tarafından verilen kimlikler tüm kabul " -"edilebilir." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8722,6 +8945,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8771,6 +9001,30 @@ msgstr "" msgid "Can we match the photo you took with the one on your ID?" msgstr "KimliÄŸiniz üzerindeki fotoÄŸrafla çektiÄŸinizini eÅŸleÅŸtirebilir miyiz?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"DoÄŸrulama sürecinin bir parçası olarak hem yüzünüzün fotÄŸrafını hem de " +"devlet tarafından verilmiÅŸ fotoÄŸraflı kimliÄŸinizin fotoÄŸrafını çekmelisiniz." +" Yetkilendirme hizmetimiz çekmiÅŸ olduÄŸunuz fotoÄŸrafınızı kimlik fotoÄŸrafınız" +" ile karşılaÅŸtırararak kimliÄŸinizi doÄŸrular." + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"FotoÄŸrafınızı ÅŸifrelemek ve inceleme için yetkilendirme hizmetimize " +"göndermek için uygun olan en yüksek seviyede güvenliÄŸi kullanıyoruz. " +"FotoÄŸrafınız ve bilgileriniz kaydedilmez ve doÄŸrulama süreci tamamlandıktan " +"sonra %(platformName)s üzerinde hiçbir yerde görülmez." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -8806,6 +9060,13 @@ msgstr "" "Adınızı ve fotoÄŸrafınızı içeren bir ehliyet, pasaport veya diÄŸer hükümet " "tarafından verilen kimlik" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Web Kamera" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8904,6 +9165,11 @@ msgstr "Sertifika yoluna yükseltmeden önce, hesabınızı etkinleÅŸtirmelisini msgid "Check your email for an activation message." msgstr "Aktivasyon mesajı için e-postanızı kontrol edin." +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Toplam" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "{courseName} için Profesyonel Sertifika" @@ -8948,6 +9214,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "TeÅŸekkürler! {courseName} için olan ödemenizi aldık." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"Lütfen kayıtlarınız için bu sayfanın çıktısını fatura olarak alın. Aynı " +"bilgileri içeren bir de e-posta alacaksınız." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "SipariÅŸ No." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Miktar" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Lütfen Bildirin" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "Ãœzerinde çarpı iÅŸareti öğeler iade edilmiÅŸtir." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Faturalandı" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Fatura bulunamadı" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "Sonraki Adım: KimliÄŸinizi doÄŸrulayın" @@ -8983,6 +9281,10 @@ msgstr "" " keÅŸfedebilirsiniz. KimliÄŸinizi doÄŸrulamak için %(platformName)s üzerinden " "periyodik hatırlatma alacaksınız." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "KimliÄŸinizi daha sonra mı doÄŸrulamak istersiniz?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "Süreç İçinde Kimlik DoÄŸrulama" @@ -8991,12 +9293,9 @@ msgstr "Süreç İçinde Kimlik DoÄŸrulama" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"Bilgilerinizi aldık ve kimliÄŸinizi doÄŸruluyoruz. DoÄŸrulama süreci " -"tamalandığında (genelde 1-2 gün içerisinde tamamlanır) ana panelinize mesaj " -"gelecektir. Bu süre içinde mevcut olan ders içeriklerine ulaÅŸabilirsiniz." #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -9032,10 +9331,6 @@ msgstr "FotoÄŸraf gereklilikleri:" msgid "Does the photo of you show your whole face?" msgstr "FotoÄŸraf yüzünüzün tamamını gösteriyor mu?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "FotoÄŸraf kimlik fotoÄŸrafına uyuyor mu?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "KimliÄŸiniz üzerindeki adınız okunaklı mı?" @@ -10263,12 +10558,16 @@ msgid "" "Draft saved on {lastSavedStart}{editedOn}{lastSavedEnd} by " "{editedByStart}{editedBy}{editedByEnd}" msgstr "" +"Taslak {lastSavedStart}{editedOn}{lastSavedEnd} tarihinde " +"{editedByStart}{editedBy}{editedByEnd} tarafından kaydedildi" #: cms/templates/js/publish-xblock.underscore msgid "" "Last published {lastPublishedStart}{publishedOn}{lastPublishedEnd} by " "{publishedByStart}{publishedBy}{publishedByEnd}" msgstr "" +"En son {lastPublishedStart}{publishedOn}{lastPublishedEnd} tarihinde " +"{publishedByStart}{publishedBy}{publishedByEnd} tarafından yayına alındı" #: cms/templates/js/publish-xblock.underscore #, python-format @@ -10526,6 +10825,21 @@ msgstr "Özel bir sınav olarak oluÅŸtur" msgid "Exam Types" msgstr "Sınav Türleri" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Zamanlanmış" @@ -10724,14 +11038,14 @@ msgstr "" msgid "Read more" msgstr "Daha fazlası" -#: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" -msgstr "Altyazıları göster ({totalTranscripts})" - #: cms/templates/js/video-transcripts.underscore msgid "No transcript uploaded." msgstr "Herhangi bir altyazı yüklenmedi." +#: cms/templates/js/video-transcripts.underscore +msgid "Show transcripts ({totalTranscripts})" +msgstr "Altyazıları göster ({totalTranscripts})" + #: cms/templates/js/xblock-access-editor.underscore msgid "Set Access" msgstr "EriÅŸim Ver" diff --git a/conf/locale/uk/LC_MESSAGES/django.mo b/conf/locale/uk/LC_MESSAGES/django.mo index 47898acc525658da6efa87eb29c52bb1e0c9d7b9..84f55e30be37f72ea4d1b226ac84985b7c7d4448 100644 Binary files a/conf/locale/uk/LC_MESSAGES/django.mo and b/conf/locale/uk/LC_MESSAGES/django.mo differ diff --git a/conf/locale/uk/LC_MESSAGES/django.po b/conf/locale/uk/LC_MESSAGES/django.po index 024b5bb503fee9b01e325cd767a26adae53e0f4f..1ee8091a8e2c179930178ea3488b005a16f20338 100644 --- a/conf/locale/uk/LC_MESSAGES/django.po +++ b/conf/locale/uk/LC_MESSAGES/django.po @@ -19,12 +19,12 @@ # Mykhailo Parfeniuk <sopyer@gmail.com>, 2016 # Natalia Vynogradenko <tannaha@gmail.com>, 2017-2018 # Nikolai Belochub, 2014 -# Oleksandr Pylypenko <inactive+opylypenko@transifex.com>, 2014 +# cc322e8fc6cc292f0f00d8b7420e7410_e468d09 <95dee59251c2de5d1d21e213a66df19d_243275>, 2014 # olexiim <olexiim@gmail.com>, 2014-2015 # Olga Filipova <chudaol@gmail.com>, 2015-2017 # Olga Filipova <olga.filipova@feedzai.com>, 2016,2018 # Zapadenska <oruda@ymail.com>, 2014 -# Sergii <inactive+felytic@transifex.com>, 2014 +# b05b3114c658f75176891a498d64259e_fde2d81 <2bbdcf581dfc2149465c711c88b61acb_243008>, 2014 # Tsybulska Karolina <kirakivuk@gmail.com>, 2014 # Volodymyr Matskiv <xxwolfsilver@gmail.com>, 2014 # Waheed Ahmed <waheed@edx.org>, 2019 @@ -63,16 +63,16 @@ # Galya Galkina <galyagalkina11@gmail.com>, 2015 # Irene Korotkova <irca.gav@gmail.com>, 2017 # IvanPrimachenko <jastudent1@gmail.com>, 2014-2015 -# junnyml <inactive+junnyml@transifex.com>, 2014 +# aed7ad9d75d010b63d79e2c3891aea63_fb18719 <8b0617f0cc0569340367bf1571e18cac_188092>, 2014 # Mykhailo Kolianko, 2016 # Natalia Vynogradenko <tannaha@gmail.com>, 2017-2018 # 557b934119df08e2e59a177854f0e6ac, 2014 -# Oleksandr Pylypenko <inactive+opylypenko@transifex.com>, 2014 +# cc322e8fc6cc292f0f00d8b7420e7410_e468d09 <95dee59251c2de5d1d21e213a66df19d_243275>, 2014 # olexiim <olexiim@gmail.com>, 2014-2015 # Olga Filipova <chudaol@gmail.com>, 2014-2016 # Olga Filipova <olga.filipova@feedzai.com>, 2018 # Radmila Segol <geroneja@yahoo.com>, 2016 -# Sergii <inactive+felytic@transifex.com>, 2015 +# b05b3114c658f75176891a498d64259e_fde2d81 <2bbdcf581dfc2149465c711c88b61acb_243008>, 2015 # Zoriana Zaiats, 2015 # Tetiana Korshun, 2014 # Евгений МовÑеÑов <yevgeniy.movsesov@gmail.com>, 2020 @@ -122,7 +122,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed <waheed@edx.org>, 2019\n" "Language-Team: Ukrainian (https://www.transifex.com/open-edx/teams/6205/uk/)\n" @@ -131,7 +131,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -474,13 +474,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ–Ð· відкритим іменем '{username}' вже Ñ–Ñнує." +msgid "An account with the Email '{email}' already exists." +msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ–Ð· електронною адреÑою '{email}' вже Ñ–Ñнує." #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ–Ð· електронною адреÑою '{email}' вже Ñ–Ñнує." +msgid "An account with the Public Username '{username}' already exists." +msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ–Ð· відкритим іменем '{username}' вже Ñ–Ñнує." #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2448,9 +2448,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -4412,11 +4412,11 @@ msgstr "" "до модулів завдань будуть враховуватиÑÑ Ð² оціночному/відбірковому алгоритмі " "вÑтупного випробуваннÑ." -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Enrollment Track Groups" msgstr "Групи відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ€ÐµÑ”Ñтрації" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "Розділ Ð´Ð»Ñ Ñегментації кориÑтувачів за поÑлідовніÑÑ‚ÑŽ реєÑтрації" @@ -6039,57 +6039,6 @@ msgstr "" "КориÑтувач {username} ({email}) подав запит на Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ ÐºÐ¾ÑˆÑ‚Ñ–Ð². Ð”Ð»Ñ " "обробки цього запиту, будь лаÑка, перейдіть по поÑиланню (поÑиланнÑм) нижче." -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "КвитанціÑ" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "Платіж не виконано" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "" -"З цією операцією виникла проблема. Грошові кошти не були знÑÑ‚Ñ– з рахунку." - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "" -"ПереконайтеÑÑ Ð² правильноÑÑ‚Ñ– введеної інформації, Ñпробуйте ÑкориÑтатиÑÑ " -"іншою картою або оплатити іншим ÑпоÑобом." - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "" -"Під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ вашого платежу виникла помилка. Грошові кошти не були знÑÑ‚Ñ– " -"з рахунку." - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "Будь лаÑка, Ñпробуйте ще раз через декілька хвилин." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "ЗвернітьÑÑ Ð·Ð° допомогою в {payment_support_link}." - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "При Ñтворенні квитанції про оплату ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°." - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "" -"Якщо ÐºÑƒÑ€Ñ Ð½Ðµ з'ÑвитьÑÑ Ð½Ð° вашій панелі керуваннÑ, напишіть " -"{payment_support_link}." - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "Отримайте Ñертифікат" @@ -6151,10 +6100,22 @@ msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтупу до цього курÑу" msgid "You do not have access to this course on a mobile device" msgstr "Цей ÐºÑƒÑ€Ñ Ð½ÐµÐ´Ð¾Ñтупний вам з мобільного додатка" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/djangoapps/courseware/course_tools.py msgid "Upgrade to Verified" msgstr "Підвищити до Ñ€Ñ–Ð²Ð½Ñ Â«ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð¸Ð¹ Ñертифікат»" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -6174,6 +6135,11 @@ msgstr "{relative} - {absolute}" msgid "in {relative} - {absolute}" msgstr "в {relative} - {absolute}" +#: lms/djangoapps/courseware/date_summary.py +#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py +msgid "Enrollment Date" +msgstr "Дата запиÑу на курÑ" + #: lms/djangoapps/courseware/date_summary.py msgid "Course Starts" msgstr "ÐšÑƒÑ€Ñ Ñ€Ð¾Ð·Ð¿Ð¾Ñ‡Ð½ÐµÑ‚ÑŒÑÑ" @@ -6838,16 +6804,20 @@ msgid "Good" msgstr "Добре" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" -msgstr "%(comment_username)s відповів на <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" +msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt msgid "View discussion" msgstr "ПереглÑнути тему" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "%(comment_username)s відповів на <b>%(thread_title)s</b>:" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6989,8 +6959,8 @@ msgid "Student" msgstr "Студент" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "ПерÑонал" @@ -7122,29 +7092,6 @@ msgstr "відповіді на завданнÑ" msgid "Could not find problem with this location." msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð· даним міÑцезнаходженнÑм." -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "Ðеможливо знайти рахунок з номером '{num}'." - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "Продаж по цій квитанції вже була анульована." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "ÐšÐ²Ð¸Ñ‚Ð°Ð½Ñ†Ñ–Ñ {0} була анульована." - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "Ð¦Ñ ÐºÐ²Ð¸Ñ‚Ð°Ð½Ñ†Ñ–Ñ Ð²Ð¶Ðµ була активована." - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "РеєÑтраційні коди Ð´Ð»Ñ ÐºÐ²Ð¸Ñ‚Ð°Ð½Ñ†Ñ–Ñ— {0} були повторно активовані." - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "ID курÑа" @@ -7175,9 +7122,8 @@ msgstr "ID кориÑтувача" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача" @@ -7288,45 +7234,6 @@ msgid "The file must contain a 'username' column, an 'email' column, or both." msgstr "" "Файл повинен міÑтити Ñтовпець «username», Ñтовпець «email», або обидва." -#: lms/djangoapps/instructor/views/api.py -msgid "Coupon Code" -msgstr "Код купона" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "Ідентифікатор курÑу" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "% знижка" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "ОпиÑ" - -#: lms/djangoapps/instructor/views/api.py -msgid "Expiration Date" -msgstr "Дата Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "Ðктивний" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "КількіÑÑ‚ÑŒ викориÑтаних кодів" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "Загальна кількіÑÑ‚ÑŒ міÑць, Ñплачених зі знижкою" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "Загальна Ñума знижки" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -7347,16 +7254,6 @@ msgstr "оглÑд" msgid "proctored exam results" msgstr "результати контрольованих Ñ–Ñпитів" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "Ðе вдалоÑÑ Ñ€Ð¾Ð·Ð¿Ñ–Ð·Ð½Ð°Ñ‚Ð¸ Ñуму у виглÑді деÑÑткового чиÑла" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "" -"Ðе вдалоÑÑ Ð³ÐµÐ½ÐµÑ€ÑƒÐ²Ð°Ñ‚Ð¸ компенÑаційні коди із-за неправильної конфігурації " -"курÑу." - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -7603,65 +7500,6 @@ msgstr "" "правильноÑÑ‚Ñ– ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача/адреÑÑ– електронної пошти та обраного курÑу, " "потім повторіть Ñпробу." -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "ідентифікаційний номер купона - None" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "купона з ідентифікаційним номером ({coupon_id}) не Ñ–Ñнує" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "купон з ідентифікаційним номером ({coupon_id}) вже недійÑний" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "купон з ідентифікаційним номером ({coupon_id}) уÑпішно оновлено" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "" -"Код ({code}), що ви намагалиÑÑ Ð²Ð¸Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸, вже викориÑтовуєтьÑÑ Ð² ÑкоÑÑ‚Ñ– " -"реєÑтраційного коду." - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "Будь лаÑка, введіть цілочиÑельний код купона Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð½Ð¸Ð¶ÐºÐ¸." - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "Будь лаÑка, введіть величину знижки по купону, меншу або рівну 100" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "Будь лаÑка, введіть дати в цьому форматі, тобто міÑÑць/день/рік" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "купон з кодом ({code}) уÑпішно додано" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "Купон ({code}) Ð´Ð»Ñ Ð´Ð°Ð½Ð¾Ð³Ð¾ курÑу вже був активований." - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "ідентифікаційний номер купона не знайдено" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "купон з ідентифікаційним номером ({coupon_id}) уÑпішно оновлено" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "Викладач" @@ -7777,29 +7615,6 @@ msgstr "Завершено" msgid "Incomplete" msgstr "Ðезавершено" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "Ðе знайдено реєÑтраційний код ({code}) Ð´Ð»Ñ ÐºÑƒÑ€Ñу {course_name}." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "Цей реєÑтраційний код недійÑний. Його вже не можна викориÑтовувати." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "Цей реєÑтраційний код відзначений Ñк невикориÑтаний." - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "РеєÑтраційний код відновлений." - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "Код Ð·Ð°Ñ€Ð°Ñ…ÑƒÐ²Ð°Ð½Ð½Ñ ({code}) неможливо повернути." - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7997,10 +7812,6 @@ msgstr "Ðазва" msgid "Year of Birth" msgstr "Рік ÐародженнÑ" -#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py -msgid "Enrollment Date" -msgstr "Дата запиÑу на курÑ" - #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py msgid "Currently Enrolled" msgstr "Зараз запиÑаний" @@ -8202,8 +8013,8 @@ msgstr " (з {total})" #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "Програми" @@ -8934,6 +8745,11 @@ msgstr "Загальна вартіÑÑ‚ÑŒ" msgid "Currency" msgstr "Валюта" +#: lms/djangoapps/shoppingcart/reports.py wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "ОпиÑ" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "Коментарі" @@ -9078,14 +8894,6 @@ msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” прав Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду цієї Ñто msgid "View and regenerate certificates." msgstr "ПереглÑнути повторно Ñ– Ñтворити Ñертифікати." -#: lms/djangoapps/support/views/index.py -msgid "Manual Refund" -msgstr " ÐŸÐ¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "ВідÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ÑˆÐºÐ¾Ð´ÑƒÐ²Ð°Ð½ÑŒ, виданих безпоÑередньо через CyberSource." - #: lms/djangoapps/support/views/index.py msgid "Enrollment" msgstr "Ð—Ð°Ñ€Ð°Ñ…ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° курÑ" @@ -9159,38 +8967,9 @@ msgstr "КориÑтувача Ввімкнено УÑпішно" msgid "User Disabled Successfully" msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ðµ уÑпiшно" -#: lms/djangoapps/support/views/refund.py -msgid "Email Address" -msgstr "Поштова Ñкринька" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course ID" -msgstr "ID курÑу" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "КориÑтувач не знайдений" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "Ð”Ð»Ñ ÐºÑƒÑ€Ñа {course_id} ще діє Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ ÐºÐ¾ÑˆÑ‚Ñ–Ð²." - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "Ð—Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача {user} на ÐºÑƒÑ€Ñ {course_id} не знайдено" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "КориÑтувач {user} відрахований з курÑу {course_id}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "Повернуто {cost} за Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ â„– {order_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -10256,8 +10035,8 @@ msgstr "" "%(start_link)scheatsheet%(end_link)sÐ´Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¸." #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "Доданки" @@ -10715,6 +10494,10 @@ msgid "Configuration may not be specified at more than one level at once." msgstr "" "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ може бути вказана одночаÑно на більш ніж одному рівні." +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -11133,6 +10916,10 @@ msgstr "Відомий випадок помилки" msgid "Schedule start < course start" msgstr "Початок розкладу < початку курÑу" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "Ідентифікатор курÑу" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "Ð’ÑÑ–" @@ -11141,6 +10928,10 @@ msgstr "Ð’ÑÑ–" msgid "Experience" msgstr "ДоÑвід" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course ID" +msgstr "ID курÑу" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -11604,7 +11395,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -11806,6 +11596,14 @@ msgstr "" "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ— про ваш доÑтуп виникла помилка. Будь лаÑка, " "напишіть нам електронного лиÑта." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11819,6 +11617,15 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "Ðадто багато Ñпроб входу. Спробуйте ще раз пізніше." +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11826,15 +11633,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "username@domain.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -11851,6 +11649,12 @@ msgstr "" msgid "Create Account" msgstr "Створити обліковий запиÑ" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "username@domain.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -11867,6 +11671,11 @@ msgstr "" "Обліковий Ð·Ð°Ð¿Ð¸Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, пов'Ñзаний з цією адреÑою електронної пошти, не" " може змінити пароль." +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "Ðе вдалоÑÑ Ñкинути пароль" @@ -11890,11 +11699,6 @@ msgstr "" "Ñтворений.{bold_start}{email}{bold_end} тепер Ñ” оÑновною електронною адреÑою" " Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "Виникла помилка при Ñкиданні паролю. Будь лаÑка, Ñпробуйте ще" @@ -12132,6 +11936,18 @@ msgstr "" "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача, Ñтворене Ð´Ð»Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— відео конвєєра , наприклад, " "veda_service_user" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "ПримуÑово" @@ -12150,6 +11966,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "Це неприпуÑтиме значеннÑ." @@ -12893,8 +12713,8 @@ msgstr "Ðавчальний ÐºÑƒÑ€Ñ ÑƒÑпішно екÑпортовано в msgid "Vertical" msgstr "Вертикальний" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "Розділ" @@ -13177,6 +12997,18 @@ msgstr "ТранÑÐºÑ€Ð¸Ð¿Ñ†Ñ–Ñ Ð² прогреÑÑ–" msgid "Transcript Ready" msgstr "ТранÑкрипт готовий" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "Ðеобхідний файл зображеннÑ." @@ -13325,8 +13157,8 @@ msgstr "Контент" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "ÐалаштуваннÑ" @@ -13374,14 +13206,14 @@ msgstr "Ðомер КурÑу:" msgid "Course Run:" msgstr "" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "КурÑи" @@ -13405,8 +13237,9 @@ msgstr "Викладачі" msgid "Requirements" msgstr "Вимоги" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "" @@ -13456,15 +13289,15 @@ msgstr "" msgid "Choose Language" msgstr "" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "Обліковий запиÑ" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -13536,8 +13369,8 @@ msgstr "" msgid "Usermenu dropdown" msgstr "" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "Вийти" @@ -13703,8 +13536,8 @@ msgstr "" msgid "View all Courses" msgstr "ПереглÑнути уÑÑ– курÑи" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "Панель управліннÑ" @@ -13723,8 +13556,8 @@ msgstr "" #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "Обрати курÑи" @@ -13742,7 +13575,7 @@ msgstr "" msgid "Search Your Courses" msgstr "" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "" @@ -13767,7 +13600,7 @@ msgstr "Отримувати лиÑти від курÑу" msgid "Save Settings" msgstr "Зберегти налаштуваннÑ" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -13777,9 +13610,87 @@ msgstr "Зберегти налаштуваннÑ" msgid "Unenroll" msgstr "ВідпиÑатиÑÑ Ð²Ñ–Ð´ курÑу" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "ПереглÑнути блок в Студії" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -13811,7 +13722,7 @@ msgstr "" msgid "You should Register before trying to access the Unit" msgstr "" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "" @@ -13911,7 +13822,7 @@ msgid "" "available on the {link_start}progress page{link_end}." msgstr "" -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "" @@ -14049,17 +13960,15 @@ msgstr "" msgid "working" msgstr "" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" #: lms/templates/module-error.html @@ -14099,7 +14008,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "" #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -14163,28 +14080,6 @@ msgstr "Електронна адреÑа" msgid "Return To %s" msgstr "" -#: lms/templates/reset_deadlines_banner.html -msgid "It looks like you've missed some important deadlines. Visit " -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "edx.org" -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid " to reset your deadlines and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "" @@ -14233,7 +14128,7 @@ msgstr "" msgid "Sequence" msgstr "" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -14364,18 +14259,18 @@ msgstr "" msgid "Reset Learner's Attempts to Zero" msgstr "Скинути Ñпроби Ñтудентів до нулÑ" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "Перезарахувати бали Ñтудента" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "Перезарахувати тільки, Ñкщо бал підвищитьÑÑ" @@ -14413,7 +14308,7 @@ msgstr "" msgid "Textbook Navigation" msgstr "" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "" @@ -14579,7 +14474,7 @@ msgid "" " not mean to do this, {undo_link_start}you can re-subscribe{link_end}." msgstr "" -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "Панель ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð´Ð»Ñ:" @@ -14587,8 +14482,8 @@ msgstr "Панель ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð´Ð»Ñ:" msgid "More options" msgstr "" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "" @@ -15778,35 +15673,6 @@ msgstr "" msgid "About edX Certificates" msgstr "" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "" - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -16005,11 +15871,11 @@ msgid "This content is graded" msgstr "" #: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." +msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" #: lms/templates/courseware/course_about.html -msgid "An error has occurred. Please ensure that you are logged in to enroll." +msgid "An error occurred. Please try again later." msgstr "" #: lms/templates/courseware/course_about.html @@ -16023,10 +15889,6 @@ msgstr "" msgid "View Course" msgstr "ПереглÑнути курÑ" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "" @@ -16039,10 +15901,6 @@ msgstr "" msgid "Enrollment is Closed" msgstr "Ð—Ð°Ð¿Ð¸Ñ Ð½Ð° ÐºÑƒÑ€Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¾" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "" @@ -16164,6 +16022,13 @@ msgstr "" msgid "Courseware" msgstr "Ðавчальна програма" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "" @@ -16192,7 +16057,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -16200,14 +16065,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" msgstr "" -#: lms/templates/courseware/error-message.html -msgid "" -"We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible." +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -16846,7 +16708,7 @@ msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." +"complete (usually within 5-7 days)." msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html @@ -16857,7 +16719,7 @@ msgstr "" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." +"5-7 days)." msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html @@ -17532,129 +17394,6 @@ msgid "" "verification process on your dashboard." msgstr "" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "Дата: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "Кінцева дата: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -17817,8 +17556,8 @@ msgstr "" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} Ð”Ð¾Ð¼Ð°ÑˆÐ½Ñ Ð¡Ñ‚Ð¾Ñ€Ñ–Ð½ÐºÐ°" @@ -17839,19 +17578,11 @@ msgstr "" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "СиÑтемний адмініÑтратор" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "" @@ -17888,6 +17619,12 @@ msgstr "" msgid "Enter information about the coupon code below." msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "" @@ -18457,6 +18194,11 @@ msgstr "" msgid "Coupon Codes" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "" @@ -19743,6 +19485,10 @@ msgstr "" msgid "Purchase order number (if any)" msgstr "" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "" @@ -20036,6 +19782,10 @@ msgstr[1] "" msgstr[2] "" msgstr[3] "" +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "" @@ -20246,46 +19996,6 @@ msgstr "" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "" @@ -20420,7 +20130,7 @@ msgstr "" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" #: lms/templates/verify_student/reverify_not_allowed.html @@ -20985,8 +20695,8 @@ msgid "Already registered?" msgstr "" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "Увійти" @@ -21084,12 +20794,8 @@ msgid "The page that you were looking for was not found." msgstr "Сторінку, Ñку ви шукали, не знайдено." #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." +msgid "Go back to the {homepage}." msgstr "" -"ПовернітьÑÑ Ð´Ð¾ домашньої Ñторінки {homepage} або повідомте нам про будь-Ñкі" -" Ñторінки, Ñкі могли бути переміщені, повідомленнÑм на {email}." #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -21113,10 +20819,6 @@ msgid "" "error as soon as possible." msgstr "" -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "" - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "" @@ -21756,9 +21458,7 @@ msgstr "" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" #: cms/templates/error.html @@ -21769,9 +21469,7 @@ msgstr "Ðа Ñервері виникла помилка" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" #: cms/templates/error.html @@ -24916,8 +24614,8 @@ msgstr "%(file)s був змінений на верÑÑ–ÑŽ #%(revision)d" msgid "%(file)s has been saved." msgstr "%(file)s був збережений." -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "ЗображеннÑ" @@ -25125,8 +24823,8 @@ msgstr "ОчиÑтити ÑпиÑок Ñповіщень" msgid "Search..." msgstr "Пошук..." -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "ЗареєÑтроватиÑÑ" diff --git a/conf/locale/uk/LC_MESSAGES/djangojs.mo b/conf/locale/uk/LC_MESSAGES/djangojs.mo index e85902234ca49a8fa14387aa3f58d2ac7752c9bb..e74853d7b26afa18fd957785947aef8274c8f7cf 100644 Binary files a/conf/locale/uk/LC_MESSAGES/djangojs.mo and b/conf/locale/uk/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/uk/LC_MESSAGES/djangojs.po b/conf/locale/uk/LC_MESSAGES/djangojs.po index 857b3bc884a175092766ab63f4bdd544990187a0..09c86319b1e3247f5bddc8614e0d61d4906c5e78 100644 --- a/conf/locale/uk/LC_MESSAGES/djangojs.po +++ b/conf/locale/uk/LC_MESSAGES/djangojs.po @@ -13,8 +13,8 @@ # Irene Korotkova <irca.gav@gmail.com>, 2017 # IvanPrimachenko <jastudent1@gmail.com>, 2014 # IvanPrimachenko <jastudent1@gmail.com>, 2014 -# junnyml <inactive+junnyml@transifex.com>, 2014 -# junnyml <inactive+junnyml@transifex.com>, 2014 +# aed7ad9d75d010b63d79e2c3891aea63_fb18719 <8b0617f0cc0569340367bf1571e18cac_188092>, 2014 +# aed7ad9d75d010b63d79e2c3891aea63_fb18719 <8b0617f0cc0569340367bf1571e18cac_188092>, 2014 # marichkafox <marichka.fox@gmail.com>, 2014 # marichkafox <marichka.fox@gmail.com>, 2014 # Maryna Holovnova <MGG-2008@yandex.ru>, 2014 @@ -62,7 +62,7 @@ # EdX Team <info@edx.org>, 2020. # # Translators: -# Sergii <inactive+felytic@transifex.com>, 2019 +# b05b3114c658f75176891a498d64259e_fde2d81 <2bbdcf581dfc2149465c711c88b61acb_243008>, 2019 # Andrii Parkhomenko <andriy.parhomenko@gmail.com>, 2019 # Anna Mikhalchuk <anna.mikhalchuk@raccoongang.com>, 2019 # @@ -98,8 +98,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Ukrainian (http://www.transifex.com/open-edx/edx-platform/language/uk/)\n" "Language: uk\n" @@ -107,7 +107,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -156,6 +156,7 @@ msgstr "Видалити" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -2539,7 +2540,15 @@ msgid "Other" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx @@ -2547,21 +2556,23 @@ msgid "Details" msgstr "Деталі" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "ÐадіÑлати" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "Увійдіть до {platform}, щоб ми змогли вам краще допомогти." #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2580,6 +2591,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "Введіть деÑкі деталі Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ вашого запиту." +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2603,7 +2626,8 @@ msgstr "Перейти на домашню Ñторінку {platform}" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2785,6 +2809,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "Виникла помилка. Будь лаÑка, Ñпробуйте ще раз." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Залишити цю команду?" @@ -3311,6 +3339,7 @@ msgid "There has been an error processing your survey." msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ вашої роботи." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -5565,6 +5594,10 @@ msgstr "Так, дозволити редагувати активний Сер msgid "certificate" msgstr "Ñертифікат" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Ðалаштувати Ñертифікат" @@ -5576,8 +5609,8 @@ msgid "You have not created any certificates yet." msgstr "Ви не Ñтворили жодного Ñертифікату." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "Видалити \"<%= signatoryName %>\" зі ÑпиÑку полів?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5882,11 +5915,9 @@ msgstr "Ð’Ñім розділам потрібно мати назву та Ñк #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" -"Лише файли типів <%= fileTypes %> можуть бути завантажені. Будь лаÑка, " -"оберіть Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð» з розширеннÑм <%= fileExtensions %>." #: cms/static/js/models/uploads.js msgid "or" @@ -6066,8 +6097,8 @@ msgid "{selectedProvider} credentials saved" msgstr "{selectedProvider} облікові дані збережено" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" -msgstr "Завантажити новий PDF в “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" +msgstr "" #: cms/static/js/views/edit_chapter.js msgid "Please select a PDF file to upload." @@ -6672,18 +6703,14 @@ msgstr "Вибачте, ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" -"Сукупна довжина назви організації, номера курÑу та навчального року не може " -"перевищувати <%=limit%> Ñимволів." #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" -"Сукупна довжина назви організації та коду бібліотеки не може перевищувати " -"<%=limit%> Ñимволів." #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -7045,13 +7072,13 @@ msgid "Unscheduled" msgstr "" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "Попередній" @@ -7099,6 +7126,312 @@ msgstr "" msgid "Search" msgstr "" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "ÐадіÑлати" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "УÑÑ– повідомленнÑ" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr " ÐžÐ±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ñ Ð“Ð¾Ð»Ð¾Ð²Ð½Ð° Ñторінка" @@ -7157,10 +7490,6 @@ msgstr "" "Відзначте тут, щоб Ñ‰Ð¾Ð´Ð½Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼ÑƒÐ²Ð°Ñ‚Ð¸ оглÑд нових непрочитаних коментарів Ñ– " "відповідей на допиÑи, Ñкі ви відÑтежуєте." -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "УÑÑ– повідомленнÑ" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або електронна пошта" @@ -7394,6 +7723,10 @@ msgstr "" msgid "Join Team" msgstr "" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "" @@ -7478,94 +7811,6 @@ msgstr "" msgid "Remove unit %(unitName)s" msgstr "" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "" @@ -7693,7 +7938,7 @@ msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore @@ -7722,6 +7967,10 @@ msgid "" "{course_name}! You can expect a response in 2-4 business days." msgstr "" +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "МаÑові винÑтки" @@ -8071,14 +8320,6 @@ msgstr "" msgid "You can change sessions until {expiration_date}." msgstr "" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "" @@ -8296,7 +8537,27 @@ msgid "An error occurred. Please reload the page." msgstr "" #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -8494,17 +8755,13 @@ msgid "What You Need for Verification" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" +msgid "Device with Camera" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8512,9 +8769,7 @@ msgid "Photo Identification" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8540,14 +8795,10 @@ msgstr "" msgid "Your entire face fits inside the frame." msgstr "" -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "" - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8564,12 +8815,9 @@ msgid "Why does %(platformName)s need my photo?" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8581,13 +8829,11 @@ msgstr "" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8647,15 +8893,13 @@ msgid "Take a Photo of Your ID" msgstr "" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" #: lms/templates/verify_student/id_photo_step.underscore @@ -8680,6 +8924,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8726,6 +8977,22 @@ msgstr "" msgid "Can we match the photo you took with the one on your ID?" msgstr "" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -8754,6 +9021,13 @@ msgid "" "and photo" msgstr "" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8841,6 +9115,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "" +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "" @@ -8878,6 +9157,36 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "" @@ -8906,6 +9215,10 @@ msgid "" "%(platformName)s to verify your identity." msgstr "" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "" @@ -8914,7 +9227,7 @@ msgstr "" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" @@ -8950,10 +9263,6 @@ msgstr "" msgid "Does the photo of you show your whole face?" msgstr "" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "" @@ -10378,6 +10687,21 @@ msgstr "" msgid "Exam Types" msgstr "" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "" @@ -10546,11 +10870,11 @@ msgid "Read more" msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" +msgid "No transcript uploaded." msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "No transcript uploaded." +msgid "Show transcripts ({totalTranscripts})" msgstr "" #: cms/templates/js/xblock-access-editor.underscore diff --git a/conf/locale/vi/LC_MESSAGES/djangojs.mo b/conf/locale/vi/LC_MESSAGES/djangojs.mo index 43ccecd4c3a0d7737af69694a1adbe003e0b27da..e823baef87e919328048a8bcea0d781a56c888e6 100644 Binary files a/conf/locale/vi/LC_MESSAGES/djangojs.mo and b/conf/locale/vi/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/vi/LC_MESSAGES/djangojs.po b/conf/locale/vi/LC_MESSAGES/djangojs.po index 0de93832232a52fccfcccbe80d28849fe7e4a80e..cea6bac0abe4a0c408832620d24ddc0be21ef17e 100644 --- a/conf/locale/vi/LC_MESSAGES/djangojs.po +++ b/conf/locale/vi/LC_MESSAGES/djangojs.po @@ -6,7 +6,7 @@ # Translators: # NguyenTheTruong <41204219thetruong@gmail.com>, 2016 # Anh Phan <vietnamesel10n@gmail.com>, 2013 -# Dinh Hung Tu <inactive+dinhhungtu@transifex.com>, 2015 +# 7b361a451bd8feeed2dbd9245f836232_a786ad5 <aefa5f09660e622131eca858f9656914_301034>, 2015 # Hoang Doan <dthoang92@gmail.com>, 2014 # Hoang Ha <halink0803@gmail.com>, 2014 # Ha Ngoc Chung <ngocchung75@gmail.com>, 2013 @@ -76,7 +76,7 @@ # # Translators: # NguyenTheTruong <41204219thetruong@gmail.com>, 2016 -# Dinh Hung Tu <inactive+dinhhungtu@transifex.com>, 2015 +# 7b361a451bd8feeed2dbd9245f836232_a786ad5 <aefa5f09660e622131eca858f9656914_301034>, 2015 # Hoang Ha <halink0803@gmail.com>, 2014 # Hoà Lê Thanh <hoa.lethanh@gmail.com>, 2017 # Nguyen Don Binh <donbinhvn@gmail.com>, 2014 @@ -106,8 +106,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Vietnamese (http://www.transifex.com/open-edx/edx-platform/language/vi/)\n" "Language: vi\n" @@ -115,7 +115,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -164,6 +164,7 @@ msgstr "Xóa" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -186,6 +187,7 @@ msgstr "Äang tải lên" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -790,7 +792,6 @@ msgstr "Xóa bảng" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "Mô tả" @@ -1230,6 +1231,7 @@ msgstr "Cá»a sổ má»›i" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "Tiếp theo" @@ -2489,29 +2491,39 @@ msgid "Other" msgstr "Lá»±a chá»n khác" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" -msgstr "Chúng tôi có thể giúp gì cho bạn, {username}?" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Details" msgstr "Chi tiết" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" +msgid "the more quickly and helpfully we can respond!" msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "Gá»i" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "Chúng tôi có thể giúp gì cho bạn, {username}?" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "Äăng nháºp và o {platform} để chúng tôi có thể há»— trợ bạn tốt hÆ¡n." #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." +msgid "Need help logging in?" msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -2530,6 +2542,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "Nháºp má»™t số chi tiết cho yêu cầu há»— trợ của bạn." +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2553,7 +2577,8 @@ msgstr "Chuyển đến Trang chủ {platform}" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx @@ -2735,6 +2760,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "Có lá»—i xảy ra. Vui lòng thá» lại." +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "Rá»i nhóm nà y?" @@ -3268,6 +3297,7 @@ msgid "There has been an error processing your survey." msgstr "Xảy ra lá»—i khi xá» là phiếu Ä‘iá»u tra của bạn." #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -5460,6 +5490,10 @@ msgstr "Có, cho phép chỉnh sá»a Chứng chỉ" msgid "certificate" msgstr "chứng chỉ" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "Thiết láºp chứng chỉ của bạn" @@ -5471,8 +5505,8 @@ msgid "You have not created any certificates yet." msgstr "Bạn chÆ°a tạo bất kỳ chứng chỉ nà o." #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "Xoá \"<%= signatoryName %>\" từ danh sách ký tên?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5779,11 +5813,9 @@ msgstr "Tất cả các chÆ°Æ¡ng phải có tên và liên kết chÆ°Æ¡ng" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." msgstr "" -"Chỉ táºp tin dạng <%= fileTypes %> có thể được tải lên. Xin vui lòng chá»n má»™t" -" táºp tin kết thúc bằng <%= fileExtensions %> để tải lên." #: cms/static/js/models/uploads.js #: lms/templates/student_account/hinted_login.underscore @@ -5964,8 +5996,8 @@ msgid "{selectedProvider} credentials saved" msgstr "" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" -msgstr "Tải lên má»™t file PDF má»›i lên “<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" +msgstr "" #: cms/static/js/views/edit_chapter.js msgid "Please select a PDF file to upload." @@ -6569,18 +6601,14 @@ msgstr "Rất tiếc, có lá»—i xảy ra" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." +"fields cannot be more than <%- limit %> characters." msgstr "" -"Chiá»u dà i kết hợp của các trÆ°á»ng tổ chức, số hiệu khoá há»c, há»c kỳ không " -"được nhiá»u hÆ¡n <%=limit%> ký tá»±." #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." +"more than <%- limit %> characters." msgstr "" -"Chiá»u dà i kết hợp của trÆ°á»ng tổ chức và mã mã thÆ° viện không được nhiá»u hÆ¡n " -"<%=limit%> ký tá»±." #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -6934,13 +6962,13 @@ msgid "Unscheduled" msgstr "" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "Ngà y" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "TrÆ°á»›c" @@ -6988,6 +7016,309 @@ msgstr "Xoá tìm kiếm" msgid "Search" msgstr "Tìm kiếm" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "Ná»™p" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "" @@ -7046,10 +7377,6 @@ msgstr "" "Chá»n ô nà y để nháºn thÆ° tóm tắt hà ng ngà y vá» các hoạt Ä‘á»™ng má»›i từ các bà i " "posts mà bạn Ä‘ang theo dõi. " -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "Tên ngÆ°á»i dùng hoặc email" @@ -7288,6 +7615,10 @@ msgstr "Bạn có gặp khó khăn khi tìm má»™t Ä‘á»™i để tham gia?" msgid "Join Team" msgstr "Tham gia nhóm" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "Chi tiết nhóm" @@ -7372,98 +7703,6 @@ msgstr "" msgid "Remove unit %(unitName)s" msgstr "" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "" -"Bạn vẫn cần phải truy cáºp và o các trang web %(display_name)s để hoà n tất quá" -" trình tÃn chỉ." - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "" - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "Lấy tÃn chỉ" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "" -"Hãy in trang nà y để lÆ°u trữ, nó phục vụ nhÆ° là biên lai của bạn. Bạn cÅ©ng sẽ" -" nháºn được má»™t email vá»›i các thông tin tÆ°Æ¡ng tá»±." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "ÄÆ¡n hà ng số" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "Số lượng" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "Tổng cá»™ng" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "Xin lÆ°u ý" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "Các mặt hà ng gạch chéo là đã được hoà n trả." - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "Äã gá»i hóa Ä‘Æ¡n cho" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "Không biên nháºn có sẵn" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "Äi đến bảng Ä‘iá»u khiển" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "Bạn muốn xác nháºn danh tÃnh của bạn và o lúc khác?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "Xác nháºn ngay bây giá»" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "Äánh dấu bà i thi đã hoà n thà nh" @@ -7591,7 +7830,7 @@ msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." +"We've included it here for your application." msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore @@ -7620,6 +7859,10 @@ msgid "" "{course_name}! You can expect a response in 2-4 business days." msgstr "" +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "Äi đến bảng Ä‘iá»u khiển" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "" @@ -7957,14 +8200,6 @@ msgstr "" msgid "You can change sessions until {expiration_date}." msgstr "" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "" @@ -8179,7 +8414,27 @@ msgid "An error occurred. Please reload the page." msgstr "Có lá»—i xảy ra. Hãy tải lại trang." #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" msgstr "" #: lms/templates/student_account/hinted_login.underscore @@ -8381,17 +8636,13 @@ msgid "What You Need for Verification" msgstr "Những gì bạn cần để xác minh" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "Webcam" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8399,12 +8650,8 @@ msgid "Photo Identification" msgstr "" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." +msgid "You need a valid ID that contains your full name and photo." msgstr "" -"Bạn cần có bằng lái xe, há»™ chiếu, hoặc ID chÃnh phủ phát hà nh có tên và ảnh " -"của bạn." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8429,15 +8676,10 @@ msgstr "" msgid "Your entire face fits inside the frame." msgstr "Toà n bá»™ khuôn mặt của bạn phù hợp vá»›i bên trong khung." -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "" -"Những hình ảnh của khuôn mặt của bạn phù hợp vá»›i hình ảnh trên ID của bạn." - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8454,12 +8696,9 @@ msgid "Why does %(platformName)s need my photo?" msgstr "Tại sao %(platformName)s cần ảnh của bạn?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8471,18 +8710,12 @@ msgstr "" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"Chúng tôi sá» dụng các mức bảo máºt cao nhất có sẵn để mã hóa hình ảnh của bạn" -" và gá»i nó đến dịch vụ ủy quyá»n của chúng tôi để xem xét. Ảnh và thông tin " -"của bạn sẽ không được lÆ°u hay bất cứ nÆ¡i nà o có thể nhìn thấy trên " -"%(platformName)s sau khi quá trình xác minh hoà n tất." #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8541,20 +8774,14 @@ msgid "Take a Photo of Your ID" msgstr "Hãy hình ảnh của ID của bạn" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." +msgid "Use your webcam to take a photo of your ID." msgstr "" -"Sá» dụng webcam của bạn để có má»™t bức ảnh của ID của bạn. Chúng tôi sẽ đối " -"bức ảnh nà y vá»›i hình ảnh của khuôn mặt của bạn và tên tà i khoản của bạn." #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." msgstr "" -"Bạn cần má»™t ID có tên và ảnh của bạn. Giấy phép, há»™ chiếu, hoặc ID chÃnh phủ" -" phát hà nh của má»™t trình Ä‘iá»u khiển được tất cả chấp nháºn được." #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8578,6 +8805,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8629,6 +8863,26 @@ msgstr "" "Chúng ta có thể phù hợp vá»›i hình ảnh mà bạn đã có má»™t trong những ID của " "bạn?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"Chúng tôi sá» dụng các mức bảo máºt cao nhất có sẵn để mã hóa hình ảnh của bạn" +" và gá»i nó đến dịch vụ ủy quyá»n của chúng tôi để xem xét. Ảnh và thông tin " +"của bạn sẽ không được lÆ°u hay bất cứ nÆ¡i nà o có thể nhìn thấy trên " +"%(platformName)s sau khi quá trình xác minh hoà n tất." + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "" @@ -8659,6 +8913,13 @@ msgstr "" "Giấy phép, há»™ chiếu, hoặc ID chÃnh phủ phát hà nh của má»™t ngÆ°á»i lái xe vá»›i " "tên và ảnh của bạn" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "Webcam" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8753,6 +9014,11 @@ msgstr "" msgid "Check your email for an activation message." msgstr "" +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "Tổng cá»™ng" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "" @@ -8790,6 +9056,38 @@ msgstr "" msgid "Thank you! We have received your payment for {courseName}." msgstr "" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "" +"Hãy in trang nà y để lÆ°u trữ, nó phục vụ nhÆ° là biên lai của bạn. Bạn cÅ©ng sẽ" +" nháºn được má»™t email vá»›i các thông tin tÆ°Æ¡ng tá»±." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "ÄÆ¡n hà ng số" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "Số lượng" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "Xin lÆ°u ý" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "Các mặt hà ng gạch chéo là đã được hoà n trả." + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "Äã gá»i hóa Ä‘Æ¡n cho" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "Không biên nháºn có sẵn" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "BÆ°á»›c tiếp theo: " @@ -8825,6 +9123,10 @@ msgstr "" "khóa há»c của bạn từ bảng Ä‘iá»u khiển của bạn. Bạn sẽ nháºn được nhắc nhở định " "kỳ từ %(platformName)s là để xác minh danh tÃnh của bạn." +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "Bạn muốn xác nháºn danh tÃnh của bạn và o lúc khác?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "Việc xác nháºn danh tÃnh Ä‘ang được tiến hà nh" @@ -8833,13 +9135,9 @@ msgstr "Việc xác nháºn danh tÃnh Ä‘ang được tiến hà nh" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"Chúng tôi đã nháºn được thông tin của bạn và đang tiến xác nháºn danh tÃnh của" -" bạn. Bạn sẽ thấy má»™t tin nhắn trên bảng Ä‘iá»u khiển khi quá trình xác nháºn " -"hoà n tất (thông thÆ°á»ng trong vòng 1-2 ngà y). Trong thá»i gian chỠđợi, bạn " -"vãn có thể truy cáºp ná»™i dung các khoá há»c có sẵn." #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -8875,10 +9173,6 @@ msgstr "Những yêu cầu của hình:" msgid "Does the photo of you show your whole face?" msgstr "Hình của bạn có hiển thị toà n bá»™ khuôn mặt không?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "Hình của bạn có giống vá»›i hình trên chứng minh nhân dân không?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "Tên của bạn trên chứng minh nhân dân có dá»… dà ng Ä‘á»c Ä‘uợc không?" @@ -10366,6 +10660,21 @@ msgstr "Äặt là má»™t Bà i kiểm tra Äặc biệt" msgid "Exam Types" msgstr "Loại Bà i thi" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "Có tÃnh giá»" @@ -10566,11 +10875,11 @@ msgid "Read more" msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" +msgid "No transcript uploaded." msgstr "" #: cms/templates/js/video-transcripts.underscore -msgid "No transcript uploaded." +msgid "Show transcripts ({totalTranscripts})" msgstr "" #: cms/templates/js/xblock-access-editor.underscore diff --git a/conf/locale/zh_CN/LC_MESSAGES/django.mo b/conf/locale/zh_CN/LC_MESSAGES/django.mo index 477edcd8b426eb6de36baf07f80b8130dd9330c3..5f3f2f0a53983ca969b4669fa979a6cd0f4ded8f 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 3db72cc82a4016bb2aab2f9a3a44ebaf7e6ce723..2d2599598b6f288535fba1d7d4218d9c2b43d3b2 100644 --- a/conf/locale/zh_CN/LC_MESSAGES/django.po +++ b/conf/locale/zh_CN/LC_MESSAGES/django.po @@ -48,6 +48,7 @@ # Michael Cao <ming.cao.ming@gmail.com>, 2015 # Mingye Wang <arthur200126@gmail.com>, 2015 # Ned Batchelder <ned@edx.org>, 2016 +# 刘é¹ç¨‹ <pcliu.fd@gmail.com>, 2020 # pku9104038 <pku9104038@hotmail.com>, 2014 # pku9104038 <pku9104038@hotmail.com>, 2014 # riceball <snowyu.lee@gmail.com>, 2014 @@ -74,8 +75,8 @@ # yan9yu, 2014 # Yue Fang <yfang@juilliard.edu>, 2016 # Yuelan Sheng <shengyl.cheryl@gmail.com>, 2015 -# Yu <inactive+harrycaoyu@transifex.com>, 2015 -# Yu <inactive+harrycaoyu@transifex.com>, 2015 +# db5cc497ac4f3c6c4b3195316e6985b6_cabed74 <3af8e6fd761591a7c85c4ffdc30e97c5_286908>, 2015 +# db5cc497ac4f3c6c4b3195316e6985b6_cabed74 <3af8e6fd761591a7c85c4ffdc30e97c5_286908>, 2015 # yw liu <2877206@qq.com>, 2018 # zhouxuan <lion19930924@163.com>, 2014-2015 # 刘知远 <liuliudong@163.com>, 2013 @@ -208,6 +209,7 @@ # Mingye Wang <arthur200126@gmail.com>, 2015 # Wheathana <mr_wheat@sina.cn>, 2015 # Ned Batchelder <ned@edx.org>, 2016 +# 刘é¹ç¨‹ <pcliu.fd@gmail.com>, 2020 # perypery <410224186@qq.com>, 2014 # pku9104038 <pku9104038@hotmail.com>, 2014 # pku9104038 <pku9104038@hotmail.com>, 2014 @@ -323,8 +325,8 @@ # Wentao Han <wentao.han@gmail.com>, 2013 # Wheathana <mr_wheat@sina.cn>, 2015 # ç†Šå†¬å‡ <xdsnet@gmail.com>, 2013 -# yezhixin20 <inactive+yezhixin20@transifex.com>, 2014 -# yezhixin20 <inactive+yezhixin20@transifex.com>, 2014 +# 77fe99dcf38d5fa9d2727dfb4df61259_c85f6a2 <51905779c1925b7a3c212e4dec17a56d_177606>, 2014 +# 77fe99dcf38d5fa9d2727dfb4df61259_c85f6a2 <51905779c1925b7a3c212e4dec17a56d_177606>, 2014 # YUAN Tian <Sweetyuantian@msn.cn>, 2014 # YUAN Tian <Sweetyuantian@msn.cn>, 2014 # Yufei Xue <cmouse@163.com>, 2013 @@ -395,7 +397,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: ifLab <webmaster@iflab.org>, 2019\n" "Language-Team: Chinese (China) (https://www.transifex.com/open-edx/teams/6205/zh_CN/)\n" @@ -404,7 +406,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -429,8 +431,8 @@ msgstr "å…¥å¦è€ƒè¯•" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "å•å…ƒ" @@ -742,13 +744,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "公开用户å'{username}'对应的账å·å·²å˜åœ¨ã€‚" +msgid "An account with the Email '{email}' already exists." +msgstr "邮箱'{email}'对应的账å·å·²å˜åœ¨ã€‚" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "邮箱'{email}'对应的账å·å·²å˜åœ¨ã€‚" +msgid "An account with the Public Username '{username}' already exists." +msgstr "公开用户å'{username}'对应的账å·å·²å˜åœ¨ã€‚" #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2523,9 +2525,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -4209,12 +4211,12 @@ msgid "" " considered in the Entrance Exam scoring/gating algorithm." msgstr "输入true或false。若为true,问题模å—çš„ç”案æ交将会被考虑在入å¦è€ƒè¯•çš„得分/控制算法ä¸ã€‚" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "选课记录组" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "通过选课类别划分用户的分区" @@ -4808,17 +4810,17 @@ msgstr "解é”账户" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "å…³é—" @@ -5711,50 +5713,6 @@ msgid "" "this request, please visit the link(s) below." msgstr "{username} ({email}) 的退款è¦æ±‚å·²ç»å»ºç«‹ã€‚为了处ç†æ¤è¯·æ±‚,请访问以下è”结(s) 。" -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "收æ®" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "支付失败" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "交易出现问题。您尚未缴费。" - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "ç¡®ä¿æ‚¨çš„ä¿¡æ¯æ£ç¡®æ— 误了,或æ¢ä¸€å¼ 信用é‡è¯•æˆ–æ¢ç”¨å…¶ä»–支付方å¼ã€‚" - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "在处ç†æ‚¨çš„付款时出现系统错误。您尚未缴费。" - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "请ç‰å¾…å‡ åˆ†é’ŸåŽé‡è¯•ã€‚" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "è”ç³»{payment_support_link}寻求帮助。" - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "创建您的收æ®æ—¶å‡ºé”™ã€‚" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "如果您的课程未出现在您的课程é¢æ¿ä¸Šï¼Œè¯·è”ç³»{payment_support_link}。" - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "获å–è¯ä¹¦" @@ -5817,11 +5775,23 @@ msgstr "æ‚¨æ— æƒè®¿é—®å¦ä¹ 该课程" msgid "You do not have access to this course on a mobile device" msgstr "æ‚¨æ— æ³•åœ¨ç§»åŠ¨è®¾å¤‡ä¸Šå¦ä¹ 该课程" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "å‡çº§åˆ°éªŒè¯" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -5841,6 +5811,11 @@ msgstr "{relative} å¹´ - {absolute}" msgid "in {relative} - {absolute}" msgstr "in {relative} - {absolute}" +#: lms/djangoapps/courseware/date_summary.py +#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py +msgid "Enrollment Date" +msgstr "选课日期" + #: lms/djangoapps/courseware/date_summary.py msgid "Course Starts" msgstr "课程开始" @@ -6457,16 +6432,20 @@ msgid "Good" msgstr "好" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" -msgstr "%(comment_username)s回å¤äº†<b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" +msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt msgid "View discussion" msgstr "查看讨论" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "%(comment_username)s回å¤äº†<b>%(thread_title)s</b>:" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6594,8 +6573,8 @@ msgid "Student" msgstr "å¦ç”Ÿ" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "教员" @@ -6715,29 +6694,6 @@ msgstr "问题回ç”" msgid "Could not find problem with this location." msgstr "æ— æ³•æ–¼æ¤ä½ç½®æ‰¾åˆ°é—®é¢˜ã€‚" -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "å‘ç¥¨å· '{num}' ä¸å˜åœ¨ã€‚" - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "与æ¤ç›¸å…³è”çš„å‘票出售已ç»å¤±æ•ˆã€‚" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "å‘ç¥¨å· {0} å·²ç»æ— 效。" - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "æ¤å‘è´§å•å·²ç»æ¿€æ´»ã€‚" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "æ”¶æ® {0}的注册编å·å·²ç»è¢«é‡æ–°æ¿€æ´»ã€‚" - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "课程 ID" @@ -6768,9 +6724,8 @@ msgstr "用户ID" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "用户å" @@ -6890,54 +6845,6 @@ msgstr "该文件必须包å«ä¸€ä¸ªâ€œç¾¤ç»„â€åˆ—,该列ä¸åŒ…å«äº†ç¾¤ç»„çš„ msgid "The file must contain a 'username' column, an 'email' column, or both." msgstr "该文件必须包å«ä¸€ä¸ªâ€œusernameâ€åˆ—,或一个“emailâ€åˆ—,或两者都包å«ã€‚" -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "ä¼˜æƒ åˆ¸ç¼–ç " - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "课程编å·" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "%折扣" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "æè¿°" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "过期日期" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "是å¦æ´»è·ƒ" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "推广折扣é¢ä»£ç " - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "总折扣åé¢" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "总折扣金é¢" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -6958,14 +6865,6 @@ msgstr "调查" msgid "proctored exam results" msgstr "监考考试æˆç»©" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "æ— æ³•è§£æžæ€»æ•°ä¸ºå进制" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "由于课程的错误é…ç½®ï¼Œæ— æ³•ç”Ÿæˆå…‘æ¢ç 。" - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -7178,63 +7077,6 @@ msgid "" " try again." msgstr "å¦ç”Ÿ {student} 没有æ¤é—¨è¯¾ç¨‹ {course}之修课è¯æ˜Žã€‚请验è¯å¦ç”Ÿç”¨æˆ·å/邮箱以åŠç¡®è®¤æ‰€é€‰ä¹‹è¯¾ç¨‹æ˜¯å¦æ£ç¡®ï¼Œç„¶åŽé‡è¯•ã€‚" -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "ä¼˜æƒ åˆ¸IDä¸å˜åœ¨" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "ç¼–å·ä¸º({coupon_id})çš„ä¼˜æƒ åˆ¸ä¸å˜åœ¨" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "ç¼–å·ä¸º({coupon_id})çš„ä¼˜æƒ åˆ¸å·²ç»è¢«æ¿€æ´»" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "ç¼–å·ä¸º({coupon_id})çš„ä¼˜æƒ åˆ¸æ›´æ–°æˆåŠŸ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "您试图定义的这个å¡å· ({code})å·²ç»è¢«æ³¨å†Œç 使用了" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "请输入整数值的折扣率" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "请输入ä¸å¤§äºŽ100çš„ä¼˜æƒ åˆ¸æŠ˜æ‰£åº¦" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "è¯·ä»¥è¯¥æ ¼å¼è¾“入日期,如:月/æ—¥/å¹´" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "ä½¿ç”¨ä¼˜æƒ ä»£ç ({code})çš„ä¼˜æƒ åˆ¸æ·»åŠ æˆåŠŸã€‚" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "ä¼˜æƒ ä»£ç 为({code})çš„ä¼˜æƒ åˆ¸å¯¹äºŽè¯¥è¯¾ç¨‹å·²ç»å˜åœ¨" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "ä¼˜æƒ åˆ¸ç¼–å·æ— 法找到" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "ç¼–å·ä¸º({coupon_id})çš„ä¼˜æƒ åˆ¸æ›´æ–°æˆåŠŸ" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "主讲教师" @@ -7342,29 +7184,6 @@ msgstr "å·²ç»å®Œæˆ" msgid "Incomplete" msgstr "未完æˆ" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "对于{course_name}课程的选课ç ({code})未找到。" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "该选课ç å·²ç»è¢«å–消,ä¸èƒ½å†ä½¿ç”¨ã€‚" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "该选课ç å·²è¢«æ ‡è®°ä¸ºæœªä½¿ç”¨è¿‡çš„ã€‚" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "选课ç 已修å¤ã€‚" - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "针对redemption 注册代ç ({code})是ä¸å˜åœ¨çš„。" - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7559,10 +7378,6 @@ msgstr "æ ‡é¢˜" msgid "Year of Birth" msgstr "出生年份" -#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py -msgid "Enrollment Date" -msgstr "选课日期" - #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py msgid "Currently Enrolled" msgstr "当å‰æ³¨å†Œ" @@ -7760,8 +7575,8 @@ msgstr "( ï¼{total} )" #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "程å¼" @@ -8437,6 +8252,15 @@ msgstr "æ€»ä»·æ ¼" msgid "Currency" msgstr "è´§å¸" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "æè¿°" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "评è¯" @@ -8580,14 +8404,6 @@ msgstr "您没有访问æ¤é¡µé¢çš„æƒé™ã€‚" msgid "View and regenerate certificates." msgstr "查看并产生è¯ä¹¦ã€‚" -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "人工退费" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "直接é€è¿‡CyberSource追踪退款问题。" - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -8666,44 +8482,9 @@ msgstr "用户激活æˆåŠŸ" msgid "User Disabled Successfully" msgstr "æˆåŠŸç¦ç”¨ç”¨æˆ·" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "邮箱" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "课程编å·" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "未找到用户" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "课程 {course_id}没有通过退费窗å£ã€‚" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "在课程{course_id}ä¸æ²¡æœ‰ä¸º{user}找到订å•ã€‚" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "放弃选修{course_id}çš„{user}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "订å•{order_id}已退款{cost}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -9329,8 +9110,8 @@ msgid "Allow" msgstr "å…许" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "错误" @@ -9713,8 +9494,8 @@ msgid "" msgstr "æ¤å¤„å…许使用MarkDownè¯æ³•ã€‚请å‚阅%(start_link)så¿«æ·é”®ç®¡ç†%(end_link)s并寻求帮助。" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "附件" @@ -9750,11 +9531,10 @@ msgid "" msgstr "您å¯ä»¥ä»Žå…¶ä»–æ–‡ç« ä¸é‡ç”¨ä¸€äº›æ–‡ä»¶ã€‚但是该文件的更新ä¾èµ–äºŽåŽŸå§‹æ–‡ç« ï¼Œè¯·åˆ¤æ–该引用关系是å¦æ°å½“。" #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -10162,6 +9942,10 @@ msgstr "é…ç½®æ¤è¯¾ç¨‹è¿è¡Œçš„å‚æ•°ã€‚æ ¼å¼ä¸ºCourseKey(例如course-v1:// msgid "Configuration may not be specified at more than one level at once." msgstr "ä¸èƒ½ä¸€æ¬¡åœ¨å¤šä¸ªçº§åˆ«æŒ‡å®šé…置。" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -10537,6 +10321,10 @@ msgstr "已知错误案例" msgid "Schedule start < course start" msgstr "时间表开始时间 < 课程开始时间" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "课程编å·" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "全部" @@ -10545,6 +10333,15 @@ msgstr "全部" msgid "Experience" msgstr "ç»éªŒ" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "课程编å·" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -10979,7 +10776,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -11006,8 +10802,8 @@ msgid "Success" msgstr "æˆåŠŸ" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "æ“作" @@ -11172,6 +10968,14 @@ msgstr "注册" msgid "There was an error receiving your login information. Please email us." msgstr "接å—您的登录信æ¯æ—¶å‡ºçŽ°é”™è¯¯ï¼Œè¯·å‘电å邮件给我们。" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11187,6 +10991,15 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "失败次数超过é™åˆ¶ï¼Œè¯·ç¨åŽå†è¯•ï¼" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11194,15 +11007,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "username@domain.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -11218,6 +11022,12 @@ msgstr "您在{platform_name}上注册的邮箱" msgid "Create Account" msgstr "创建账å·" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "username@domain.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -11230,6 +11040,11 @@ msgid "" "password." msgstr "与æ¤é‚®ç®±å…³è”的用户账å·æ— 法é‡æ–°è®¾ç½®å¯†ç 。" +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "é‡æ–°è®¾ç½®å¯†ç ä¸æˆåŠŸ" @@ -11250,11 +11065,6 @@ msgid "" msgstr "" "{html_start}密ç 创建完æˆ{html_end}å·²ç»åˆ›å»ºäº†æ‚¨çš„密ç 。{bold_start}{email}{bold_end}现在是您的主登录电å邮件。" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "é‡è®¾å¯†ç æ—¶å‘生错误,请é‡è¯•" @@ -11484,6 +11294,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "用于视频管线整åˆçš„用户å,例如:veda_service_user。" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "强制开å¯" @@ -11502,6 +11324,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "è¯¥å€¼æ— æ•ˆã€‚" @@ -12187,8 +12013,8 @@ msgstr "课程æˆåŠŸè¢«å¯¼å‡ºåˆ°Gitæº" msgid "Vertical" msgstr "纵列å—" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "ç« " @@ -12459,6 +12285,18 @@ msgstr "å—幕转载进行ä¸" msgid "Transcript Ready" msgstr "å—幕完æˆ" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "å¿…é¡»æ供图片文件。" @@ -12603,8 +12441,8 @@ msgstr "内容" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "设置" @@ -12652,14 +12490,14 @@ msgstr "课程代ç :" msgid "Course Run:" msgstr "课程长度:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "课程" @@ -12683,8 +12521,9 @@ msgstr "主讲教师" msgid "Requirements" msgstr "ä¿®ä¹ è¦æ±‚" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "细节" @@ -12738,15 +12577,15 @@ msgstr "" msgid "Choose Language" msgstr "选择è¯è¨€" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "è´¦å·" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -12818,8 +12657,8 @@ msgstr "用户èœå•" msgid "Usermenu dropdown" msgstr "用户èœå•ä¸‹æ‹‰åˆ—表" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "退出" @@ -12979,8 +12818,8 @@ msgstr "开课日期: {date}" msgid "View all Courses" msgstr "æµè§ˆæ‰€æœ‰è¯¾ç¨‹" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "课程é¢æ¿" @@ -12999,8 +12838,8 @@ msgstr "您尚未å‚åŠ ä»»ä½•è¯¾ç¨‹ã€‚" #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "探索课程" @@ -13018,7 +12857,7 @@ msgstr "è¯¾ç¨‹åŠ è½½é”™è¯¯" msgid "Search Your Courses" msgstr "查找课程" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "清空æœç´¢ç»“æžœ" @@ -13043,7 +12882,7 @@ msgstr "接收课程邮件" msgid "Save Settings" msgstr "ä¿å˜è®¾ç½®" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -13053,9 +12892,87 @@ msgstr "ä¿å˜è®¾ç½®" msgid "Unenroll" msgstr "放弃选修" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "在 Studio ä¸æŸ¥çœ‹å•å…ƒ" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -13087,7 +13004,7 @@ msgstr "该邮箱已被å¦ä¸€ä¸ªè´¦å·ä½¿ç”¨ã€‚" msgid "You should Register before trying to access the Unit" msgstr "您在查看å•å…ƒå‰åº”先注册。" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "选修" @@ -13191,7 +13108,7 @@ msgstr "" "由于截æ¢æ—¥æœŸå·²è¿‡ï¼Œæ¤ä½œä¸šä¸å†å¯ç”¨ã€‚{line_break} 如果您已ç»å®Œæˆæ¤ä½œä¸šï¼Œæ‚¨å¯ä»¥åœ¨ {link_start}进度页é¢{link_end} " "上查询作业æˆç»©ã€‚" -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "查找课程" @@ -13326,19 +13243,16 @@ msgstr "(é‡æ–°åŠ 载以刷新您的页é¢)" msgid "working" msgstr "è¿è¡Œä¸" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "{platform_name} å¹³å°çš„æœåŠ¡å™¨å‘生了错误" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"éžå¸¸æŠ±æ‰ï¼Œè¯¥æ¨¡å—æš‚æ—¶æ— æ³•ä½¿ç”¨ï¼Œæˆ‘ä»¬çš„æ•™å‘˜æ£åœ¨åŠªåŠ›å°½ä¿®å¤é—®é¢˜ã€‚è¦æŠ¥å‘Šæ‚¨å‘现的任何问题或é‡åˆ°ç½‘ç«™éžæ£å¸¸ï¼Œè¯·å‘{tech_support_email}å‘é€é‚®ä»¶" #: lms/templates/module-error.html msgid "Raw data:" @@ -13377,7 +13291,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "您æ£åœ¨ä»¥ {i_start}{user_name}{i_end} 身份查看课程。" #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -13438,28 +13360,6 @@ msgstr "邮箱" msgid "Return To %s" msgstr "返回%s" -#: lms/templates/reset_deadlines_banner.html -msgid "It looks like you've missed some important deadlines. Visit " -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "edx.org" -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid " to reset your deadlines and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "é‡æ–°è®¢é˜…æˆåŠŸï¼" @@ -13509,7 +13409,7 @@ msgstr "" msgid "Sequence" msgstr "åºåˆ—" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -13638,18 +13538,18 @@ msgstr "æˆç»©ï¼ˆä»…用于覆盖原æ¥çš„æˆç»©è®¾ç½®ï¼‰" msgid "Reset Learner's Attempts to Zero" msgstr "å°†å¦å‘˜çš„å°è¯•æ¬¡æ•°ç½®ä¸º0" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "åˆ é™¤å¦ç”ŸçŠ¶æ€" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "对å¦ç”Ÿçš„æ交记录é‡æ–°è¯„分" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "如果评分æ高,é‡æ–°æ‰“分" @@ -13687,7 +13587,7 @@ msgstr "{course_number} æ•™æ" msgid "Textbook Navigation" msgstr "课本导航" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "页é¢" @@ -13798,9 +13698,9 @@ msgstr "第 {current_page} 页/ å…±{total_pages}页" msgid "Recent git load activity for {course_id}" msgstr "近期 {course_id}çš„gitåŠ è½½æ´»åŠ¨" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -13857,7 +13757,7 @@ msgid "" msgstr "" "您ä¸å°†å†æŽ¥æ”¶åˆ°{platform_name}论å›é‚®ä»¶æ醒,请å•å‡»{dashboard_link_start}æ¤å¤„{link_end}返回您的课程é¢æ¿ã€‚如果您ä¸æ˜¯æœ‰æ„å–消,请å•å‡»{undo_link_start}æ¤å¤„{link_end}é‡æ–°è®¢é˜…消æ¯ã€‚" -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "课程é¢æ¿ï¼š" @@ -13865,8 +13765,8 @@ msgstr "课程é¢æ¿ï¼š" msgid "More options" msgstr "更多选项" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "更多选项" @@ -15103,35 +15003,6 @@ msgstr "如果所有信æ¯æ£ç¡®ä½†é—®é¢˜ä»ç„¶å˜åœ¨ï¼Œè¯·è”系技术支æŒå›¢ msgid "About edX Certificates" msgstr "关于edXè¯ä¹¦" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "付款已å–消" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "您的交易已被å–消。如果您觉得å‘生了错误,请è”ç³» {email} 。" - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "付款出错" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "åŠ è½½è®¢å•ä¿¡æ¯..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "请ç¨å€™ï¼Œæˆ‘们æ£åœ¨èŽ·å–您的订å•è¯¦æƒ…。" - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -15330,14 +15201,14 @@ msgstr "{section_format} 截æ¢æ—¥æœŸ{{date}} " msgid "This content is graded" msgstr "该内容计入总分。" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "出现错误,请ç¨åŽå†è¯•ã€‚" - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "出现错误,请ç¨åŽå†è¯•ã€‚" + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "您选修了本课程" @@ -15349,10 +15220,6 @@ msgstr "您选修了本课程" msgid "View Course" msgstr "查看课程" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "这个课程已ç»è¿›å…¥ä½ çš„ {start_cart_link}è´ç‰©è½¦{end_cart_link}。" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "该课程已满" @@ -15365,10 +15232,6 @@ msgstr "该课程åªèƒ½é€šè¿‡é‚€è¯·é€‰ä¿®" msgid "Enrollment is Closed" msgstr "选课已关é—" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "æ·»åŠ {course_name} 到è´ç‰©è½¦ {start_span}({price} USD){end_span}" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "" @@ -15490,6 +15353,13 @@ msgstr "课程工具" msgid "Courseware" msgstr "课程页é¢" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "æœç´¢è¯¾ç¨‹" @@ -15518,7 +15388,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -15526,14 +15396,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" msgstr "" -#: lms/templates/courseware/error-message.html -msgid "" -"We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible." +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -16179,8 +16046,8 @@ msgstr "您已æ交认è¯ä¿¡æ¯ã€‚" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." -msgstr "验è¯è¿‡ç¨‹å®ŒæˆåŽï¼ˆé€šå¸¸åœ¨1-2天内),您会在课程é¢æ¿ä¸çœ‹åˆ°æ¶ˆæ¯ã€‚" +"complete (usually within 5-7 days)." +msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -16190,8 +16057,8 @@ msgstr "您的当å‰éªŒè¯å°†é©¬ä¸Šè¿‡æœŸï¼" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." -msgstr "您已æ交了é‡æ–°éªŒè¯ä¿¡æ¯ã€‚验è¯è¿‡ç¨‹å®ŒæˆåŽï¼ˆé€šå¸¸åœ¨1-2天内),您会在课程é¢æ¿ä¸çœ‹åˆ°æ¶ˆæ¯ã€‚" +"5-7 days)." +msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -16868,136 +16735,6 @@ msgid "" msgstr "" "我们已收到您的信æ¯ï¼Œå¹¶ä¸”身份认è¯æµç¨‹å·²å¼€å§‹ã€‚请在接下æ¥å‡ 天内查看我们给您å‘的一å°é‚®ä»¶ï¼Œä»¥ç¡®è®¤æ‚¨è®¤è¯æ˜¯å¦æˆåŠŸã€‚您也å¯ä»¥åœ¨é¢æ¿ä¸æŸ¥çœ‹æ‚¨çš„认è¯çŠ¶æ€ã€‚" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "感谢您è´ä¹°{course_name}。" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "{currency_symbol}{total_price}çš„å‘票已附上。您在收到å‘票åŽéœ€ç«‹å³ä»˜æ¬¾ã€‚您å¯ä»¥åœ¨å‘票里找到付款方å¼ã€‚" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "附件ä¸æ˜¯å¸¦æœ‰æ‚¨çš„选课ç çš„.csv文件。您å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„邮件模æ¿å°†é€‰è¯¾ç 分å‘给您的å¦ç”Ÿã€‚æ¯ä¸ªå¦ç”Ÿå¿…须使用一个å•ç‹¬çš„选课ç 。" - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"谢谢,\n" -"{platform_name}团队" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "亲爱的 [[Name]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "我们为您æ供了一个{course_name}选课ç 。å‚åŠ è¯¥è¯¾ç¨‹ï¼Œè¯·ç‚¹å‡»ä»¥ä¸‹é“¾æŽ¥:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "附件CSV文件ä¸çš„html链接" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "在您选课之åŽï¼Œæ‚¨å¯ä»¥åœ¨æ‚¨çš„å¦ç”Ÿè¯¾ç¨‹é¢æ¿ä¸çœ‹åˆ°è¯¥è¯¾ç¨‹ã€‚在课程开始åŽï¼Œæ‚¨å°±å¯ä»¥çœ‹åˆ°è¯¾ç¨‹çš„相关资料。" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"诚挚的,\n" -"[[Your Signature]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "å‘票" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "日期: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "å‘票å·ç : {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "æ¡æ¬¾ï¼šæ”¶åˆ°ä»˜æ¬¾" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "截æ¢æ—¥æœŸ: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "付款给:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "客户å‚考编ç : {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "应付金é¢: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "课程å称: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"ä»·æ ¼: {currency_symbol}{course_price} æ•°é‡: {quantity} å°è®¡: " -"{currency_symbol}{sub_total} 折扣: {currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "总计: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "支付说明" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"如果我们没有收到付款,使用这些选课ç çš„å¦ç”Ÿå°†è¢«å–æ¶ˆä¸Šè¯¾èµ„æ ¼å¹¶æ— æ³•è®¿é—®è¯¾ç¨‹èµ„æ–™ã€‚æ‰€æœ‰ä»˜æ¬¾éƒ½æ— æ³•é€€æ¢ã€‚欲了解更多信æ¯ï¼Œè¯·å‚è§{site_name}å–消政ç–。" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "支付问题请è”ç³»{contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -17170,8 +16907,8 @@ msgstr "申请ç»æµŽèµ„助" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} 主页" @@ -17193,19 +16930,11 @@ msgstr "马上探索课程" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "系统管ç†å‘˜" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "è´ç‰©è½¦" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "补充内容链接" @@ -17242,6 +16971,12 @@ msgstr "æ·»åŠ ä¼˜æƒ åˆ¸ä»£ç " msgid "Enter information about the coupon code below." msgstr "在下é¢è¾“å…¥ä¼˜æƒ åˆ¸ä»£ç " +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "ä¼˜æƒ åˆ¸ä»£ç " + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "折扣率" @@ -17790,6 +17525,11 @@ msgstr "ä¸‹è½½ä¼˜æƒ åˆ¸ä»£ç " msgid "Coupon Codes" msgstr "ä¼˜æƒ åˆ¸ä»£ç " +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "过期日期" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "ä¼˜æƒ åˆ¸(%)" @@ -19065,6 +18805,10 @@ msgstr "采è´æœºæž„" msgid "Purchase order number (if any)" msgstr "订å•å·(如果å˜åœ¨)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "邮箱" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "email@example.com" @@ -19355,6 +19099,10 @@ msgid_plural "" "{course_names} have been removed because the enrollment period has closed." msgstr[0] "å› é€‰è¯¾æ—¶é™å·²å…³é—,{course_names} 已被移除。" +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "è´ç‰©è½¦" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "å°é¢å›¾ç‰‡" @@ -19567,46 +19315,6 @@ msgstr "å¦å‘˜å¸®åŠ©ï¼šç®¡ç†ç”¨æˆ·" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "准备就该订å•é€€è´¹" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "订å•æ ‡è¯†ï¼š" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "选课:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "已选修" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "已弃选" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "费用:" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "è¯ä¹¦çŠ¶æ€ï¼š" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "订å•çŠ¶æ€ï¼š" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "完æˆæ—¶é—´ï¼š" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "退费申请时间:" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "用户调查" @@ -19743,8 +19451,8 @@ msgstr "身份验è¯" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." -msgstr "您已æ交了认è¯ä¿¡æ¯ã€‚当认è¯è¿‡ç¨‹ç»“æŸåŽï¼Œæ‚¨ä¼šåœ¨æ‚¨çš„课程é¢æ¿ä¸çœ‹åˆ°ä¸€æ¡æ¶ˆæ¯(通常在1-2天内)。" +" within 5-7 days)." +msgstr "" #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -20312,8 +20020,8 @@ msgid "Already registered?" msgstr "å·²ç»æ³¨å†Œè¿‡äº†ï¼Ÿ" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "登录" @@ -20416,10 +20124,8 @@ msgid "The page that you were looking for was not found." msgstr "您查找的页é¢æ— 法找到。" #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." -msgstr "返回到{homepage}或å‘电å邮件至{email}告诉我们被移动的页é¢ã€‚" +msgid "Go back to the {homepage}." +msgstr "" #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -20441,10 +20147,6 @@ msgid "" "error as soon as possible." msgstr "我们已ç»è®°å½•ä¸‹è¿™ä¸ªé”™è¯¯ï¼Œæˆ‘们的员工æ£åœ¨è¯•å›¾å°½å¿«è§£å†³è¿™ä¸ªé—®é¢˜ã€‚" -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "如果问题ä»ç„¶å˜åœ¨ï¼Œè¯·å‘é€ç”µå邮件至{email_link}。" - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "教室å¯è®¿é—®æ€§æ”¿ç–" @@ -21056,11 +20758,8 @@ msgstr "您请求的页é¢æ— 法找到" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" -"很抱æ‰ï¼Œæˆ‘ä»¬æ— æ³•æ‰¾åˆ°æ‚¨è¯·æ±‚çš„{studio_name}页é¢ã€‚您å¯èƒ½å¸Œæœ›è¿”回至{studio_name}课程é¢æ¿åŽé‡æ–°å°è¯•ã€‚如果您ä»é‡åˆ°é—®é¢˜ï¼Œè¯·éšæ—¶{link_start}è”ç³»{studio_name}支æŒ{link_end}以获å–更多帮助。" #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -21070,11 +20769,8 @@ msgstr "æœåŠ¡å™¨å‘生错误" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" -"很抱æ‰ï¼ŒæœåŠ¡å™¨åœ¨å¤„ç†æ‚¨çš„上一个请求时é‡åˆ°é—®é¢˜ã€‚您å¯èƒ½å¸Œæœ›è¿”回至{studio_name}课程é¢æ¿æˆ–é‡æ–°æ交请求。如果您ä»é‡åˆ°é—®é¢˜ï¼Œè¯·éšæ—¶{link_start}è”ç³»{studio_name}支æŒ{link_end}以寻求帮助。" #: cms/templates/error.html msgid "Back to dashboard" @@ -24082,8 +23778,8 @@ msgstr "%(file)så·²ç»è¢«å˜æ›´åˆ°ä¿®è®¢ç‰ˆæœ¬#%(revision)d" msgid "%(file)s has been saved." msgstr "%(file)så·²ç»è¢«ä¿å˜ã€‚" -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "图片" @@ -24276,8 +23972,8 @@ msgstr "清空通知列表" msgid "Search..." msgstr "æœç´¢" -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "注册" diff --git a/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo b/conf/locale/zh_CN/LC_MESSAGES/djangojs.mo index bf401e5c0f45deb64fc7596651777eebcc8e9832..611260779848a01dc264c6d35ed3cef40858160f 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 37564e1e9262d95d65cc44bba0bff7bea18ae6c3..b0a7b4da58fb5ef385be1556860aa7b702c6b675 100644 --- a/conf/locale/zh_CN/LC_MESSAGES/djangojs.po +++ b/conf/locale/zh_CN/LC_MESSAGES/djangojs.po @@ -173,6 +173,7 @@ # Lionel Chen <chenlinchuan@me.com>, 2014 # LIU NIAN <lauraqq@gmail.com>, 2015 # meelo <bbvy@qq.com>, 2015 +# qiaoyafeng <qiao_yafeng@qq.com>, 2020 # Rom, 2015 # Rom, 2015 # louyihua <supermouselyh@hotmail.com>, 2014-2015 @@ -181,7 +182,7 @@ # Yue Fang <yfang@juilliard.edu>, 2016 # Zihui Cheng <z7cheng@ucsd.edu>, 2015 # 代 å…´æ—º <525224259@qq.com>, 2016 -# 伟波 黄 <inactive+gtc_ZjEzMTJ@transifex.com>, 2016 +# 8cfb674aa14009d921df29d97d1751e8_9eeecd0 <ff77ddda63493ab7c7af47446c7f91e9_481994>, 2016 # å¥è¶… å¼ <jc.zhang@eliteu.com.cn>, 2019 # å¼ é€¸æ¶µ <jeanzhang970128@gmail.com>, 2014 # å¾® æŽ <w.li@eliteu.com.cn>, 2018 @@ -206,8 +207,8 @@ # Jiazhen Tan <jessie12@live.cn>, 2016 # jsgang <jsgang9@gmail.com>, 2015-2017 # LIU NIAN <lauraqq@gmail.com>, 2015 -# peipeixiang <inactive+peipeixiang@transifex.com>, 2015 -# peipeixiang <inactive+peipeixiang@transifex.com>, 2015 +# dae18ada8f5d984070f88a11bd09a0d3_87cf90e <6d2a6f2312a2a802f0de112b58b74c46_176438>, 2015 +# dae18ada8f5d984070f88a11bd09a0d3_87cf90e <6d2a6f2312a2a802f0de112b58b74c46_176438>, 2015 # Rom, 2015 # Rom, 2015 # San <github@zhujunsan.net>, 2015 @@ -215,8 +216,8 @@ # Xuejia Tong <snowytong@hotmail.com>, 2016 # Yingying Zhang <1714277256@qq.com>, 2016 # yohann yang <heinerseiden@yahoo.com>, 2016 -# Yu <inactive+harrycaoyu@transifex.com>, 2015 -# Yu <inactive+harrycaoyu@transifex.com>, 2015 +# db5cc497ac4f3c6c4b3195316e6985b6_cabed74 <3af8e6fd761591a7c85c4ffdc30e97c5_286908>, 2015 +# db5cc497ac4f3c6c4b3195316e6985b6_cabed74 <3af8e6fd761591a7c85c4ffdc30e97c5_286908>, 2015 # å˜‰æ° æŽ <jj.li@eliteu.com.cn>, 2018 # 刘啸林 <liuxiaolinfk@gmail.com>, 2016 # ç™¾æ° é™ˆ <bj.chen@eliteu.com.cn>, 2018 @@ -225,8 +226,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Chinese (China) (http://www.transifex.com/open-edx/edx-platform/language/zh_CN/)\n" "Language: zh_CN\n" @@ -234,7 +235,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -283,6 +284,7 @@ msgstr "åˆ é™¤" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -305,6 +307,7 @@ msgstr "ä¸Šä¼ ä¸" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -334,6 +337,7 @@ msgstr "选择文件" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "是的" @@ -913,7 +917,6 @@ msgstr "åˆ é™¤è¡¨æ ¼" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "æè¿°" @@ -1353,6 +1356,7 @@ msgstr "新建窗å£" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "下一个" @@ -2577,30 +2581,40 @@ msgid "Other" msgstr "其他" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" -msgstr "亲爱的{username},有什么å¯ä»¥å¸®åŠ©æ‚¨ï¼Ÿ" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Details" msgstr "细节" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" -msgstr "您æ供的信æ¯è¶Šè¯¦ç»†ï¼Œæˆ‘们越能快速并有效地帮助到您ï¼" +msgid "the more quickly and helpfully we can respond!" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "æ交" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "亲爱的{username},有什么å¯ä»¥å¸®åŠ©æ‚¨ï¼Ÿ" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "请登录{platform},以获得更好的帮助。" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." -msgstr "å¦‚æžœæ‚¨æ— æ³•è®¿é—®è´¦å·ï¼Œè¯·é€šè¿‡ç”µå邮件è”系我们{email}。" +msgid "Need help logging in?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "" @@ -2616,6 +2630,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "输入您所需è¦çš„支æŒçš„细节。" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2639,8 +2665,9 @@ msgstr "å‰å¾€{platform}主页" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." -msgstr "感谢您æ交的申请ï¼æˆ‘们会在24å°æ—¶å†…è”系您。" +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." +msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx msgid "Cancel upload" @@ -2819,6 +2846,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "å‘生错误。 å†è¯•ä¸€æ¬¡ã€‚" +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "离开这个团队?" @@ -3304,6 +3335,7 @@ msgid "There has been an error processing your survey." msgstr "在处ç†æ‚¨çš„调查时出现了一个错误。" #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -5336,6 +5368,10 @@ msgstr "是的,å…许编辑激活的è¯ä¹¦" msgid "certificate" msgstr "è¯ä¹¦" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "设置您的è¯ä¹¦" @@ -5347,8 +5383,8 @@ msgid "You have not created any certificates yet." msgstr "您尚未创建任何è¯ä¹¦ã€‚" #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "确定è¦ä»Žç¾ç½²è€…列表ä¸åˆ 除 \"<%= signatoryName %>\" å—?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5649,9 +5685,9 @@ msgstr "æ‰€æœ‰ç« èŠ‚éƒ½å¿…é¡»æ‹¥æœ‰å称和内容" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." -msgstr "åªæœ‰ <%= fileTypes %> æ ¼å¼çš„文件å¯ä»¥ä¸Šä¼ 。请选择扩展å为 <%= fileExtensions %> çš„æ–‡ä»¶ä¸Šä¼ ã€‚" +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." +msgstr "" #: cms/static/js/models/uploads.js #: lms/templates/student_account/hinted_login.underscore @@ -5829,8 +5865,8 @@ msgid "{selectedProvider} credentials saved" msgstr "{selectedProvider} è¯ä¹¦å·²ä¿å˜" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" -msgstr "ä¸Šä¼ æ–°çš„PDF文件至“<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" +msgstr "" #: cms/static/js/views/edit_chapter.js msgid "Please select a PDF file to upload." @@ -6389,14 +6425,14 @@ msgstr "很抱æ‰ï¼Œæ¤å¤„出现错误" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." -msgstr "机构ã€è¯¾ç¨‹ç¼–å·å’Œå¼€è¯¾æ—¶é—´å—段åˆåœ¨ä¸€èµ·ä¸èƒ½è¶…过 <%=limit%> 个å—符。" +"fields cannot be more than <%- limit %> characters." +msgstr "" #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." -msgstr "机构和知识库编å·å—段åˆåœ¨ä¸€èµ·ä¸èƒ½è¶…过 <%=limit%> 个å—符" +"more than <%- limit %> characters." +msgstr "" #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -6741,13 +6777,13 @@ msgid "Unscheduled" msgstr "尚未计划" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "日期" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "上一æ¥" @@ -6795,6 +6831,309 @@ msgstr "清空æœç´¢ç»“æžœ" msgid "Search" msgstr "æœç´¢" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "æ交" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "所有讨论帖" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "讨论区" @@ -6851,10 +7190,6 @@ msgid "" "new, unread activity from posts you are following." msgstr "勾选æ¤é¡¹ï¼Œæ¯å¤©æŽ¥æ”¶ä¸€å°é‚®ä»¶ï¼Œé€šçŸ¥æ‚¨æ‰€å…³æ³¨çš„讨论帖的最新未读情况。" -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "所有讨论帖" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "用户å/邮箱" @@ -7088,6 +7423,10 @@ msgstr "您是å¦åœ¨æ‰¾å›¢é˜ŸåŠ 入过程ä¸é‡åˆ°å›°éš¾ï¼Ÿ" msgid "Join Team" msgstr "åŠ å…¥å›¢é˜Ÿ" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "团队详情" @@ -7172,94 +7511,6 @@ msgstr "åˆ é™¤èŠ‚ %(subsectionDisplayName)s" msgid "Remove unit %(unitName)s" msgstr "åˆ é™¤å•å…ƒ %(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "您ä»ç„¶éœ€è¦è®¿é—® %(display_name)s 网站完æˆå¦åˆ†é¢†å–æµç¨‹ã€‚" - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "è¦å®Œæˆè¯¾ç¨‹å¦åˆ†ï¼Œ%(display_name)s è¦æ±‚ %(platform_name)s å¦å‘˜æ交一份å¦åˆ†ç”³è¯·ã€‚" - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "获得å¦åˆ†" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "谢谢您,%(full_name)sï¼æˆ‘们已ç»æ”¶åˆ°äº†æ‚¨ä¸º%(course_name)s的付款。" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "请打å°æ¤é¡µç•™ä½œçºªå½•ï¼Œè¿™æ˜¯æ‚¨çš„收æ®ã€‚您也会收到一å°æœ‰ç›¸åŒä¿¡æ¯çš„电å邮件。" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "订å•å·ï¼š" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "金é¢" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "总计" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "请注æ„" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "划掉的项目已退款。" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "è´¦å•å¯„ç»™" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "没有å¯æ供的收æ®ã€‚" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "å‰å¾€è¯¾ç¨‹é¢æ¿" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "如果您现在ä¸éªŒè¯èº«ä»½ï¼Œæ‚¨ä»å¯ä»¥é€šè¿‡è¯¾ç¨‹é¢æ¿æµè§ˆè¯¾ç¨‹ã€‚但您会定期从 {platformName} 收到身份验è¯æ醒。" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "希望ç¨åŽå†éªŒè¯æ‚¨çš„身份?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "现在认è¯" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "æ ‡è®°è€ƒè¯•å®Œæˆ" @@ -7388,8 +7639,8 @@ msgstr "关于您" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." -msgstr "以下信æ¯å·²ç»æ˜¯æ‚¨çš„ {platform} 简述的一部分。我们已将其列入您的申请ä¸ã€‚" +"We've included it here for your application." +msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7417,6 +7668,10 @@ msgid "" "{course_name}! You can expect a response in 2-4 business days." msgstr "感谢您æ交 {course_name} çš„ç»æµŽæ´åŠ©ç”³è¯·ï¼æ‚¨å°†åœ¨ 2 至 4 个工作日内得到回å¤ã€‚" +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "å‰å¾€è¯¾ç¨‹é¢æ¿" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "批é‡ç‰¹æ®Šå¤„ç†" @@ -7754,14 +8009,6 @@ msgstr "æ‚¨å·²æ— æ³•æ›´æ”¹å¦æœŸã€‚" msgid "You can change sessions until {expiration_date}." msgstr "您å¯åœ¨{expiration_date}å‰æ›´æ”¹å¦æœŸã€‚" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "最终æˆç»©" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "为{courseName}课程" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "查看å˜æ¡£çš„课程" @@ -7977,8 +8224,28 @@ msgid "An error occurred. Please reload the page." msgstr "å‘生了一个错误,请é‡æ–°åŠ 载页é¢ã€‚" #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" -msgstr "登录时需è¦å¸®åŠ©ï¼Ÿ" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" +msgstr "" #: lms/templates/student_account/hinted_login.underscore #: lms/templates/student_account/login.underscore @@ -8176,17 +8443,13 @@ msgid "What You Need for Verification" msgstr "认è¯æ‰€éœ€" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "æ‘„åƒå¤´" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8194,10 +8457,8 @@ msgid "Photo Identification" msgstr "照片识别" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." -msgstr "您需è¦é©¾ç…§ã€æŠ¤ç…§æˆ–者其他由政府ç¾å‘的带有您姓å和照片的身份è¯ä»¶ã€‚" +msgid "You need a valid ID that contains your full name and photo." +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8222,14 +8483,10 @@ msgstr "您的é¢éƒ¨å…‰ç…§å¾ˆå¥½ã€‚" msgid "Your entire face fits inside the frame." msgstr "æ‚¨çš„æ•´å¼ è„¸éƒ½åœ¨æ¡†å†…ã€‚" -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "您的é¢éƒ¨ç…§ç‰‡ä¸Žæ‚¨èº«ä»½è¯ä»¶ä¸Šçš„照片相符。" - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8246,14 +8503,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "为什么%(platformName)s需è¦æˆ‘的照片?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"作为认è¯è¿‡ç¨‹ä¸ä¸€éƒ¨åˆ†ï¼Œæ‚¨éœ€è¦æ‹æ‘„ä¸¤å¼ ç…§ç‰‡ï¼šæ‚¨çš„é¢éƒ¨ä»¥åŠæ‚¨çš„身份è¯ä»¶ï¼ˆè¯¥è¯ä»¶é¡»ç”±æ”¿åºœç¾å‘且有您的照片)。我们的授æƒæœåŠ¡éƒ¨å°†é€šè¿‡å¯¹æ¯”您的é¢éƒ¨ç…§ç‰‡å’Œæ‚¨çš„è¯ä»¶ä¸Šçš„照片æ¥ç¡®è®¤æ‚¨çš„身份。" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8264,15 +8517,12 @@ msgstr "%(platformName)sç”¨è¿™å¼ ç…§ç‰‡åšä»€ä¹ˆï¼Ÿ" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"我们会采用最高级别的安全技术æ¥åŠ 密您的照片并å‘é€åˆ°æˆ‘们的授æƒæœåŠ¡ç”¨äºŽå®¡æ ¸ç›®çš„;一旦完æˆäº†è®¤è¯è¿‡ç¨‹ï¼Œ%(platformName)sä¸ä¼šç»§ç»ä¿å˜è¿™äº›ç…§ç‰‡å’Œä¿¡æ¯ã€‚" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8331,16 +8581,14 @@ msgid "Take a Photo of Your ID" msgstr "æ‹æ‘„您的身份è¯ä»¶" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." -msgstr "请用摄åƒå¤´æ‹æ‘„ä¸€å¼ æ‚¨èº«ä»½è¯ä»¶çš„照片,我们将查看该照片是å¦ä¸Žæ‚¨çš„é¢éƒ¨ç…§ç‰‡åŠæ‚¨åœ¨è´¦å·ä¸å¡«å†™çš„姓å匹é…。" +msgid "Use your webcam to take a photo of your ID." +msgstr "" #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." -msgstr "您需è¦ä¸€ä»½å¸¦æœ‰æ‚¨å§“å和照片的身份è¯ä»¶ï¼Œæˆ‘们å¯ä»¥æŽ¥å—驾照ã€æŠ¤ç…§ä»¥åŠå…¶ä»–由政府ç¾å‘的身份è¯ä»¶ã€‚" +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." +msgstr "" #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8364,6 +8612,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8410,6 +8665,24 @@ msgstr "" msgid "Can we match the photo you took with the one on your ID?" msgstr "我们能å¦å°†æ‚¨æ‹çš„照片与您身份è¯ä»¶ä¸Šçš„照片进行比对?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"作为认è¯è¿‡ç¨‹ä¸ä¸€éƒ¨åˆ†ï¼Œæ‚¨éœ€è¦æ‹æ‘„ä¸¤å¼ ç…§ç‰‡ï¼šæ‚¨çš„é¢éƒ¨ä»¥åŠæ‚¨çš„身份è¯ä»¶ï¼ˆè¯¥è¯ä»¶é¡»ç”±æ”¿åºœç¾å‘且有您的照片)。我们的授æƒæœåŠ¡éƒ¨å°†é€šè¿‡å¯¹æ¯”您的é¢éƒ¨ç…§ç‰‡å’Œæ‚¨çš„è¯ä»¶ä¸Šçš„照片æ¥ç¡®è®¤æ‚¨çš„身份。" + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"我们会采用最高级别的安全技术æ¥åŠ 密您的照片并å‘é€åˆ°æˆ‘们的授æƒæœåŠ¡ç”¨äºŽå®¡æ ¸ç›®çš„;一旦完æˆäº†è®¤è¯è¿‡ç¨‹ï¼Œ%(platformName)sä¸ä¼šç»§ç»ä¿å˜è¿™äº›ç…§ç‰‡å’Œä¿¡æ¯ã€‚" + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "感谢您返回认è¯æ‚¨åœ¨ {courseName} ä¸çš„ ID" @@ -8438,6 +8711,13 @@ msgid "" "and photo" msgstr "驾照ã€æŠ¤ç…§æˆ–者其他由政府ç¾å‘的带有您姓å和照片的身份è¯ä»¶" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "æ‘„åƒå¤´" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8525,6 +8805,11 @@ msgstr "在您å‡çº§è‡³è¯ä¹¦è·¯å¾„之å‰ï¼Œæ‚¨å¿…须激活您的账å·ã€‚" msgid "Check your email for an activation message." msgstr "检查您的电å邮箱是å¦æ”¶åˆ°æ¿€æ´»æ¶ˆæ¯ã€‚" +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "总计" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "{courseName} 的专业è¯ä¹¦" @@ -8562,6 +8847,36 @@ msgstr "您将使用您的网络摄åƒå¤´æ‹æ‘„ä¸€å¼ åŒæ—¶æ˜¾ç¤ºæ‚¨çš„脸部和 msgid "Thank you! We have received your payment for {courseName}." msgstr "谢谢ï¼æˆ‘们已ç»æ”¶åˆ°æ‚¨çš„ {courseName} 付款。" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "请打å°æ¤é¡µç•™ä½œçºªå½•ï¼Œè¿™æ˜¯æ‚¨çš„收æ®ã€‚您也会收到一å°æœ‰ç›¸åŒä¿¡æ¯çš„电å邮件。" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "订å•å·ï¼š" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "金é¢" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "请注æ„" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "划掉的项目已退款。" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "è´¦å•å¯„ç»™" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "没有å¯æ供的收æ®ã€‚" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "下一æ¥ï¼šç¡®è®¤æ‚¨çš„身份" @@ -8590,6 +8905,10 @@ msgid "" "%(platformName)s to verify your identity." msgstr "如果您现在ä¸éªŒè¯æ‚¨çš„身份,您ä»å¯ä»¥é€šè¿‡æŽ§åˆ¶é¢æ¿æµè§ˆè¯¾ç¨‹ã€‚但您会定期从%(platformName)s收到身份验è¯æ醒。" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "希望ç¨åŽå†éªŒè¯æ‚¨çš„身份?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "身份验è¯æ£åœ¨è¿›è¡Œä¸" @@ -8598,11 +8917,9 @@ msgstr "身份验è¯æ£åœ¨è¿›è¡Œä¸" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"我们已ç»æ”¶åˆ°æ‚¨çš„ä¿¡æ¯å¹¶æ£åœ¨éªŒè¯æ‚¨çš„身份。验è¯æµç¨‹ç»“æŸåŽ(一般在 1-2 " -"天内),您将在您的控制é¢æ¿ä¸Šæ”¶åˆ°ä¸€æ¡æ¶ˆæ¯ã€‚与æ¤åŒæ—¶ï¼Œæ‚¨ä»ç„¶å¯ä»¥è®¿é—®æ‰€æœ‰çš„课程内容。" #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -8636,10 +8953,6 @@ msgstr "照片è¦æ±‚:" msgid "Does the photo of you show your whole face?" msgstr "è¿™å¼ ç…§ç‰‡ä¸æœ‰æ‚¨çš„æ•´å¼ è„¸å—?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "è¿™å¼ ç…§ç‰‡å’Œæ‚¨èº«ä»½è¯ä»¶ä¸Šçš„照片相匹é…å—?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "您身份è¯ä»¶ä¸Šçš„åå—是å¦æ¸…æ™°å¯è§ï¼Ÿ" @@ -10051,6 +10364,21 @@ msgstr "设置为特殊测验" msgid "Exam Types" msgstr "测试类别" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "计时" @@ -10221,14 +10549,14 @@ msgstr "" msgid "Read more" msgstr "了解更多" -#: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" -msgstr "显示å—幕 ({totalTranscripts})" - #: cms/templates/js/video-transcripts.underscore msgid "No transcript uploaded." msgstr "æœªä¸Šä¼ å—幕。" +#: cms/templates/js/video-transcripts.underscore +msgid "Show transcripts ({totalTranscripts})" +msgstr "显示å—幕 ({totalTranscripts})" + #: cms/templates/js/xblock-access-editor.underscore msgid "Set Access" msgstr "设置é™åˆ¶" diff --git a/conf/locale/zh_HANS/LC_MESSAGES/django.mo b/conf/locale/zh_HANS/LC_MESSAGES/django.mo index 477edcd8b426eb6de36baf07f80b8130dd9330c3..5f3f2f0a53983ca969b4669fa979a6cd0f4ded8f 100644 Binary files a/conf/locale/zh_HANS/LC_MESSAGES/django.mo and b/conf/locale/zh_HANS/LC_MESSAGES/django.mo differ diff --git a/conf/locale/zh_HANS/LC_MESSAGES/django.po b/conf/locale/zh_HANS/LC_MESSAGES/django.po index 3db72cc82a4016bb2aab2f9a3a44ebaf7e6ce723..2d2599598b6f288535fba1d7d4218d9c2b43d3b2 100644 --- a/conf/locale/zh_HANS/LC_MESSAGES/django.po +++ b/conf/locale/zh_HANS/LC_MESSAGES/django.po @@ -48,6 +48,7 @@ # Michael Cao <ming.cao.ming@gmail.com>, 2015 # Mingye Wang <arthur200126@gmail.com>, 2015 # Ned Batchelder <ned@edx.org>, 2016 +# 刘é¹ç¨‹ <pcliu.fd@gmail.com>, 2020 # pku9104038 <pku9104038@hotmail.com>, 2014 # pku9104038 <pku9104038@hotmail.com>, 2014 # riceball <snowyu.lee@gmail.com>, 2014 @@ -74,8 +75,8 @@ # yan9yu, 2014 # Yue Fang <yfang@juilliard.edu>, 2016 # Yuelan Sheng <shengyl.cheryl@gmail.com>, 2015 -# Yu <inactive+harrycaoyu@transifex.com>, 2015 -# Yu <inactive+harrycaoyu@transifex.com>, 2015 +# db5cc497ac4f3c6c4b3195316e6985b6_cabed74 <3af8e6fd761591a7c85c4ffdc30e97c5_286908>, 2015 +# db5cc497ac4f3c6c4b3195316e6985b6_cabed74 <3af8e6fd761591a7c85c4ffdc30e97c5_286908>, 2015 # yw liu <2877206@qq.com>, 2018 # zhouxuan <lion19930924@163.com>, 2014-2015 # 刘知远 <liuliudong@163.com>, 2013 @@ -208,6 +209,7 @@ # Mingye Wang <arthur200126@gmail.com>, 2015 # Wheathana <mr_wheat@sina.cn>, 2015 # Ned Batchelder <ned@edx.org>, 2016 +# 刘é¹ç¨‹ <pcliu.fd@gmail.com>, 2020 # perypery <410224186@qq.com>, 2014 # pku9104038 <pku9104038@hotmail.com>, 2014 # pku9104038 <pku9104038@hotmail.com>, 2014 @@ -323,8 +325,8 @@ # Wentao Han <wentao.han@gmail.com>, 2013 # Wheathana <mr_wheat@sina.cn>, 2015 # ç†Šå†¬å‡ <xdsnet@gmail.com>, 2013 -# yezhixin20 <inactive+yezhixin20@transifex.com>, 2014 -# yezhixin20 <inactive+yezhixin20@transifex.com>, 2014 +# 77fe99dcf38d5fa9d2727dfb4df61259_c85f6a2 <51905779c1925b7a3c212e4dec17a56d_177606>, 2014 +# 77fe99dcf38d5fa9d2727dfb4df61259_c85f6a2 <51905779c1925b7a3c212e4dec17a56d_177606>, 2014 # YUAN Tian <Sweetyuantian@msn.cn>, 2014 # YUAN Tian <Sweetyuantian@msn.cn>, 2014 # Yufei Xue <cmouse@163.com>, 2013 @@ -395,7 +397,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: ifLab <webmaster@iflab.org>, 2019\n" "Language-Team: Chinese (China) (https://www.transifex.com/open-edx/teams/6205/zh_CN/)\n" @@ -404,7 +406,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. #-#-#-#-# django-partial.po (edx-platform) #-#-#-#-# #. Translators: 'Discussion' refers to the tab in the courseware that leads to @@ -429,8 +431,8 @@ msgstr "å…¥å¦è€ƒè¯•" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "å•å…ƒ" @@ -742,13 +744,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "公开用户å'{username}'对应的账å·å·²å˜åœ¨ã€‚" +msgid "An account with the Email '{email}' already exists." +msgstr "邮箱'{email}'对应的账å·å·²å˜åœ¨ã€‚" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "邮箱'{email}'对应的账å·å·²å˜åœ¨ã€‚" +msgid "An account with the Public Username '{username}' already exists." +msgstr "公开用户å'{username}'对应的账å·å·²å˜åœ¨ã€‚" #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2523,9 +2525,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -4209,12 +4211,12 @@ msgid "" " considered in the Entrance Exam scoring/gating algorithm." msgstr "输入true或false。若为true,问题模å—çš„ç”案æ交将会被考虑在入å¦è€ƒè¯•çš„得分/控制算法ä¸ã€‚" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "选课记录组" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "通过选课类别划分用户的分区" @@ -4808,17 +4810,17 @@ msgstr "解é”账户" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "å…³é—" @@ -5711,50 +5713,6 @@ msgid "" "this request, please visit the link(s) below." msgstr "{username} ({email}) 的退款è¦æ±‚å·²ç»å»ºç«‹ã€‚为了处ç†æ¤è¯·æ±‚,请访问以下è”结(s) 。" -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "收æ®" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "支付失败" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "交易出现问题。您尚未缴费。" - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "ç¡®ä¿æ‚¨çš„ä¿¡æ¯æ£ç¡®æ— 误了,或æ¢ä¸€å¼ 信用é‡è¯•æˆ–æ¢ç”¨å…¶ä»–支付方å¼ã€‚" - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "在处ç†æ‚¨çš„付款时出现系统错误。您尚未缴费。" - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "请ç‰å¾…å‡ åˆ†é’ŸåŽé‡è¯•ã€‚" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "è”ç³»{payment_support_link}寻求帮助。" - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "创建您的收æ®æ—¶å‡ºé”™ã€‚" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "如果您的课程未出现在您的课程é¢æ¿ä¸Šï¼Œè¯·è”ç³»{payment_support_link}。" - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "获å–è¯ä¹¦" @@ -5817,11 +5775,23 @@ msgstr "æ‚¨æ— æƒè®¿é—®å¦ä¹ 该课程" msgid "You do not have access to this course on a mobile device" msgstr "æ‚¨æ— æ³•åœ¨ç§»åŠ¨è®¾å¤‡ä¸Šå¦ä¹ 该课程" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "å‡çº§åˆ°éªŒè¯" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -5841,6 +5811,11 @@ msgstr "{relative} å¹´ - {absolute}" msgid "in {relative} - {absolute}" msgstr "in {relative} - {absolute}" +#: lms/djangoapps/courseware/date_summary.py +#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py +msgid "Enrollment Date" +msgstr "选课日期" + #: lms/djangoapps/courseware/date_summary.py msgid "Course Starts" msgstr "课程开始" @@ -6457,16 +6432,20 @@ msgid "Good" msgstr "好" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" -msgstr "%(comment_username)s回å¤äº†<b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" +msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt msgid "View discussion" msgstr "查看讨论" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "%(comment_username)s回å¤äº†<b>%(thread_title)s</b>:" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6594,8 +6573,8 @@ msgid "Student" msgstr "å¦ç”Ÿ" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "教员" @@ -6715,29 +6694,6 @@ msgstr "问题回ç”" msgid "Could not find problem with this location." msgstr "æ— æ³•æ–¼æ¤ä½ç½®æ‰¾åˆ°é—®é¢˜ã€‚" -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "å‘ç¥¨å· '{num}' ä¸å˜åœ¨ã€‚" - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "与æ¤ç›¸å…³è”çš„å‘票出售已ç»å¤±æ•ˆã€‚" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "å‘ç¥¨å· {0} å·²ç»æ— 效。" - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "æ¤å‘è´§å•å·²ç»æ¿€æ´»ã€‚" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "æ”¶æ® {0}的注册编å·å·²ç»è¢«é‡æ–°æ¿€æ´»ã€‚" - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "课程 ID" @@ -6768,9 +6724,8 @@ msgstr "用户ID" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "用户å" @@ -6890,54 +6845,6 @@ msgstr "该文件必须包å«ä¸€ä¸ªâ€œç¾¤ç»„â€åˆ—,该列ä¸åŒ…å«äº†ç¾¤ç»„çš„ msgid "The file must contain a 'username' column, an 'email' column, or both." msgstr "该文件必须包å«ä¸€ä¸ªâ€œusernameâ€åˆ—,或一个“emailâ€åˆ—,或两者都包å«ã€‚" -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "ä¼˜æƒ åˆ¸ç¼–ç " - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "课程编å·" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "%折扣" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "æè¿°" - -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -msgid "Expiration Date" -msgstr "过期日期" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "是å¦æ´»è·ƒ" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "推广折扣é¢ä»£ç " - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "总折扣åé¢" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "总折扣金é¢" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -6958,14 +6865,6 @@ msgstr "调查" msgid "proctored exam results" msgstr "监考考试æˆç»©" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "æ— æ³•è§£æžæ€»æ•°ä¸ºå进制" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "由于课程的错误é…ç½®ï¼Œæ— æ³•ç”Ÿæˆå…‘æ¢ç 。" - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -7178,63 +7077,6 @@ msgid "" " try again." msgstr "å¦ç”Ÿ {student} 没有æ¤é—¨è¯¾ç¨‹ {course}之修课è¯æ˜Žã€‚请验è¯å¦ç”Ÿç”¨æˆ·å/邮箱以åŠç¡®è®¤æ‰€é€‰ä¹‹è¯¾ç¨‹æ˜¯å¦æ£ç¡®ï¼Œç„¶åŽé‡è¯•ã€‚" -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "ä¼˜æƒ åˆ¸IDä¸å˜åœ¨" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "ç¼–å·ä¸º({coupon_id})çš„ä¼˜æƒ åˆ¸ä¸å˜åœ¨" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "ç¼–å·ä¸º({coupon_id})çš„ä¼˜æƒ åˆ¸å·²ç»è¢«æ¿€æ´»" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "ç¼–å·ä¸º({coupon_id})çš„ä¼˜æƒ åˆ¸æ›´æ–°æˆåŠŸ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "您试图定义的这个å¡å· ({code})å·²ç»è¢«æ³¨å†Œç 使用了" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "请输入整数值的折扣率" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "请输入ä¸å¤§äºŽ100çš„ä¼˜æƒ åˆ¸æŠ˜æ‰£åº¦" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "è¯·ä»¥è¯¥æ ¼å¼è¾“入日期,如:月/æ—¥/å¹´" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "ä½¿ç”¨ä¼˜æƒ ä»£ç ({code})çš„ä¼˜æƒ åˆ¸æ·»åŠ æˆåŠŸã€‚" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "ä¼˜æƒ ä»£ç 为({code})çš„ä¼˜æƒ åˆ¸å¯¹äºŽè¯¥è¯¾ç¨‹å·²ç»å˜åœ¨" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "ä¼˜æƒ åˆ¸ç¼–å·æ— 法找到" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "ç¼–å·ä¸º({coupon_id})çš„ä¼˜æƒ åˆ¸æ›´æ–°æˆåŠŸ" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "主讲教师" @@ -7342,29 +7184,6 @@ msgstr "å·²ç»å®Œæˆ" msgid "Incomplete" msgstr "未完æˆ" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "对于{course_name}课程的选课ç ({code})未找到。" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "该选课ç å·²ç»è¢«å–消,ä¸èƒ½å†ä½¿ç”¨ã€‚" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "该选课ç å·²è¢«æ ‡è®°ä¸ºæœªä½¿ç”¨è¿‡çš„ã€‚" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "选课ç 已修å¤ã€‚" - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "针对redemption 注册代ç ({code})是ä¸å˜åœ¨çš„。" - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7559,10 +7378,6 @@ msgstr "æ ‡é¢˜" msgid "Year of Birth" msgstr "出生年份" -#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py -msgid "Enrollment Date" -msgstr "选课日期" - #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py msgid "Currently Enrolled" msgstr "当å‰æ³¨å†Œ" @@ -7760,8 +7575,8 @@ msgstr "( ï¼{total} )" #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "程å¼" @@ -8437,6 +8252,15 @@ msgstr "æ€»ä»·æ ¼" msgid "Currency" msgstr "è´§å¸" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "æè¿°" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "评è¯" @@ -8580,14 +8404,6 @@ msgstr "您没有访问æ¤é¡µé¢çš„æƒé™ã€‚" msgid "View and regenerate certificates." msgstr "查看并产生è¯ä¹¦ã€‚" -#: lms/djangoapps/support/views/index.py lms/templates/support/refund.html -msgid "Manual Refund" -msgstr "人工退费" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "直接é€è¿‡CyberSource追踪退款问题。" - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -8666,44 +8482,9 @@ msgstr "用户激活æˆåŠŸ" msgid "User Disabled Successfully" msgstr "æˆåŠŸç¦ç”¨ç”¨æˆ·" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "邮箱" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "课程编å·" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "未找到用户" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "课程 {course_id}没有通过退费窗å£ã€‚" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "在课程{course_id}ä¸æ²¡æœ‰ä¸º{user}找到订å•ã€‚" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "放弃选修{course_id}çš„{user}" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "订å•{order_id}已退款{cost}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -9329,8 +9110,8 @@ msgid "Allow" msgstr "å…许" #: lms/templates/oauth2_provider/authorize.html -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "错误" @@ -9713,8 +9494,8 @@ msgid "" msgstr "æ¤å¤„å…许使用MarkDownè¯æ³•ã€‚请å‚阅%(start_link)så¿«æ·é”®ç®¡ç†%(end_link)s并寻求帮助。" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "附件" @@ -9750,11 +9531,10 @@ msgid "" msgstr "您å¯ä»¥ä»Žå…¶ä»–æ–‡ç« ä¸é‡ç”¨ä¸€äº›æ–‡ä»¶ã€‚但是该文件的更新ä¾èµ–äºŽåŽŸå§‹æ–‡ç« ï¼Œè¯·åˆ¤æ–该引用关系是å¦æ°å½“。" #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -10162,6 +9942,10 @@ msgstr "é…ç½®æ¤è¯¾ç¨‹è¿è¡Œçš„å‚æ•°ã€‚æ ¼å¼ä¸ºCourseKey(例如course-v1:// msgid "Configuration may not be specified at more than one level at once." msgstr "ä¸èƒ½ä¸€æ¬¡åœ¨å¤šä¸ªçº§åˆ«æŒ‡å®šé…置。" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -10537,6 +10321,10 @@ msgstr "已知错误案例" msgid "Schedule start < course start" msgstr "时间表开始时间 < 课程开始时间" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "课程编å·" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "全部" @@ -10545,6 +10333,15 @@ msgstr "全部" msgid "Experience" msgstr "ç»éªŒ" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "课程编å·" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -10979,7 +10776,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -11006,8 +10802,8 @@ msgid "Success" msgstr "æˆåŠŸ" #: openedx/core/djangoapps/user_api/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "æ“作" @@ -11172,6 +10968,14 @@ msgstr "注册" msgid "There was an error receiving your login information. Please email us." msgstr "接å—您的登录信æ¯æ—¶å‡ºçŽ°é”™è¯¯ï¼Œè¯·å‘电å邮件给我们。" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11187,6 +10991,15 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "失败次数超过é™åˆ¶ï¼Œè¯·ç¨åŽå†è¯•ï¼" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -11194,15 +11007,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "username@domain.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -11218,6 +11022,12 @@ msgstr "您在{platform_name}上注册的邮箱" msgid "Create Account" msgstr "创建账å·" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "username@domain.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -11230,6 +11040,11 @@ msgid "" "password." msgstr "与æ¤é‚®ç®±å…³è”的用户账å·æ— 法é‡æ–°è®¾ç½®å¯†ç 。" +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "é‡æ–°è®¾ç½®å¯†ç ä¸æˆåŠŸ" @@ -11250,11 +11065,6 @@ msgid "" msgstr "" "{html_start}密ç 创建完æˆ{html_end}å·²ç»åˆ›å»ºäº†æ‚¨çš„密ç 。{bold_start}{email}{bold_end}现在是您的主登录电å邮件。" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "é‡è®¾å¯†ç æ—¶å‘生错误,请é‡è¯•" @@ -11484,6 +11294,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "用于视频管线整åˆçš„用户å,例如:veda_service_user。" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "强制开å¯" @@ -11502,6 +11324,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "è¯¥å€¼æ— æ•ˆã€‚" @@ -12187,8 +12013,8 @@ msgstr "课程æˆåŠŸè¢«å¯¼å‡ºåˆ°Gitæº" msgid "Vertical" msgstr "纵列å—" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "ç« " @@ -12459,6 +12285,18 @@ msgstr "å—幕转载进行ä¸" msgid "Transcript Ready" msgstr "å—幕完æˆ" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "å¿…é¡»æ供图片文件。" @@ -12603,8 +12441,8 @@ msgstr "内容" #: cms/templates/settings.html cms/templates/settings_advanced.html #: cms/templates/settings_graders.html cms/templates/widgets/header.html #: lms/templates/wiki/includes/article_menu.html -#: wiki/templates/wiki/settings.html #: wiki/templates/wiki/includes/article_menu.html +#: wiki/templates/wiki/settings.html msgid "Settings" msgstr "设置" @@ -12652,14 +12490,14 @@ msgstr "课程代ç :" msgid "Course Run:" msgstr "课程长度:" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "课程" @@ -12683,8 +12521,9 @@ msgstr "主讲教师" msgid "Requirements" msgstr "ä¿®ä¹ è¦æ±‚" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "细节" @@ -12738,15 +12577,15 @@ msgstr "" msgid "Choose Language" msgstr "选择è¯è¨€" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "è´¦å·" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -12818,8 +12657,8 @@ msgstr "用户èœå•" msgid "Usermenu dropdown" msgstr "用户èœå•ä¸‹æ‹‰åˆ—表" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "退出" @@ -12979,8 +12818,8 @@ msgstr "开课日期: {date}" msgid "View all Courses" msgstr "æµè§ˆæ‰€æœ‰è¯¾ç¨‹" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "课程é¢æ¿" @@ -12999,8 +12838,8 @@ msgstr "您尚未å‚åŠ ä»»ä½•è¯¾ç¨‹ã€‚" #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "探索课程" @@ -13018,7 +12857,7 @@ msgstr "è¯¾ç¨‹åŠ è½½é”™è¯¯" msgid "Search Your Courses" msgstr "查找课程" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "清空æœç´¢ç»“æžœ" @@ -13043,7 +12882,7 @@ msgstr "接收课程邮件" msgid "Save Settings" msgstr "ä¿å˜è®¾ç½®" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -13053,9 +12892,87 @@ msgstr "ä¿å˜è®¾ç½®" msgid "Unenroll" msgstr "放弃选修" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "在 Studio ä¸æŸ¥çœ‹å•å…ƒ" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -13087,7 +13004,7 @@ msgstr "该邮箱已被å¦ä¸€ä¸ªè´¦å·ä½¿ç”¨ã€‚" msgid "You should Register before trying to access the Unit" msgstr "您在查看å•å…ƒå‰åº”先注册。" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "选修" @@ -13191,7 +13108,7 @@ msgstr "" "由于截æ¢æ—¥æœŸå·²è¿‡ï¼Œæ¤ä½œä¸šä¸å†å¯ç”¨ã€‚{line_break} 如果您已ç»å®Œæˆæ¤ä½œä¸šï¼Œæ‚¨å¯ä»¥åœ¨ {link_start}进度页é¢{link_end} " "上查询作业æˆç»©ã€‚" -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "查找课程" @@ -13326,19 +13243,16 @@ msgstr "(é‡æ–°åŠ 载以刷新您的页é¢)" msgid "working" msgstr "è¿è¡Œä¸" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr "{platform_name} å¹³å°çš„æœåŠ¡å™¨å‘生了错误" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"éžå¸¸æŠ±æ‰ï¼Œè¯¥æ¨¡å—æš‚æ—¶æ— æ³•ä½¿ç”¨ï¼Œæˆ‘ä»¬çš„æ•™å‘˜æ£åœ¨åŠªåŠ›å°½ä¿®å¤é—®é¢˜ã€‚è¦æŠ¥å‘Šæ‚¨å‘现的任何问题或é‡åˆ°ç½‘ç«™éžæ£å¸¸ï¼Œè¯·å‘{tech_support_email}å‘é€é‚®ä»¶" #: lms/templates/module-error.html msgid "Raw data:" @@ -13377,7 +13291,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "您æ£åœ¨ä»¥ {i_start}{user_name}{i_end} 身份查看课程。" #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -13438,28 +13360,6 @@ msgstr "邮箱" msgid "Return To %s" msgstr "返回%s" -#: lms/templates/reset_deadlines_banner.html -msgid "It looks like you've missed some important deadlines. Visit " -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "edx.org" -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid " to reset your deadlines and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "é‡æ–°è®¢é˜…æˆåŠŸï¼" @@ -13509,7 +13409,7 @@ msgstr "" msgid "Sequence" msgstr "åºåˆ—" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -13638,18 +13538,18 @@ msgstr "æˆç»©ï¼ˆä»…用于覆盖原æ¥çš„æˆç»©è®¾ç½®ï¼‰" msgid "Reset Learner's Attempts to Zero" msgstr "å°†å¦å‘˜çš„å°è¯•æ¬¡æ•°ç½®ä¸º0" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "åˆ é™¤å¦ç”ŸçŠ¶æ€" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "对å¦ç”Ÿçš„æ交记录é‡æ–°è¯„分" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "如果评分æ高,é‡æ–°æ‰“分" @@ -13687,7 +13587,7 @@ msgstr "{course_number} æ•™æ" msgid "Textbook Navigation" msgstr "课本导航" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "页é¢" @@ -13798,9 +13698,9 @@ msgstr "第 {current_page} 页/ å…±{total_pages}页" msgid "Recent git load activity for {course_id}" msgstr "近期 {course_id}çš„gitåŠ è½½æ´»åŠ¨" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html #: wiki/plugins/attachments/templates/wiki/plugins/attachments/search.html msgid "Date" @@ -13857,7 +13757,7 @@ msgid "" msgstr "" "您ä¸å°†å†æŽ¥æ”¶åˆ°{platform_name}论å›é‚®ä»¶æ醒,请å•å‡»{dashboard_link_start}æ¤å¤„{link_end}返回您的课程é¢æ¿ã€‚如果您ä¸æ˜¯æœ‰æ„å–消,请å•å‡»{undo_link_start}æ¤å¤„{link_end}é‡æ–°è®¢é˜…消æ¯ã€‚" -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "课程é¢æ¿ï¼š" @@ -13865,8 +13765,8 @@ msgstr "课程é¢æ¿ï¼š" msgid "More options" msgstr "更多选项" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "更多选项" @@ -15103,35 +15003,6 @@ msgstr "如果所有信æ¯æ£ç¡®ä½†é—®é¢˜ä»ç„¶å˜åœ¨ï¼Œè¯·è”系技术支æŒå›¢ msgid "About edX Certificates" msgstr "关于edXè¯ä¹¦" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "付款已å–消" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "您的交易已被å–消。如果您觉得å‘生了错误,请è”ç³» {email} 。" - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "付款出错" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "åŠ è½½è®¢å•ä¿¡æ¯..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "请ç¨å€™ï¼Œæˆ‘们æ£åœ¨èŽ·å–您的订å•è¯¦æƒ…。" - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -15330,14 +15201,14 @@ msgstr "{section_format} 截æ¢æ—¥æœŸ{{date}} " msgid "This content is graded" msgstr "该内容计入总分。" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "出现错误,请ç¨åŽå†è¯•ã€‚" - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "出现错误,请ç¨åŽå†è¯•ã€‚" + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "您选修了本课程" @@ -15349,10 +15220,6 @@ msgstr "您选修了本课程" msgid "View Course" msgstr "查看课程" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "这个课程已ç»è¿›å…¥ä½ çš„ {start_cart_link}è´ç‰©è½¦{end_cart_link}。" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "该课程已满" @@ -15365,10 +15232,6 @@ msgstr "该课程åªèƒ½é€šè¿‡é‚€è¯·é€‰ä¿®" msgid "Enrollment is Closed" msgstr "选课已关é—" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "æ·»åŠ {course_name} 到è´ç‰©è½¦ {start_span}({price} USD){end_span}" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "" @@ -15490,6 +15353,13 @@ msgstr "课程工具" msgid "Courseware" msgstr "课程页é¢" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "æœç´¢è¯¾ç¨‹" @@ -15518,7 +15388,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -15526,14 +15396,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" msgstr "" -#: lms/templates/courseware/error-message.html -msgid "" -"We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible." +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -16179,8 +16046,8 @@ msgstr "您已æ交认è¯ä¿¡æ¯ã€‚" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." -msgstr "验è¯è¿‡ç¨‹å®ŒæˆåŽï¼ˆé€šå¸¸åœ¨1-2天内),您会在课程é¢æ¿ä¸çœ‹åˆ°æ¶ˆæ¯ã€‚" +"complete (usually within 5-7 days)." +msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -16190,8 +16057,8 @@ msgstr "您的当å‰éªŒè¯å°†é©¬ä¸Šè¿‡æœŸï¼" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." -msgstr "您已æ交了é‡æ–°éªŒè¯ä¿¡æ¯ã€‚验è¯è¿‡ç¨‹å®ŒæˆåŽï¼ˆé€šå¸¸åœ¨1-2天内),您会在课程é¢æ¿ä¸çœ‹åˆ°æ¶ˆæ¯ã€‚" +"5-7 days)." +msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -16868,136 +16735,6 @@ msgid "" msgstr "" "我们已收到您的信æ¯ï¼Œå¹¶ä¸”身份认è¯æµç¨‹å·²å¼€å§‹ã€‚请在接下æ¥å‡ 天内查看我们给您å‘的一å°é‚®ä»¶ï¼Œä»¥ç¡®è®¤æ‚¨è®¤è¯æ˜¯å¦æˆåŠŸã€‚您也å¯ä»¥åœ¨é¢æ¿ä¸æŸ¥çœ‹æ‚¨çš„认è¯çŠ¶æ€ã€‚" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "感谢您è´ä¹°{course_name}。" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "{currency_symbol}{total_price}çš„å‘票已附上。您在收到å‘票åŽéœ€ç«‹å³ä»˜æ¬¾ã€‚您å¯ä»¥åœ¨å‘票里找到付款方å¼ã€‚" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "附件ä¸æ˜¯å¸¦æœ‰æ‚¨çš„选课ç çš„.csv文件。您å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„邮件模æ¿å°†é€‰è¯¾ç 分å‘给您的å¦ç”Ÿã€‚æ¯ä¸ªå¦ç”Ÿå¿…须使用一个å•ç‹¬çš„选课ç 。" - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"谢谢,\n" -"{platform_name}团队" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "亲爱的 [[Name]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "我们为您æ供了一个{course_name}选课ç 。å‚åŠ è¯¥è¯¾ç¨‹ï¼Œè¯·ç‚¹å‡»ä»¥ä¸‹é“¾æŽ¥:" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "附件CSV文件ä¸çš„html链接" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "在您选课之åŽï¼Œæ‚¨å¯ä»¥åœ¨æ‚¨çš„å¦ç”Ÿè¯¾ç¨‹é¢æ¿ä¸çœ‹åˆ°è¯¥è¯¾ç¨‹ã€‚在课程开始åŽï¼Œæ‚¨å°±å¯ä»¥çœ‹åˆ°è¯¾ç¨‹çš„相关资料。" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"诚挚的,\n" -"[[Your Signature]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "å‘票" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "日期: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "å‘票å·ç : {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "æ¡æ¬¾ï¼šæ”¶åˆ°ä»˜æ¬¾" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "截æ¢æ—¥æœŸ: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "付款给:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "客户å‚考编ç : {reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "应付金é¢: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "课程å称: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" -"ä»·æ ¼: {currency_symbol}{course_price} æ•°é‡: {quantity} å°è®¡: " -"{currency_symbol}{sub_total} 折扣: {currency_symbol}{discount}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "总计: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "支付说明" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" -"如果我们没有收到付款,使用这些选课ç çš„å¦ç”Ÿå°†è¢«å–æ¶ˆä¸Šè¯¾èµ„æ ¼å¹¶æ— æ³•è®¿é—®è¯¾ç¨‹èµ„æ–™ã€‚æ‰€æœ‰ä»˜æ¬¾éƒ½æ— æ³•é€€æ¢ã€‚欲了解更多信æ¯ï¼Œè¯·å‚è§{site_name}å–消政ç–。" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "支付问题请è”ç³»{contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -17170,8 +16907,8 @@ msgstr "申请ç»æµŽèµ„助" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name} 主页" @@ -17193,19 +16930,11 @@ msgstr "马上探索课程" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "系统管ç†å‘˜" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "è´ç‰©è½¦" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "补充内容链接" @@ -17242,6 +16971,12 @@ msgstr "æ·»åŠ ä¼˜æƒ åˆ¸ä»£ç " msgid "Enter information about the coupon code below." msgstr "在下é¢è¾“å…¥ä¼˜æƒ åˆ¸ä»£ç " +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "ä¼˜æƒ åˆ¸ä»£ç " + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "折扣率" @@ -17790,6 +17525,11 @@ msgstr "ä¸‹è½½ä¼˜æƒ åˆ¸ä»£ç " msgid "Coupon Codes" msgstr "ä¼˜æƒ åˆ¸ä»£ç " +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "过期日期" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "ä¼˜æƒ åˆ¸(%)" @@ -19065,6 +18805,10 @@ msgstr "采è´æœºæž„" msgid "Purchase order number (if any)" msgstr "订å•å·(如果å˜åœ¨)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "邮箱" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "email@example.com" @@ -19355,6 +19099,10 @@ msgid_plural "" "{course_names} have been removed because the enrollment period has closed." msgstr[0] "å› é€‰è¯¾æ—¶é™å·²å…³é—,{course_names} 已被移除。" +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "è´ç‰©è½¦" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "å°é¢å›¾ç‰‡" @@ -19567,46 +19315,6 @@ msgstr "å¦å‘˜å¸®åŠ©ï¼šç®¡ç†ç”¨æˆ·" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "准备就该订å•é€€è´¹" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "订å•æ ‡è¯†ï¼š" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "选课:" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "已选修" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "已弃选" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "费用:" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "è¯ä¹¦çŠ¶æ€ï¼š" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "订å•çŠ¶æ€ï¼š" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "完æˆæ—¶é—´ï¼š" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "退费申请时间:" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "用户调查" @@ -19743,8 +19451,8 @@ msgstr "身份验è¯" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." -msgstr "您已æ交了认è¯ä¿¡æ¯ã€‚当认è¯è¿‡ç¨‹ç»“æŸåŽï¼Œæ‚¨ä¼šåœ¨æ‚¨çš„课程é¢æ¿ä¸çœ‹åˆ°ä¸€æ¡æ¶ˆæ¯(通常在1-2天内)。" +" within 5-7 days)." +msgstr "" #: lms/templates/verify_student/reverify_not_allowed.html msgid "You cannot verify your identity at this time." @@ -20312,8 +20020,8 @@ msgid "Already registered?" msgstr "å·²ç»æ³¨å†Œè¿‡äº†ï¼Ÿ" #: themes/stanford-style/lms/templates/register-sidebar.html -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Log in" msgstr "登录" @@ -20416,10 +20124,8 @@ msgid "The page that you were looking for was not found." msgstr "您查找的页é¢æ— 法找到。" #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." -msgstr "返回到{homepage}或å‘电å邮件至{email}告诉我们被移动的页é¢ã€‚" +msgid "Go back to the {homepage}." +msgstr "" #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -20441,10 +20147,6 @@ msgid "" "error as soon as possible." msgstr "我们已ç»è®°å½•ä¸‹è¿™ä¸ªé”™è¯¯ï¼Œæˆ‘们的员工æ£åœ¨è¯•å›¾å°½å¿«è§£å†³è¿™ä¸ªé—®é¢˜ã€‚" -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "如果问题ä»ç„¶å˜åœ¨ï¼Œè¯·å‘é€ç”µå邮件至{email_link}。" - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "教室å¯è®¿é—®æ€§æ”¿ç–" @@ -21056,11 +20758,8 @@ msgstr "您请求的页é¢æ— 法找到" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" -"很抱æ‰ï¼Œæˆ‘ä»¬æ— æ³•æ‰¾åˆ°æ‚¨è¯·æ±‚çš„{studio_name}页é¢ã€‚您å¯èƒ½å¸Œæœ›è¿”回至{studio_name}课程é¢æ¿åŽé‡æ–°å°è¯•ã€‚如果您ä»é‡åˆ°é—®é¢˜ï¼Œè¯·éšæ—¶{link_start}è”ç³»{studio_name}支æŒ{link_end}以获å–更多帮助。" #: cms/templates/error.html msgid "The Server Encountered an Error" @@ -21070,11 +20769,8 @@ msgstr "æœåŠ¡å™¨å‘生错误" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" -"很抱æ‰ï¼ŒæœåŠ¡å™¨åœ¨å¤„ç†æ‚¨çš„上一个请求时é‡åˆ°é—®é¢˜ã€‚您å¯èƒ½å¸Œæœ›è¿”回至{studio_name}课程é¢æ¿æˆ–é‡æ–°æ交请求。如果您ä»é‡åˆ°é—®é¢˜ï¼Œè¯·éšæ—¶{link_start}è”ç³»{studio_name}支æŒ{link_end}以寻求帮助。" #: cms/templates/error.html msgid "Back to dashboard" @@ -24082,8 +23778,8 @@ msgstr "%(file)så·²ç»è¢«å˜æ›´åˆ°ä¿®è®¢ç‰ˆæœ¬#%(revision)d" msgid "%(file)s has been saved." msgstr "%(file)så·²ç»è¢«ä¿å˜ã€‚" -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "图片" @@ -24276,8 +23972,8 @@ msgstr "清空通知列表" msgid "Search..." msgstr "æœç´¢" -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "注册" diff --git a/conf/locale/zh_HANS/LC_MESSAGES/djangojs.mo b/conf/locale/zh_HANS/LC_MESSAGES/djangojs.mo index bf401e5c0f45deb64fc7596651777eebcc8e9832..611260779848a01dc264c6d35ed3cef40858160f 100644 Binary files a/conf/locale/zh_HANS/LC_MESSAGES/djangojs.mo and b/conf/locale/zh_HANS/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/zh_HANS/LC_MESSAGES/djangojs.po b/conf/locale/zh_HANS/LC_MESSAGES/djangojs.po index 37564e1e9262d95d65cc44bba0bff7bea18ae6c3..b0a7b4da58fb5ef385be1556860aa7b702c6b675 100644 --- a/conf/locale/zh_HANS/LC_MESSAGES/djangojs.po +++ b/conf/locale/zh_HANS/LC_MESSAGES/djangojs.po @@ -173,6 +173,7 @@ # Lionel Chen <chenlinchuan@me.com>, 2014 # LIU NIAN <lauraqq@gmail.com>, 2015 # meelo <bbvy@qq.com>, 2015 +# qiaoyafeng <qiao_yafeng@qq.com>, 2020 # Rom, 2015 # Rom, 2015 # louyihua <supermouselyh@hotmail.com>, 2014-2015 @@ -181,7 +182,7 @@ # Yue Fang <yfang@juilliard.edu>, 2016 # Zihui Cheng <z7cheng@ucsd.edu>, 2015 # 代 å…´æ—º <525224259@qq.com>, 2016 -# 伟波 黄 <inactive+gtc_ZjEzMTJ@transifex.com>, 2016 +# 8cfb674aa14009d921df29d97d1751e8_9eeecd0 <ff77ddda63493ab7c7af47446c7f91e9_481994>, 2016 # å¥è¶… å¼ <jc.zhang@eliteu.com.cn>, 2019 # å¼ é€¸æ¶µ <jeanzhang970128@gmail.com>, 2014 # å¾® æŽ <w.li@eliteu.com.cn>, 2018 @@ -206,8 +207,8 @@ # Jiazhen Tan <jessie12@live.cn>, 2016 # jsgang <jsgang9@gmail.com>, 2015-2017 # LIU NIAN <lauraqq@gmail.com>, 2015 -# peipeixiang <inactive+peipeixiang@transifex.com>, 2015 -# peipeixiang <inactive+peipeixiang@transifex.com>, 2015 +# dae18ada8f5d984070f88a11bd09a0d3_87cf90e <6d2a6f2312a2a802f0de112b58b74c46_176438>, 2015 +# dae18ada8f5d984070f88a11bd09a0d3_87cf90e <6d2a6f2312a2a802f0de112b58b74c46_176438>, 2015 # Rom, 2015 # Rom, 2015 # San <github@zhujunsan.net>, 2015 @@ -215,8 +216,8 @@ # Xuejia Tong <snowytong@hotmail.com>, 2016 # Yingying Zhang <1714277256@qq.com>, 2016 # yohann yang <heinerseiden@yahoo.com>, 2016 -# Yu <inactive+harrycaoyu@transifex.com>, 2015 -# Yu <inactive+harrycaoyu@transifex.com>, 2015 +# db5cc497ac4f3c6c4b3195316e6985b6_cabed74 <3af8e6fd761591a7c85c4ffdc30e97c5_286908>, 2015 +# db5cc497ac4f3c6c4b3195316e6985b6_cabed74 <3af8e6fd761591a7c85c4ffdc30e97c5_286908>, 2015 # å˜‰æ° æŽ <jj.li@eliteu.com.cn>, 2018 # 刘啸林 <liuxiaolinfk@gmail.com>, 2016 # ç™¾æ° é™ˆ <bj.chen@eliteu.com.cn>, 2018 @@ -225,8 +226,8 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" -"PO-Revision-Date: 2019-09-29 20:43+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" +"PO-Revision-Date: 2020-06-14 20:45+0000\n" "Last-Translator: edx_transifex_bot <i18n-working-group+edx-transifex-bot@edx.org>\n" "Language-Team: Chinese (China) (http://www.transifex.com/open-edx/edx-platform/language/zh_CN/)\n" "Language: zh_CN\n" @@ -234,7 +235,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #: cms/static/cms/js/xblock/cms.runtime.v1.js #: cms/static/js/certificates/views/signatory_details.js @@ -283,6 +284,7 @@ msgstr "åˆ é™¤" #: cms/templates/js/section-name-edit.underscore #: cms/templates/js/signatory-actions.underscore #: cms/templates/js/xblock-string-field-editor.underscore +#: common/static/common/templates/discussion/templates.underscore #: lms/djangoapps/support/static/support/templates/enrollment-modal.underscore #: lms/djangoapps/teams/static/teams/templates/edit-team.underscore #: lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -305,6 +307,7 @@ msgstr "ä¸Šä¼ ä¸" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/student_account/tos_modal.js #: cms/templates/js/course-video-settings.underscore +#: common/static/common/templates/discussion/templates.underscore #: common/static/common/templates/image-modal.underscore #: openedx/features/learner_profile/static/learner_profile/templates/share_modal.underscore msgid "Close" @@ -334,6 +337,7 @@ msgstr "选择文件" #: cms/static/js/views/course_info_update.js cms/static/js/views/tabs.js #: common/lib/xmodule/xmodule/js/src/html/edit.js #: lms/static/js/Markdown.Editor.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/learner_dashboard/verification_popover.underscore msgid "OK" msgstr "是的" @@ -913,7 +917,6 @@ msgstr "åˆ é™¤è¡¨æ ¼" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/certificate-editor.underscore #: cms/templates/js/group-configuration-editor.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Description" msgstr "æè¿°" @@ -1353,6 +1356,7 @@ msgstr "新建窗å£" #: common/lib/xmodule/xmodule/js/src/html/edit.js #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Next" msgstr "下一个" @@ -2577,30 +2581,40 @@ msgid "Other" msgstr "其他" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "What can we help you with, {username}?" -msgstr "亲爱的{username},有什么å¯ä»¥å¸®åŠ©æ‚¨ï¼Ÿ" +msgid "Course Discussion Forum" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "" +"While our support team is happy to assist with the edX platform, the course " +"staff has the expertise for specific assignment questions, grading or the " +"proper procedures in each course. Please post all course related questions " +"within the Discussion Forum where the Course Staff can directly respond." +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx msgid "Details" msgstr "细节" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -msgid "The more you tell us, the more quickly and helpfully we can respond!" -msgstr "您æ供的信æ¯è¶Šè¯¦ç»†ï¼Œæˆ‘们越能快速并有效地帮助到您ï¼" +msgid "the more quickly and helpfully we can respond!" +msgstr "" #: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx -#: lms/templates/verify_student/incourse_reverify.underscore -msgid "Submit" -msgstr "æ交" +msgid "Create Support Ticket" +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +msgid "What can we help you with, {username}?" +msgstr "亲爱的{username},有什么å¯ä»¥å¸®åŠ©æ‚¨ï¼Ÿ" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx msgid "Sign in to {platform} so we can help you better." msgstr "请登录{platform},以获得更好的帮助。" #: lms/djangoapps/support/static/support/jsx/logged_out_user.jsx -msgid "" -"If you are unable to access your account contact us via email using {email}." -msgstr "å¦‚æžœæ‚¨æ— æ³•è®¿é—®è´¦å·ï¼Œè¯·é€šè¿‡ç”µå邮件è”系我们{email}。" +msgid "Need help logging in?" +msgstr "" #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx msgid "" @@ -2616,6 +2630,18 @@ msgstr "" msgid "Enter some details for your support request." msgstr "输入您所需è¦çš„支æŒçš„细节。" +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid "" +"Due to the recent increase in interest in online education and edX, we are " +"currently experiencing an unusually high volume of support requests. We " +"appreciate your patience as we work to review each request. Please check the" +" " +msgstr "" + +#: lms/djangoapps/support/static/support/jsx/single_support_form.jsx +msgid " as many questions may have already been answered." +msgstr "" + #: lms/djangoapps/support/static/support/jsx/single_support_form.jsx #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "Contact Us" @@ -2639,8 +2665,9 @@ msgstr "å‰å¾€{platform}主页" #: lms/djangoapps/support/static/support/jsx/success.jsx msgid "" -"Thank you for submitting a request! We will contact you within 24 hours." -msgstr "感谢您æ交的申请ï¼æˆ‘们会在24å°æ—¶å†…è”系您。" +"Thank you for submitting a request! We appreciate your patience while we " +"work to review your request." +msgstr "" #: lms/djangoapps/support/static/support/jsx/upload_progress.jsx msgid "Cancel upload" @@ -2819,6 +2846,10 @@ msgstr "" msgid "An error occurred. Try again." msgstr "å‘生错误。 å†è¯•ä¸€æ¬¡ã€‚" +#: lms/djangoapps/teams/static/teams/js/views/team_profile.js +msgid "No assignments for team" +msgstr "" + #: lms/djangoapps/teams/static/teams/js/views/team_profile.js msgid "Leave this team?" msgstr "离开这个团队?" @@ -3304,6 +3335,7 @@ msgid "There has been an error processing your survey." msgstr "在处ç†æ‚¨çš„调查时出现了一个错误。" #: lms/static/js/courseware/credit_progress.js +#: common/static/common/templates/discussion/templates.underscore #: lms/templates/discovery/facet.underscore #: lms/templates/edxnotes/note-item.underscore msgid "More" @@ -5336,6 +5368,10 @@ msgstr "是的,å…许编辑激活的è¯ä¹¦" msgid "certificate" msgstr "è¯ä¹¦" +#: cms/static/js/certificates/views/certificate_preview.js +msgid "Deactivating" +msgstr "" + #: cms/static/js/certificates/views/certificates_list.js msgid "Set up your certificate" msgstr "设置您的è¯ä¹¦" @@ -5347,8 +5383,8 @@ msgid "You have not created any certificates yet." msgstr "您尚未创建任何è¯ä¹¦ã€‚" #: cms/static/js/certificates/views/signatory_editor.js -msgid "Delete \"<%= signatoryName %>\" from the list of signatories?" -msgstr "确定è¦ä»Žç¾ç½²è€…列表ä¸åˆ 除 \"<%= signatoryName %>\" å—?" +msgid "Delete \"<%- signatoryName %>\" from the list of signatories?" +msgstr "" #: cms/static/js/certificates/views/signatory_editor.js #: cms/static/js/views/course_info_update.js @@ -5649,9 +5685,9 @@ msgstr "æ‰€æœ‰ç« èŠ‚éƒ½å¿…é¡»æ‹¥æœ‰å称和内容" #: cms/static/js/models/uploads.js msgid "" -"Only <%= fileTypes %> files can be uploaded. Please select a file ending in " -"<%= fileExtensions %> to upload." -msgstr "åªæœ‰ <%= fileTypes %> æ ¼å¼çš„文件å¯ä»¥ä¸Šä¼ 。请选择扩展å为 <%= fileExtensions %> çš„æ–‡ä»¶ä¸Šä¼ ã€‚" +"Only <%- fileTypes %> files can be uploaded. Please select a file ending in " +"<%- (fileExtensions) %> to upload." +msgstr "" #: cms/static/js/models/uploads.js #: lms/templates/student_account/hinted_login.underscore @@ -5829,8 +5865,8 @@ msgid "{selectedProvider} credentials saved" msgstr "{selectedProvider} è¯ä¹¦å·²ä¿å˜" #: cms/static/js/views/edit_chapter.js -msgid "Upload a new PDF to “<%= name %>â€" -msgstr "ä¸Šä¼ æ–°çš„PDF文件至“<%= name %>â€" +msgid "Upload a new PDF to “<%- name %>â€" +msgstr "" #: cms/static/js/views/edit_chapter.js msgid "Please select a PDF file to upload." @@ -6389,14 +6425,14 @@ msgstr "很抱æ‰ï¼Œæ¤å¤„出现错误" #: cms/static/js/views/utils/create_course_utils.js msgid "" "The combined length of the organization, course number, and course run " -"fields cannot be more than <%=limit%> characters." -msgstr "机构ã€è¯¾ç¨‹ç¼–å·å’Œå¼€è¯¾æ—¶é—´å—段åˆåœ¨ä¸€èµ·ä¸èƒ½è¶…过 <%=limit%> 个å—符。" +"fields cannot be more than <%- limit %> characters." +msgstr "" #: cms/static/js/views/utils/create_library_utils.js msgid "" "The combined length of the organization and library code fields cannot be " -"more than <%=limit%> characters." -msgstr "机构和知识库编å·å—段åˆåœ¨ä¸€èµ·ä¸èƒ½è¶…过 <%=limit%> 个å—符" +"more than <%- limit %> characters." +msgstr "" #: cms/static/js/views/utils/move_xblock_utils.js msgid "Success! \"{displayName}\" has been moved." @@ -6741,13 +6777,13 @@ msgid "Unscheduled" msgstr "尚未计划" #: cms/templates/js/course_info_update.underscore -#: lms/templates/commerce/receipt.underscore #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Date" msgstr "日期" #: cms/templates/js/paging-header.underscore #: common/static/common/templates/components/paging-footer.underscore +#: common/static/common/templates/discussion/templates.underscore msgid "Previous" msgstr "上一æ¥" @@ -6795,6 +6831,309 @@ msgstr "清空æœç´¢ç»“æžœ" msgid "Search" msgstr "æœç´¢" +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This thread is closed." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a response:" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "Submit" +msgstr "æ交" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "discussion posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "question posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pinned" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Reported" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Closed" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Related to: %(courseware_title_linked)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post is visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post is visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Add a clear and descriptive title to encourage participation. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Edit your post below." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "Show Comment (%(num_comments)s)" +msgid_plural "Show Comments (%(num_comments)s)" +msgstr[0] "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "marked as answer %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s by %(user)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "endorsed %(time_ago)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update response" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "posted %(time_ago)s by %(author)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Editing comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Update comment" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "answered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "unanswered question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Following" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Community TA" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "{unread_comments_count} new" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "" +"%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s " +"unread comments)%(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "%(comments_count)s %(span_sr_open)scomments %(span_close)s" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add a Post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Visible to" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Discussion admins, moderators, and TAs can make their posts visible to all " +"students or specify a single group." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "All Groups" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "follow this post" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "post anonymously to classmates" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Error posting your message." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#, python-format +msgid "This post will be visible only to %(group_name)s." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "This post will be visible to everyone." +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Topic area" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Add your post to a relevant topic to help others find it. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Community TA)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "(Staff)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore +msgid "All Posts" +msgstr "所有讨论帖" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Return to all posts" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "View discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Load more" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Post type" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "" +"Questions raise issues that need answers. Discussions share ideas and start " +"conversations. (Required)" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Question" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Discussion" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Endorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unendorse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Mark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unmark as Answer" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Follow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unfollow" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Vote for this post," +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report abuse" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Report" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unreport" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Pin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Unpin" +msgstr "" + +#: common/static/common/templates/discussion/templates.underscore +msgid "Open" +msgstr "" + #: lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore msgid "Discussion Home" msgstr "讨论区" @@ -6851,10 +7190,6 @@ msgid "" "new, unread activity from posts you are following." msgstr "勾选æ¤é¡¹ï¼Œæ¯å¤©æŽ¥æ”¶ä¸€å°é‚®ä»¶ï¼Œé€šçŸ¥æ‚¨æ‰€å…³æ³¨çš„讨论帖的最新未读情况。" -#: lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore -msgid "All Posts" -msgstr "所有讨论帖" - #: lms/djangoapps/support/static/support/templates/certificates.underscore msgid "username or email" msgstr "用户å/邮箱" @@ -7088,6 +7423,10 @@ msgstr "您是å¦åœ¨æ‰¾å›¢é˜ŸåŠ 入过程ä¸é‡åˆ°å›°éš¾ï¼Ÿ" msgid "Join Team" msgstr "åŠ å…¥å›¢é˜Ÿ" +#: lms/djangoapps/teams/static/teams/templates/team-profile.underscore +msgid "Team Assignments" +msgstr "" + #: lms/djangoapps/teams/static/teams/templates/team-profile.underscore msgid "Team Details" msgstr "团队详情" @@ -7172,94 +7511,6 @@ msgstr "åˆ é™¤èŠ‚ %(subsectionDisplayName)s" msgid "Remove unit %(unitName)s" msgstr "åˆ é™¤å•å…ƒ %(unitName)s" -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"You still need to visit the %(display_name)s website to complete the credit " -"process." -msgstr "您ä»ç„¶éœ€è¦è®¿é—® %(display_name)s 网站完æˆå¦åˆ†é¢†å–æµç¨‹ã€‚" - -#: lms/templates/commerce/provider.underscore -#, python-format -msgid "" -"To finalize course credit, %(display_name)s requires %(platform_name)s " -"learners to submit a credit request." -msgstr "è¦å®Œæˆè¯¾ç¨‹å¦åˆ†ï¼Œ%(display_name)s è¦æ±‚ %(platform_name)s å¦å‘˜æ交一份å¦åˆ†ç”³è¯·ã€‚" - -#: lms/templates/commerce/provider.underscore -msgid "Get Credit" -msgstr "获得å¦åˆ†" - -#: lms/templates/commerce/receipt.underscore -#, python-format -msgid "" -"Thank you %(full_name)s! We have received your payment for %(course_name)s." -msgstr "谢谢您,%(full_name)sï¼æˆ‘们已ç»æ”¶åˆ°äº†æ‚¨ä¸º%(course_name)s的付款。" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "" -"Please print this page for your records; it serves as your receipt. You will" -" also receive an email with the same information." -msgstr "请打å°æ¤é¡µç•™ä½œçºªå½•ï¼Œè¿™æ˜¯æ‚¨çš„收æ®ã€‚您也会收到一å°æœ‰ç›¸åŒä¿¡æ¯çš„电å邮件。" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Order No." -msgstr "订å•å·ï¼š" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Amount" -msgstr "金é¢" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Total" -msgstr "总计" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Please Note" -msgstr "请注æ„" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Crossed out items have been refunded." -msgstr "划掉的项目已退款。" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Billed to" -msgstr "è´¦å•å¯„ç»™" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "No receipt available" -msgstr "没有å¯æ供的收æ®ã€‚" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/financial-assistance/financial_assessment_submitted.underscore -msgid "Go to Dashboard" -msgstr "å‰å¾€è¯¾ç¨‹é¢æ¿" - -#: lms/templates/commerce/receipt.underscore -msgid "" -"If you don't verify your identity now, you can still explore your course " -"from your dashboard. You will receive periodic reminders from {platformName}" -" to verify your identity." -msgstr "如果您现在ä¸éªŒè¯èº«ä»½ï¼Œæ‚¨ä»å¯ä»¥é€šè¿‡è¯¾ç¨‹é¢æ¿æµè§ˆè¯¾ç¨‹ã€‚但您会定期从 {platformName} 收到身份验è¯æ醒。" - -#: lms/templates/commerce/receipt.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Want to confirm your identity later?" -msgstr "希望ç¨åŽå†éªŒè¯æ‚¨çš„身份?" - -#: lms/templates/commerce/receipt.underscore -msgid "Verify Now" -msgstr "现在认è¯" - #: lms/templates/courseware/proctored-exam-controls.underscore msgid "Mark Exam As Completed" msgstr "æ ‡è®°è€ƒè¯•å®Œæˆ" @@ -7388,8 +7639,8 @@ msgstr "关于您" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "" "The following information is already a part of your {platform} profile. " -"We\\'ve included it here for your application." -msgstr "以下信æ¯å·²ç»æ˜¯æ‚¨çš„ {platform} 简述的一部分。我们已将其列入您的申请ä¸ã€‚" +"We've included it here for your application." +msgstr "" #: lms/templates/financial-assistance/financial_assessment_form.underscore msgid "Email address" @@ -7417,6 +7668,10 @@ msgid "" "{course_name}! You can expect a response in 2-4 business days." msgstr "感谢您æ交 {course_name} çš„ç»æµŽæ´åŠ©ç”³è¯·ï¼æ‚¨å°†åœ¨ 2 至 4 个工作日内得到回å¤ã€‚" +#: lms/templates/financial-assistance/financial_assessment_submitted.underscore +msgid "Go to Dashboard" +msgstr "å‰å¾€è¯¾ç¨‹é¢æ¿" + #: lms/templates/instructor/instructor_dashboard_2/certificate-bulk-white-list.underscore msgid "Bulk Exceptions" msgstr "批é‡ç‰¹æ®Šå¤„ç†" @@ -7754,14 +8009,6 @@ msgstr "æ‚¨å·²æ— æ³•æ›´æ”¹å¦æœŸã€‚" msgid "You can change sessions until {expiration_date}." msgstr "您å¯åœ¨{expiration_date}å‰æ›´æ”¹å¦æœŸã€‚" -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "Final Grade" -msgstr "最终æˆç»©" - -#: lms/templates/learner_dashboard/course_enroll.underscore -msgid "for {courseName}" -msgstr "为{courseName}课程" - #: lms/templates/learner_dashboard/course_enroll.underscore msgid "View Archived Course" msgstr "查看å˜æ¡£çš„课程" @@ -7977,8 +8224,28 @@ msgid "An error occurred. Please reload the page." msgstr "å‘生了一个错误,请é‡æ–°åŠ 载页é¢ã€‚" #: lms/templates/student_account/form_field.underscore -msgid "Need help logging in?" -msgstr "登录时需è¦å¸®åŠ©ï¼Ÿ" +msgid "Need help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Forgot my password" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Other sign-in issues" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Sign in with your company or school" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Need other help signing in?" +msgstr "" + +#: lms/templates/student_account/form_field.underscore +msgid "Create an account" +msgstr "" #: lms/templates/student_account/hinted_login.underscore #: lms/templates/student_account/login.underscore @@ -8176,17 +8443,13 @@ msgid "What You Need for Verification" msgstr "认è¯æ‰€éœ€" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/intro_step.underscore -#: lms/templates/verify_student/make_payment_step.underscore -#: lms/templates/verify_student/make_payment_step_ab_testing.underscore -#: lms/templates/verify_student/payment_confirmation_step.underscore -msgid "Webcam" -msgstr "æ‘„åƒå¤´" +msgid "Device with Camera" +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"You need a computer or cell phone that has a webcam. When you receive a " -"browser prompt, make sure that you allow access to the camera." +"You need a device that has a webcam. If you receive a browser prompt for " +"access to your camera, please make sure to click 'Allow'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8194,10 +8457,8 @@ msgid "Photo Identification" msgstr "照片识别" #: lms/templates/verify_student/face_photo_step.underscore -msgid "" -"You need a driver's license, passport, or other government-issued ID that " -"has your name and photo." -msgstr "您需è¦é©¾ç…§ã€æŠ¤ç…§æˆ–者其他由政府ç¾å‘的带有您姓å和照片的身份è¯ä»¶ã€‚" +msgid "You need a valid ID that contains your full name and photo." +msgstr "" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8222,14 +8483,10 @@ msgstr "您的é¢éƒ¨å…‰ç…§å¾ˆå¥½ã€‚" msgid "Your entire face fits inside the frame." msgstr "æ‚¨çš„æ•´å¼ è„¸éƒ½åœ¨æ¡†å†…ã€‚" -#: lms/templates/verify_student/face_photo_step.underscore -msgid "The photo of your face matches the photo on your ID." -msgstr "您的é¢éƒ¨ç…§ç‰‡ä¸Žæ‚¨èº«ä»½è¯ä»¶ä¸Šçš„照片相符。" - #: lms/templates/verify_student/face_photo_step.underscore msgid "" -"To use the current photo, select the Take Photo button {icon}. To take " -"another photo, select the Retake Photo button {icon}." +"To take the photo of your face, click on the camera button {icon}. If you " +"need to try again, click 'Retake Photo'." msgstr "" #: lms/templates/verify_student/face_photo_step.underscore @@ -8246,14 +8503,10 @@ msgid "Why does %(platformName)s need my photo?" msgstr "为什么%(platformName)s需è¦æˆ‘的照片?" #: lms/templates/verify_student/face_photo_step.underscore -#: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore msgid "" -"As part of the verification process, you take a photo of both your face and " -"a government-issued photo ID. Our authorization service confirms your " -"identity by comparing the photo you take with the photo on your ID." +"We use your verification photos to confirm your identity and ensure the " +"validity of your certificate." msgstr "" -"作为认è¯è¿‡ç¨‹ä¸ä¸€éƒ¨åˆ†ï¼Œæ‚¨éœ€è¦æ‹æ‘„ä¸¤å¼ ç…§ç‰‡ï¼šæ‚¨çš„é¢éƒ¨ä»¥åŠæ‚¨çš„身份è¯ä»¶ï¼ˆè¯¥è¯ä»¶é¡»ç”±æ”¿åºœç¾å‘且有您的照片)。我们的授æƒæœåŠ¡éƒ¨å°†é€šè¿‡å¯¹æ¯”您的é¢éƒ¨ç…§ç‰‡å’Œæ‚¨çš„è¯ä»¶ä¸Šçš„照片æ¥ç¡®è®¤æ‚¨çš„身份。" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8264,15 +8517,12 @@ msgstr "%(platformName)sç”¨è¿™å¼ ç…§ç‰‡åšä»€ä¹ˆï¼Ÿ" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore -#: lms/templates/verify_student/incourse_reverify.underscore #, python-format msgid "" -"We use the highest levels of security available to encrypt your photo and " -"send it to our authorization service for review. Your photo and information " -"are not saved or visible anywhere on %(platformName)s after the verification" -" process is complete." +"We securely encrypt your photo and send it to our authorization service for " +"review. Your photo and information are not saved or visible anywhere on " +"%(platformName)s after the verification process is complete." msgstr "" -"我们会采用最高级别的安全技术æ¥åŠ 密您的照片并å‘é€åˆ°æˆ‘们的授æƒæœåŠ¡ç”¨äºŽå®¡æ ¸ç›®çš„;一旦完æˆäº†è®¤è¯è¿‡ç¨‹ï¼Œ%(platformName)sä¸ä¼šç»§ç»ä¿å˜è¿™äº›ç…§ç‰‡å’Œä¿¡æ¯ã€‚" #: lms/templates/verify_student/face_photo_step.underscore #: lms/templates/verify_student/id_photo_step.underscore @@ -8331,16 +8581,14 @@ msgid "Take a Photo of Your ID" msgstr "æ‹æ‘„您的身份è¯ä»¶" #: lms/templates/verify_student/id_photo_step.underscore -msgid "" -"Use your webcam to take a photo of your ID. We will match this photo with " -"the photo of your face and the name on your account." -msgstr "请用摄åƒå¤´æ‹æ‘„ä¸€å¼ æ‚¨èº«ä»½è¯ä»¶çš„照片,我们将查看该照片是å¦ä¸Žæ‚¨çš„é¢éƒ¨ç…§ç‰‡åŠæ‚¨åœ¨è´¦å·ä¸å¡«å†™çš„姓å匹é…。" +msgid "Use your webcam to take a photo of your ID." +msgstr "" #: lms/templates/verify_student/id_photo_step.underscore msgid "" -"You need an ID with your name and photo. A driver's license, passport, or " -"other government-issued IDs are all acceptable." -msgstr "您需è¦ä¸€ä»½å¸¦æœ‰æ‚¨å§“å和照片的身份è¯ä»¶ï¼Œæˆ‘们å¯ä»¥æŽ¥å—驾照ã€æŠ¤ç…§ä»¥åŠå…¶ä»–由政府ç¾å‘的身份è¯ä»¶ã€‚" +"You need an ID with your name and photo. A driver's license, passport, or ID" +" are all acceptable." +msgstr "" #: lms/templates/verify_student/id_photo_step.underscore #: lms/templates/verify_student/incourse_reverify.underscore @@ -8364,6 +8612,13 @@ msgstr "" msgid "Use the Retake Photo button if you are not pleased with your photo" msgstr "" +#: lms/templates/verify_student/id_photo_step.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a photo ID. Our authorization service confirms your identity by comparing " +"the photo you take with the photo on your ID." +msgstr "" + #: lms/templates/verify_student/id_photo_step.underscore msgid "" "You may be able to complete the image capture procedure without assistance, " @@ -8410,6 +8665,24 @@ msgstr "" msgid "Can we match the photo you took with the one on your ID?" msgstr "我们能å¦å°†æ‚¨æ‹çš„照片与您身份è¯ä»¶ä¸Šçš„照片进行比对?" +#: lms/templates/verify_student/incourse_reverify.underscore +msgid "" +"As part of the verification process, you take a photo of both your face and " +"a government-issued photo ID. Our authorization service confirms your " +"identity by comparing the photo you take with the photo on your ID." +msgstr "" +"作为认è¯è¿‡ç¨‹ä¸ä¸€éƒ¨åˆ†ï¼Œæ‚¨éœ€è¦æ‹æ‘„ä¸¤å¼ ç…§ç‰‡ï¼šæ‚¨çš„é¢éƒ¨ä»¥åŠæ‚¨çš„身份è¯ä»¶ï¼ˆè¯¥è¯ä»¶é¡»ç”±æ”¿åºœç¾å‘且有您的照片)。我们的授æƒæœåŠ¡éƒ¨å°†é€šè¿‡å¯¹æ¯”您的é¢éƒ¨ç…§ç‰‡å’Œæ‚¨çš„è¯ä»¶ä¸Šçš„照片æ¥ç¡®è®¤æ‚¨çš„身份。" + +#: lms/templates/verify_student/incourse_reverify.underscore +#, python-format +msgid "" +"We use the highest levels of security available to encrypt your photo and " +"send it to our authorization service for review. Your photo and information " +"are not saved or visible anywhere on %(platformName)s after the verification" +" process is complete." +msgstr "" +"我们会采用最高级别的安全技术æ¥åŠ 密您的照片并å‘é€åˆ°æˆ‘们的授æƒæœåŠ¡ç”¨äºŽå®¡æ ¸ç›®çš„;一旦完æˆäº†è®¤è¯è¿‡ç¨‹ï¼Œ%(platformName)sä¸ä¼šç»§ç»ä¿å˜è¿™äº›ç…§ç‰‡å’Œä¿¡æ¯ã€‚" + #: lms/templates/verify_student/intro_step.underscore msgid "Thanks for returning to verify your ID in: {courseName}" msgstr "感谢您返回认è¯æ‚¨åœ¨ {courseName} ä¸çš„ ID" @@ -8438,6 +8711,13 @@ msgid "" "and photo" msgstr "驾照ã€æŠ¤ç…§æˆ–者其他由政府ç¾å‘的带有您姓å和照片的身份è¯ä»¶" +#: lms/templates/verify_student/intro_step.underscore +#: lms/templates/verify_student/make_payment_step.underscore +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Webcam" +msgstr "æ‘„åƒå¤´" + #: lms/templates/verify_student/make_payment_step.underscore #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "You are enrolling in: {courseName}" @@ -8525,6 +8805,11 @@ msgstr "在您å‡çº§è‡³è¯ä¹¦è·¯å¾„之å‰ï¼Œæ‚¨å¿…须激活您的账å·ã€‚" msgid "Check your email for an activation message." msgstr "检查您的电å邮箱是å¦æ”¶åˆ°æ¿€æ´»æ¶ˆæ¯ã€‚" +#: lms/templates/verify_student/make_payment_step_ab_testing.underscore +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Total" +msgstr "总计" + #: lms/templates/verify_student/make_payment_step_ab_testing.underscore msgid "Professional Certificate for {courseName}" msgstr "{courseName} 的专业è¯ä¹¦" @@ -8562,6 +8847,36 @@ msgstr "您将使用您的网络摄åƒå¤´æ‹æ‘„ä¸€å¼ åŒæ—¶æ˜¾ç¤ºæ‚¨çš„脸部和 msgid "Thank you! We have received your payment for {courseName}." msgstr "谢谢ï¼æˆ‘们已ç»æ”¶åˆ°æ‚¨çš„ {courseName} 付款。" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "" +"Please print this page for your records; it serves as your receipt. You will" +" also receive an email with the same information." +msgstr "请打å°æ¤é¡µç•™ä½œçºªå½•ï¼Œè¿™æ˜¯æ‚¨çš„收æ®ã€‚您也会收到一å°æœ‰ç›¸åŒä¿¡æ¯çš„电å邮件。" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Order No." +msgstr "订å•å·ï¼š" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Amount" +msgstr "金é¢" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Please Note" +msgstr "请注æ„" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Crossed out items have been refunded." +msgstr "划掉的项目已退款。" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Billed to" +msgstr "è´¦å•å¯„ç»™" + +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "No receipt available" +msgstr "没有å¯æ供的收æ®ã€‚" + #: lms/templates/verify_student/payment_confirmation_step.underscore msgid "Next Step: Confirm your identity" msgstr "下一æ¥ï¼šç¡®è®¤æ‚¨çš„身份" @@ -8590,6 +8905,10 @@ msgid "" "%(platformName)s to verify your identity." msgstr "如果您现在ä¸éªŒè¯æ‚¨çš„身份,您ä»å¯ä»¥é€šè¿‡æŽ§åˆ¶é¢æ¿æµè§ˆè¯¾ç¨‹ã€‚但您会定期从%(platformName)s收到身份验è¯æ醒。" +#: lms/templates/verify_student/payment_confirmation_step.underscore +msgid "Want to confirm your identity later?" +msgstr "希望ç¨åŽå†éªŒè¯æ‚¨çš„身份?" + #: lms/templates/verify_student/reverify_success_step.underscore msgid "Identity Verification In Progress" msgstr "身份验è¯æ£åœ¨è¿›è¡Œä¸" @@ -8598,11 +8917,9 @@ msgstr "身份验è¯æ£åœ¨è¿›è¡Œä¸" msgid "" "We have received your information and are verifying your identity. You will " "see a message on your dashboard when the verification process is complete " -"(usually within 1-2 days). In the meantime, you can still access all " +"(usually within 5-7 days). In the meantime, you can still access all " "available course content." msgstr "" -"我们已ç»æ”¶åˆ°æ‚¨çš„ä¿¡æ¯å¹¶æ£åœ¨éªŒè¯æ‚¨çš„身份。验è¯æµç¨‹ç»“æŸåŽ(一般在 1-2 " -"天内),您将在您的控制é¢æ¿ä¸Šæ”¶åˆ°ä¸€æ¡æ¶ˆæ¯ã€‚与æ¤åŒæ—¶ï¼Œæ‚¨ä»ç„¶å¯ä»¥è®¿é—®æ‰€æœ‰çš„课程内容。" #: lms/templates/verify_student/reverify_success_step.underscore msgid "Return to Your Dashboard" @@ -8636,10 +8953,6 @@ msgstr "照片è¦æ±‚:" msgid "Does the photo of you show your whole face?" msgstr "è¿™å¼ ç…§ç‰‡ä¸æœ‰æ‚¨çš„æ•´å¼ è„¸å—?" -#: lms/templates/verify_student/review_photos_step.underscore -msgid "Does the photo of you match your ID photo?" -msgstr "è¿™å¼ ç…§ç‰‡å’Œæ‚¨èº«ä»½è¯ä»¶ä¸Šçš„照片相匹é…å—?" - #: lms/templates/verify_student/review_photos_step.underscore msgid "Is your name on your ID readable?" msgstr "您身份è¯ä»¶ä¸Šçš„åå—是å¦æ¸…æ™°å¯è§ï¼Ÿ" @@ -10051,6 +10364,21 @@ msgstr "设置为特殊测验" msgid "Exam Types" msgstr "测试类别" +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This subsection was released to learners as a special exam, but was reverted" +" back to a basic exam. You may not configure it as a special exam now. " +"Contact edX Support for assistance." +msgstr "" + +#: cms/templates/js/timed-examination-preference-editor.underscore +msgid "" +"This special exam has been released to learners. You may not convert it to " +"another type of special exam. You may revert this subsection back to being a" +" basic exam by selecting 'None', but you will NOT be able to configure it as" +" a special exam in the future." +msgstr "" + #: cms/templates/js/timed-examination-preference-editor.underscore msgid "Timed" msgstr "计时" @@ -10221,14 +10549,14 @@ msgstr "" msgid "Read more" msgstr "了解更多" -#: cms/templates/js/video-transcripts.underscore -msgid "Show transcripts ({totalTranscripts})" -msgstr "显示å—幕 ({totalTranscripts})" - #: cms/templates/js/video-transcripts.underscore msgid "No transcript uploaded." msgstr "æœªä¸Šä¼ å—幕。" +#: cms/templates/js/video-transcripts.underscore +msgid "Show transcripts ({totalTranscripts})" +msgstr "显示å—幕 ({totalTranscripts})" + #: cms/templates/js/xblock-access-editor.underscore msgid "Set Access" msgstr "设置é™åˆ¶" diff --git a/conf/locale/zh_TW/LC_MESSAGES/django.mo b/conf/locale/zh_TW/LC_MESSAGES/django.mo index 5538107887437ef2c04121749596d9d5d387dda6..fcc64242e12fd60e756df95107beb26955358351 100644 Binary files a/conf/locale/zh_TW/LC_MESSAGES/django.mo and b/conf/locale/zh_TW/LC_MESSAGES/django.mo differ diff --git a/conf/locale/zh_TW/LC_MESSAGES/django.po b/conf/locale/zh_TW/LC_MESSAGES/django.po index fe940d12a1f9029333f426dc134ae64782fec76a..326a65baa86c035ebaad08f14a832c7c35e49533 100644 --- a/conf/locale/zh_TW/LC_MESSAGES/django.po +++ b/conf/locale/zh_TW/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ # Translators: # ahan <ahan.net@gmail.com>, 2014 # ahan <ahan.net@gmail.com>, 2014 -# bhsfmiao <inactive+bhsfmiao@transifex.com>, 2014 +# 8cdb4758e2f8f89e1b6f455d24a57c7b_26aedc9 <d42fecad8431def0e25dc12221e713ed_169300>, 2014 # CHI, KUAN-MING <sappy5678@gmail.com>, 2015 # 陳åç¦ <christtabris@gmail.com>, 2014 # LIU,SHU-HAO <jeremy55662004@gmail.com>, 2014 @@ -19,7 +19,7 @@ # Lin Yu-Chun <iftwoplustwoequalsfive@gmail.com>, 2013-2015 # LIU,SHU-HAO <jeremy55662004@gmail.com>, 2014 # LIU,SHU-HAO <jeremy55662004@gmail.com>, 2014-2015 -# bhsfmiao <inactive+bhsfmiao@transifex.com>, 2014 +# 8cdb4758e2f8f89e1b6f455d24a57c7b_26aedc9 <d42fecad8431def0e25dc12221e713ed_169300>, 2014 # MOH CHIN LAM <chinlam91@gmail.com>, 2015 # å€å£¬è±ª <oldmon@livemail.tw>, 2014 # Lin Yu-Chun <iftwoplustwoequalsfive@gmail.com>, 2013-2014 @@ -79,7 +79,7 @@ # ahan <ahan.net@gmail.com>, 2014 # ahan <ahan.net@gmail.com>, 2014 # Andrew Lau <alau52@yahoo.com>, 2017 -# bhsfmiao <inactive+bhsfmiao@transifex.com>, 2014 +# 8cdb4758e2f8f89e1b6f455d24a57c7b_26aedc9 <d42fecad8431def0e25dc12221e713ed_169300>, 2014 # LIU,SHU-HAO <jeremy55662004@gmail.com>, 2014 # HSU-CHENG CHIANG <tosti.chiang@gmail.com>, 2013 # Joey Chiou <Joeyc0916@gmail.com>, 2013-2014 @@ -92,7 +92,7 @@ # lin feather <further.33.44@gmail.com>, 2016 # Lin Yu-Chun <iftwoplustwoequalsfive@gmail.com>, 2013-2014 # LIU,SHU-HAO <jeremy55662004@gmail.com>, 2014 -# bhsfmiao <inactive+bhsfmiao@transifex.com>, 2014 +# 8cdb4758e2f8f89e1b6f455d24a57c7b_26aedc9 <d42fecad8431def0e25dc12221e713ed_169300>, 2014 # MOH CHIN LAM <chinlam91@gmail.com>, 2014-2015 # å€å£¬è±ª <oldmon@livemail.tw>, 2014 # Lin Yu-Chun <iftwoplustwoequalsfive@gmail.com>, 2013-2014 @@ -118,7 +118,7 @@ # This file is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE. # # Translators: -# bhsfmiao <inactive+bhsfmiao@transifex.com>, 2014 +# 8cdb4758e2f8f89e1b6f455d24a57c7b_26aedc9 <d42fecad8431def0e25dc12221e713ed_169300>, 2014 # LIU,SHU-HAO <jeremy55662004@gmail.com>, 2014 # HSU-CHENG CHIANG <tosti.chiang@gmail.com>, 2013 # JEN-HAO HSIEH <orienthauz@gmail.com>, 2015 @@ -130,7 +130,7 @@ # lin31504 <lin31504@gmail.com>, 2014 # Lin Yu-Chun <iftwoplustwoequalsfive@gmail.com>, 2014 # LIU,SHU-HAO <jeremy55662004@gmail.com>, 2014-2015 -# bhsfmiao <inactive+bhsfmiao@transifex.com>, 2014 +# 8cdb4758e2f8f89e1b6f455d24a57c7b_26aedc9 <d42fecad8431def0e25dc12221e713ed_169300>, 2014 # MOH CHIN LAM <chinlam91@gmail.com>, 2014-2015 # myles <i@myles.hk>, 2016 # Lin Yu-Chun <iftwoplustwoequalsfive@gmail.com>, 2013-2014 @@ -177,7 +177,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2020-04-12 20:42+0000\n" +"POT-Creation-Date: 2020-06-21 20:42+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed <waheed@edx.org>, 2019\n" "Language-Team: Chinese (Taiwan) (https://www.transifex.com/open-edx/teams/6205/zh_TW/)\n" @@ -186,7 +186,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"Generated-By: Babel 1.3\n" +"Generated-By: Babel 2.8.0\n" #. Translators: 'Discussion' refers to the tab in the courseware that leads to #. the discussion forums @@ -208,8 +208,8 @@ msgstr "è³‡æ ¼è€ƒè©¦" #: cms/djangoapps/contentstore/views/helpers.py #: common/lib/xmodule/xmodule/unit_block.py -#: lms/djangoapps/instructor/views/tools.py lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: lms/djangoapps/instructor/views/tools.py lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Unit" msgstr "單元" @@ -516,13 +516,13 @@ msgstr "" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Public Username '{username}' already exists." -msgstr "使用者帳號 '{username}' å·²å˜åœ¨ã€‚" +msgid "An account with the Email '{email}' already exists." +msgstr "é›»å郵件 '{email}' å°æ‡‰çš„帳戶已å˜åœ¨ã€‚" #: common/djangoapps/student/helpers.py #, python-brace-format -msgid "An account with the Email '{email}' already exists." -msgstr "é›»å郵件 '{email}' å°æ‡‰çš„帳戶已å˜åœ¨ã€‚" +msgid "An account with the Public Username '{username}' already exists." +msgstr "使用者帳號 '{username}' å·²å˜åœ¨ã€‚" #: common/djangoapps/student/management/commands/manage_group.py msgid "Removed group: \"{}\"" @@ -2283,9 +2283,9 @@ msgstr "" #: common/lib/xmodule/xmodule/capa_base.py #: lms/templates/admin/user_api/accounts/cancel_retirement_action.html #: cms/templates/index.html cms/templates/videos_index_pagination.html -#: lms/templates/manage_user_standing.html #: lms/templates/dashboard/_entitlement_reason_survey.html #: lms/templates/dashboard/_reason_survey.html +#: lms/templates/manage_user_standing.html #: lms/templates/peer_grading/peer_grading_problem.html #: lms/templates/survey/survey.html #: lms/templates/widgets/footer-language-selector.html @@ -3951,12 +3951,12 @@ msgid "" " considered in the Entrance Exam scoring/gating algorithm." msgstr "輸入 true 或者 false。如果是 true,æ交的å•é¡Œæ¨¡çµ„å°‡æœƒè¢«åˆ—å…¥è³‡æ ¼å¸è€ƒè©¦çš„演算法ä¸ã€‚" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py #: cms/templates/group_configurations.html msgid "Enrollment Track Groups" msgstr "" -#: common/lib/xmodule/xmodule/partitions/partitions_service.py +#: common/lib/xmodule/xmodule/partitions/enrollment_track_partition_generator.py msgid "Partition for segmenting users by enrollment track" msgstr "" @@ -4550,17 +4550,17 @@ msgstr "" #. interface (a menu or piece of UI that takes the full focus of the screen) #: common/templates/admin/student/loginfailures/change_form_template.html #: lms/templates/wiki/edit.html lms/templates/wiki/history.html -#: lms/templates/wiki/includes/cheatsheet.html lms/templates/dashboard.html -#: lms/templates/forgot_password_modal.html lms/templates/signup_modal.html -#: lms/templates/ccx/schedule.html +#: lms/templates/wiki/includes/cheatsheet.html lms/templates/ccx/schedule.html +#: lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html +#: lms/templates/forgot_password_modal.html #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html #: lms/templates/instructor/instructor_dashboard_2/generate_registarion_codes_modal.html #: lms/templates/instructor/instructor_dashboard_2/invalidate_registration_code_modal.html #: lms/templates/instructor/instructor_dashboard_2/set_course_mode_price_modal.html #: lms/templates/modal/_modal-settings-language.html -#: themes/edx.org/lms/templates/dashboard.html +#: lms/templates/signup_modal.html themes/edx.org/lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html msgid "Close" msgstr "關閉" @@ -5445,50 +5445,6 @@ msgid "" "this request, please visit the link(s) below." msgstr "{username} ({email}) 的退款è¦æ±‚已經建立。為了處ç†æ¤è«‹æ±‚,請訪å•ä»¥ä¸‹è¯çµ(s) 。" -#: lms/djangoapps/commerce/views.py -msgid "Receipt" -msgstr "收據" - -#: lms/djangoapps/commerce/views.py -msgid "Payment Failed" -msgstr "付款失敗" - -#: lms/djangoapps/commerce/views.py -msgid "There was a problem with this transaction. You have not been charged." -msgstr "本次交易出ç¾å•é¡Œã€‚您還未被扣款。" - -#: lms/djangoapps/commerce/views.py -msgid "" -"Make sure your information is correct, or try again with a different card or" -" another form of payment." -msgstr "請確èªæ‚¨çš„資訊無誤,或使用其他å¡ç‰‡æˆ–付款方å¼å†è©¦ä¸€æ¬¡ã€‚" - -#: lms/djangoapps/commerce/views.py -msgid "" -"A system error occurred while processing your payment. You have not been " -"charged." -msgstr "在處ç†æ‚¨çš„ä»˜æ¬¾äº‹é …æ™‚å‡ºç¾äº†ä¸€å€‹ç³»çµ±éŒ¯èª¤ã€‚您還未被扣款。" - -#: lms/djangoapps/commerce/views.py -msgid "Please wait a few minutes and then try again." -msgstr "請在ç‰å¾…幾分é˜å¾Œï¼Œå†å˜—試一次。" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "For help, contact {payment_support_link}." -msgstr "如需å”助,請è¯ç¹« {payment_support_link}。" - -#: lms/djangoapps/commerce/views.py -msgid "An error occurred while creating your receipt." -msgstr "在產生您的收據時出ç¾äº†å•é¡Œã€‚" - -#: lms/djangoapps/commerce/views.py -#, python-brace-format -msgid "" -"If your course does not appear on your dashboard, contact " -"{payment_support_link}." -msgstr "如果您的課程並未出ç¾åœ¨èª²ç¨‹é¢æ¿ä¸Šï¼Œè«‹è¯ç¹« {payment_support_link}。" - #: lms/djangoapps/course_goals/models.py msgid "Earn a certificate" msgstr "" @@ -5550,11 +5506,23 @@ msgstr "您沒有進入這門課程的權é™ã€‚" msgid "You do not have access to this course on a mobile device" msgstr "您沒有在行動è£ç½®ä¸Šé€²å…¥é€™é–€èª²ç¨‹çš„權é™ã€‚" +#: lms/djangoapps/courseware/access_response.py +msgid "You must be enrolled in the course" +msgstr "" + +#: lms/djangoapps/courseware/access_response.py +msgid "You must be logged in to see this course" +msgstr "" + #: lms/djangoapps/courseware/course_tools.py #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Upgrade to Verified" msgstr "" +#: lms/djangoapps/courseware/course_tools.py +msgid "Financial Assistance" +msgstr "" + #: lms/djangoapps/courseware/courses.py msgid "Assignment" msgstr "" @@ -5574,6 +5542,11 @@ msgstr "{relative} å¹´ - {absolute}" msgid "in {relative} - {absolute}" msgstr "in {relative} - {absolute}" +#: lms/djangoapps/courseware/date_summary.py +#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py +msgid "Enrollment Date" +msgstr "註冊日期" + #: lms/djangoapps/courseware/date_summary.py msgid "Course Starts" msgstr "課程開始" @@ -6184,9 +6157,8 @@ msgid "Good" msgstr "好" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html -#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt #, python-format -msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgid "%(comment_username)s replied to" msgstr "" #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html @@ -6194,6 +6166,11 @@ msgstr "" msgid "View discussion" msgstr "" +#: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.txt +#, python-format +msgid "%(comment_username)s replied to <b>%(thread_title)s</b>:" +msgstr "" + #: lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/subject.txt #, python-format msgid "Response to %(thread_title)s" @@ -6321,8 +6298,8 @@ msgid "Student" msgstr "å¸ç”Ÿ" #: lms/djangoapps/instructor/paidcourse_enrollment_report.py -#: lms/templates/preview_menu.html #: lms/templates/instructor/instructor_dashboard_2/membership.html +#: lms/templates/preview_menu.html msgid "Staff" msgstr "工作人員" @@ -6440,29 +6417,6 @@ msgstr "" msgid "Could not find problem with this location." msgstr "無法於æ¤ä½ç½®æ‰¾åˆ°å•é¡Œã€‚" -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number '{num}' does not exist." -msgstr "發票號碼 '{num}' 並ä¸å˜åœ¨ã€‚" - -#: lms/djangoapps/instructor/views/api.py -msgid "The sale associated with this invoice has already been invalidated." -msgstr "與æ¤ç›¸é—œè¯çš„發票出售已經失效。" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "Invoice number {0} has been invalidated." -msgstr "發票號碼 {0}已經無失效。" - -#: lms/djangoapps/instructor/views/api.py -msgid "This invoice is already active." -msgstr "æ¤ç™¼ç¥¨å·²ç¶“被啟用。" - -#: lms/djangoapps/instructor/views/api.py -#, python-brace-format -msgid "The registration codes for invoice {0} have been re-activated." -msgstr "發票{0}的註冊代碼已被é‡æ–°å•Ÿå‹•ã€‚" - #: lms/djangoapps/instructor/views/api.py msgid "CourseID" msgstr "課程 ID" @@ -6493,9 +6447,8 @@ msgstr "使用者編號" #: lms/djangoapps/instructor/views/tools.py #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py #: openedx/core/djangoapps/schedules/admin.py -#: lms/templates/staff_problem_info.html #: lms/templates/api_admin/catalogs/search.html -#: lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/staff_problem_info.html msgid "Username" msgstr "使用者帳號" @@ -6615,52 +6568,6 @@ msgstr "æ¤æª”æ¡ˆå¿…é ˆ'cohort'的行並包å«åŒä¼´å稱。" msgid "The file must contain a 'username' column, an 'email' column, or both." msgstr "æ¤æª”æ¡ˆå¿…é ˆ'cohort'的行,'email' 的行,或者兩者。" -#: lms/djangoapps/instructor/views/api.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html -msgid "Coupon Code" -msgstr "å„ªæƒ åˆ¸ä»£ç¢¼" - -#: lms/djangoapps/instructor/views/api.py -#: openedx/core/djangoapps/schedules/admin.py -msgid "Course Id" -msgstr "課程 ID" - -#: lms/djangoapps/instructor/views/api.py -msgid "% Discount" -msgstr "%折扣" - -#: lms/djangoapps/instructor/views/api.py -#: lms/djangoapps/shoppingcart/reports.py -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: wiki/plugins/attachments/forms.py -#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html -msgid "Description" -msgstr "敘述" - -#: lms/djangoapps/instructor/views/api.py -msgid "Expiration Date" -msgstr "逾期時間" - -#: lms/djangoapps/instructor/views/api.py -msgid "Is Active" -msgstr "啟用" - -#: lms/djangoapps/instructor/views/api.py -msgid "Code Redeemed Count" -msgstr "推廣折扣é¡ä»£ç¢¼" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Seats" -msgstr "總折扣åé¡" - -#: lms/djangoapps/instructor/views/api.py -msgid "Total Discounted Amount" -msgstr "總折扣金é¡" - #: lms/djangoapps/instructor/views/api.py #: lms/djangoapps/instructor_task/api_helper.py msgid "detailed enrollment" @@ -6681,14 +6588,6 @@ msgstr "" msgid "proctored exam results" msgstr "" -#: lms/djangoapps/instructor/views/api.py -msgid "Could not parse amount as a decimal" -msgstr "無法解æžç¸½æ•¸ç‚ºå進制" - -#: lms/djangoapps/instructor/views/api.py -msgid "Unable to generate redeem codes because of course misconfiguration." -msgstr "å› ç‚ºèª²ç¨‹è¨å®šéŒ¯èª¤ä¸èƒ½ç”¢ç”Ÿå…Œæ›ç¢¼ã€‚" - #: lms/djangoapps/instructor/views/api.py #, python-brace-format msgid "Enrollment status for {student}: unknown" @@ -6902,63 +6801,6 @@ msgid "" msgstr "" "å¸ç”Ÿ {student} 沒有æ¤é–€èª²ç¨‹ {course}之修課è‰æ˜Žã€‚è«‹é©—è‰å¸ç”Ÿä½¿ç”¨è€…帳號/email以åŠç¢ºèªæ‰€é¸ä¹‹èª²ç¨‹æ˜¯å¦æ£ç¢ºï¼Œç„¶å¾Œå†è©¦ä¸€æ¬¡ã€‚" -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id is None" -msgstr "ç„¡æ¤å„ªæƒ 券è˜åˆ¥ç¢¼" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) DoesNotExist" -msgstr "æ¤å„ªæƒ 券的è˜åˆ¥ç¢¼({coupon_id})並ä¸å˜åœ¨" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) is already inactive" -msgstr "æ¤å„ªæƒ 券的è˜åˆ¥ç¢¼({coupon_id})已經 inactive" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated successfully" -msgstr "æ¤å„ªæƒ 券的è˜åˆ¥ç¢¼({coupon_id})已更新æˆåŠŸ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "" -"The code ({code}) that you have tried to define is already in use as a " -"registration code" -msgstr "您試著定義的代碼({code})已經使用在註冊代碼上" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Integer Value for Coupon Discount" -msgstr "è«‹è¼¸å…¥æ•´æ•¸çš„å„ªæƒ åˆ¸æŠ˜æ‰£å€¼" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please Enter the Coupon Discount Value Less than or Equal to 100" -msgstr "請輸入ä¸å¤§æ–¼100çš„å„ªæƒ åˆ¸æŠ˜æ‰£å€¼" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "Please enter the date in this format i-e month/day/year" -msgstr "è«‹ä¾ç…§æ¤æ ¼å¼æœˆï¼æ—¥ï¼å¹´è¼¸å…¥æ—¥æœŸ" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) added successfully" -msgstr "æ¤å„ªæƒ 券之åºè™Ÿ({code})å¢žåŠ æˆåŠŸã€‚" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon code ({code}) already exists for this course" -msgstr "æ¤èª²ç¨‹å„ªæƒ 券之åºè™Ÿ({code})已經å˜åœ¨" - -#: lms/djangoapps/instructor/views/coupons.py -msgid "coupon id not found" -msgstr "ç„¡æ¤å„ªæƒ 券è˜åˆ¥ç¢¼" - -#: lms/djangoapps/instructor/views/coupons.py -#, python-brace-format -msgid "coupon with the coupon id ({coupon_id}) updated Successfully" -msgstr "æ¤å„ªæƒ 券的è˜åˆ¥ç¢¼({coupon_id}) 已更新æˆåŠŸ" - #: lms/djangoapps/instructor/views/instructor_dashboard.py msgid "Instructor" msgstr "教師功能é¢æ¿" @@ -7067,29 +6909,6 @@ msgstr "完æˆ" msgid "Incomplete" msgstr "未完æˆ" -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "" -"The enrollment code ({code}) was not found for the {course_name} course." -msgstr "找ä¸åˆ°èª²ç¨‹ {course_name} 之註冊代碼 ({code}) 。" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been canceled. It can no longer be used." -msgstr "æ¤è¨»å†Šä»£ç¢¼å·²è¢«å–消。將永久於法使用。" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "This enrollment code has been marked as unused." -msgstr "æ¤è¨»å†Šä»£ç¢¼å·²è¢«æ¨™è¨»ç‚ºä¸èƒ½ä½¿ç”¨ã€‚" - -#: lms/djangoapps/instructor/views/registration_codes.py -msgid "The enrollment code has been restored." -msgstr "註冊代碼已被修復。" - -#: lms/djangoapps/instructor/views/registration_codes.py -#, python-brace-format -msgid "The redemption does not exist against enrollment code ({code})." -msgstr "é‡å°redemption 註冊代碼 ({code})是ä¸å˜åœ¨çš„。" - #: lms/djangoapps/instructor/views/tools.py #, python-brace-format msgid "Could not find student matching identifier: {student_identifier}" @@ -7284,10 +7103,6 @@ msgstr "標題" msgid "Year of Birth" msgstr "出生年份" -#: lms/djangoapps/instructor_task/tasks_helper/enrollments.py -msgid "Enrollment Date" -msgstr "註冊日期" - #: lms/djangoapps/instructor_task/tasks_helper/enrollments.py msgid "Currently Enrolled" msgstr "當å‰è¨»å†Š" @@ -7486,8 +7301,8 @@ msgstr "(out of {total})" #: lms/djangoapps/learner_dashboard/programs.py #: lms/templates/header/navbar-authenticated.html #: lms/templates/learner_dashboard/programs.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Programs" msgstr "" @@ -8148,6 +7963,15 @@ msgstr "ç¸½åƒ¹æ ¼" msgid "Currency" msgstr "貨幣" +#: lms/djangoapps/shoppingcart/reports.py +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: wiki/plugins/attachments/forms.py +#: wiki/plugins/attachments/templates/wiki/plugins/attachments/history.html +msgid "Description" +msgstr "敘述" + #: lms/djangoapps/shoppingcart/reports.py msgid "Comments" msgstr "è©•è«–" @@ -8290,14 +8114,6 @@ msgstr "您沒有權é™æª¢è¦–æ¤é é¢ã€‚" msgid "View and regenerate certificates." msgstr "查看並產生è‰æ›¸ã€‚" -#: lms/djangoapps/support/views/index.py -msgid "Manual Refund" -msgstr "人工退款" - -#: lms/djangoapps/support/views/index.py -msgid "Track refunds issued directly through CyberSource." -msgstr "直接é€éŽCyberSource追蹤退款å•é¡Œã€‚" - #: lms/djangoapps/support/views/index.py #: lms/templates/ccx/coach_dashboard.html lms/templates/ccx/enrollment.html #: lms/templates/support/enrollment.html @@ -8376,44 +8192,9 @@ msgstr "" msgid "User Disabled Successfully" msgstr "" -#: lms/djangoapps/support/views/refund.py -#: lms/templates/shoppingcart/billing_details.html -msgid "Email Address" -msgstr "é›»å郵件地å€" - -#: lms/djangoapps/support/views/refund.py -#: openedx/core/djangoapps/schedules/admin.py -#: cms/templates/maintenance/_force_publish_course.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html -#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html -#: lms/templates/support/feature_based_enrollments.html -msgid "Course ID" -msgstr "課程編號" - -#: lms/djangoapps/support/views/refund.py -msgid "User not found" -msgstr "無法找到使用者" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Course {course_id} not past the refund window." -msgstr "課程 {course_id} 並未張貼在退款視窗ä¸ã€‚" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "No order found for {user} in course {course_id}" -msgstr "找ä¸åˆ°ä½¿ç”¨è€… {user} 於課程 {course_id} 的訂單" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Unenrolled {user} from {course_id}" -msgstr "å–消 {user} æ–¼ {course_id} 課程的註冊" - -#: lms/djangoapps/support/views/refund.py -#, python-brace-format -msgid "Refunded {cost} for order id {order_id}" -msgstr "退款 {cost} 給訂單編號 {order_id}" +#: lms/djangoapps/survey/utils.py +msgid "You must complete a survey" +msgstr "" #: lms/djangoapps/teams/models.py msgid "Optional language the team uses as ISO 639-1 code." @@ -9031,8 +8812,8 @@ msgstr "" msgid "Allow" msgstr "" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Error" msgstr "錯誤" @@ -9395,8 +9176,8 @@ msgid "" msgstr "" #: lms/templates/wiki/plugins/attachments/index.html -#: wiki/plugins/attachments/wiki_plugin.py #: wiki/plugins/attachments/templates/wiki/plugins/attachments/index.html +#: wiki/plugins/attachments/wiki_plugin.py msgid "Attachments" msgstr "附件" @@ -9427,11 +9208,10 @@ msgid "" msgstr "您å¯ä»¥å¾žå…¶ä»–æ–‡ç« ä¸é‡è¤‡ä½¿ç”¨æª”案。" #: lms/templates/wiki/plugins/attachments/index.html -#: lms/templates/dashboard.html lms/templates/index.html #: lms/templates/api_admin/catalogs/search.html #: lms/templates/courseware/courses.html -#: lms/templates/courseware/courseware.html -#: lms/templates/edxnotes/edxnotes.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html +#: lms/templates/edxnotes/edxnotes.html lms/templates/index.html #: lms/templates/ux/reference/bootstrap/course-skeleton.html #: openedx/features/course_experience/templates/course_experience/course-home-fragment.html #: openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -9811,6 +9591,10 @@ msgstr "" msgid "Configuration may not be specified at more than one level at once." msgstr "" +#: openedx/core/djangoapps/content/learning_sequences/apps.py +msgid "Learning Sequences" +msgstr "" + #: openedx/core/djangoapps/content_libraries/models.py msgid "Administer users and author content" msgstr "" @@ -10183,6 +9967,10 @@ msgstr "" msgid "Schedule start < course start" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +msgid "Course Id" +msgstr "課程 ID" + #: openedx/core/djangoapps/schedules/admin.py msgid "All" msgstr "" @@ -10191,6 +9979,15 @@ msgstr "" msgid "Experience" msgstr "" +#: openedx/core/djangoapps/schedules/admin.py +#: cms/templates/maintenance/_force_publish_course.html +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +#: lms/templates/support/feature_based_enrollments.html +#: lms/templates/sysadmin_dashboard_gitlogs.html +msgid "Course ID" +msgstr "課程編號" + #: openedx/core/djangoapps/schedules/apps.py #: openedx/core/djangoapps/schedules/models.py msgid "Schedules" @@ -10391,6 +10188,7 @@ msgid "" msgstr "" #: openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +#: lms/templates/dates_banner.html msgid "Upgrade now" msgstr "" @@ -10620,7 +10418,6 @@ msgid "" msgstr "" #: openedx/core/djangoapps/user_api/accounts/views.py -#: openedx/core/djangoapps/user_authn/views/login.py msgid "" "This account has been temporarily locked due to excessive login failures. " "Try again later." @@ -10645,8 +10442,8 @@ msgstr "" msgid "Success" msgstr "æˆåŠŸ" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/staff_problem_info.html msgid "Actions" msgstr "動作" @@ -10805,6 +10602,14 @@ msgstr "註冊" msgid "There was an error receiving your login information. Please email us." msgstr "接å—您的登入訊æ¯æ™‚發生錯誤,請用電å郵件與我們è¯çµ¡ã€‚" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"To protect your account, it’s been temporarily locked. Try again in " +"{locked_out_period} minutes.{li_start}To be on the safe side, you can reset " +"your password {link_start}here{link_end} before you try again." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -10818,6 +10623,15 @@ msgstr "" msgid "Too many failed login attempts. Try again later." msgstr "登入失敗太多次,請ç¨å¾Œå†è©¦ï¼" +#: openedx/core/djangoapps/user_authn/views/login.py +#, python-brace-format +msgid "" +"Email or password is incorrect.{li_start}You have {remaining_attempts} more " +"sign-in attempts before your account is temporarily " +"locked.{li_end}{li_start}If you've forgotten your password, click " +"{link_start}here{link_end} to reset.{li_end}" +msgstr "" + #: openedx/core/djangoapps/user_authn/views/login.py #, python-brace-format msgid "" @@ -10825,15 +10639,6 @@ msgid "" "{link_start}{provider} account{link_end}." msgstr "" -#. Translators: This example email address is used as a placeholder in -#. a field on the login form meant to hold the user's email address. -#. Translators: This example email address is used as a placeholder in -#. a field on the password reset form meant to hold the user's email address. -#: openedx/core/djangoapps/user_authn/views/login_form.py -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "username@domain.com" -msgstr "username@domain.com" - #. Translators: These instructions appear on the login form, immediately #. below a field meant to hold the user's email address. #. Translators: These instructions appear on the password reset form, @@ -10849,6 +10654,12 @@ msgstr "您在 {platform_name} 上註冊的電å郵件" msgid "Create Account" msgstr "" +#. Translators: This example email address is used as a placeholder in +#. a field on the password reset form meant to hold the user's email address. +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "username@domain.com" +msgstr "username@domain.com" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "" "That e-mail address doesn't have an associated user account. Are you sure " @@ -10861,6 +10672,11 @@ msgid "" "password." msgstr "與æ¤é›»å郵件地å€é—œè¯çš„用戶帳戶ä¸èƒ½é‡æ–°è¨ç½®å¯†ç¢¼ã€‚" +#: openedx/core/djangoapps/user_authn/views/password_reset.py +msgid "" +"Your previous request is in progress, please try again in a few moments." +msgstr "" + #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Password reset unsuccessful" msgstr "é‡æ–°è¨ç½®å¯†ç¢¼ä¸æˆåŠŸ" @@ -10880,11 +10696,6 @@ msgid "" "created. {bold_start}{email}{bold_end} is now your primary login email." msgstr "" -#: openedx/core/djangoapps/user_authn/views/password_reset.py -msgid "" -"Your previous request is in progress, please try again in a few moments." -msgstr "" - #: openedx/core/djangoapps/user_authn/views/password_reset.py msgid "Some error occured during password change. Please try again" msgstr "" @@ -11110,6 +10921,18 @@ msgid "" "Username created for Video Pipeline Integration, e.g. veda_service_user." msgstr "" +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Oauth client name of VEM service." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "video encode manager API URL." +msgstr "" + +#: openedx/core/djangoapps/video_pipeline/models.py +msgid "Username created for VEM Integration, e.g. vem_service_user." +msgstr "" + #: openedx/core/djangoapps/waffle_utils/models.py msgid "Force On" msgstr "" @@ -11128,6 +10951,10 @@ msgstr "" msgid "This content is only accessible to enrolled learners. " msgstr "" +#: openedx/core/lib/api/view_utils.py +msgid "The about me field must be at most {} characters long." +msgstr "" + #: openedx/core/lib/api/view_utils.py msgid "This value is invalid." msgstr "æ¤æ•¸å€¼æ˜¯ç„¡æ•ˆçš„。" @@ -11806,8 +11633,8 @@ msgstr "課程æˆåŠŸåŒ¯å‡ºåˆ°Git資æºåº«" msgid "Vertical" msgstr "åž‚ç›´" -#: cms/templates/course_outline.html lms/templates/seq_module.html -#: lms/templates/ccx/schedule.html +#: cms/templates/course_outline.html lms/templates/ccx/schedule.html +#: lms/templates/seq_module.html msgid "Section" msgstr "ç« ç¯€" @@ -12078,6 +11905,18 @@ msgstr "" msgid "Transcript Ready" msgstr "" +#. Translators: This is the status for a video whose transcription job was +#. failed for some languages +#: cms/djangoapps/contentstore/views/videos.py +msgid "Partial Failure" +msgstr "" + +#. Translators: This is the status for a video whose transcription job has +#. failed altogether +#: cms/djangoapps/contentstore/views/videos.py +msgid "Transcript Failed" +msgstr "" + #: cms/djangoapps/contentstore/views/videos.py msgid "An image file is required." msgstr "" @@ -12267,14 +12106,14 @@ msgstr "課程編號:" msgid "Course Run:" msgstr "" -#: cms/templates/index.html lms/templates/sysadmin_dashboard.html -#: lms/templates/sysadmin_dashboard_gitlogs.html -#: lms/templates/courseware/courses.html +#: cms/templates/index.html lms/templates/courseware/courses.html #: lms/templates/header/navbar-authenticated.html #: lms/templates/header/navbar-not-authenticated.html +#: lms/templates/navigation/bootstrap/navbar-authenticated.html #: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/navbar-not-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/sysadmin_dashboard.html +#: lms/templates/sysadmin_dashboard_gitlogs.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html msgid "Courses" msgstr "課程" @@ -12298,8 +12137,9 @@ msgstr "" msgid "Requirements" msgstr "課程è¦æ±‚" -#: cms/templates/studio_xblock_wrapper.html lms/templates/module-error.html +#: cms/templates/studio_xblock_wrapper.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/module-error.html msgid "Details" msgstr "細節" @@ -12351,15 +12191,15 @@ msgstr "" msgid "Choose Language" msgstr "é¸æ“‡èªžè¨€" -#: cms/templates/widgets/header.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "Account" msgstr "帳號" #: cms/templates/widgets/header.html #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/static_templates/help.html #: themes/edx.org/lms/templates/header/navbar-authenticated.html #: wiki/plugins/help/wiki_plugin.py @@ -12431,8 +12271,8 @@ msgstr "" msgid "Usermenu dropdown" msgstr "" -#: cms/templates/widgets/user_dropdown.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: cms/templates/widgets/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Sign Out" msgstr "登出" @@ -12592,8 +12432,8 @@ msgstr "開始日期:{date}" msgid "View all Courses" msgstr "檢視所有課程" -#: lms/templates/dashboard.html lms/templates/user_dropdown.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/dashboard.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html #: themes/edx.org/lms/templates/dashboard.html msgid "Dashboard" msgstr "我的課程" @@ -12612,8 +12452,8 @@ msgstr "" #: lms/templates/dashboard.html #: lms/templates/header/navbar-not-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html #: themes/edx.org/lms/templates/dashboard.html msgid "Explore courses" msgstr "探索課程" @@ -12631,7 +12471,7 @@ msgstr "課程讀å–錯誤" msgid "Search Your Courses" msgstr "æœå°‹æ‚¨çš„課程" -#: lms/templates/dashboard.html lms/templates/courseware/courseware.html +#: lms/templates/courseware/courseware.html lms/templates/dashboard.html #: themes/edx.org/lms/templates/dashboard.html msgid "Clear search" msgstr "清除æœå°‹" @@ -12656,7 +12496,7 @@ msgstr "接收課程郵件" msgid "Save Settings" msgstr "儲å˜è¨å®š" -#: lms/templates/dashboard.html lms/templates/ccx/enrollment.html +#: lms/templates/ccx/enrollment.html lms/templates/dashboard.html #: lms/templates/dashboard/_dashboard_course_listing.html #: lms/templates/dashboard/_dashboard_entitlement_actions.html #: lms/templates/dashboard/_dashboard_entitlement_unenrollment_modal.html @@ -12666,9 +12506,87 @@ msgstr "儲å˜è¨å®š" msgid "Unenroll" msgstr "å–消註冊" -#: lms/templates/edit_unit_link.html -msgid "View Unit in Studio" -msgstr "在Studioä¸æª¢è¦–單元" +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule. " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future by visiting " +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" Don't worry—you won't lose any of the progress you've made when you shift " +"your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"It looks like you missed some important deadlines based on our suggested " +"schedule." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"To keep yourself on track, you can update this schedule and shift the past " +"due assignments into the future. Don't worry—you won't lose any of the " +"progress you've made when you shift your due dates." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "You are auditing this course," +msgstr "" + +#: lms/templates/dates_banner.html +msgid " which means that you are unable to participate in graded assignments." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. Graded assignments and schedule adjustment are available to " +"Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" It looks like you missed some important deadlines based on our suggested " +"schedule. To complete graded assignments as part of this course and shift " +"the past due assignments into the future, you can upgrade today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Upgrade to shift due dates" +msgstr "" + +#: lms/templates/dates_banner.html +msgid "Graded assignments are available to Verified Track learners." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +" To complete graded assignments as part of this course, you can upgrade " +"today." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "We've built a suggested schedule to help you stay on track." +msgstr "" + +#: lms/templates/dates_banner.html +msgid "" +"But don't worry—it's flexible so you can learn at your own pace. If you " +"happen to fall behind on our suggested dates, you'll be able to adjust them " +"to keep yourself on track." +msgstr "" #: lms/templates/email_change_failed.html lms/templates/email_exists.html msgid "E-mail change failed" @@ -12700,7 +12618,7 @@ msgstr "該電å郵件信箱地å€å·²ç¶“å˜åœ¨ä¸€å€‹å¸³æˆ¶ã€‚" msgid "You should Register before trying to access the Unit" msgstr "在進入本單元å‰ï¼Œæ‚¨æ‡‰å…ˆè¨»å†Šã€‚" -#: lms/templates/enroll_staff.html lms/templates/courseware/course_about.html +#: lms/templates/courseware/course_about.html lms/templates/enroll_staff.html msgctxt "self" msgid "Enroll" msgstr "" @@ -12800,7 +12718,7 @@ msgid "" "available on the {link_start}progress page{link_end}." msgstr "" -#: lms/templates/index.html lms/templates/courseware/courses.html +#: lms/templates/courseware/courses.html lms/templates/index.html #: themes/stanford-style/lms/templates/index.html msgid "Search for a course" msgstr "æœå°‹èª²ç¨‹" @@ -12935,20 +12853,16 @@ msgstr "(é‡æ–°è¼‰å…¥ä»¥é‡æ–°æ•´ç†æ‚¨çš„é é¢)" msgid "working" msgstr "進行ä¸" -#: lms/templates/module-error.html #: lms/templates/courseware/courseware-error.html +#: lms/templates/module-error.html msgid "There has been an error on the {platform_name} servers" msgstr " {platform_name}的系統出ç¾äº†éŒ¯èª¤" #: lms/templates/module-error.html -#: lms/templates/courseware/courseware-error.html msgid "" "We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible. Please email us at {tech_support_email} to " -"report any problems or downtime." +" fix it as soon as possible. " msgstr "" -"éžå¸¸æŠ±æ‰ï¼Œè©²æ¨¡çµ„暫時無法使用,我們的工作人員將盡速修復å•é¡Œã€‚è¦å›žå ±æ‚¨ç™¼ç¾çš„任何å•é¡Œæˆ–é‡åˆ°ç¶²ç«™åœæ“ºï¼Œè«‹ç™¼é€é›»å郵件至 " -"{tech_support_email}。" #: lms/templates/module-error.html msgid "Raw data:" @@ -12987,7 +12901,15 @@ msgid "You are now viewing the course as {i_start}{user_name}{i_end}." msgstr "您ç¾åœ¨æ£ä»¥ {i_start}{user_name}{i_end}查看課程。" #: lms/templates/preview_menu.html -msgid "View this unit in the new experience" +msgid "View in the new experience" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Studio" +msgstr "" + +#: lms/templates/preview_menu.html +msgid "View in Insights" msgstr "" #: lms/templates/problem.html @@ -13048,28 +12970,6 @@ msgstr "é›»å郵件" msgid "Return To %s" msgstr "返回%s" -#: lms/templates/reset_deadlines_banner.html -msgid "It looks like you've missed some important deadlines. Visit " -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "edx.org" -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid " to reset your deadlines and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "" -"It looks like you've missed some important deadlines. Reset your deadlines " -"and get started today." -msgstr "" - -#: lms/templates/reset_deadlines_banner.html -msgid "Reset my deadlines" -msgstr "" - #: lms/templates/resubscribe.html msgid "Re-subscribe Successful!" msgstr "é‡æ–°è¨‚é–±æˆåŠŸï¼" @@ -13118,7 +13018,7 @@ msgstr "" msgid "Sequence" msgstr "" -#: lms/templates/seq_module.html +#: lms/templates/courseware/dates.html lms/templates/seq_module.html #: openedx/features/course_experience/templates/course_experience/course-outline-fragment.html msgid "Completed" msgstr "" @@ -13247,18 +13147,18 @@ msgstr "" msgid "Reset Learner's Attempts to Zero" msgstr "" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Delete Learner's State" msgstr "" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Learner's Submission" msgstr "" -#: lms/templates/staff_problem_info.html #: lms/templates/instructor/instructor_dashboard_2/student_admin.html +#: lms/templates/staff_problem_info.html msgid "Rescore Only If Score Improves" msgstr "" @@ -13296,7 +13196,7 @@ msgstr "{course_number} 課本" msgid "Textbook Navigation" msgstr "課本導航" -#: lms/templates/staticbook.html lms/templates/courseware/gradebook.html +#: lms/templates/courseware/gradebook.html lms/templates/staticbook.html msgid "Page" msgstr "é é¢" @@ -13407,9 +13307,9 @@ msgstr "{total_pages}ä¸{current_page}é é¢" msgid "Recent git load activity for {course_id}" msgstr "" -#: lms/templates/sysadmin_dashboard_gitlogs.html #: lms/templates/ccx/schedule.html #: lms/templates/instructor/instructor_dashboard_2/certificates.html +#: lms/templates/sysadmin_dashboard_gitlogs.html msgid "Date" msgstr "日期" @@ -13463,7 +13363,7 @@ msgid "" " not mean to do this, {undo_link_start}you can re-subscribe{link_end}." msgstr "" -#: lms/templates/user_dropdown.html lms/templates/header/user_dropdown.html +#: lms/templates/header/user_dropdown.html lms/templates/user_dropdown.html msgid "Dashboard for:" msgstr "我的課程:" @@ -13471,8 +13371,8 @@ msgstr "我的課程:" msgid "More options" msgstr "更多é¸é …" -#: lms/templates/user_dropdown.html lms/templates/header/header.html -#: lms/templates/header/user_dropdown.html +#: lms/templates/header/header.html lms/templates/header/user_dropdown.html +#: lms/templates/user_dropdown.html msgid "More Options" msgstr "" @@ -14650,35 +14550,6 @@ msgstr "如果所有的資訊是æ£ç¢ºçš„,å•é¡Œä»ç„¶å˜åœ¨ï¼Œè«‹è¯ç¹«æŠ€è¡“ msgid "About edX Certificates" msgstr "" -#: lms/templates/commerce/checkout_cancel.html -msgid "Checkout Cancelled" -msgstr "交易å–消" - -#: lms/templates/commerce/checkout_cancel.html -msgid "" -"Your transaction has been cancelled. If you feel an error has occurred, " -"contact {email}." -msgstr "您的交易已經被å–消。如果您覺得有å•é¡Œï¼Œè«‹è¯ç¹«{email}。" - -#: lms/templates/commerce/checkout_error.html -msgid "Checkout Error" -msgstr "çµå¸³éŒ¯èª¤" - -#: lms/templates/commerce/checkout_error.html -msgid "" -"An error has occurred with your payment. {b_start}You have not been " -"charged.{b_end} Please try to submit your payment again. If this problem " -"persists, contact {email}." -msgstr "" - -#: lms/templates/commerce/checkout_receipt.html -msgid "Loading Order Data..." -msgstr "載入訂單ä¸..." - -#: lms/templates/commerce/checkout_receipt.html -msgid "Please wait while we retrieve your order details." -msgstr "è«‹ç¨å€™ï¼Œæˆ‘們æ£åœ¨å–得您的訂單資訊。" - #: lms/templates/course_modes/_upgrade_button.html #: lms/templates/course_modes/choose.html #: themes/edx.org/lms/templates/course_modes/_upgrade_button.html @@ -14876,14 +14747,14 @@ msgstr "" msgid "This content is graded" msgstr "" -#: lms/templates/courseware/course_about.html -msgid "An error occurred. Please try again later." -msgstr "發生錯誤。請ç¨å¾Œå†è©¦ä¸€æ¬¡ã€‚" - #: lms/templates/courseware/course_about.html msgid "An error has occurred. Please ensure that you are logged in to enroll." msgstr "" +#: lms/templates/courseware/course_about.html +msgid "An error occurred. Please try again later." +msgstr "發生錯誤。請ç¨å¾Œå†è©¦ä¸€æ¬¡ã€‚" + #: lms/templates/courseware/course_about.html msgid "You are enrolled in this course" msgstr "您åƒåŠ æ¤èª²ç¨‹" @@ -14895,10 +14766,6 @@ msgstr "您åƒåŠ æ¤èª²ç¨‹" msgid "View Course" msgstr "檢視課程" -#: lms/templates/courseware/course_about.html -msgid "This course is in your {start_cart_link}cart{end_cart_link}." -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Course is full" msgstr "課程已滿" @@ -14911,10 +14778,6 @@ msgstr "åªèƒ½ç¶“由邀請註冊這課程" msgid "Enrollment is Closed" msgstr "註冊功能已經關閉" -#: lms/templates/courseware/course_about.html -msgid "Add {course_name} to Cart {start_span}({price} USD){end_span}" -msgstr "" - #: lms/templates/courseware/course_about.html msgid "Enroll Now" msgstr "" @@ -15036,6 +14899,13 @@ msgstr "課程工具" msgid "Courseware" msgstr "課程教æ" +#: lms/templates/courseware/courseware-error.html +#: lms/templates/courseware/error-message.html +msgid "" +"We're sorry, this module is temporarily unavailable. Our staff is working to" +" fix it as soon as possible." +msgstr "" + #: lms/templates/courseware/courseware.html msgid "Course Search" msgstr "課程æœå°‹" @@ -15064,7 +14934,7 @@ msgid "Important Dates" msgstr "" #: lms/templates/courseware/dates.html -msgid "Due Today" +msgid "Today" msgstr "" #: lms/templates/courseware/dates.html @@ -15072,14 +14942,11 @@ msgid "Verified Only" msgstr "" #: lms/templates/courseware/dates.html -msgid "" -"{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access." +msgid "Due Next" msgstr "" -#: lms/templates/courseware/error-message.html -msgid "" -"We're sorry, this module is temporarily unavailable. Our staff is working to" -" fix it as soon as possible." +#: lms/templates/courseware/dates.html +msgid "Not yet released" msgstr "" #: lms/templates/courseware/gradebook.html @@ -15715,8 +15582,8 @@ msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "" "You will see a message on your dashboard when the verification process is " -"complete (usually within 1-2 days)." -msgstr "é©—è‰éŽç¨‹å®Œæˆå¾Œ(至少需1-2個工作天),您將會在課程介é¢ä¸Šçœ‹åˆ°ä¸€å‰‡è¨Šæ¯ã€‚" +"complete (usually within 5-7 days)." +msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your current verification will expire soon!" @@ -15726,8 +15593,8 @@ msgstr "" msgid "" "You have submitted your reverification information. You will see a message " "on your dashboard when the verification process is complete (usually within " -"1-2 days)." -msgstr "您已æ交您的驗è‰è¨Šæ¯ã€‚當驗è‰éŽç¨‹å®Œæˆ(至少需1-2個工作天),您將會在課程介é¢ä¸Šçœ‹åˆ°ä¸€å‰‡è¨Šæ¯ã€‚" +"5-7 days)." +msgstr "" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "You have successfully verified your ID with edX" @@ -16403,133 +16270,6 @@ msgid "" "verification process on your dashboard." msgstr "" -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Thank you for purchasing enrollments in {course_name}." -msgstr "æ„Ÿè¬ä½ 訂購 {course_name}。" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"An invoice for {currency_symbol}{total_price} is attached. Payment is due " -"upon receipt. You can find information about payment methods on the invoice." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"A .csv file that lists your enrollment codes is attached. You can use the " -"email template below to distribute enrollment codes to your students. Each " -"student must use a separate enrollment code." -msgstr "" - -#. Translators: This is the signature of an email. "\n" is a newline -#. character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Thanks,\n" -"The {platform_name} Team" -msgstr "" -"æ„Ÿè¬,\n" -" {platform_name} 團隊" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "Dear [[Name]]:" -msgstr "親愛的 [[Name]]:" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"We have provided a course enrollment code for you in {course_name}. To " -"enroll in the course, click the following link:" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "HTML link from the attached CSV file" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"After you enroll, you can see the course on your student dashboard. You can " -"see course materials after the course start date." -msgstr "" - -#. Translators: please translate the text inside [[ ]]. This is meant as a -#. template for course teams to use. -#. This is the signature of an email. "\n" is a newline character -#. and should be placed between the closing word and the signature. -#: lms/templates/emails/registration_codes_sale_email.txt -msgid "" -"Sincerely,\n" -"[[Your Signature]]" -msgstr "" -"敬上,\n" -"[[Your Signature]]" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "INVOICE" -msgstr "發票" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Date: {date}" -msgstr "日期: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Invoice No: {invoice_number}" -msgstr "統一編號: {invoice_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Terms: Due Upon Receipt" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Due Date: {date}" -msgstr "截æ¢æ—¥æœŸ: {date}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Bill to:" -msgstr "付款方:" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Customer Reference Number: {reference_number}" -msgstr "消費者åƒè€ƒè™Ÿç¢¼ï¼š{reference_number}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Balance Due: {currency_symbol}{sale_price}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Course: {course_name}" -msgstr "課程: {course_name}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"Price: {currency_symbol}{course_price} Quantity: {quantity} " -"Sub-Total: {currency_symbol}{sub_total} Discount: " -"{currency_symbol}{discount}" -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Total: {currency_symbol}{sale_price}" -msgstr "總é¡: {currency_symbol}{sale_price}" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "Payment Instructions" -msgstr "付款說明" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "" -"If we do not receive payment, the learner enrollments that use these codes " -"will be canceled and learners will not be able to access course materials. " -"All purchases are final. For more information, see the {site_name} " -"cancellation policy." -msgstr "" - -#: lms/templates/emails/registration_codes_sale_invoice_attachment.txt -msgid "For payment questions, contact {contact_email}" -msgstr "å°æ–¼ä»˜æ¬¾å•é¡Œï¼Œè«‹è¯ç¹« {contact_email}" - #: lms/templates/emails/reject_name_change.txt msgid "" "We are sorry. Our course staff did not approve your request to change your " @@ -16692,8 +16432,8 @@ msgstr "申請資助" #: lms/templates/header/brand.html #: lms/templates/header/navbar-logo-header.html -#: lms/templates/navigation/navbar-logo-header.html #: lms/templates/navigation/bootstrap/navbar-logo-header.html +#: lms/templates/navigation/navbar-logo-header.html msgid "{platform_name} Home Page" msgstr "{platform_name}首é " @@ -16715,19 +16455,11 @@ msgstr "" #. Translators: This is short for "System administration". #: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html #: lms/templates/navigation/bootstrap/navbar-authenticated.html +#: lms/templates/navigation/navbar-authenticated.html msgid "Sysadmin" msgstr "系統管ç†å“¡" -#: lms/templates/header/navbar-authenticated.html -#: lms/templates/navigation/navbar-authenticated.html -#: lms/templates/navigation/bootstrap/navbar-authenticated.html -#: lms/templates/shoppingcart/shopping_cart.html -#: themes/edx.org/lms/templates/header/navbar-authenticated.html -msgid "Shopping Cart" -msgstr "購物車" - #: lms/templates/header/navbar-not-authenticated.html msgid "Supplemental Links" msgstr "" @@ -16764,6 +16496,12 @@ msgstr "åŠ å…¥å„ªæƒ å·ä»£ç¢¼" msgid "Enter information about the coupon code below." msgstr "è¼¸å…¥æœ‰é—œæ–¼å„ªæƒ ä»£ç¢¼çš„è¨Šæ¯" +#: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/executive_summary.html +msgid "Coupon Code" +msgstr "å„ªæƒ åˆ¸ä»£ç¢¼" + #: lms/templates/instructor/instructor_dashboard_2/add_coupon_modal.html msgid "Discount Percentage" msgstr "打折" @@ -17308,6 +17046,11 @@ msgstr "" msgid "Coupon Codes" msgstr "" +#: lms/templates/instructor/instructor_dashboard_2/e-commerce.html +#: lms/templates/instructor/instructor_dashboard_2/edit_coupon_modal.html +msgid "Expiration Date" +msgstr "" + #: lms/templates/instructor/instructor_dashboard_2/e-commerce.html msgid "Coupon (%)" msgstr "" @@ -18567,6 +18310,10 @@ msgstr "購買組織" msgid "Purchase order number (if any)" msgstr "購買訂單編號 (if any)" +#: lms/templates/shoppingcart/billing_details.html +msgid "Email Address" +msgstr "é›»å郵件地å€" + #: lms/templates/shoppingcart/billing_details.html msgid "email@example.com" msgstr "email@example.com" @@ -18854,6 +18601,10 @@ msgid_plural "" "{course_names} have been removed because the enrollment period has closed." msgstr[0] "{course_names} å› å·²ä¸é–‹æ”¾è¨»å†Šè€Œè¢«ç§»é™¤ã€‚" +#: lms/templates/shoppingcart/shopping_cart.html +msgid "Shopping Cart" +msgstr "購物車" + #: lms/templates/shoppingcart/shopping_cart.html msgid "Cover Image" msgstr "å°é¢åœ–片" @@ -19064,46 +18815,6 @@ msgstr "" msgid "Program Enrollments Inspector" msgstr "" -#: lms/templates/support/refund.html -msgid "About to refund this order:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Order Id:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Enrollment:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "enrolled" -msgstr "" - -#: lms/templates/support/refund.html -msgid "unenrolled" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Cost:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "CertificateItem Status:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Order Status:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Fulfilled Time:" -msgstr "" - -#: lms/templates/support/refund.html -msgid "Refund Request Time:" -msgstr "" - #: lms/templates/survey/survey.html msgid "User Survey" msgstr "使用者å•å·" @@ -19240,7 +18951,7 @@ msgstr "身份驗è‰" msgid "" "You have already submitted your verification information. You will see a " "message on your dashboard when the verification process is complete (usually" -" within 1-2 days)." +" within 5-7 days)." msgstr "" #: lms/templates/verify_student/reverify_not_allowed.html @@ -19898,10 +19609,8 @@ msgid "The page that you were looking for was not found." msgstr "無法找到您所æœå°‹çš„é é¢" #: cms/templates/404.html -msgid "" -"Go back to the {homepage} or let us know about any pages that may have been " -"moved at {email}." -msgstr "回到 {homepage} 或發電å郵件至 {email} 告訴我們å¯èƒ½è¢«ç§»å‹•çš„é é¢ã€‚" +msgid "Go back to the {homepage}." +msgstr "" #: cms/templates/500.html msgid "{studio_name} Server Error" @@ -19923,10 +19632,6 @@ msgid "" "error as soon as possible." msgstr "我們已經記錄下這個錯誤,åŒæ™‚技術人員æ£è©¦åœ–儘快解決這個å•é¡Œã€‚" -#: cms/templates/500.html -msgid "If the problem persists, please email us at {email_link}." -msgstr "如果å•é¡Œä»ç„¶å˜åœ¨ï¼Œè«‹å¯„é›»å郵件至 {email_link}." - #: cms/templates/accessibility.html msgid "Studio Accessibility Policy" msgstr "" @@ -20539,9 +20244,7 @@ msgstr "無法找到您請求的é é¢" #: cms/templates/error.html msgid "" "We're sorry. We couldn't find the {studio_name} page you're looking for. You" -" may want to return to the {studio_name} Dashboard and try again. If you are" -" still having problems accessing things, please feel free to " -"{link_start}contact {studio_name} support{link_end} for further help." +" may want to return to the {studio_name} Dashboard and try again." msgstr "" #: cms/templates/error.html @@ -20552,9 +20255,7 @@ msgstr "伺æœå™¨ç™¼ç”ŸéŒ¯èª¤" msgid "" "We're sorry. There was a problem with the server while trying to process " "your last request. You may want to return to the {studio_name} Dashboard or " -"try this request again. If you are still having problems accessing things, " -"please feel free to {link_start}contact {studio_name} support{link_end} for " -"further help." +"try this request again." msgstr "" #: cms/templates/error.html @@ -23527,8 +23228,8 @@ msgstr "%(file)s已經修改æˆ#%(revision)d修訂版" msgid "%(file)s has been saved." msgstr "%(file)s 已經被儲å˜ã€‚" -#: wiki/plugins/images/wiki_plugin.py #: wiki/plugins/images/templates/wiki/plugins/images/index.html +#: wiki/plugins/images/wiki_plugin.py msgid "Images" msgstr "圖片" @@ -23720,8 +23421,8 @@ msgstr "" msgid "Search..." msgstr "" -#: wiki/templates/wiki/base.html wiki/templates/wiki/accounts/login.html -#: wiki/templates/wiki/accounts/signup.html +#: wiki/templates/wiki/accounts/login.html +#: wiki/templates/wiki/accounts/signup.html wiki/templates/wiki/base.html msgid "Sign up" msgstr "" diff --git a/docs/decisions/0003-reduce-bokchoy-testing.rst b/docs/decisions/0003-reduce-bokchoy-testing.rst index c9f522cf712e402ca543924c093872f2c50e2c02..afb54e4d12f5e7d55b62bfff764484f5c5f6a509 100644 --- a/docs/decisions/0003-reduce-bokchoy-testing.rst +++ b/docs/decisions/0003-reduce-bokchoy-testing.rst @@ -1,6 +1,6 @@ Status ====== -Draft +Accepted Context @@ -46,7 +46,7 @@ Test Plan #. Collect data on which issues bokchoy would have caught by running them manually out-of-band from the standard CI/CD process. * We'll look at the failures on the out-of-band bokchoy job to find any true failures that would be caught by the removed tests. - * On a Daily cadense for 1 month. + * On a Daily cadence for 1 month. #. Assess Impact of change. @@ -59,15 +59,24 @@ Outcome: Decision on whether or not to reduce the number of bokchoy tests. Experiment Results ================== -TBD +Bokchoy tests were disabled for PRs for 3 weeks. In that time only one change went out that was not caught by other test suites. The change in question did not impact edx.org and was specific how configuration is read into the system. The bokchoy tests did not detect any other failures that were not caught by other tests. The `PR` where we monitored Bokchoy daily has more specific details. + +.. _PR: https://github.com/edx/edx-platform/pull/23682 Decision ======== -TBD - Based on experiment outcome. +We initially used the a11y suite as a placeholder for a set of reduced tests. Given the results of the tests, we will not pull in any tests from the full bokchoy suite and only keep the a11y tests. Consequences ============ -TBD +* Bokchoy testing infrastructure will remain off +* Bokchoy tests jobs will be removed all together rather than just disabled +* All bokchoy code in edx-platform not related to the a11y tests will be removed +* Testing Strategy for UI that is not part of a microfrontend + * end-to-end smoke tests via the e2e-tests suite should only be for critical happy paths + * UI and frontend logic should be tested using UI unit tests(currently Jasmine). + * Django backends and rendered HTML should be tested with integration tests that use the `Django test client` +.. _Django test client: https://docs.djangoproject.com/en/2.2/topics/testing/tools/#the-test-client diff --git a/docs/decisions/0004-managing-django-settings.rst b/docs/decisions/0004-managing-django-settings.rst new file mode 100644 index 0000000000000000000000000000000000000000..b7b3c2f98d161e3f9f4c16cc20de32bf29ae2cf5 --- /dev/null +++ b/docs/decisions/0004-managing-django-settings.rst @@ -0,0 +1,97 @@ +Status +====== + +Accepted + + +Context +======= + +Settings are confusing right now and there are way too many layers. We have +multiple python settings file that "inherit" from each other. In some cases some +layers of the inheritance tree also pull settings from config files leading to +more confusion. + + +Decision +======== + +Rather than having multiple python settings files that override things +differently we will move to just a few python files with most of the settings +variance living in YAML config files that are managed by environment operators. +The structure of these files try to match `OEP-45` as bast as we can. Because +the edx-platform houses both the ``LMS`` and ``Studio`` applications, our +implementation will differ slightly from the guidance provided by `OEP-45`. + +LMS and CMS settings will continue to live under ``lms/envs/...`` and ``cms/envs/...``. + +Underneath those folders, we will follow the layout suggested by `OEP-45`. + + +To recap that here: + +``__init__.py`` will handle the loading of defaults, environment overrides, and ensuring that required settings are set. + +``defaults.py`` will house and document all default settings. + +``required.py`` will document and validate that required settings have been defined. + +For edx-platform there may be cases where settings are additive, in this case +the managing of those additive settings will be managed within +``__init__.py`` + +For example, FEATURES, or JWT_AUTH are both settings where we +currently pull parts of the data from the config and inject it into an existing +data structure. While it is possible that in the future we would make these be +more explicit, we don't want to take on that work now as it may increase +complexity. + + +.. _OEP-45: https://github.com/edx/open-edx-proposals/pull/143/files + +Consequences +============ + +Rather than having both python and yaml override files for our dev and test +environments, we will move towards having all settings defined in a yaml file +and for all environments to use __init__.py to load their settings. + +The following files should be obviated by this change: + +* bok_choy_docker.py +* bok_choy.py +* devstack_docker.py +* devstack_optimized.py +* devstack.py +* devstack_with_worker.py +* load_test.py +* openstack.py +* static.py +* test.py +* test_static_optimized.py + +If there exist default YAML files for any of the above environments they should +be updated to absorb any overrides that lived in these python settings files. +Any environments that use these files should be updated. + +Alternatives Considered +======================= + +Don't use YAML files, just python modules +----------------------------------------- + +Instead of having YAML and then translating that to python, we can just have +python settings files for all variants we want. + +Pros: + +* Settings can still be in a single place per environment. +* You get the full power of python when building out settings. +* Settings values can be complex python objects. + +Cons: +* Because settings have secrets, we would have to keep our settings file out of + the public repository. +* This wouldn't solve the problem where we would still try to "inherit" from other settings files and make it harder to read the current value of any given setting. + +This alternative gives us a lot more power but it's power that we don't actually need. Building limitiations into what settings can be helps us keep them simple and understandable. diff --git a/docs/docs_settings.py b/docs/docs_settings.py index be521a9d701166b1c4caa840867685fce7aaa2aa..285e589b4fa01e469128844c22092b6ae3d8d908 100644 --- a/docs/docs_settings.py +++ b/docs/docs_settings.py @@ -14,6 +14,7 @@ if os.environ['EDX_PLATFORM_SETTINGS'] == 'devstack_docker': COURSE_IMPORT_EXPORT_STORAGE, SCRAPE_YOUTUBE_THUMBNAILS_JOB_QUEUE, VIDEO_TRANSCRIPT_MIGRATIONS_JOB_QUEUE, + UPDATE_SEARCH_INDEX_JOB_QUEUE, ) else: from lms.envs.devstack import * @@ -22,6 +23,7 @@ else: COURSE_IMPORT_EXPORT_STORAGE, SCRAPE_YOUTUBE_THUMBNAILS_JOB_QUEUE, VIDEO_TRANSCRIPT_MIGRATIONS_JOB_QUEUE, + UPDATE_SEARCH_INDEX_JOB_QUEUE, ) # Turn on all the boolean feature flags, so that conditionally included diff --git a/docs/guides/extension_points.rst b/docs/guides/extension_points.rst new file mode 100644 index 0000000000000000000000000000000000000000..870e73efc22214d4a068f1819e27c91b733f3016 --- /dev/null +++ b/docs/guides/extension_points.rst @@ -0,0 +1,180 @@ +Options for Extending the edX Platform +-------------------------------------- + +Open edX platform development follows the `Open-Closed Principle`_: we want Open edX to be an extensible platform that allows developers to build extensions that integrate with the core of the platform. This allows the core to remain small, while volatile extensions remain in the periphery. + +As you can see in this document, there are many different ways to integrate with Open edX. However, we know that there are still some features/integrations that are not possible today without modifying the core. If you have such a need, please consider proposing a new extension point in the core that would make possible the functionality you have in mind. When you submit a pull request for a new extension point, be sure to include a change to this file to document your new extension point. (Doing so will also notify reviewers that want to help with making the platform more extensible.) + +Throughout this document, we will refer to the **Status** (**Adoption** and **Completion**) of each specific integration point. The Completion refers to how complete and stable an integration point is: either "Limited" (incomplete, or unstable) or "Stable" (complete and stable enough for general use in some or all cases). Adoption shows how the integration point is currently being used, and whether or not it should be used in the future: + +* **Adopt**: Technologies we have high confidence in to serve our purpose, also in large scale. Technologies with a usage culture in our production environment, low risk and recommended to be widely used. +* **Trial**: Technologies that we have seen work with success in project work to solve a real problem; first serious usage experience that confirm benefits and can uncover limitations. Trial technologies are slightly more risky. +* **Assess**: Technologies that we are considering using; to be listed on this page, they must exist as a prototype in the codebase. +* **Hold**: Technologies not recommended to be used for new projects. Technologies that we think are not (yet) worth to (further) invest in. They should not be used for new projects, but usually can be continued for existing projects. + +.. _Open-Closed Principle: https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle + +.. contents:: **Integration Methods Overview** + + +REST API Integration with External Applications +=============================================== + +*Status: Adopt, Limited* + +The Open edX platform provides a suite of REST APIs that any type of external application can use. Auto-generated API documentation for the main LMS and Studio APIs is available at (LMS URL)/api-docs/ and (Studio URL)/api-docs/ . + +Things that you can develop as an external application using REST APIs include: + +* Marketing sites / course catalogs +* Custom learning frontends +* Native mobile applications +* E-commerce and subscription management portals +* Administration tools +* Custom course authoring tools + +You can write your external application using any language and framework you'd like. The API specifications are available in OpenAPI format (e.g. at /api-docs/?format=openapi), and you can use the `OpenAPI Generator`_ to generate an API client library in the language of your choice. + +Be aware that most existing REST APIs are not considered stable, and some platform features lack a REST API. We welcome help as we work to standardize our API practices and version them to create API stability. + +.. _OpenAPI Generator: https://github.com/OpenAPITools/openapi-generator + +Content Integrations +==================== + +If you want to provide learners with new content experiences within courses, options include: + +.. list-table:: + :header-rows: 1 + :widths: 15 10 75 + + * - Type + - Status + - Details + * - **XBlocks** + - Adopt, Stable + - XBlocks are python plugins specific to Open edX that get installed into edx-platform and can be used to build courses. An XBlock defines a new *type* of interactive component, and authors can then create many instances of that content type in their courses (each with different settings and content). If you only need to support Open edX, XBlocks provide the best user experience. Open edX operators must install an XBlock into their Open edX instance before it can be used. See the `XBlock tutorial`_ to learn more about XBlocks. + * - **LTI** + - Adopt, Stable + - Learning Tools Interoperability is a standard that allows an individual piece of learnable/interactive content (the "tool") to be embedded via an IFrame in a host Learning Platform (the "consumer") such as Open edX. Open edX supports LTI content in both directions: `as a consumer`_ (external content appearing in an Open edX course) and `as a provider`_ (Open edX course content appearing in an external Learning Platform). If you need to support multiple Learning Platforms, and not just Open edX, LTI is usually the best way to integrate your content. Note that not all LTI versions/features are supported, however. + * - **Custom JavaScript Applications** + - Adopt, Stable + - If you have a single piece of content, such as a single interactive HTML5 animation or problem, and you want to use it in an Open edX course, you can create it as a `custom JavaScript application`_. Unlike XBlocks, these applications can be implemented without intervention by the Open edX operator. + * - **External Graders** + - Hold, Stable + - An external grader is a service that receives learner responses to a problem, processes those responses, and returns feedback and a problem grade to the edX platform. You build and deploy an external grader separately from the edX platform. An external grader is particularly useful for software programming courses where learners are asked to submit complex code. See the `external grader documentation`_ for details. + +For a more detailed comparison of content integration options, see `Options for Extending the edX Platform`_ in the *Open edX Developer's Guide*. + +.. _XBlock tutorial: https://edx.readthedocs.io/projects/xblock-tutorial/en/latest/ +.. _as a consumer: https://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/lti_component.html +.. _as a provider: https://edx.readthedocs.io/projects/edx-installing-configuring-and-running/en/latest/configuration/lti/ +.. _Options for Extending the edX Platform: https://edx.readthedocs.io/projects/edx-developer-guide/en/latest/extending_platform/extending.html +.. _custom JavaScript application: https://edx.readthedocs.io/projects/edx-developer-guide/en/latest/extending_platform/javascript.html +.. _external grader documentation: https://edx.readthedocs.io/projects/open-edx-ca/en/latest/exercises_tools/external_graders.html + + + + +Platform Features (Integrating Python Code) +=========================================== + +If you wish to customize aspects of the learner or educator experiences, you'll most likely need to create a Python plugin that can be installed into the platform and which uses Python APIs to extend the platform's functionality. + +Most python plugins are enabled using one of two methods: + +1. A Python Entry point: the core Open edX platform provides a standard plugin loading mechanism in |openedx.core.lib.plugins|_ which uses `stevedore`_ to find all installed python packages that declare a specific "entry point" in their setup.py file. See the ``entry_points`` defined in edx-platform's own ``setup.py`` for examples. +2. A Django setting: Some plugins require modification of Django settings, which is typically done by editing ``/edx/etc/lms.yml`` (in Production) or ``edx-platform/lms/envs/private.py`` (on Devstack). + +.. |openedx.core.lib.plugins| replace:: ``openedx.core.lib.plugins`` +.. _openedx.core.lib.plugins: https://github.com/edx/edx-platform/blob/master/openedx/core/lib/plugins.py +.. _stevedore: https://pypi.org/project/stevedore/ + +Here are the different integration points that python plugins can use: + +.. list-table:: + :header-rows: 1 + :widths: 15 10 75 + + * - Plugin Type + (and entry point or setting) + - Status + - Details + * - Django App Plugin (``lms.djangoapp`` and ``cms.djangoapp``) + - Adopt, Stable + - A "Django app plugin" is a self-contained Django `Application`_ that can define models (MySQL tables), new REST APIs, signal listeners, asynchronous tasks, and more. Even some parts of the core platform are implemented as Django app plugins, for better separation of concerns (``announcements``, ``credentials``, ``grades``, etc.) Read the `Django app plugin documentation`_ to learn more. + + Plugins can also inject custom data into django template contexts, to affect standard pages delivered by the core platform. See `Plugin Contexts`_ to learn more. + * - Course tab (``openedx.course_tab``) + - Hold, Stable + - A course tab plugin adds a new tab shown to learners within a course. ``courseware``, ``course_info``, and ``discussion`` are examples of built-in tab plugins. Read the `course tabs documentation`_ to learn more. + + This API may be changing soon with the new Courseware microfrontend implementation. + * - Course tool (``openedx.course_tool``) + - Hold, Stable + - The course home page (the landing page for the course) includes a "Course Tools" section that provides links to "tools" associated with the course. Examples of course tool plugins included in the core are reviews, updates, and bookmarks. See |course_tools.py|_ to learn more. + + This API may be changing soon with the new Courseware microfrontend implementation. + * - Custom registration form app (``REGISTRATION_EXTENSION_FORM`` Django setting in the LMS) + - Trial, Stable + - By default, the registration page for each instance of Open edX has fields that ask for information such as a user’s name, country, and highest level of education completed. You can add custom fields to the registration page for your own Open edX instance. These fields can be different types, including text entry fields and drop-down lists. See `Adding Custom Fields to the Registration Page`_. + * - Learning Context (``openedx.learning_context``) + - Trial, Limited + - A "Learning Context" is a course, a library, a program, a blog, an external site, or some other collection of content where learning happens. If you are trying to build a totally new learning experience that's not a type of course, you may need to implement a new learning context. Learning contexts are a new abstraction and are only supported in the nascent Blockstore-based XBlock runtime. Since existing courses use modulestore instead of Blockstore, they are not yet implemented as learning contexts. However, Blockstore-based content libraries are. See |learning_context.py|_ to learn more. + * - User partition scheme (``openedx.user_partition_scheme`` and ``openedx.dynamic_partition_generator``) + - Unknown, Stable + - A user partition scheme is a named way for dividing users in a course into groups, usually to show different content to different users or to run experiments. Partitions may be added to a course manually, or automatically added by a "dynamic partition generator." The core platform includes partition scheme plugins like ``random``, ``cohort``, and ``enrollment_track``. See the |UserPartition docstring|_ to learn more. + * - XBlock (``xblock.v1``) + - Adopt, Stable + - An XBlock provides a new type of learnable content that can be used in courses, content libraries, etc. See `Content Integrations`_. + * - XBlock unit tests (``xblock.test.v0``) + - Assess, Limited + - XBlocks can also install test code that will then be run alongside the platform's usual python unit tests. It's unclear how well-supported this is at the moment. + +.. _Application: https://docs.djangoproject.com/en/3.0/ref/applications/ +.. _Django app plugin documentation: https://github.com/edx/edx-platform/blob/master/openedx/core/djangoapps/plugins/README.rst +.. _Plugin Contexts: https://github.com/edx/edx-platform/blob/master/openedx/core/djangoapps/plugins/docs/decisions/0003-plugin-contexts.rst +.. _course tabs documentation: https://openedx.atlassian.net/wiki/spaces/AC/pages/30965919/Adding+a+new+course+tab +.. |course_tools.py| replace:: ``course_tools.py`` +.. _course_tools.py: https://github.com/edx/edx-platform/blob/master/openedx/features/course_experience/course_tools.py +.. _Adding Custom Fields to the Registration Page: https://edx.readthedocs.io/projects/edx-installing-configuring-and-running/en/latest/configuration/customize_registration_page.html +.. |learning_context.py| replace:: ``learning_context.py`` +.. _learning_context.py: https://github.com/edx/edx-platform/blob/master/openedx/core/djangoapps/xblock/learning_context/learning_context.py +.. |UserPartition docstring| replace:: ``UserPartition`` docstring +.. _UserPartition docstring: https://github.com/edx/edx-platform/blob/f8cc58618a39c9f7b8e9e1001eb2d7a10395797e/common/lib/xmodule/xmodule/partitions/partitions.py#L105-L120 + +Platform Look & Feel +==================== + +Themes ("Comprehensive Theming") +******************************** + +*Status: Hold, Stable* + +Changing the look and feel of the edX platform is generally done by creating a new "theme". See `Changing Themes for an Open edX Site`_ for documentation. Note that most theming documentation applies to the legacy UI components used in edX, which are .html files (django/mako templates) rendered by the backend and styled using either the "v1" or "v2" (a.k.a. "Pattern Library") stylesheets. However, the platform UI is slowly being replaced by new React-based "MicroFrontEnds" (MFEs), and a different approach is required for theming MFEs (see `Theming Microfrontends`_). + +Theming Microfrontends +********************** + +*Status: Trial, Limited* + +Methods for theming MFEs are still being developed. It is likely to involve: + +#. Branding: modifying fonts, colors, and logos via themes/css (there is an |example edx theme|_ that you can use as a template for defining fonts and colors, but some MFEs currently lack a mechanism for changing the theme). +#. Configuration: modifying settings and toggles via MFE configuration settings +#. Customization: gives the ability to override specific elements like the header and footer to better reflect your branding or offer different functionality - see `Overriding Brand Specific Elements`_. +#. Frontend Plugins: runtime configuration of frontend components in designated slots on frontend pages + +In addition, Open edX operators will be able to replace entire MFEs with completely custom MFE implementations that use the same backend APIs. + +.. |example edx theme| replace:: example ``edx`` theme +.. _example edx theme: https://github.com/edx/paragon/tree/master/scss/edx +.. _Changing Themes for an Open edX Site: https://edx.readthedocs.io/projects/edx-installing-configuring-and-running/en/latest/configuration/changing_appearance/theming/ +.. _Overriding Brand Specific Elements: https://edx.readthedocs.io/projects/edx-developer-docs/en/latest/developers_guide/micro_frontends_in_open_edx.html#overriding-brand-specific-elements + +Custom frontends +**************** + +*Status: Trial, Limited* + +If you need a *very* custom look and feel for your users, and you have the time and resources required for a huge project, you can consider creating a custom frontend for Open edX, which is a completely separate application that runs on its own domain and integrates with Open edX using REST APIs. The edX Mobile App can be thought of as an example of a separate frontend that connects to Open edX using only REST APIs. Another example is `LabXchange <https://www.labxchange.org/>`_. If you develop your custom frontend using Django, you may wish to use the `auth-backends <https://github.com/edx/auth-backends>`_ django plugin for user authentication. diff --git a/docs/guides/guides.rst b/docs/guides/guides.rst index a92ac7a3bf31aa01a1e7026d859fb03a38d90492..5eb3aa5e270c418b39c8aad7bb757116a89a3658 100644 --- a/docs/guides/guides.rst +++ b/docs/guides/guides.rst @@ -4,6 +4,7 @@ Guides .. toctree:: :maxdepth: 2 + extension_points testing/testing frontend/javascript frontend/styling diff --git a/docs/guides/testing/testing.rst b/docs/guides/testing/testing.rst index a7b0825b9a3d11fe061c682f5447d7e8e80cd643..9f7f098a9f1f669c9d2bda31e4206e567d4044f0 100644 --- a/docs/guides/testing/testing.rst +++ b/docs/guides/testing/testing.rst @@ -161,6 +161,10 @@ against a database created by applying the migrations instead, use the paver test_system -s lms --enable-migrations +To see the migration output, use:: + + paver test_system -s lms --enable-migrations --verbose --disable_capture + To run a single django test class use this command:: paver test_system -t lms/djangoapps/courseware/tests/tests.py::ActivateLoginTest diff --git a/docs/swagger.yaml b/docs/swagger.yaml index b02947c814af6915fce4613774e7d9e494e838f6..fa2065eb07a7a655be965b197b18d20a85a7bd3b 100755 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -19,10 +19,10 @@ paths: /badges/v1/assertions/user/{username}/: get: operationId: badges_v1_assertions_user_read - summary: '** Use cases **' + summary: '**Use Cases**' description: "Request a list of assertions for a user, optionally constrained\ - \ to a course.\n\n** Example Requests **\n\n GET /api/badges/v1/assertions/user/{username}/\n\ - \n** Response Values **\n\n Body comprised of a list of objects with the\ + \ to a course.\n\n**Example Requests**\n\n GET /api/badges/v1/assertions/user/{username}/\n\ + \n**Response Values**\n\n Body comprised of a list of objects with the\ \ following fields:\n\n * badge_class: The badge class the assertion was\ \ awarded for. Represented as an object\n with the following fields:\n\ \ * slug: The identifier for the badge class\n * issuing_component:\ @@ -35,28 +35,27 @@ paths: \ * image_url: The baked assertion image derived from the badge_class icon--\ \ contains metadata about the award\n in its headers.\n * assertion_url:\ \ The URL to the OpenBadges BadgeAssertion object, for verification by compatible\ - \ tools\n and software.\n\n** Params **\n\n * slug (optional): The\ - \ identifier for a particular badge class to filter by.\n * issuing_component\ - \ (optional): The issuing component for a particular badge class to filter\ - \ by\n (requires slug to have been specified, or this will be ignored.)\ - \ If slug is provided and this is not,\n assumes the issuing_component\ - \ should be empty.\n * course_id (optional): Returns assertions that were\ - \ awarded as part of a particular course. If slug is\n provided, and\ - \ this field is not specified, assumes that the target badge has an empty\ - \ course_id field.\n '*' may be used to get all badges with the specified\ - \ slug, issuing_component combination across all courses.\n\n** Returns **\n\ - \n * 200 on success, with a list of Badge Assertion objects.\n * 403\ - \ if a user who does not have permission to masquerade as\n another user\ - \ specifies a username other than their own.\n * 404 if the specified user\ - \ does not exist\n\n {\n \"count\": 7,\n \"previous\": null,\n\ - \ \"num_pages\": 1,\n \"results\": [\n {\n \ - \ \"badge_class\": {\n \"slug\": \"special_award\"\ - ,\n \"issuing_component\": \"openedx__course\",\n \ - \ \"display_name\": \"Very Special Award\",\n \ - \ \"course_id\": \"course-v1:edX+DemoX+Demo_Course\",\n \ - \ \"description\": \"Awarded for people who did something incredibly\ - \ special\",\n \"criteria\": \"Do something incredibly\ - \ special.\",\n \"image\": \"http://example.com/media/badge_classes/badges/special_xdpqpBv_9FYOZwN.png\"\ + \ tools\n and software.\n\n**Params**\n\n * slug (optional): The identifier\ + \ for a particular badge class to filter by.\n * issuing_component (optional):\ + \ The issuing component for a particular badge class to filter by\n (requires\ + \ slug to have been specified, or this will be ignored.) If slug is provided\ + \ and this is not,\n assumes the issuing_component should be empty.\n\ + \ * course_id (optional): Returns assertions that were awarded as part\ + \ of a particular course. If slug is\n provided, and this field is not\ + \ specified, assumes that the target badge has an empty course_id field.\n\ + \ '*' may be used to get all badges with the specified slug, issuing_component\ + \ combination across all courses.\n\n**Returns**\n\n * 200 on success,\ + \ with a list of Badge Assertion objects.\n * 403 if a user who does not\ + \ have permission to masquerade as\n another user specifies a username\ + \ other than their own.\n * 404 if the specified user does not exist\n\n\ + \ {\n \"count\": 7,\n \"previous\": null,\n \"num_pages\"\ + : 1,\n \"results\": [\n {\n \"badge_class\"\ + : {\n \"slug\": \"special_award\",\n \ + \ \"issuing_component\": \"openedx__course\",\n \"display_name\"\ + : \"Very Special Award\",\n \"course_id\": \"course-v1:edX+DemoX+Demo_Course\"\ + ,\n \"description\": \"Awarded for people who did something\ + \ incredibly special\",\n \"criteria\": \"Do something\ + \ incredibly special.\",\n \"image\": \"http://example.com/media/badge_classes/badges/special_xdpqpBv_9FYOZwN.png\"\ \n },\n \"image_url\": \"http://badges.example.com/media/issued/cd75b69fc1c979fcc1697c8403da2bdf.png\"\ ,\n \"assertion_url\": \"http://badges.example.com/public/assertions/07020647-e772-44dd-98b7-d13d34335ca6\"\ \n },\n ...\n ]\n }" @@ -111,7 +110,7 @@ paths: \ list contains 10 bookmarks by default. The page\nsize can be altered by\ \ passing parameter \"page_size=<page_size>\".\n\nTo include the optional\ \ fields pass the values in \"fields\" parameter\nas a comma separated list.\ - \ Possible values are:\n\n* \"display_name\"\n* \"path\"\n\n# Example Requests\n\ + \ Possible values are:\n\n* \"display_name\"\n* \"path\"\n\n**Example Requests**\n\ \nGET /api/bookmarks/v1/bookmarks/?course_id={course_id1}&fields=display_name,path" parameters: - name: page @@ -143,8 +142,8 @@ paths: description: "The POST request only needs to contain one parameter \"usage_id\"\ .\n\nHttp400 is returned if the format of the request is not correct,\nthe\ \ usage_id is invalid or a block corresponding to the usage_id\ncould not\ - \ be found.\n\n# Example Requests\n\nPOST /api/bookmarks/v1/bookmarks/\nRequest\ - \ data: {\"usage_id\": <usage-id>}" + \ be found.\n\n**Example Requests**\n\nPOST /api/bookmarks/v1/bookmarks/\n\ + Request data: {\"usage_id\": <usage-id>}" parameters: [] responses: '201': @@ -156,7 +155,7 @@ paths: get: operationId: bookmarks_v1_bookmarks_read summary: Get a specific bookmark for a user. - description: "# Example Requests\n\nGET /api/bookmarks/v1/bookmarks/{username},{usage_id}?fields=display_name,path" + description: "**Example Requests**\n\nGET /api/bookmarks/v1/bookmarks/{username},{usage_id}?fields=display_name,path" parameters: [] responses: '200': @@ -216,9 +215,7 @@ paths: get: operationId: ccx_v0_ccx_list summary: Gets a list of CCX Courses for a given Master Course. - description: "Additional parameters are allowed for pagination purposes.\n\n\ - Args:\n request (Request): Django request object.\n\nReturn:\n A JSON\ - \ serialized representation of a list of CCX courses." + description: Additional parameters are allowed for pagination purposes. parameters: - name: page in: query @@ -257,9 +254,7 @@ paths: - ccx post: operationId: ccx_v0_ccx_create - summary: Creates a new CCX course for a given Master Course. - description: "Args:\n request (Request): Django request object.\n\nReturn:\n\ - \ A JSON serialized representation a newly created CCX course." + description: Creates a new CCX course for a given Master Course. parameters: - name: data in: body @@ -277,10 +272,7 @@ paths: /ccx/v0/ccx/{ccx_course_id}/: get: operationId: ccx_v0_ccx_read - summary: Gets a CCX Course information. - description: "Args:\n request (Request): Django request object.\n ccx_course_id\ - \ (string): URI element specifying the CCX course location.\n\nReturn:\n \ - \ A JSON serialized representation of the CCX course." + description: Gets a CCX Course information. parameters: [] responses: '200': @@ -291,9 +283,7 @@ paths: - ccx patch: operationId: ccx_v0_ccx_partial_update - summary: Modifies a CCX course. - description: "Args:\n request (Request): Django request object.\n ccx_course_id\ - \ (string): URI element specifying the CCX course location." + description: Modifies a CCX course. parameters: - name: data in: body @@ -309,9 +299,7 @@ paths: - ccx delete: operationId: ccx_v0_ccx_delete - summary: Deletes a CCX course. - description: "Args:\n request (Request): Django request object.\n ccx_course_id\ - \ (string): URI element specifying the CCX course location." + description: Deletes a CCX course. parameters: [] responses: '204': @@ -367,11 +355,7 @@ paths: /certificates/v0/certificates/{username}/courses/{course_id}/: get: operationId: certificates_v0_certificates_courses_read - summary: Gets a certificate information. - description: "Args:\n request (Request): Django request object.\n username\ - \ (string): URI element specifying the user's username.\n course_id (string):\ - \ URI element specifying the course location.\n\nReturn:\n A JSON serialized\ - \ representation of the certificate." + description: Gets a certificate information. parameters: [] responses: '200': @@ -475,9 +459,7 @@ paths: - cohorts delete: operationId: cohorts_v1_courses_cohorts_users_delete - summary: Removes and user from a specific cohort. - description: "Note: It's better to use the post method to move users between\ - \ cohorts." + description: Removes and user from a specific cohort. parameters: [] responses: '204': @@ -1190,6 +1172,67 @@ paths: in: path required: true type: string + /courses/v1/course_ids/: + get: + operationId: courses_v1_course_ids_list + summary: '**Use Cases**' + description: "Request a list of course IDs for all courses the specified user\ + \ can\n access based on the provided parameters.\n\n**Example Requests**\n\ + \n GET /api/courses/v1/courses_ids/\n\n**Response Values**\n\n Body\ + \ comprises a list of course ids and pagination details.\n\n**Parameters**\n\ + \n username (optional):\n The username of the specified user whose\ + \ visible courses we\n want to see.\n\n role (required):\n \ + \ Course ids are filtered such that only those for which the\n user\ + \ has the specified role are returned. Role can be \"staff\"\n or \"\ + instructor\".\n Case-insensitive.\n\n**Returns**\n\n * 200 on success,\ + \ with a list of course ids and pagination details\n * 400 if an invalid\ + \ parameter was sent or the username was not provided\n for an authenticated\ + \ request.\n * 403 if a user who does not have permission to masquerade\ + \ as\n another user who specifies a username other than their own.\n\ + \ * 404 if the specified user does not exist, or the requesting user does\n\ + \ not have permission to view their courses.\n\n Example response:\n\ + \n {\n \"results\":\n [\n \ + \ \"course-v1:edX+DemoX+Demo_Course\"\n ],\n \ + \ \"pagination\": {\n \"previous\": null,\n \ + \ \"num_pages\": 1,\n \"next\": null,\n \"\ + count\": 1\n }\n }" + parameters: + - name: page + in: query + description: A page number within the paginated result set. + required: false + type: integer + - name: page_size + in: query + description: Number of results to return per page. + required: false + type: integer + responses: + '200': + description: '' + schema: + required: + - count + - results + type: object + properties: + count: + type: integer + next: + type: string + format: uri + x-nullable: true + previous: + type: string + format: uri + x-nullable: true + results: + type: array + items: + type: string + tags: + - courses + parameters: [] /courses/v1/courses/: get: operationId: courses_v1_courses_list @@ -1197,32 +1240,29 @@ paths: description: "Request information on all courses visible to the specified user.\n\ \n**Example Requests**\n\n GET /api/courses/v1/courses/\n\n**Response Values**\n\ \n Body comprises a list of objects as returned by `CourseDetailView`.\n\ - \n**Parameters**\n search_term (optional):\n Search term to filter\ + \n**Parameters**\n\n search_term (optional):\n Search term to filter\ \ courses (used by ElasticSearch).\n\n username (optional):\n The\ \ username of the specified user whose visible courses we\n want to\ \ see. The username is not required only if the API is\n requested\ \ by an Anonymous user.\n\n org (optional):\n If specified, visible\ \ `CourseOverview` objects are filtered\n such that only those belonging\ \ to the organization with the\n provided org code (e.g., \"HarvardX\"\ - ) are returned.\n Case-insensitive.\n\n role (optional):\n \ - \ If specified, visible `CourseOverview` objects are filtered\n such\ - \ that only those for which the user has the specified role\n are returned.\ - \ Multiple role parameters can be specified.\n Case-insensitive.\n\n\ - **Returns**\n\n * 200 on success, with a list of course discovery objects\ - \ as returned\n by `CourseDetailView`.\n * 400 if an invalid parameter\ - \ was sent or the username was not provided\n for an authenticated request.\n\ - \ * 403 if a user who does not have permission to masquerade as\n \ - \ another user specifies a username other than their own.\n * 404 if the\ - \ specified user does not exist, or the requesting user does\n not have\ - \ permission to view their courses.\n\n Example response:\n\n [\n\ - \ {\n \"blocks_url\": \"/api/courses/v1/blocks/?course_id=edX%2Fexample%2F2012_Fall\"\ - ,\n \"media\": {\n \"course_image\": {\n \ - \ \"uri\": \"/c4x/edX/example/asset/just_a_test.jpg\",\n \ - \ \"name\": \"Course Image\"\n }\n },\n \ - \ \"description\": \"An example course.\",\n \"end\": \"2015-09-19T18:00:00Z\"\ - ,\n \"enrollment_end\": \"2015-07-15T00:00:00Z\",\n \ - \ \"enrollment_start\": \"2015-06-15T00:00:00Z\",\n \"course_id\"\ - : \"edX/example/2012_Fall\",\n \"name\": \"Example Course\",\n\ + ) are returned.\n Case-insensitive.\n\n**Returns**\n\n * 200 on\ + \ success, with a list of course discovery objects as returned\n by `CourseDetailView`.\n\ + \ * 400 if an invalid parameter was sent or the username was not provided\n\ + \ for an authenticated request.\n * 403 if a user who does not have\ + \ permission to masquerade as\n another user specifies a username other\ + \ than their own.\n * 404 if the specified user does not exist, or the\ + \ requesting user does\n not have permission to view their courses.\n\ + \n Example response:\n\n [\n {\n \"blocks_url\"\ + : \"/api/courses/v1/blocks/?course_id=edX%2Fexample%2F2012_Fall\",\n \ + \ \"media\": {\n \"course_image\": {\n \"\ + uri\": \"/c4x/edX/example/asset/just_a_test.jpg\",\n \"name\"\ + : \"Course Image\"\n }\n },\n \"description\"\ + : \"An example course.\",\n \"end\": \"2015-09-19T18:00:00Z\",\n\ + \ \"enrollment_end\": \"2015-07-15T00:00:00Z\",\n \"\ + enrollment_start\": \"2015-06-15T00:00:00Z\",\n \"course_id\":\ + \ \"edX/example/2012_Fall\",\n \"name\": \"Example Course\",\n\ \ \"number\": \"example\",\n \"org\": \"edX\",\n \ \ \"start\": \"2015-07-17T12:00:00Z\",\n \"start_display\"\ : \"July 17, 2015\",\n \"start_type\": \"timestamp\"\n \ @@ -1484,6 +1524,76 @@ paths: in: path required: true type: string + ? /courseware/course/(P{course_key_string}[/+]+{var}[/+]+api/courseware/course/(P{course_key_string}[/+]+(/|+)[/+]+{var}[/]+) + : get: + operationId: courseware_course_+]+api_courseware_course_+]+(_|+)[_]+)_read + summary: '**Use Cases**' + description: "Request details for a course\n\n**Example Requests**\n\n GET\ + \ /api/courseware/course/{course_key}\n\n**Response Values**\n\n Body consists\ + \ of the following fields:\n\n * effort: A textual description of the weekly\ + \ hours of effort expected\n in the course.\n * end: Date the course\ + \ ends, in ISO 8601 notation\n * enrollment_end: Date enrollment ends,\ + \ in ISO 8601 notation\n * enrollment_start: Date enrollment begins, in\ + \ ISO 8601 notation\n * id: A unique identifier of the course; a serialized\ + \ representation\n of the opaque key identifying the course.\n *\ + \ media: An object that contains named media items. Included here:\n \ + \ * course_image: An image to show for the course. Represented\n \ + \ as an object with the following fields:\n * uri: The location\ + \ of the image\n * name: Name of the course\n * number: Catalog number\ + \ of the course\n * org: Name of the organization that owns the course\n\ + \ * short_description: A textual description of the course\n * start:\ + \ Date the course begins, in ISO 8601 notation\n * start_display: Readably\ + \ formatted start of the course\n * start_type: Hint describing how `start_display`\ + \ is set. One of:\n * `\"string\"`: manually set by the course author\n\ + \ * `\"timestamp\"`: generated from the `start` timestamp\n \ + \ * `\"empty\"`: no start date is specified\n * pacing: Course pacing.\ + \ Possible values: instructor, self\n * tabs: Course tabs\n * enrollment:\ + \ Enrollment status of authenticated user\n * mode: `audit`, `verified`,\ + \ etc\n * is_active: boolean\n * can_load_course: Whether the user\ + \ can view the course (AccessResponse object)\n * is_staff: Whether the\ + \ user has staff access to the course\n\n**Parameters:**\n\n requested_fields\ + \ (optional) comma separated list:\n If set, then only those fields\ + \ will be returned.\n username (optional) username to masquerade as (if\ + \ requesting user is staff)\n\n**Returns**\n\n * 200 on success with above\ + \ fields.\n * 400 if an invalid parameter was sent or the username was\ + \ not provided\n for an authenticated request.\n * 403 if a user who\ + \ does not have permission to masquerade as\n another user specifies\ + \ a username other than their own.\n * 404 if the course is not available\ + \ or cannot be seen." + parameters: [] + responses: + '200': + description: '' + tags: + - courseware + parameters: + - name: course_key_string + in: path + required: true + type: string + - name: var + in: path + required: true + type: string + ? /courseware/sequence/(P{usage_key_string}{var}|api/courseware/sequence/(P{usage_key_string}(:i4x://[/]+/[/]+/[/]+/[@]+(:@[/]+))|{var}) + : get: + operationId: courseware_sequence_courseware_sequence__[_]+_[_]+_[_]+_[@]+(:@[_read + description: Return response to a GET request. + parameters: [] + responses: + '200': + description: '' + tags: + - courseware + parameters: + - name: usage_key_string + in: path + required: true + type: string + - name: var + in: path + required: true + type: string /credit/v1/courses/: get: operationId: credit_v1_courses_list @@ -2356,6 +2466,21 @@ paths: in: path required: true type: string + /edx_proctoring/v1/retire_user/{user_id}/: + post: + operationId: edx_proctoring_v1_retire_user_create + description: Obfuscates all PII for a given user_id + parameters: [] + responses: + '201': + description: '' + tags: + - edx_proctoring + parameters: + - name: user_id + in: path + required: true + type: string /edxnotes/v1/retire_user/: post: operationId: edxnotes_v1_retire_user_create @@ -2370,9 +2495,7 @@ paths: /embargo/v1/course_access/: get: operationId: embargo_v1_course_access_list - summary: GET /api/embargo/v1/course_access/ - description: "Arguments:\n request (HttpRequest)\n\nReturn:\n Response:\ - \ True or False depending on the check." + description: GET /api/embargo/v1/course_access/ parameters: [] responses: '200': @@ -2384,12 +2507,7 @@ paths: get: operationId: enrollment_v1_course_read summary: Read enrollment information for a particular course. - description: "HTTP Endpoint for retrieving course level enrollment information.\n\ - \nArgs:\n request (Request): To get current course enrollment information,\ - \ a GET request will return\n information for the specified course.\n\ - \ course_id (str): URI element specifying the course location. Enrollment\ - \ information will be\n returned.\n\nReturn:\n A JSON serialized\ - \ representation of the course enrollment details." + description: HTTP Endpoint for retrieving course level enrollment information. parameters: [] responses: '200': @@ -2441,13 +2559,7 @@ paths: summary: Create, read, or update enrollment information for a user. description: "HTTP Endpoint for all CRUD operations for a user course enrollment.\ \ Allows creation, reading, and\nupdates of the current enrollment for a particular\ - \ course.\n\nArgs:\n request (Request): To get current course enrollment\ - \ information, a GET request will return\n information for the current\ - \ user and the specified course.\n course_id (str): URI element specifying\ - \ the course location. Enrollment information will be\n returned, created,\ - \ or updated for this particular course.\n username (str): The username\ - \ associated with this enrollment request.\n\nReturn:\n A JSON serialized\ - \ representation of the course enrollment." + \ course." parameters: [] responses: '200': @@ -2465,13 +2577,7 @@ paths: summary: Create, read, or update enrollment information for a user. description: "HTTP Endpoint for all CRUD operations for a user course enrollment.\ \ Allows creation, reading, and\nupdates of the current enrollment for a particular\ - \ course.\n\nArgs:\n request (Request): To get current course enrollment\ - \ information, a GET request will return\n information for the current\ - \ user and the specified course.\n course_id (str): URI element specifying\ - \ the course location. Enrollment information will be\n returned, created,\ - \ or updated for this particular course.\n username (str): The username\ - \ associated with this enrollment request.\n\nReturn:\n A JSON serialized\ - \ representation of the course enrollment." + \ course." parameters: [] responses: '200': @@ -2700,6 +2806,39 @@ paths: required: true type: string pattern: '[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}' + /entitlements/v1/entitlements/{uuid}/enrollments: + post: + operationId: entitlements_v1_entitlements_enrollments_create + description: "On POST this method will be called and will handle enrolling a\ + \ user in the\nprovided course_run_id from the data. This is called on a specific\ + \ entitlement\nUUID so the course_run_id has to correspond to the Course that\ + \ is assigned to\nthe Entitlement.\n\nWhen this API is called for a user who\ + \ is already enrolled in a run that User\nwill be unenrolled from their current\ + \ run and enrolled in the new run if it is\navailable." + parameters: [] + responses: + '201': + description: '' + tags: + - entitlements + delete: + operationId: entitlements_v1_entitlements_enrollments_delete + summary: On DELETE call to this API we will unenroll the course enrollment for + the provided uuid + description: "If is_refund parameter is provided then unenroll the user, set\ + \ Entitlement expiration, and issue\na refund" + parameters: [] + responses: + '204': + description: '' + tags: + - entitlements + parameters: + - name: uuid + in: path + required: true + type: string + format: uuid /experiments/v0/custom/REV-934/: get: operationId: experiments_v0_custom_REV-934_list @@ -2795,24 +2934,6 @@ paths: tags: - experiments parameters: [] - /experiments/v0/data/bulk_upsert/: - put: - operationId: experiments_v0_data_bulk_upsert - description: '' - parameters: - - name: data - in: body - required: true - schema: - $ref: '#/definitions/ExperimentData' - responses: - '200': - description: '' - schema: - $ref: '#/definitions/ExperimentData' - tags: - - experiments - parameters: [] /experiments/v0/data/{id}/: get: operationId: experiments_v0_data_read @@ -2939,24 +3060,6 @@ paths: tags: - experiments parameters: [] - /experiments/v0/key-value/bulk_upsert/: - put: - operationId: experiments_v0_key-value_bulk_upsert - description: '' - parameters: - - name: data - in: body - required: true - schema: - $ref: '#/definitions/ExperimentKeyValue' - responses: - '200': - description: '' - schema: - $ref: '#/definitions/ExperimentKeyValue' - tags: - - experiments - parameters: [] /experiments/v0/key-value/{id}/: get: operationId: experiments_v0_key-value_read @@ -3020,11 +3123,7 @@ paths: /grades/v1/courses/: get: operationId: grades_v1_courses_list - description: "Gets a course progress status.\nArgs:\n request (Request):\ - \ Django request object.\n course_id (string): URI element specifying the\ - \ course location.\n Can also be passed as a GET parameter\ - \ instead.\nReturn:\n A JSON serialized representation of the requesting\ - \ user's current grade status." + description: Gets a course progress status. parameters: - name: cursor in: query @@ -3045,11 +3144,7 @@ paths: /grades/v1/courses/{course_id}/: get: operationId: grades_v1_courses_read - description: "Gets a course progress status.\nArgs:\n request (Request):\ - \ Django request object.\n course_id (string): URI element specifying the\ - \ course location.\n Can also be passed as a GET parameter\ - \ instead.\nReturn:\n A JSON serialized representation of the requesting\ - \ user's current grade status." + description: Gets a course progress status. parameters: [] responses: '200': @@ -3156,10 +3251,7 @@ paths: get: operationId: grades_v1_subsection_read description: "Returns subection grade data, override grade data and a history\ - \ of changes made to\na specific users specific subsection grade.\n\nArgs:\n\ - \ subsection_id: String representation of a usage_key, which is an opaque\ - \ key of\n a persistant subection grade.\n user_id: An integer represenation\ - \ of a user" + \ of changes made to\na specific users specific subsection grade." parameters: [] responses: '200': @@ -3457,8 +3549,9 @@ paths: /organizations/v0/organizations/: get: operationId: organizations_v0_organizations_list - description: "Organization view to fetch list organization data or single organization\n\ - using organization short name." + description: "Organization view to:\n - fetch list organization data or single\ + \ organization using organization short name.\n - create or update an organization\ + \ via the PUT endpoint." parameters: - name: page in: query @@ -3499,8 +3592,9 @@ paths: /organizations/v0/organizations/{short_name}/: get: operationId: organizations_v0_organizations_read - description: "Organization view to fetch list organization data or single organization\n\ - using organization short name." + description: "Organization view to:\n - fetch list organization data or single\ + \ organization using organization short name.\n - create or update an organization\ + \ via the PUT endpoint." parameters: [] responses: '200': @@ -3509,6 +3603,39 @@ paths: $ref: '#/definitions/Organization' tags: - organizations + put: + operationId: organizations_v0_organizations_update + description: We perform both Update and Create action via the PUT method. + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/Organization' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/Organization' + tags: + - organizations + patch: + operationId: organizations_v0_organizations_partial_update + description: We disable PATCH because all updates and creates should use the + PUT action above. + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/Organization' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/Organization' + tags: + - organizations parameters: - name: short_name in: path @@ -3721,13 +3848,15 @@ paths: type: string /program_enrollments/v1/programs/{program_uuid}/overview/: get: - operationId: program_enrollments_v1_programs_overview_list - description: "Defines the GET endpoint for overviews of course enrollments\n\ - for a user as part of a program." + operationId: program_enrollments_v1_programs_overview_read + description: "A view for getting data associated with a user's course enrollments\n\ + as part of a program enrollment." parameters: [] responses: '200': description: '' + schema: + $ref: '#/definitions/CourseRunOverviewList' tags: - program_enrollments parameters: @@ -3735,6 +3864,119 @@ paths: in: path required: true type: string + /program_enrollments/v1/users/{username}/programs/{program_uuid}/courses: + get: + operationId: program_enrollments_v1_users_programs_courses_list + summary: Get an overview of each of a user's course enrollments associated with + a program. + description: "This endpoint exists to get an overview of each course-run enrollment\n\ + that a user has for course-runs within a given program.\nFields included are\ + \ the title, upcoming due dates, etc.\nThis API endpoint is intended for use\ + \ with the\n[Program Learner Portal MFE](https://github.com/edx/frontend-app-learner-portal-programs).\n\ + \nIt is important to note that the set of enrollments that this endpoint returns\n\ + is different than a user's set of *program-course-run enrollments*.\nSpecifically,\ + \ this endpoint may include course runs that are *within*\nthe specified program\ + \ but were not *enrolled in* via the specified program.\n\n**Example Response:**\n\ + ```json\n{\n \"next\": null,\n \"previous\": null,\n \"results\"\ + : [\n {\n \"course_run_id\": \"edX+AnimalsX+Aardvarks\"\ + ,\n \"display_name\": \"Astonishing Aardvarks\",\n \"\ + course_run_url\": \"https://courses.edx.org/courses/course-v1:edX+AnimalsX+Aardvarks/course/\"\ + ,\n \"start_date\": \"2017-02-05T05:00:00Z\",\n \"end_date\"\ + : \"2018-02-05T05:00:00Z\",\n \"course_run_status\": \"completed\"\ + \n \"emails_enabled\": true,\n \"due_dates\": [\n \ + \ {\n \"name\": \"Introduction: What even\ + \ is an aardvark?\",\n \"url\": \"https://courses.edx.org/courses/course-v1:edX+AnimalsX+Aardvarks/jump_to/\n\ + \ block-v1:edX+AnimalsX+Aardvarks+type@chapter+block@1414ffd5143b4b508f739b563ab468b7\"\ + ,\n \"date\": \"2017-05-01T05:00:00Z\"\n \ + \ },\n {\n \"name\": \"Quiz: Aardvark or\ + \ Anteater?\",\n \"url\": \"https://courses.edx.org/courses/course-v1:edX+AnimalsX+Aardvarks/jump_to/\n\ + \ block-v1:edX+AnimalsX+Aardvarks+type@sequential+block@edx_introduction\"\ + ,\n \"date\": \"2017-03-05T00:00:00Z\"\n \ + \ }\n ],\n \"micromasters_title\": \"Animals\",\n \ + \ \"certificate_download_url\": \"https://courses.edx.org/certificates/123\"\ + \n },\n {\n \"course_run_id\": \"edX+AnimalsX+Baboons\"\ + ,\n \"display_name\": \"Breathtaking Baboons\",\n \"\ + course_run_url\": \"https://courses.edx.org/courses/course-v1:edX+AnimalsX+Baboons/course/\"\ + ,\n \"start_date\": \"2018-02-05T05:00:00Z\",\n \"end_date\"\ + : null,\n \"course_run_status\": \"in_progress\"\n \"\ + emails_enabled\": false,\n \"due_dates\": [],\n \"micromasters_title\"\ + : \"Animals\",\n \"certificate_download_url\": \"https://courses.edx.org/certificates/123\"\ + ,\n \"resume_course_run_url\": \"https://courses.edx.org/courses/course-v1:edX+AnimalsX+Baboons/jump_to/\n\ + \ block-v1:edX+AnimalsX+Baboons+type@sequential+block@edx_introduction\"\ + \n }\n ]\n}\n```" + parameters: + - name: cursor + in: query + description: The pagination cursor value. + required: false + type: string + - name: page_size + in: query + description: Number of results to return per page. Defaults to 10. Maximum + is 25. + type: integer + - name: username + in: path + description: The username of the user for which enrollment overviews will + be fetched. For now, this must be the requesting user; otherwise, 403 + will be returned. In the future, global staff users may be able to supply + other usernames. + type: string + required: true + - name: program_uuid + in: path + description: UUID of a program. Enrollments will be returned for course + runs in this program. + type: string + required: true + responses: + '200': + description: '' + schema: + $ref: '#/definitions/PageOfCourseRunOverview' + '401': + description: The requester is not authenticated. + '403': + description: The requester cannot access the specified program and/or the + requester may not retrieve this data for the specified user. + '404': + description: The requested program does not exist. + tags: + - program_enrollments + parameters: + - name: program_uuid + in: path + required: true + type: string + - name: username + in: path + required: true + type: string + /team/v0/bulk_team_membership/{course_id}: + get: + operationId: team_v0_bulk_team_membership_read + description: Download CSV with team membership data for given course run. + parameters: [] + responses: + '200': + description: '' + tags: + - team + post: + operationId: team_v0_bulk_team_membership_create + description: Process uploaded CSV to modify team memberships for given course + run. + parameters: [] + responses: + '201': + description: '' + tags: + - team + parameters: + - name: course_id + in: path + required: true + type: string /team/v0/team_membership/: get: operationId: team_v0_team_membership_list @@ -3907,10 +4149,10 @@ paths: get: operationId: third_party_auth_v0_providers_user_status_list summary: GET /api/third_party_auth/v0/providers/user_status/ - description: "**GET Response Values**\n{\n \"accepts_logins\": true,\n \ - \ \"name\": \"Google\",\n \"disconnect_url\": \"/auth/disconnect/google-oauth2/?\"\ + description: "**GET Response Values**\n```\n{\n \"accepts_logins\": true,\n\ + \ \"name\": \"Google\",\n \"disconnect_url\": \"/auth/disconnect/google-oauth2/?\"\ ,\n \"connect_url\": \"/auth/login/google-oauth2/?auth_entry=account_settings&next=%2Faccount%2Fsettings\"\ - ,\n \"connected\": false,\n \"id\": \"oa2-google-oauth2\"\n}" + ,\n \"connected\": false,\n \"id\": \"oa2-google-oauth2\"\n}\n```" parameters: [] responses: '200': @@ -4004,11 +4246,7 @@ paths: get: operationId: third_party_auth_v0_users_list summary: Read provider information for a user. - description: "Allows reading the list of providers for a specified user.\n\n\ - Args:\n request (Request): The HTTP GET request\n\nRequest Parameters:\n\ - \ Must provide one of 'email' or 'username'. If both are provided,\n \ - \ the username will be ignored.\n\nReturn:\n JSON serialized list of\ - \ the providers linked to this user." + description: Allows reading the list of providers for a specified user. parameters: [] responses: '200': @@ -4020,10 +4258,7 @@ paths: get: operationId: third_party_auth_v0_users_read summary: Read provider information for a user. - description: "Allows reading the list of providers for a specified user.\n\n\ - Args:\n request (Request): The HTTP GET request\n username (str): Fetch\ - \ the list of providers linked to this user\n\nReturn:\n JSON serialized\ - \ list of the providers linked to this user." + description: Allows reading the list of providers for a specified user. parameters: [] responses: '200': @@ -4038,7 +4273,8 @@ paths: /user/v1/accounts: get: operationId: user_v1_accounts_list - description: GET /api/user/v1/accounts?username={username1,username2} + description: "GET /api/user/v1/accounts?username={username1,username2}\nGET\ + \ /api/user/v1/accounts?email={user_email}" parameters: [] responses: '200': @@ -4064,16 +4300,17 @@ paths: /user/v1/accounts/replace_usernames/: post: operationId: user_v1_accounts_replace_usernames_create - description: "POST /api/user/v1/accounts/replace_usernames/\n{\n \"username_mappings\"\ - : [\n {\"current_username_1\": \"desired_username_1\"},\n {\"\ - current_username_2\": \"desired_username_2\"}\n ]\n}\n\n**POST Parameters**\n\ - \nA POST request must include the following parameter.\n\n* username_mappings:\ - \ Required. A list of objects that map the current username (key)\n to the\ - \ desired username (value)\n\n**POST Response Values**\n\nAs long as data\ - \ validation passes, the request will return a 200 with a new mapping\nof\ - \ old usernames (key) to new username (value)\n\n{\n \"successful_replacements\"\ - : [\n {\"old_username_1\": \"new_username_1\"}\n ],\n \"failed_replacements\"\ - : [\n {\"old_username_2\": \"new_username_2\"}\n ]\n}" + description: "POST /api/user/v1/accounts/replace_usernames/\n```\n{\n \"\ + username_mappings\": [\n {\"current_username_1\": \"desired_username_1\"\ + },\n {\"current_username_2\": \"desired_username_2\"}\n ]\n}\n```\n\ + \n**POST Parameters**\n\nA POST request must include the following parameter.\n\ + \n* username_mappings: Required. A list of objects that map the current username\ + \ (key)\n to the desired username (value)\n\n**POST Response Values**\n\n\ + As long as data validation passes, the request will return a 200 with a new\ + \ mapping\nof old usernames (key) to new username (value)\n\n```\n{\n \"\ + successful_replacements\": [\n {\"old_username_1\": \"new_username_1\"\ + }\n ],\n \"failed_replacements\": [\n {\"old_username_2\": \"\ + new_username_2\"}\n ]\n}\n```" parameters: [] responses: '201': @@ -4085,9 +4322,9 @@ paths: post: operationId: user_v1_accounts_post summary: POST /api/user/v1/accounts/retire/ - description: "{\n 'username': 'user_to_retire'\n}\n\nRetires the user with\ - \ the given username. This includes\nretiring this username, the associated\ - \ email address, and\nany other PII associated with this user." + description: "```\n{\n 'username': 'user_to_retire'\n}\n```\n\nRetires the\ + \ user with the given username. This includes\nretiring this username, the\ + \ associated email address, and\nany other PII associated with this user." parameters: [] responses: '201': @@ -4099,8 +4336,8 @@ paths: post: operationId: user_v1_accounts_post summary: POST /api/user/v1/accounts/retire_misc/ - description: "{\n 'username': 'user_to_retire'\n}\n\nRetires the user with\ - \ the given username in the LMS." + description: "```\n{\n 'username': 'user_to_retire'\n}\n```\n\nRetires the\ + \ user with the given username in the LMS." parameters: [] responses: '201': @@ -4112,8 +4349,8 @@ paths: post: operationId: user_v1_accounts_cleanup summary: POST /api/user/v1/accounts/retirement_cleanup/ - description: "{\n 'usernames': ['user1', 'user2', ...]\n}\n\nDeletes a batch\ - \ of retirement requests by username." + description: "```\n{\n 'usernames': ['user1', 'user2', ...]\n}\n```\n\nDeletes\ + \ a batch of retirement requests by username." parameters: [] responses: '201': @@ -4137,8 +4374,9 @@ paths: put: operationId: user_v1_accounts_retirement_partner_report_update summary: PUT /api/user/v1/accounts/retirement_partner_report/ - description: "{\n 'username': 'user_to_retire'\n}\n\nCreates a UserRetirementPartnerReportingStatus\ - \ object for the given user\nas part of the retirement pipeline." + description: "```\n{\n 'username': 'user_to_retire'\n}\n```\n\nCreates a\ + \ UserRetirementPartnerReportingStatus object for the given user\nas part\ + \ of the retirement pipeline." parameters: [] responses: '200': @@ -4193,13 +4431,13 @@ paths: patch: operationId: user_v1_accounts_update_retirement_status_partial_update summary: PATCH /api/user/v1/accounts/update_retirement_status/ - description: "{\n 'username': 'user_to_retire',\n 'new_state': 'LOCKING_COMPLETE',\n\ - \ 'response': 'User account locked and logged out.'\n}\n\nUpdates the RetirementStatus\ - \ row for the given user to the new\nstatus, and append any messages to the\ - \ message log.\n\nNote that this implementation DOES NOT use the \"merge patch\"\ - \nimplementation seen in AccountViewSet. Slumber, the project\nwe use to power\ - \ edx-rest-api-client, does not currently support\nit. The content type for\ - \ this request is 'application/json'." + description: "```\n{\n 'username': 'user_to_retire',\n 'new_state': 'LOCKING_COMPLETE',\n\ + \ 'response': 'User account locked and logged out.'\n}\n```\n\nUpdates\ + \ the RetirementStatus row for the given user to the new\nstatus, and append\ + \ any messages to the message log.\n\nNote that this implementation DOES NOT\ + \ use the \"merge patch\"\nimplementation seen in AccountViewSet. Slumber,\ + \ the project\nwe use to power edx-rest-api-client, does not currently support\n\ + it. The content type for this request is 'application/json'." parameters: [] responses: '200': @@ -4222,10 +4460,8 @@ paths: patch: operationId: user_v1_accounts_partial_update summary: PATCH /api/user/v1/accounts/{username}/ - description: "Note that this implementation is the \"merge patch\" implementation\ - \ proposed in\nhttps://tools.ietf.org/html/rfc7396. The content_type must\ - \ be \"application/merge-patch+json\" or\nelse an error response with status\ - \ code 415 will be returned." + description: Note that this implementation is the "merge patch" implementation + proposed in parameters: [] responses: '200': @@ -4398,14 +4634,13 @@ paths: post: operationId: user_v1_validation_registration_create summary: POST /api/user/v1/validation/registration/ - description: "Expects request of the form\n>>> {\n>>> \"name\": \"Dan the\ - \ Validator\",\n>>> \"username\": \"mslm\",\n>>> \"email\": \"mslm@gmail.com\"\ - ,\n>>> \"confirm_email\": \"mslm@gmail.com\",\n>>> \"password\": \"\ - password123\",\n>>> \"country\": \"PK\"\n>>> }\nwhere each key is the\ - \ appropriate form field name and the value is\nuser input. One may enter\ - \ individual inputs if needed. Some inputs\ncan get extra verification checks\ - \ if entered along with others,\nlike when the password may not equal the\ - \ username." + description: "Expects request of the form\n```\n{\n \"name\": \"Dan the Validator\"\ + ,\n \"username\": \"mslm\",\n \"email\": \"mslm@gmail.com\",\n \"\ + confirm_email\": \"mslm@gmail.com\",\n \"password\": \"password123\",\n\ + \ \"country\": \"PK\"\n}\n```\nwhere each key is the appropriate form field\ + \ name and the value is\nuser input. One may enter individual inputs if needed.\ + \ Some inputs\ncan get extra verification checks if entered along with others,\n\ + like when the password may not equal the username." parameters: [] responses: '201': @@ -4517,6 +4752,63 @@ paths: tags: - val parameters: [] + /val/v0/videos/transcript-credentials/{provider}/{org}: + get: + operationId: val_v0_videos_transcript-credentials_read + summary: Retrieves the transcript credentials for a given organization and provider. + description: "**Example requests**:\n\n GET api/val/v0/videos/transcript-credentials/{provider}/{org}\n\ + \n**GET Parameters**:\n\n The following parameters are required to get\ + \ the credentials:\n\n * provider(str): transcript provider, which\ + \ is either 3PlayMedia or Cielo24.\n\n * org(str): organization whose\ + \ credentials are to be fetch.\n\n**Response Values**\n\n For a successful\ + \ request, the following values are returned along with 200 status:\n\n \ + \ * api_key(str): provider key\n\n * api_secret_key(str): provider\ + \ api secret key(only for 3PlayMedia)\n\n * provider(str): transcript\ + \ provider\n\n * org(str): organization whose credentials are fetched.\n\ + \n For the error, 400 response code is returned with:\n\n * message(str):\ + \ error message" + parameters: [] + responses: + '200': + description: '' + tags: + - val + parameters: + - name: org + in: path + description: This value must match the value of organization in studio/edx-platform. + required: true + type: string + - name: provider + in: path + required: true + type: string + /val/v0/videos/transcript-preferences/{course_id}: + get: + operationId: val_v0_videos_transcript-preferences_read + summary: Retrieves the transcript preferences for a given course. + description: "**Example requests**\n\n GET api/val/v0/videos/transcript-preferences/{course_id}\n\ + \n**Parameters**\n\n * course_id(str): course whose preferences are to\ + \ be fetched\n\n**Response Values**\n\n * course_id(str): course id whose\ + \ preferences are fetched\n\n * provider(str): transcript provider name\n\ + \n * cielo24_fidelity(str/None): Cielo24 fidelity choice\n\n * cielo24_turnaround(str/None):\ + \ Cielo24 turnaround time choice\n\n * three_play_turnaround(str/None):\ + \ 3playMedia turnaround\n\n * preferred_languages(list): list of languages(str\ + \ values)\n\n * video_source_language(str): video language\n\n * modified(datetime):\ + \ last modified date" + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/TranscriptPreference' + tags: + - val + parameters: + - name: course_id + in: path + required: true + type: string /val/v0/videos/video-images/update/: post: operationId: val_v0_videos_video-images_update_create @@ -4532,8 +4824,7 @@ paths: /val/v0/videos/video-transcripts/create/: post: operationId: val_v0_videos_video-transcripts_create_create - summary: Creates a video transcript instance with the given information. - description: "Arguments:\n request: A WSGI request." + description: Creates a video transcript instance with the given information. parameters: [] responses: '201': @@ -4603,7 +4894,10 @@ paths: /xblock/v2/xblocks/{usage_key_str}/: get: operationId: xblock_v2_xblocks_read - description: Get metadata about the specified block. + summary: Get metadata about the specified block. + description: "Accepts an \"include\" query parameter which must be a comma separated\ + \ list of keys to include. Valid keys are\n\"index_dictionary\" and \"student_view_data\"\ + ." parameters: [] responses: '200': @@ -5320,6 +5614,7 @@ definitions: title: Order number type: string maxLength: 128 + minLength: 1 x-nullable: true support_details: title: Support details @@ -5569,6 +5864,136 @@ definitions: active: title: Active type: boolean + logo_url: + title: Logo url + type: string + minLength: 1 + DueDate: + required: + - name + - url + - date + type: object + properties: + name: + title: Name + type: string + minLength: 1 + url: + title: Url + type: string + minLength: 1 + date: + title: Date + type: string + format: date-time + CourseRunOverview: + required: + - course_run_id + - display_name + - course_run_url + - start_date + - end_date + - course_run_status + - due_dates + type: object + properties: + course_run_id: + title: Course run id + description: ID for the course run. + type: string + minLength: 1 + display_name: + title: Display name + description: Display name of the course run. + type: string + minLength: 1 + resume_course_run_url: + title: Resume course run url + description: The absolute url that takes the user back to their position in + the course run; if absent, user has not made progress in the course. + type: string + minLength: 1 + course_run_url: + title: Course run url + description: The absolute url for the course run. + type: string + minLength: 1 + start_date: + title: Start date + description: Start date for the course run; null if no start date. + type: string + format: date-time + end_date: + title: End date + description: End date for the course run; null if no end date. + type: string + format: date-time + course_run_status: + title: Course run status + description: The user's status of the course run. + type: string + enum: + - in_progress + - upcoming + - completed + emails_enabled: + title: Emails enabled + description: Boolean representing whether emails are enabled for the course;if + absent, the bulk email feature is either not enable at the platformlevel + or is not enabled for the course; if True or False, bulk emailfeature is + enabled, and value represents whether or not user wantsto receive emails. + type: boolean + due_dates: + description: List of subsection due dates for the course run. Due dates are + only returned if the course run is in progress. + type: array + items: + $ref: '#/definitions/DueDate' + micromasters_title: + title: Micromasters title + description: Title of the MicroMasters program that the course run is a part + of; if absent, the course run is not a part of a MicroMasters program. + type: string + minLength: 1 + certificate_download_url: + title: Certificate download url + description: URL to download a certificate, if available; if absent, certificate + is not downloadable. + type: string + minLength: 1 + CourseRunOverviewList: + required: + - course_runs + type: object + properties: + course_runs: + type: array + items: + $ref: '#/definitions/CourseRunOverview' + PageOfCourseRunOverview: + required: + - results + type: object + properties: + previous: + title: Previous + description: Link to the previous page or results, or null if this is the + first. + type: string + format: uri + minLength: 1 + next: + title: Next + description: Link to the next page of results, or null if this is the last. + type: string + format: uri + minLength: 1 + results: + description: The list of result objects on this page. + type: array + items: + $ref: '#/definitions/CourseRunOverview' UserMapping: type: object properties: @@ -5657,3 +6082,66 @@ definitions: type: string maxLength: 255 minLength: 1 + error_description: + title: Error Description + type: string + x-nullable: true + TranscriptPreference: + required: + - course_id + - provider + type: object + properties: + course_id: + title: Course ID + type: string + maxLength: 255 + minLength: 1 + provider: + title: Provider + type: string + enum: + - Custom + - 3PlayMedia + - Cielo24 + cielo24_fidelity: + title: Cielo24 Fidelity + type: string + enum: + - MECHANICAL + - PREMIUM + - PROFESSIONAL + x-nullable: true + cielo24_turnaround: + title: Cielo24 Turnaround + type: string + enum: + - STANDARD + - PRIORITY + x-nullable: true + three_play_turnaround: + title: 3PlayMedia Turnaround + type: string + enum: + - extended + - standard + - expedited + - rush + - same_day + - two_hour + x-nullable: true + preferred_languages: + title: Preferred languages + type: string + readOnly: true + video_source_language: + title: Video Source Language + description: This specifies the speech language of a Video. + type: string + maxLength: 50 + x-nullable: true + modified: + title: Modified + type: string + format: date-time + readOnly: true diff --git a/lms/djangoapps/badges/api/views.py b/lms/djangoapps/badges/api/views.py index 72b3ff71400bc1778a470f256aa345a27331b4d1..29546874650e74f23df221dbefaa2ff824502da3 100644 --- a/lms/djangoapps/badges/api/views.py +++ b/lms/djangoapps/badges/api/views.py @@ -27,15 +27,15 @@ class InvalidCourseKeyError(APIException): class UserBadgeAssertions(generics.ListAPIView): """ - ** Use cases ** + **Use Cases** Request a list of assertions for a user, optionally constrained to a course. - ** Example Requests ** + **Example Requests** GET /api/badges/v1/assertions/user/{username}/ - ** Response Values ** + **Response Values** Body comprised of a list of objects with the following fields: @@ -53,7 +53,7 @@ class UserBadgeAssertions(generics.ListAPIView): * assertion_url: The URL to the OpenBadges BadgeAssertion object, for verification by compatible tools and software. - ** Params ** + **Params** * slug (optional): The identifier for a particular badge class to filter by. * issuing_component (optional): The issuing component for a particular badge class to filter by @@ -63,7 +63,7 @@ class UserBadgeAssertions(generics.ListAPIView): provided, and this field is not specified, assumes that the target badge has an empty course_id field. '*' may be used to get all badges with the specified slug, issuing_component combination across all courses. - ** Returns ** + **Returns** * 200 on success, with a list of Badge Assertion objects. * 403 if a user who does not have permission to masquerade as diff --git a/lms/djangoapps/badges/apps.py b/lms/djangoapps/badges/apps.py index 97f299e8b739984beb0be9b7bad6e90dbe2fab69..f637ba7c6090a71c6609bd51ea42309b0d19fe62 100644 --- a/lms/djangoapps/badges/apps.py +++ b/lms/djangoapps/badges/apps.py @@ -18,4 +18,4 @@ class BadgesConfig(AppConfig): """ Connect signal handlers. """ - from . import handlers # pylint: disable=unused-variable + from . import handlers # pylint: disable=unused-import diff --git a/lms/djangoapps/branding/api.py b/lms/djangoapps/branding/api.py index a9aa9ea18b563055f702622e245e32f120d99215..651a868a237cdbadf2b36f0a4d0aa19683892cfb 100644 --- a/lms/djangoapps/branding/api.py +++ b/lms/djangoapps/branding/api.py @@ -495,7 +495,7 @@ def _absolute_url(is_secure, url_path): """ site_name = configuration_helpers.get_value('SITE_NAME', settings.SITE_NAME) parts = ("https" if is_secure else "http", site_name, url_path, '', '', '') - return six.moves.urllib.parse.urlunparse(parts) # pylint: disable=too-many-function-args + return six.moves.urllib.parse.urlunparse(parts) def _absolute_url_staticfile(is_secure, name): diff --git a/lms/djangoapps/bulk_email/signals.py b/lms/djangoapps/bulk_email/signals.py index 8a48acd0e271602f17bdc67489fbac0d515e35ee..319110d04f029ee97a369cf392d20fb2a525e4c4 100644 --- a/lms/djangoapps/bulk_email/signals.py +++ b/lms/djangoapps/bulk_email/signals.py @@ -12,7 +12,7 @@ from .models import Optout @receiver(USER_RETIRE_MAILINGS) -def force_optout_all(sender, **kwargs): # pylint: disable=unused-argument +def force_optout_all(sender, **kwargs): """ When a user is retired from all mailings this method will create an Optout row for any courses they may be enrolled in. diff --git a/lms/djangoapps/bulk_email/views.py b/lms/djangoapps/bulk_email/views.py index 5879b7411e5c7d1509312e2be7c158f12a9d278a..c3e5344f9f53de002b300551c51a92156ddd8aa5 100644 --- a/lms/djangoapps/bulk_email/views.py +++ b/lms/djangoapps/bulk_email/views.py @@ -11,7 +11,7 @@ from django.contrib.auth.models import User from django.http import Http404 from bulk_email.models import Optout -from courseware.courses import get_course_by_id +from lms.djangoapps.courseware.courses import get_course_by_id from edxmako.shortcuts import render_to_response from lms.djangoapps.discussion.notification_prefs.views import ( UsernameCipher, diff --git a/lms/djangoapps/ccx/api/v0/tests/test_views.py b/lms/djangoapps/ccx/api/v0/tests/test_views.py index 95f08f655d0b0b5eda25d3f5486d608c2efe4ab3..77e3d74c77e34caf4e1f0ce854d78120ac7b2b59 100644 --- a/lms/djangoapps/ccx/api/v0/tests/test_views.py +++ b/lms/djangoapps/ccx/api/v0/tests/test_views.py @@ -11,9 +11,6 @@ from datetime import timedelta import ddt import mock import six -import six.moves.urllib.error # pylint: disable=import-error -import six.moves.urllib.parse # pylint: disable=import-error -import six.moves.urllib.request # pylint: disable=import-error from ccx_keys.locator import CCXLocator from django.conf import settings from django.contrib.auth.models import User @@ -25,12 +22,12 @@ from rest_framework import status from rest_framework.test import APITestCase from six.moves import range, zip -from lms.djangoapps.courseware import courses from lms.djangoapps.ccx.api.v0 import views from lms.djangoapps.ccx.models import CcxFieldOverride, CustomCourseForEdX from lms.djangoapps.ccx.overrides import override_field_for_ccx from lms.djangoapps.ccx.tests.utils import CcxTestCase from lms.djangoapps.ccx.utils import ccx_course as ccx_course_cm +from lms.djangoapps.courseware import courses from lms.djangoapps.instructor.access import allow_access, list_with_level from lms.djangoapps.instructor.enrollment import enroll_email, get_email_params from student.models import CourseEnrollment @@ -911,7 +908,7 @@ class CcxDetailTest(CcxRestApiTest): resp.data.get('max_students_allowed'), self.ccx.max_student_enrollments_allowed ) - self.assertEqual(resp.data.get('coach_email'), self.ccx.coach.email) # pylint: disable=no-member + self.assertEqual(resp.data.get('coach_email'), self.ccx.coach.email) self.assertEqual(resp.data.get('master_course_id'), six.text_type(self.ccx.course_id)) six.assertCountEqual(self, resp.data.get('course_modules'), self.master_course_chapters) @@ -994,7 +991,7 @@ class CcxDetailTest(CcxRestApiTest): """ display_name = self.ccx.display_name max_students_allowed = self.ccx.max_student_enrollments_allowed - coach_email = self.ccx.coach.email # pylint: disable=no-member + coach_email = self.ccx.coach.email ccx_structure = self.ccx.structure resp = self.client.patch(self.detail_url, {}, format='json', HTTP_AUTHORIZATION=self.auth) self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT) diff --git a/lms/djangoapps/ccx/api/v0/views.py b/lms/djangoapps/ccx/api/v0/views.py index a26149893257eb640ddc9a5df97cd77f03a4f593..cecf7aa2358883f182aee727a305102895ec8018 100644 --- a/lms/djangoapps/ccx/api/v0/views.py +++ b/lms/djangoapps/ccx/api/v0/views.py @@ -648,7 +648,7 @@ class CCXDetailView(GenericAPIView): serializer = self.get_serializer(ccx_course_object) return Response(serializer.data) - def delete(self, request, ccx_course_id=None): # pylint: disable=unused-argument + def delete(self, request, ccx_course_id=None): """ Deletes a CCX course. diff --git a/lms/djangoapps/ccx/tests/factories.py b/lms/djangoapps/ccx/tests/factories.py index 97f39616e28d234fe8d69158b0334952e42b9013..dc3ce3fa7c3a42897fc329964ced970ef7859e63 100644 --- a/lms/djangoapps/ccx/tests/factories.py +++ b/lms/djangoapps/ccx/tests/factories.py @@ -10,7 +10,8 @@ from lms.djangoapps.ccx.models import CustomCourseForEdX from student.tests.factories import UserFactory -class CcxFactory(DjangoModelFactory): # pylint: disable=missing-docstring +# pylint: disable=missing-class-docstring +class CcxFactory(DjangoModelFactory): class Meta(object): model = CustomCourseForEdX diff --git a/lms/djangoapps/ccx/tests/test_views.py b/lms/djangoapps/ccx/tests/test_views.py index ec7373edc004b670bab6465405d9ade33ab3549d..b9db00e17875f29fce5d16ccc9035a3645a45cd9 100644 --- a/lms/djangoapps/ccx/tests/test_views.py +++ b/lms/djangoapps/ccx/tests/test_views.py @@ -9,7 +9,6 @@ import re import ddt import six -import six.moves.urllib.parse # pylint: disable=import-error from six.moves import range, zip from ccx_keys.locator import CCXLocator from django.conf import settings @@ -631,7 +630,7 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase): ) data = { button_tuple[0]: button_tuple[1], - student_form_input_name: u','.join([student.email, ]), # pylint: disable=no-member + student_form_input_name: u','.join([student.email, ]), } if send_email: data['email-students'] = 'Notify-students-by-email' @@ -642,7 +641,7 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase): self.assertIn(302, response.redirect_chain[0]) self.assertEqual(len(outbox), outbox_count) if send_email: - self.assertIn(student.email, outbox[0].recipients()) # pylint: disable=no-member + self.assertIn(student.email, outbox[0].recipients()) # a CcxMembership exists for this student self.assertTrue( CourseEnrollment.objects.filter(course_id=self.course.id, user=student).exists() @@ -727,7 +726,7 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase): ) data = { button_tuple[0]: button_tuple[1], - student_form_input_name: u','.join([student.email, ]), # pylint: disable=no-member + student_form_input_name: u','.join([student.email, ]), } if send_email: data['email-students'] = 'Notify-students-by-email' @@ -738,7 +737,7 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase): self.assertIn(302, response.redirect_chain[0]) self.assertEqual(len(outbox), outbox_count) if send_email: - self.assertIn(student.email, outbox[0].recipients()) # pylint: disable=no-member + self.assertIn(student.email, outbox[0].recipients()) # a CcxMembership does not exists for this student self.assertFalse( CourseEnrollment.objects.filter(course_id=self.course.id, user=student).exists() diff --git a/lms/djangoapps/ccx/views.py b/lms/djangoapps/ccx/views.py index 85f22f869fc31d18d9c475405acea104a8e04136..768e967bf4f9a0fbde233d87e0fa80bc19898be2 100644 --- a/lms/djangoapps/ccx/views.py +++ b/lms/djangoapps/ccx/views.py @@ -446,7 +446,7 @@ def get_ccx_schedule(course, ccx): @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) @coach_dashboard -def ccx_schedule(request, course, ccx=None): # pylint: disable=unused-argument +def ccx_schedule(request, course, ccx=None): """ get json representation of ccx schedule """ diff --git a/lms/djangoapps/certificates/api.py b/lms/djangoapps/certificates/api.py index 365a2ef957a71684929c82a1a6110f7d75a4e96a..d0176aa0fc119a63d1f450f14cd23b553d5377ca 100644 --- a/lms/djangoapps/certificates/api.py +++ b/lms/djangoapps/certificates/api.py @@ -132,6 +132,28 @@ def get_certificate_for_user(username, course_key): return format_certificate_for_user(username, cert) +def get_certificates_for_user_by_course_keys(user, course_keys): + """ + Retrieve certificate information for a particular user for a set of courses. + + Arguments: + user (User) + course_keys (set[CourseKey]) + + Returns: dict[CourseKey: dict] + Mapping from course keys to dict of certificate data. + Course keys for courses for which the user does not have a certificate + will be omitted. + """ + certs = GeneratedCertificate.eligible_certificates.filter( + user=user, course_id__in=course_keys + ) + return { + cert.course_id: format_certificate_for_user(user.username, cert) + for cert in certs + } + + def get_recently_modified_certificates(course_keys=None, start_date=None, end_date=None): """ Returns a QuerySet of GeneratedCertificate objects filtered by the input @@ -148,7 +170,7 @@ def get_recently_modified_certificates(course_keys=None, start_date=None, end_da if end_date: cert_filter_args['modified_date__lte'] = end_date - return GeneratedCertificate.objects.filter(**cert_filter_args).order_by('modified_date') # pylint: disable=no-member + return GeneratedCertificate.objects.filter(**cert_filter_args).order_by('modified_date') def generate_user_certificates(student, course_key, course=None, insecure=False, generation_mode='batch', diff --git a/lms/djangoapps/certificates/apis/v0/permissions.py b/lms/djangoapps/certificates/apis/v0/permissions.py new file mode 100644 index 0000000000000000000000000000000000000000..a666071904921a2990143d8c8afe1e21bdb6a225 --- /dev/null +++ b/lms/djangoapps/certificates/apis/v0/permissions.py @@ -0,0 +1,26 @@ +""" +This module provides a custom DRF Permission class for supporting the course certificates +to Admin users and users whom they belongs to. +""" + +from django.contrib.auth.models import User +from rest_framework.permissions import BasePermission + +from openedx.core.djangoapps.user_api.models import UserPreference + + +class IsOwnerOrPublicCertificates(BasePermission): + """ + Method that will ensure whether the requesting user is staff or + the user whom the certificate belongs to + """ + def has_permission(self, request, view): + requested_profile_username = view.kwargs.get('username') + # check whether requesting user is the owner of certs or not + if request.user.username == requested_profile_username: + return True + + user = User.objects.get(username=requested_profile_username) + cert_privacy = UserPreference.get_value(user, 'visibility.course_certificates') + + return cert_privacy == 'all_users' diff --git a/lms/djangoapps/certificates/apis/v0/tests/test_views.py b/lms/djangoapps/certificates/apis/v0/tests/test_views.py index e2536211d33bcd67a5763bf457c7d79e14096f45..b99eebdf15493f1050b0da1c04e972846babc816 100644 --- a/lms/djangoapps/certificates/apis/v0/tests/test_views.py +++ b/lms/djangoapps/certificates/apis/v0/tests/test_views.py @@ -169,7 +169,8 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC download_url='www.google.com', grade="0.88", ) - + self.student.is_staff = True + self.student.save() self.namespaced_url = 'certificates_api:v0:certificates:list' def get_url(self, username): @@ -204,13 +205,10 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC @ddt.data(*list(AuthType)) def test_another_user(self, auth_type, mock_log): """ - Returns 200 with empty list for OAuth, Session, and JWT auth. - Returns 200 for jwt_restricted and user:me filter unset. + Returns 403 response for non-staff user on all auth types. """ resp = self.get_response(auth_type, requesting_user=self.other_student) - - self.assertEqual(resp.status_code, status.HTTP_200_OK) - self.assertEqual(len(resp.data), 0) + self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN) @ddt.data(*list(AuthType)) def test_another_user_with_certs_shared_public(self, auth_type): @@ -226,11 +224,51 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC value='all_users', ).save() - resp = self.get_response(auth_type, requesting_user=self.other_student) + resp = self.get_response(auth_type, requesting_user=self.global_staff) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(len(resp.data), 1) + def test_owner_can_access_its_certs(self): + """ + Tests the owner of the certs can access the certificate list api + """ + self.student.profile.year_of_birth = 1977 + self.student.profile.save() + UserPreferenceFactory.build( + user=self.student, + key='visibility.course_certificates', + value='private', + ).save() + + resp = self.get_response(AuthType.session, requesting_user=self.student) + self.assertEqual(resp.status_code, status.HTTP_200_OK) + + # verifies that other than owner cert list api is not accessible + resp = self.get_response(AuthType.session, requesting_user=self.other_student) + self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN) + + def test_public_profile_certs_is_accessible(self): + """ + Tests the public profile certs can be accessed by all users + """ + self.student.profile.year_of_birth = 1977 + self.student.profile.save() + UserPreferenceFactory.build( + user=self.student, + key='visibility.course_certificates', + value='all_users', + ).save() + + resp = self.get_response(AuthType.session, requesting_user=self.student) + self.assertEqual(resp.status_code, status.HTTP_200_OK) + + resp = self.get_response(AuthType.session, requesting_user=self.other_student) + self.assertEqual(resp.status_code, status.HTTP_200_OK) + + resp = self.get_response(AuthType.session, requesting_user=self.global_staff) + self.assertEqual(resp.status_code, status.HTTP_200_OK) + @ddt.data(*list(AuthType)) def test_another_user_with_certs_shared_custom(self, auth_type): """ @@ -250,7 +288,7 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC value='all_users', ).save() - resp = self.get_response(auth_type, requesting_user=self.other_student) + resp = self.get_response(auth_type, requesting_user=self.global_staff) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(len(resp.data), 1) @@ -259,7 +297,7 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC @ddt.data(*JWT_AUTH_TYPES) def test_jwt_on_behalf_of_other_user(self, auth_type, mock_log): """ Returns 403 when scopes are enforced with JwtHasUserFilterForRequestedUser. """ - jwt_token = self._create_jwt_token(self.other_student, auth_type, include_me_filter=True) + jwt_token = self._create_jwt_token(self.global_staff, auth_type, include_me_filter=True) resp = self.get_response(AuthType.jwt, token=jwt_token) if auth_type == AuthType.jwt_restricted: @@ -267,7 +305,7 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC self._assert_in_log("JwtHasUserFilterForRequestedUser", mock_log.warning) else: self.assertEqual(resp.status_code, status.HTTP_200_OK) - self.assertEqual(len(resp.data), 0) + self.assertEqual(len(resp.data), 1) @patch('edx_rest_framework_extensions.permissions.log') @ddt.data(*JWT_AUTH_TYPES) @@ -278,7 +316,7 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC student_no_cert = UserFactory.create(password=self.user_password) resp = self.get_response( AuthType.session, - requesting_user=student_no_cert, + requesting_user=self.global_staff, requested_user=student_no_cert, ) self.assertEqual(resp.status_code, status.HTTP_200_OK) @@ -290,17 +328,17 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC with self.assertNumQueries(20): resp = self.get_response( AuthType.jwt, - requesting_user=student_no_cert, + requesting_user=self.global_staff, requested_user=student_no_cert, ) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(len(resp.data), 0) # Test student with 1 certificate - with self.assertNumQueries(14): + with self.assertNumQueries(10): resp = self.get_response( AuthType.jwt, - requesting_user=self.student, + requesting_user=self.global_staff, requested_user=self.student, ) self.assertEqual(resp.status_code, status.HTTP_200_OK) @@ -337,10 +375,10 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC download_url='www.google.com', grade="0.88", ) - with self.assertNumQueries(14): + with self.assertNumQueries(10): resp = self.get_response( AuthType.jwt, - requesting_user=student_2_certs, + requesting_user=self.global_staff, requested_user=student_2_certs, ) self.assertEqual(resp.status_code, status.HTTP_200_OK) @@ -357,7 +395,7 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC response = self.get_response( AuthType.jwt, - requesting_user=self.student, + requesting_user=self.global_staff, requested_user=self.student, ) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -368,7 +406,7 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC response = self.get_response( AuthType.jwt, - requesting_user=self.student, + requesting_user=self.global_staff, requested_user=self.student, ) kwargs = {"certificate_uuid": self.cert.verify_uuid} @@ -394,7 +432,7 @@ class CertificatesListRestApiTest(AuthAndScopesTestMixin, SharedModuleStoreTestC response = self.get_response( AuthType.jwt, - requesting_user=self.student, + requesting_user=self.global_staff, requested_user=self.student, ) self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/lms/djangoapps/certificates/apis/v0/views.py b/lms/djangoapps/certificates/apis/v0/views.py index 0875ec8c9d51441509576809eefcb53ef06e3319..0f33f18073a40b020f4ec171e40f1d384002d1a7 100644 --- a/lms/djangoapps/certificates/apis/v0/views.py +++ b/lms/djangoapps/certificates/apis/v0/views.py @@ -23,6 +23,8 @@ from openedx.core.djangoapps.content.course_overviews.models import CourseOvervi from openedx.core.djangoapps.user_api.accounts.api import visible_fields from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser +from .permissions import IsOwnerOrPublicCertificates + log = logging.getLogger(__name__) User = get_user_model() @@ -158,6 +160,7 @@ class CertificatesListView(APIView): permissions.JwtHasUserFilterForRequestedUser ) ), + (C(permissions.IsStaff) | IsOwnerOrPublicCertificates), ) required_scopes = ['certificates:read'] diff --git a/lms/djangoapps/certificates/apps.py b/lms/djangoapps/certificates/apps.py index d259b088abbf91f70095fd382ab1a62e5a349c89..7150a864cbd1c82d08f38345a91e0f5eb83a4fbe 100644 --- a/lms/djangoapps/certificates/apps.py +++ b/lms/djangoapps/certificates/apps.py @@ -22,7 +22,7 @@ class CertificatesConfig(AppConfig): """ # Can't import models at module level in AppConfigs, and models get # included from the signal handlers - from . import signals # pylint: disable=unused-variable + from . import signals # pylint: disable=unused-import if settings.FEATURES.get('ENABLE_SPECIAL_EXAMS'): from .services import CertificateService set_runtime_service('certificates', CertificateService()) diff --git a/lms/djangoapps/certificates/management/commands/fix_ungraded_certs.py b/lms/djangoapps/certificates/management/commands/fix_ungraded_certs.py index 664b47069d9c57f2c906540d05077ba55f57209c..a687b39fe9db8835a2f2b5ba82e535d784efc9c9 100644 --- a/lms/djangoapps/certificates/management/commands/fix_ungraded_certs.py +++ b/lms/djangoapps/certificates/management/commands/fix_ungraded_certs.py @@ -45,7 +45,7 @@ class Command(BaseCommand): def handle(self, *args, **options): course_id = options['course'] log.info(u'Fetching ungraded students for %s.', course_id) - ungraded = GeneratedCertificate.objects.filter( # pylint: disable=no-member + ungraded = GeneratedCertificate.objects.filter( course_id__exact=course_id ).filter(grade__exact='') course = courses.get_course_by_id(course_id) diff --git a/lms/djangoapps/certificates/management/commands/gen_cert_report.py b/lms/djangoapps/certificates/management/commands/gen_cert_report.py index 80550b8397b0549562690b914e1e38bfb9fd2b03..5750504e5767e6529867f2f79654c0ed9130939b 100644 --- a/lms/djangoapps/certificates/management/commands/gen_cert_report.py +++ b/lms/djangoapps/certificates/management/commands/gen_cert_report.py @@ -65,15 +65,15 @@ class Command(BaseCommand): enrolled_total = User.objects.filter( courseenrollment__course_id=course_id ) - verified_enrolled = GeneratedCertificate.objects.filter( # pylint: disable=no-member + verified_enrolled = GeneratedCertificate.objects.filter( course_id__exact=course_id, mode__exact='verified' ) - honor_enrolled = GeneratedCertificate.objects.filter( # pylint: disable=no-member + honor_enrolled = GeneratedCertificate.objects.filter( course_id__exact=course_id, mode__exact='honor' ) - audit_enrolled = GeneratedCertificate.objects.filter( # pylint: disable=no-member + audit_enrolled = GeneratedCertificate.objects.filter( course_id__exact=course_id, mode__exact='audit' ) @@ -86,7 +86,7 @@ class Command(BaseCommand): 'audit_enrolled': audit_enrolled.count() } - status_tally = GeneratedCertificate.objects.filter( # pylint: disable=no-member + status_tally = GeneratedCertificate.objects.filter( course_id__exact=course_id ).values('status').annotate( dcount=Count('status') @@ -98,7 +98,7 @@ class Command(BaseCommand): } ) - mode_tally = GeneratedCertificate.objects.filter( # pylint: disable=no-member + mode_tally = GeneratedCertificate.objects.filter( course_id__exact=course_id, status__exact='downloadable' ).values('mode').annotate( diff --git a/lms/djangoapps/certificates/management/commands/resubmit_error_certificates.py b/lms/djangoapps/certificates/management/commands/resubmit_error_certificates.py index 609db7f0f8f1d29ecf45112222e7e629d0f29756..c142157fff051079cb9b1d17953ed7107985d3b8 100644 --- a/lms/djangoapps/certificates/management/commands/resubmit_error_certificates.py +++ b/lms/djangoapps/certificates/management/commands/resubmit_error_certificates.py @@ -84,7 +84,7 @@ class Command(BaseCommand): # Retrieve the IDs of generated certificates with # error status in the set of courses we're considering. queryset = ( - GeneratedCertificate.objects.select_related('user') # pylint: disable=no-member + GeneratedCertificate.objects.select_related('user') ).filter(status=CertificateStatuses.error) if only_course_keys: queryset = queryset.filter(course_id__in=only_course_keys) diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index 9a762336bff7e830bab41109fa3b34993ca90b5e..9a40eaf81c9b50268194b3ec16f3a325ccde07cb 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -74,7 +74,7 @@ from badges.events.course_meta import completion_check, course_group_check from course_modes.models import CourseMode from lms.djangoapps.instructor_task.models import InstructorTask from openedx.core.djangoapps.content.course_overviews.models import CourseOverview -from openedx.core.djangoapps.signals.signals import COURSE_CERT_AWARDED, COURSE_CERT_CHANGED +from openedx.core.djangoapps.signals.signals import COURSE_CERT_AWARDED, COURSE_CERT_CHANGED, COURSE_CERT_REVOKED from openedx.core.djangoapps.xmodule_django.models import NoneToEmptyManager from util.milestones_helpers import fulfill_course_milestone, is_prerequisite_courses_enabled @@ -319,7 +319,7 @@ class GeneratedCertificate(models.Model): return { cert.course_id for cert - in cls.objects.filter(user=user).only('course_id') # pylint: disable=no-member + in cls.objects.filter(user=user).only('course_id') } @classmethod @@ -369,8 +369,14 @@ class GeneratedCertificate(models.Model): self.download_url = '' self.grade = '' self.status = CertificateStatuses.unavailable - self.save() + COURSE_CERT_REVOKED.send_robust( + sender=self.__class__, + user=self.user, + course_key=self.course_id, + mode=self.mode, + status=self.status, + ) def mark_notpassing(self, grade): """ diff --git a/lms/djangoapps/certificates/queue.py b/lms/djangoapps/certificates/queue.py index 07632f65a8b8724d27b3be133545098b1d027462..6abf5ecce95d874c53a450d0d2b6977cf38cfa80 100644 --- a/lms/djangoapps/certificates/queue.py +++ b/lms/djangoapps/certificates/queue.py @@ -332,7 +332,6 @@ class XQueueCertInterface(object): mode_is_verified, generate_pdf ) - # pylint: disable=no-member cert, created = GeneratedCertificate.objects.get_or_create(user=student, course_id=course_id) cert.mode = cert_mode diff --git a/lms/djangoapps/certificates/tests/factories.py b/lms/djangoapps/certificates/tests/factories.py index 0fd4c148ca17b59150eaae476670bd234d3fa561..61df9af239221fadd588fbc3d057577099ea5345 100644 --- a/lms/djangoapps/certificates/tests/factories.py +++ b/lms/djangoapps/certificates/tests/factories.py @@ -1,5 +1,4 @@ # Factories are self documenting -# pylint: disable=missing-docstring from uuid import uuid4 diff --git a/lms/djangoapps/certificates/tests/test_api.py b/lms/djangoapps/certificates/tests/test_api.py index f09385a417f3e33a69fffc745372f5ff52cbfb29..783677874c87541bc0fe639ac227d42942d4b959 100644 --- a/lms/djangoapps/certificates/tests/test_api.py +++ b/lms/djangoapps/certificates/tests/test_api.py @@ -372,6 +372,11 @@ class CertificateGetTests(SharedModuleStoreTestCase): display_name='Verified Course 2', cert_html_view_enabled=False ) + cls.no_cert_course = CourseFactory.create( + org='edx', + number='verified_3', + display_name='Verified Course 3', + ) # certificate for the first course GeneratedCertificateFactory.create( user=cls.student, @@ -442,6 +447,21 @@ class CertificateGetTests(SharedModuleStoreTestCase): self.assertEqual(certs[0]['download_url'], 'www.google.com') self.assertEqual(certs[1]['download_url'], 'www.gmail.com') + def test_get_certificates_for_user_by_course_keys(self): + """ + Test to get certificates for a user for certain course keys, + in a dictionary indexed by those course keys. + """ + certs = certs_api.get_certificates_for_user_by_course_keys( + user=self.student, + course_keys={self.web_cert_course.id, self.no_cert_course.id}, + ) + assert set(certs.keys()) == {self.web_cert_course.id} + cert = certs[self.web_cert_course.id] + self.assertEqual(cert['username'], self.student.username) + self.assertEqual(cert['course_key'], self.web_cert_course.id) + self.assertEqual(cert['download_url'], 'www.google.com') + def test_no_certificate_for_user(self): """ Test the case when there is no certificate for a user for a specific course. diff --git a/lms/djangoapps/certificates/tests/test_models.py b/lms/djangoapps/certificates/tests/test_models.py index 3d26cebd39b4b84d7065085fdcdb78b39978d4cb..f68260da6c4bd8e78c47e4ebd041cfc5804a7d17 100644 --- a/lms/djangoapps/certificates/tests/test_models.py +++ b/lms/djangoapps/certificates/tests/test_models.py @@ -9,6 +9,7 @@ from django.core.exceptions import ValidationError from django.core.files.uploadedfile import SimpleUploadedFile from django.test import TestCase from django.test.utils import override_settings +from mock import patch from opaque_keys.edx.locator import CourseKey, CourseLocator from path import Path as path @@ -32,7 +33,6 @@ from xmodule.modulestore.tests.factories import CourseFactory FEATURES_INVALID_FILE_PATH = settings.FEATURES.copy() FEATURES_INVALID_FILE_PATH['CERTS_HTML_VIEW_CONFIG_PATH'] = 'invalid/path/to/config.json' -# pylint: disable=invalid-name TEST_DIR = path(__file__).dirname() TEST_DATA_DIR = 'common/test/data/' PLATFORM_ROOT = TEST_DIR.parent.parent.parent.parent @@ -357,3 +357,16 @@ class CertificateInvalidationTest(SharedModuleStoreTestCase): self.assertFalse( CertificateInvalidation.has_certificate_invalidation(self.user, self.course_id) ) + + @patch('openedx.core.djangoapps.programs.tasks.v1.tasks.revoke_program_certificates.delay') + @patch( + 'openedx.core.djangoapps.credentials.models.CredentialsApiConfig.is_learner_issuance_enabled', + return_value=True, + ) + def test_revoke_program_certificates(self, mock_issuance, mock_revoke_task): # pylint: disable=unused-argument + """ Verify that `revoke_program_certificates` is invoked upon invalidation. """ + # Invalidate user certificate + self.certificate.invalidate() + + self.assertEqual(mock_revoke_task.call_count, 1) + self.assertEqual(mock_revoke_task.call_args[0], (self.user.username, self.course_id)) diff --git a/lms/djangoapps/certificates/tests/test_webview_views.py b/lms/djangoapps/certificates/tests/test_webview_views.py index c6d86d3282192ab5d3da3ac56ebe457abf535019..e92af03b6a3dd3ad78e55ea993318680eccb9f5b 100644 --- a/lms/djangoapps/certificates/tests/test_webview_views.py +++ b/lms/djangoapps/certificates/tests/test_webview_views.py @@ -15,7 +15,7 @@ from django.test.utils import override_settings from django.urls import reverse from mock import patch from six.moves import range -from six.moves.urllib.parse import urlencode # pylint: disable=import-error +from six.moves.urllib.parse import urlencode from course_modes.models import CourseMode from lms.djangoapps.badges.events.course_complete import get_completion_badge @@ -1582,7 +1582,13 @@ class CertificateEventTests(CommonCertificatesTestCase, EventTrackingTestCase): ) response = self.client.get(test_url) self.assertEqual(response.status_code, 200) - actual_event = self.get_event() + + # There are two events being emitted in this flow. + # One for page hit (due to the tracker in the middleware) and + # one due to the certificate being visited. + # We are interested in the second one. + actual_event = self.get_event(1) + self.assertEqual(actual_event['name'], 'edx.certificate.evidence_visited') assert_event_matches( { @@ -1617,6 +1623,13 @@ class CertificateEventTests(CommonCertificatesTestCase, EventTrackingTestCase): } ) response = self.client.get(test_url) + + # There are two events being emitted in this flow. + # One for page hit (due to the tracker in the middleware) and + # one due to the certificate being visited. + # We are interested in the second one. + actual_event = self.get_event(1) + self.assertEqual(response.status_code, 200) assert_event_matches( { @@ -1635,5 +1648,5 @@ class CertificateEventTests(CommonCertificatesTestCase, EventTrackingTestCase): 'enrollment_mode': 'honor', }, }, - self.get_event() + actual_event ) diff --git a/lms/djangoapps/certificates/views/support.py b/lms/djangoapps/certificates/views/support.py index d0fb0911eb30da081ce70cfc99758560c341a248..01b75f3630d2a9b2aac511b418a5a76881f68a7f 100644 --- a/lms/djangoapps/certificates/views/support.py +++ b/lms/djangoapps/certificates/views/support.py @@ -89,7 +89,6 @@ def search_certificates(request): ] """ - # pylint: disable=too-many-function-args unbleached_filter = six.moves.urllib.parse.unquote(six.moves.urllib.parse.quote_plus(request.GET.get("user", ""))) user_filter = bleach.clean(unbleached_filter) if not user_filter: @@ -108,7 +107,6 @@ def search_certificates(request): cert["modified"] = cert["modified"].isoformat() cert["regenerate"] = not cert['is_pdf_certificate'] - # pylint: disable=redundant-keyword-arg course_id = six.moves.urllib.parse.quote_plus(request.GET.get("course_id", ""), safe=':/') if course_id: try: diff --git a/lms/djangoapps/certificates/views/webview.py b/lms/djangoapps/certificates/views/webview.py index 8948b860591de1a894b5b61c86ef4b243d5f0fdf..4d6dfbd28fe61103e9ac57aa04ba57f983158175 100644 --- a/lms/djangoapps/certificates/views/webview.py +++ b/lms/djangoapps/certificates/views/webview.py @@ -397,7 +397,7 @@ def _track_certificate_events(request, context, course, user, user_certificate): } ) else: - log.warn( + log.warning( u"Could not find badge for %s on course %s.", user.id, course_key, diff --git a/lms/djangoapps/commerce/apps.py b/lms/djangoapps/commerce/apps.py index 9c0c217cccb6518462c4ac043efa742d57dcb48d..9e94283d69a59b56627d4bfcf5a3943f28223e61 100644 --- a/lms/djangoapps/commerce/apps.py +++ b/lms/djangoapps/commerce/apps.py @@ -16,4 +16,4 @@ class CommerceConfig(AppConfig): """ Connect handlers to signals. """ - from . import signals # pylint: disable=unused-variable + from . import signals # pylint: disable=unused-import diff --git a/lms/djangoapps/commerce/migrations/0001_data__add_ecommerce_service_user.py b/lms/djangoapps/commerce/migrations/0001_data__add_ecommerce_service_user.py index 468c3d98437a993ed1632a784b1fd18390d33d38..0ebf5b6fe034aa305551accbd2211468c24edfde 100644 --- a/lms/djangoapps/commerce/migrations/0001_data__add_ecommerce_service_user.py +++ b/lms/djangoapps/commerce/migrations/0001_data__add_ecommerce_service_user.py @@ -2,6 +2,7 @@ from django.conf import settings +from django.contrib.auth import get_user_model from django.contrib.auth.models import User from django.db import migrations, models @@ -10,6 +11,7 @@ EMAIL = USERNAME + '@fake.email' def forwards(apps, schema_editor): """Add the service user.""" + User = get_user_model() user, created = User.objects.get_or_create(username=USERNAME, email=EMAIL) if created: user.set_unusable_password() @@ -21,6 +23,11 @@ def backwards(apps, schema_editor): class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('user_api', '0002_retirementstate_userretirementstatus'), + ] + operations = [ migrations.RunPython(forwards, backwards), ] diff --git a/lms/djangoapps/commerce/tests/mocks.py b/lms/djangoapps/commerce/tests/mocks.py index 7b41f09bc283c24c0e5212e2d5dd2d5e455a0614..4b0813f99265c7a1d06e9ffcfb2e62bc8a6193b8 100644 --- a/lms/djangoapps/commerce/tests/mocks.py +++ b/lms/djangoapps/commerce/tests/mocks.py @@ -60,9 +60,9 @@ class mock_ecommerce_api_endpoint(object): """ raise NotImplementedError - def _exception_body(self, request, uri, headers): # pylint: disable=unused-argument + def _exception_body(self, request, uri, headers): """Helper used to create callbacks in order to have httpretty raise Exceptions.""" - raise self.exception # pylint: disable=raising-bad-type + raise self.exception def __enter__(self): httpretty.enable() diff --git a/lms/djangoapps/commerce/tests/test_signals.py b/lms/djangoapps/commerce/tests/test_signals.py index 473bcd6eb17c071068cf5db501fd1b5129b04eef..0917c94e1240b64798da6271083c672405d8caad 100644 --- a/lms/djangoapps/commerce/tests/test_signals.py +++ b/lms/djangoapps/commerce/tests/test_signals.py @@ -16,7 +16,7 @@ from django.test import TestCase from django.test.utils import override_settings from opaque_keys.edx.keys import CourseKey from requests import Timeout -from six.moves.urllib.parse import urljoin # pylint: disable=import-error +from six.moves.urllib.parse import urljoin from course_modes.models import CourseMode from student.signals import REFUND_ORDER diff --git a/lms/djangoapps/commerce/tests/test_utils.py b/lms/djangoapps/commerce/tests/test_utils.py index 6e3b688c6521c2f4b192362f5dbc072022325c0a..45f4283b9f1f75f9dd7f96ee6ff39f0f66b68239 100644 --- a/lms/djangoapps/commerce/tests/test_utils.py +++ b/lms/djangoapps/commerce/tests/test_utils.py @@ -11,7 +11,7 @@ from django.test.client import RequestFactory from django.test.utils import override_settings from mock import patch from opaque_keys.edx.locator import CourseLocator -from six.moves.urllib.parse import urlencode # pylint: disable=import-error +from six.moves.urllib.parse import urlencode from waffle.testutils import override_switch from course_modes.models import CourseMode diff --git a/lms/djangoapps/commerce/tests/test_views.py b/lms/djangoapps/commerce/tests/test_views.py index 628e86c7006512ff0611c472c2f447d3cf840219..22637c808015ba89191e38f55a0612816db6fc84 100644 --- a/lms/djangoapps/commerce/tests/test_views.py +++ b/lms/djangoapps/commerce/tests/test_views.py @@ -1,18 +1,6 @@ """ Tests for commerce views. """ - -import json - -import ddt -import mock -from django.urls import reverse - -from course_modes.models import CourseMode -from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme -from student.models import CourseEnrollment from student.tests.factories import UserFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory class UserMixin(object): @@ -25,123 +13,3 @@ class UserMixin(object): def _login(self): """ Log into LMS. """ self.client.login(username=self.user.username, password='test') - - -@ddt.ddt -class ReceiptViewTests(UserMixin, ModuleStoreTestCase): - """ Tests for the receipt view. """ - - def setUp(self): - """ - Add a user and a course - """ - super(ReceiptViewTests, self).setUp() - self.user = UserFactory() - self.client.login(username=self.user.username, password='test') - self.course = CourseFactory.create( - org='edX', - course='900', - run='test_run' - ) - - def test_login_required(self): - """ The view should redirect to the login page if the user is not logged in. """ - self.client.logout() - response = self.client.post(reverse('commerce:checkout_receipt')) - self.assertEqual(response.status_code, 302) - - def post_to_receipt_page(self, post_data): - """ DRY helper """ - response = self.client.post(reverse('commerce:checkout_receipt'), params={'basket_id': 1}, data=post_data) - self.assertEqual(response.status_code, 200) - return response - - def test_user_verification_status_success(self): - """ - Test user verification status. If the user enrollment for the course belongs to verified modes - e.g. Verified, Professional then verification is required. - """ - # Enroll as verified in the course with the current user. - CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.VERIFIED) - response = self.client.get( - reverse('commerce:user_verification_status'), data={'course_id': str(self.course.id)} - ) - json_data = json.loads(response.content.decode('utf-8')) - self.assertEqual(json_data['is_verification_required'], True) - - # Enroll as honor in the course with the current user. - CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.HONOR) - response = self.client.get( - reverse('commerce:user_verification_status'), data={'course_id': str(self.course.id)} - ) - json_data = json.loads(response.content.decode('utf-8')) - self.assertEqual(json_data['is_verification_required'], False) - - def test_user_verification_status_failure(self): - """ - Test user verification status failure. View should required HttpResponseBadRequest 400 if course id is missing. - """ - response = self.client.get(reverse('commerce:user_verification_status')) - self.assertEqual(response.status_code, 400) - - @ddt.data('decision', 'reason_code', 'signed_field_names', None) - def test_is_cybersource(self, post_key): - """ - Ensure the view uses three specific POST keys to detect a request initiated by Cybersource. - """ - self._login() - post_data = {'decision': 'REJECT', 'reason_code': '200', 'signed_field_names': 'dummy'} - if post_key is not None: - # a key will be missing; we will not expect the receipt page to handle a cybersource decision - del post_data[post_key] - expected_pattern = r"<title>(\s+)Receipt" - else: - expected_pattern = r"<title>(\s+)Payment Failed" - response = self.post_to_receipt_page(post_data) - self.assertRegex(response.content.decode('utf-8'), expected_pattern) - - @ddt.data('ACCEPT', 'REJECT', 'ERROR') - def test_cybersource_decision(self, decision): - """ - Ensure the view renders a page appropriately depending on the Cybersource decision. - """ - self._login() - post_data = {'decision': decision, 'reason_code': '200', 'signed_field_names': 'dummy'} - expected_pattern = r"<title>(\s+)Receipt" if decision == 'ACCEPT' else r"<title>(\s+)Payment Failed" - response = self.post_to_receipt_page(post_data) - self.assertRegex(response.content.decode('utf-8'), expected_pattern) - - @ddt.data(True, False) - @mock.patch('lms.djangoapps.commerce.views.is_user_payment_error') - def test_cybersource_message(self, is_user_message_expected, mock_is_user_payment_error): - """ - Ensure that the page displays the right message for the reason_code (it - may be a user error message or a system error message). - """ - mock_is_user_payment_error.return_value = is_user_message_expected - self._login() - response = self.post_to_receipt_page({'decision': 'REJECT', 'reason_code': '99', 'signed_field_names': 'dummy'}) - self.assertTrue(mock_is_user_payment_error.called) - self.assertTrue(mock_is_user_payment_error.call_args[0][0], '99') - - user_message = "There was a problem with this transaction" - system_message = "A system error occurred while processing your payment" - self.assertRegex( - response.content.decode('utf-8'), - user_message if is_user_message_expected else system_message - ) - self.assertNotRegexpMatches( - response.content.decode('utf-8'), - user_message if not is_user_message_expected else system_message - ) - - @with_comprehensive_theme("edx.org") - def test_hide_nav_header(self): - self._login() - post_data = {'decision': 'ACCEPT', 'reason_code': '200', 'signed_field_names': 'dummy'} - response = self.post_to_receipt_page(post_data) - - # Verify that the header navigation links are hidden for the edx.org version - self.assertNotContains(response, "How it Works") - self.assertNotContains(response, "Find courses") - self.assertNotContains(response, "Schools & Partners") diff --git a/lms/djangoapps/commerce/urls.py b/lms/djangoapps/commerce/urls.py deleted file mode 100644 index b7b31fb6c80518267a2229622197e3506a5eb1a1..0000000000000000000000000000000000000000 --- a/lms/djangoapps/commerce/urls.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -Defines the URL routes for this app. -""" - - -from django.conf.urls import url - -from . import views - -app_name = 'commerce' -urlpatterns = [ - url(r'^checkout/cancel/$', views.checkout_cancel, name='checkout_cancel'), - url(r'^checkout/error/$', views.checkout_error, name='checkout_error'), - url(r'^checkout/receipt/$', views.checkout_receipt, name='checkout_receipt'), - url(r'^checkout/verification_status/$', views.user_verification_status, name='user_verification_status'), -] diff --git a/lms/djangoapps/commerce/utils.py b/lms/djangoapps/commerce/utils.py index e82f4696033fba601557c16f8b22ed9f6694e389..7901b1662ccf7a025450823c1761f0efbea28498 100644 --- a/lms/djangoapps/commerce/utils.py +++ b/lms/djangoapps/commerce/utils.py @@ -12,7 +12,7 @@ from django.contrib.auth import get_user_model from django.urls import reverse from django.utils.translation import ugettext as _ from opaque_keys.edx.keys import CourseKey -from six.moves.urllib.parse import urlencode, urljoin # pylint: disable=import-error +from six.moves.urllib.parse import urlencode, urljoin from course_modes.models import CourseMode from openedx.core.djangoapps.commerce.utils import ecommerce_api_client, is_commerce_service_configured diff --git a/lms/djangoapps/commerce/views.py b/lms/djangoapps/commerce/views.py deleted file mode 100644 index 1a10ceae6eb01217057b2f8dbffe98d7dfedc52d..0000000000000000000000000000000000000000 --- a/lms/djangoapps/commerce/views.py +++ /dev/null @@ -1,126 +0,0 @@ -""" Commerce views. """ - - -import logging - -from django.conf import settings -from django.contrib.auth.decorators import login_required -from django.core.cache import cache -from django.http import HttpResponseBadRequest -from django.utils.translation import ugettext as _ -from django.views.decorators.csrf import csrf_exempt -from django.views.decorators.http import require_http_methods -from opaque_keys.edx.locator import CourseLocator - -from course_modes.models import CourseMode -from edxmako.shortcuts import render_to_response -from lms.djangoapps.verify_student.services import IDVerificationService -from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site -from openedx.core.djangolib.markup import HTML -from shoppingcart.processors.CyberSource2 import is_user_payment_error -from student.models import CourseEnrollment -from util.json_request import JsonResponse - -from .models import CommerceConfiguration - -log = logging.getLogger(__name__) - - -@csrf_exempt -def checkout_cancel(_request): - """ Checkout/payment cancellation view. """ - context = { - 'payment_support_email': configuration_helpers.get_value( - 'payment_support_email', settings.PAYMENT_SUPPORT_EMAIL, - ) - } - return render_to_response("commerce/checkout_cancel.html", context) - - -@csrf_exempt -def checkout_error(_request): - """ Checkout/payment error view. """ - context = { - 'payment_support_email': configuration_helpers.get_value( - 'payment_support_email', settings.PAYMENT_SUPPORT_EMAIL, - ) - } - return render_to_response("commerce/checkout_error.html", context) - - -@csrf_exempt -@login_required -def checkout_receipt(request): - """ Receipt view. """ - - page_title = _('Receipt') - is_payment_complete = True - payment_support_email = configuration_helpers.get_value('payment_support_email', settings.PAYMENT_SUPPORT_EMAIL) - payment_support_link = HTML(u'<a href=\"mailto:{email}\">{email}</a>').format(email=payment_support_email) - - is_cybersource = all(k in request.POST for k in ('signed_field_names', 'decision', 'reason_code')) - if is_cybersource and request.POST['decision'] != 'ACCEPT': - # Cybersource may redirect users to this view if it couldn't recover - # from an error while capturing payment info. - is_payment_complete = False - page_title = _('Payment Failed') - reason_code = request.POST['reason_code'] - # if the problem was with the info submitted by the user, we present more detailed messages. - if is_user_payment_error(reason_code): - error_summary = _("There was a problem with this transaction. You have not been charged.") - error_text = _( - "Make sure your information is correct, or try again with a different card or another form of payment." - ) - else: - error_summary = _("A system error occurred while processing your payment. You have not been charged.") - error_text = _("Please wait a few minutes and then try again.") - for_help_text = _(u"For help, contact {payment_support_link}.").format(payment_support_link=payment_support_link) - else: - # if anything goes wrong rendering the receipt, it indicates a problem fetching order data. - error_summary = _("An error occurred while creating your receipt.") - error_text = None # nothing particularly helpful to say if this happens. - for_help_text = _( - u"If your course does not appear on your dashboard, contact {payment_support_link}." - ).format(payment_support_link=payment_support_link) - - commerce_configuration = CommerceConfiguration.current() - # user order cache should be cleared when a new order is placed - # so user can see new order in their order history. - if is_payment_complete and commerce_configuration.enabled and commerce_configuration.is_cache_enabled: - cache_key = commerce_configuration.CACHE_KEY + '.' + str(request.user.id) - cache.delete(cache_key) - - context = { - 'page_title': page_title, - 'is_payment_complete': is_payment_complete, - 'platform_name': configuration_helpers.get_value('platform_name', settings.PLATFORM_NAME), - 'verified': IDVerificationService.user_has_valid_or_pending(request.user), - 'error_summary': error_summary, - 'error_text': error_text, - 'for_help_text': for_help_text, - 'payment_support_email': payment_support_email, - 'username': request.user.username, - 'nav_hidden': True, - 'is_request_in_themed_site': is_request_in_themed_site() - } - return render_to_response('commerce/checkout_receipt.html', context) - - -@require_http_methods(["GET"]) -@login_required -def user_verification_status(request): - """ - Check for user verification status. - :return 'True' if the user enrollment for the course belongs to verified modes e.g. Verified, Professional. - """ - course_id = request.GET.get('course_id', None) - - if course_id is None: - return HttpResponseBadRequest() - - course_key = CourseLocator.from_string(course_id) - enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(request.user, course_key) - is_verification_required = enrollment_mode in CourseMode.VERIFIED_MODES - - return JsonResponse({'is_verification_required': is_verification_required}) diff --git a/lms/djangoapps/course_api/blocks/api.py b/lms/djangoapps/course_api/blocks/api.py index 39103a1d9f850a6d81b4e1a0eebc7a207d714316..1befdb2def31c30cc623640765f5b5b477890964 100644 --- a/lms/djangoapps/course_api/blocks/api.py +++ b/lms/djangoapps/course_api/blocks/api.py @@ -29,6 +29,7 @@ def get_blocks( return_type='dict', block_types_filter=None, hide_access_denials=False, + allow_start_dates_in_future=False, ): """ Return a serialized representation of the course blocks. @@ -58,6 +59,9 @@ def get_blocks( hide_access_denials (bool): When True, filter out any blocks that were denied access to the user, even if they have access denial messages attached. + allow_start_dates_in_future (bool): When True, will allow blocks to be + returned that can bypass the StartDateTransformer's filter to show + blocks with start dates in the future. """ if HIDE_ACCESS_DENIALS_FLAG.is_enabled(): @@ -101,7 +105,8 @@ def get_blocks( transformers += [BlockCompletionTransformer()] # transform - blocks = course_blocks_api.get_course_blocks(user, usage_key, transformers) + blocks = course_blocks_api.get_course_blocks( + user, usage_key, transformers, allow_start_dates_in_future=allow_start_dates_in_future) # filter blocks by types if block_types_filter: diff --git a/lms/djangoapps/course_api/blocks/serializers.py b/lms/djangoapps/course_api/blocks/serializers.py index f45f17381e2c1e9747c55c8732769b8ceccb9591..eee1d5d4ed776e3ee5baa91613688da8b11e614d 100644 --- a/lms/djangoapps/course_api/blocks/serializers.py +++ b/lms/djangoapps/course_api/blocks/serializers.py @@ -8,7 +8,80 @@ from django.conf import settings from rest_framework import serializers from rest_framework.reverse import reverse -from .transformers import SUPPORTED_FIELDS +from lms.djangoapps.course_blocks.transformers.visibility import VisibilityTransformer + +from .transformers.block_completion import BlockCompletionTransformer +from .transformers.block_counts import BlockCountsTransformer +from .transformers.milestones import MilestonesAndSpecialExamsTransformer +from .transformers.navigation import BlockNavigationTransformer +from .transformers.student_view import StudentViewTransformer + + +class SupportedFieldType(object): + """ + Metadata about fields supported by different transformers + """ + def __init__( + self, + block_field_name, + transformer=None, + requested_field_name=None, + serializer_field_name=None, + default_value=None + ): + self.transformer = transformer + self.block_field_name = block_field_name + self.requested_field_name = requested_field_name or block_field_name + self.serializer_field_name = serializer_field_name or self.requested_field_name + self.default_value = default_value + + +# A list of metadata for additional requested fields to be used by the +# BlockSerializer` class. Each entry provides information on how that field can +# be requested (`requested_field_name`), can be found (`transformer` and +# `block_field_name`), and should be serialized (`serializer_field_name` and +# `default_value`). + +SUPPORTED_FIELDS = [ + SupportedFieldType('category', requested_field_name='type'), + SupportedFieldType('display_name', default_value=''), + SupportedFieldType('graded'), + SupportedFieldType('format'), + SupportedFieldType('start'), + SupportedFieldType('due'), + SupportedFieldType('contains_gated_content'), + SupportedFieldType('has_score'), + SupportedFieldType('weight'), + SupportedFieldType('show_correctness'), + # 'student_view_data' + SupportedFieldType(StudentViewTransformer.STUDENT_VIEW_DATA, StudentViewTransformer), + # 'student_view_multi_device' + SupportedFieldType(StudentViewTransformer.STUDENT_VIEW_MULTI_DEVICE, StudentViewTransformer), + + SupportedFieldType('special_exam_info', MilestonesAndSpecialExamsTransformer), + + # set the block_field_name to None so the entire data for the transformer is serialized + SupportedFieldType(None, BlockCountsTransformer, BlockCountsTransformer.BLOCK_COUNTS), + + SupportedFieldType( + BlockNavigationTransformer.BLOCK_NAVIGATION, + BlockNavigationTransformer, + requested_field_name='nav_depth', + serializer_field_name='descendants', + ), + + # Provide the staff visibility info stored when VisibilityTransformer ran previously + SupportedFieldType( + 'merged_visible_to_staff_only', + VisibilityTransformer, + requested_field_name='visible_to_staff_only', + ), + SupportedFieldType( + BlockCompletionTransformer.COMPLETION, + BlockCompletionTransformer, + 'completion' + ) +] # This lists the names of all fields that are allowed # to be show to users who do not have access to a particular piece diff --git a/lms/djangoapps/course_api/blocks/tests/test_api.py b/lms/djangoapps/course_api/blocks/tests/test_api.py index b7694edfc725db170bb07cbd41799176ee0ad145..a632aef1ffcb0a33a4406af98a0d925a6d1c5da6 100644 --- a/lms/djangoapps/course_api/blocks/tests/test_api.py +++ b/lms/djangoapps/course_api/blocks/tests/test_api.py @@ -20,7 +20,6 @@ from xmodule.modulestore.tests.factories import SampleCourseFactory, check_mongo from xmodule.modulestore.tests.sample_courses import BlockInfo from ..api import get_blocks -from ..toggles import ENABLE_VIDEO_URL_REWRITE class TestGetBlocks(SharedModuleStoreTestCase): @@ -159,10 +158,7 @@ class TestGetBlocksMobileHack(SharedModuleStoreTestCase): assert_containment(str(empty_container_key), blocks['blocks']) @patch('xmodule.video_module.VideoBlock.student_view_data') - @ddt.data( - True, False - ) - def test_video_urls_rewrite(self, waffle_flag_value, video_data_patch): + def test_video_urls_rewrite(self, video_data_patch): """ Verify the video blocks returned have their URL re-written for encoded videos. @@ -179,17 +175,13 @@ class TestGetBlocksMobileHack(SharedModuleStoreTestCase): } } } - with override_waffle_flag(ENABLE_VIDEO_URL_REWRITE, waffle_flag_value): - blocks = get_blocks( - self.request, self.course.location, requested_fields=['student_view_data'], student_view_data=['video'] - ) + blocks = get_blocks( + self.request, self.course.location, requested_fields=['student_view_data'], student_view_data=['video'] + ) video_block_key = str(self.course.id.make_usage_key('video', 'sample_video')) video_block_data = blocks['blocks'][video_block_key] for video_data in six.itervalues(video_block_data['student_view_data']['encoded_videos']): - if waffle_flag_value: - self.assertNotIn('cloudfront', video_data['url']) - else: - self.assertIn('cloudfront', video_data['url']) + self.assertNotIn('cloudfront', video_data['url']) @ddt.ddt @@ -243,7 +235,7 @@ class TestGetBlocksQueryCounts(TestGetBlocksQueryCountsBase): self._get_blocks( course, expected_mongo_queries=0, - expected_sql_queries=13 if with_storage_backing else 12, + expected_sql_queries=11 if with_storage_backing else 10, ) @ddt.data( @@ -260,9 +252,9 @@ class TestGetBlocksQueryCounts(TestGetBlocksQueryCountsBase): clear_course_from_cache(course.id) if with_storage_backing: - num_sql_queries = 23 + num_sql_queries = 21 else: - num_sql_queries = 13 + num_sql_queries = 11 self._get_blocks( course, diff --git a/lms/djangoapps/course_api/blocks/tests/test_forms.py b/lms/djangoapps/course_api/blocks/tests/test_forms.py index 826f8c32598aa3396e3b8bf76e6f73d97e815b50..62a8692b4f0c9d69e71c60831839768a38875f9c 100644 --- a/lms/djangoapps/course_api/blocks/tests/test_forms.py +++ b/lms/djangoapps/course_api/blocks/tests/test_forms.py @@ -5,7 +5,7 @@ Tests for Course Blocks forms import ddt import six -from six.moves.urllib.parse import urlencode # pylint: disable=import-error +from six.moves.urllib.parse import urlencode from django.http import Http404, QueryDict from opaque_keys.edx.locator import CourseLocator from rest_framework.exceptions import PermissionDenied diff --git a/lms/djangoapps/course_api/blocks/tests/test_views.py b/lms/djangoapps/course_api/blocks/tests/test_views.py index 7435f6ba96e4b039f7470cb7bfa80f813e4a8e6f..99061b2cd7ff287bbca129640a0c37df4b03f97e 100644 --- a/lms/djangoapps/course_api/blocks/tests/test_views.py +++ b/lms/djangoapps/course_api/blocks/tests/test_views.py @@ -6,7 +6,7 @@ Tests for Blocks Views from datetime import datetime import six -from six.moves.urllib.parse import urlencode, urlunparse # pylint: disable=import-error +from six.moves.urllib.parse import urlencode, urlunparse from django.urls import reverse from opaque_keys.edx.locator import CourseLocator diff --git a/lms/djangoapps/course_api/blocks/toggles.py b/lms/djangoapps/course_api/blocks/toggles.py index 157dc5cfc3df4ce41dab79b163daf3b466079d86..7335dd3faf75db3a4e2f16a1c3ea4225ac88e869 100644 --- a/lms/djangoapps/course_api/blocks/toggles.py +++ b/lms/djangoapps/course_api/blocks/toggles.py @@ -25,21 +25,3 @@ HIDE_ACCESS_DENIALS_FLAG = WaffleFlag( flag_name=u'hide_access_denials', flag_undefined_default=False ) - -# Waffle course override to rewrite video URLs for videos that have encodings available. -# .. toggle_name: course_blocks_api.enable_video_url_rewrite -# .. toggle_implementation: CourseWaffleFlag -# .. toggle_default: False -# .. toggle_description: Controlled rollout for video URL re-write utility to serve videos from edX CDN. -# .. toggle_category: course api -# .. toggle_use_cases: monitored_rollout -# .. toggle_creation_date: 2019-09-24 -# .. toggle_expiration_date: ?? -# .. toggle_warnings: None -# .. toggle_tickets: PROD-62 -# .. toggle_status: supported -ENABLE_VIDEO_URL_REWRITE = CourseWaffleFlag( - waffle_namespace=COURSE_BLOCKS_API_NAMESPACE, - flag_name="enable_video_url_rewrite", - flag_undefined_default=True -) diff --git a/lms/djangoapps/course_api/blocks/transformers/__init__.py b/lms/djangoapps/course_api/blocks/transformers/__init__.py index 5ef9850c0b4c3bf9a02375cbad3ce55d6d509bf5..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/lms/djangoapps/course_api/blocks/transformers/__init__.py +++ b/lms/djangoapps/course_api/blocks/transformers/__init__.py @@ -1,77 +0,0 @@ -""" -Course API Block Transformers -""" - - -from lms.djangoapps.course_blocks.transformers.visibility import VisibilityTransformer - -from .block_completion import BlockCompletionTransformer -from .block_counts import BlockCountsTransformer -from .milestones import MilestonesAndSpecialExamsTransformer -from .navigation import BlockNavigationTransformer -from .student_view import StudentViewTransformer - - -class SupportedFieldType(object): - """ - Metadata about fields supported by different transformers - """ - def __init__( - self, - block_field_name, - transformer=None, - requested_field_name=None, - serializer_field_name=None, - default_value=None - ): - self.transformer = transformer - self.block_field_name = block_field_name - self.requested_field_name = requested_field_name or block_field_name - self.serializer_field_name = serializer_field_name or self.requested_field_name - self.default_value = default_value - - -# A list of metadata for additional requested fields to be used by the -# BlockSerializer` class. Each entry provides information on how that field can -# be requested (`requested_field_name`), can be found (`transformer` and -# `block_field_name`), and should be serialized (`serializer_field_name` and -# `default_value`). - -SUPPORTED_FIELDS = [ - SupportedFieldType('category', requested_field_name='type'), - SupportedFieldType('display_name', default_value=''), - SupportedFieldType('graded'), - SupportedFieldType('format'), - SupportedFieldType('due'), - SupportedFieldType('has_score'), - SupportedFieldType('weight'), - SupportedFieldType('show_correctness'), - # 'student_view_data' - SupportedFieldType(StudentViewTransformer.STUDENT_VIEW_DATA, StudentViewTransformer), - # 'student_view_multi_device' - SupportedFieldType(StudentViewTransformer.STUDENT_VIEW_MULTI_DEVICE, StudentViewTransformer), - - SupportedFieldType('special_exam_info', MilestonesAndSpecialExamsTransformer), - - # set the block_field_name to None so the entire data for the transformer is serialized - SupportedFieldType(None, BlockCountsTransformer, BlockCountsTransformer.BLOCK_COUNTS), - - SupportedFieldType( - BlockNavigationTransformer.BLOCK_NAVIGATION, - BlockNavigationTransformer, - requested_field_name='nav_depth', - serializer_field_name='descendants', - ), - - # Provide the staff visibility info stored when VisibilityTransformer ran previously - SupportedFieldType( - 'merged_visible_to_staff_only', - VisibilityTransformer, - requested_field_name='visible_to_staff_only', - ), - SupportedFieldType( - BlockCompletionTransformer.COMPLETION, - BlockCompletionTransformer, - 'completion' - ) -] diff --git a/lms/djangoapps/course_api/blocks/transformers/block_completion.py b/lms/djangoapps/course_api/blocks/transformers/block_completion.py index 6d02caff2d55fe122deecd2418b1aae4d9f0f6e2..57cf23c0709c5fc1358cff2c0730eb3231d24913 100644 --- a/lms/djangoapps/course_api/blocks/transformers/block_completion.py +++ b/lms/djangoapps/course_api/blocks/transformers/block_completion.py @@ -16,6 +16,8 @@ class BlockCompletionTransformer(BlockStructureTransformer): READ_VERSION = 1 WRITE_VERSION = 1 COMPLETION = 'completion' + COMPLETE = 'complete' + RESUME_BLOCK = 'resume_block' @classmethod def name(cls): @@ -43,9 +45,46 @@ class BlockCompletionTransformer(BlockStructureTransformer): def collect(cls, block_structure): block_structure.request_xblock_fields('completion_mode') + def mark_complete(self, course_block_completions, latest_completion_block_key, block_key, block_structure): + """ + Helper function to mark a block as 'complete' as dictated by + course_block_completions (for problems) or all of a block's children being complete. + This also sets the 'resume_block' field as that is connected to the latest completed block. + + :param course_block_completions: dict[course_completion_object] = completion_value + :param latest_completion_block_key: block key for the latest completed block. + :param block_key: A opaque_keys.edx.locator.BlockUsageLocator object + :param block_structure: A BlockStructureBlockData object + """ + if block_key in course_block_completions: + block_structure.override_xblock_field(block_key, self.COMPLETE, True) + if block_key == latest_completion_block_key: + block_structure.override_xblock_field(block_key, self.RESUME_BLOCK, True) + + children = block_structure.get_children(block_key) + non_discussion_children = (child_key for child_key in children + if block_structure.get_xblock_field(child_key, 'category') != 'discussion') + child_complete = (block_structure.get_xblock_field(child_key, self.COMPLETE) + for child_key in non_discussion_children) + if children and all(child_complete): + block_structure.override_xblock_field(block_key, self.COMPLETE, True) + + if any(block_structure.get_xblock_field(child_key, self.RESUME_BLOCK) for child_key in children): + block_structure.override_xblock_field(block_key, self.RESUME_BLOCK, True) + def transform(self, usage_info, block_structure): """ - Mutates block_structure adding extra field which contains block's completion. + Mutates block_structure adding three extra fields which contains block's completion, + complete status, and if the block is a resume_block, indicating it is the most recently + completed block. + + IMPORTANT!: There is a subtle, but important difference between 'completion' and 'complete' + which are both set in this transformer: + 'completion': Returns a percentile (0.0 - 1.0) of correctness for a _problem_. This field will + be None for all other blocks that are not leaves and captured in BlockCompletion. + 'complete': Returns a boolean indicating whether the block is complete. For problems, this will + be taken from a BlockCompletion entry existing. For all other blocks, it will be marked True + if all of the children of the block are all marked complete (this is calculated recursively) """ def _is_block_an_aggregator_or_excluded(block_key): """ @@ -82,3 +121,9 @@ class BlockCompletionTransformer(BlockStructureTransformer): block_structure.set_transformer_block_field( block_key, self, self.COMPLETION, completion_value ) + + latest_completion = completions.latest() if completions.exists() else None + if latest_completion: + latest_completion_block_key = latest_completion[0] + for block_key in block_structure.post_order_traversal(): + self.mark_complete(completions_dict, latest_completion_block_key, block_key, block_structure) diff --git a/lms/djangoapps/course_api/blocks/transformers/blocks_api.py b/lms/djangoapps/course_api/blocks/transformers/blocks_api.py index 602be5de21638fe8372b1fac113389eed26f138b..5e42f277c340f1e0f300c87e51f9068a3ef4ed71 100644 --- a/lms/djangoapps/course_api/blocks/transformers/blocks_api.py +++ b/lms/djangoapps/course_api/blocks/transformers/blocks_api.py @@ -10,7 +10,6 @@ from .block_depth import BlockDepthTransformer from .navigation import BlockNavigationTransformer from .student_view import StudentViewTransformer from .video_urls import VideoBlockURLTransformer -from ..toggles import ENABLE_VIDEO_URL_REWRITE class BlocksAPITransformer(BlockStructureTransformer): @@ -69,5 +68,4 @@ class BlocksAPITransformer(BlockStructureTransformer): BlockCountsTransformer(self.block_types_to_count).transform(usage_info, block_structure) BlockDepthTransformer(self.depth).transform(usage_info, block_structure) BlockNavigationTransformer(self.nav_depth).transform(usage_info, block_structure) - if ENABLE_VIDEO_URL_REWRITE.is_enabled(block_structure.root_block_usage_key.course_key): - VideoBlockURLTransformer().transform(usage_info, block_structure) + VideoBlockURLTransformer().transform(usage_info, block_structure) diff --git a/lms/djangoapps/course_api/serializers.py b/lms/djangoapps/course_api/serializers.py index 69fa5c33ffdf8c0fc5608b37614c81a781e3a90a..931fbe83f8cc5466a2b85578f7f4e85f6266d466 100644 --- a/lms/djangoapps/course_api/serializers.py +++ b/lms/djangoapps/course_api/serializers.py @@ -3,9 +3,9 @@ Course API Serializers. Representing course catalog data """ -import six.moves.urllib.error # pylint: disable=import-error -import six.moves.urllib.parse # pylint: disable=import-error -import six.moves.urllib.request # pylint: disable=import-error +import six.moves.urllib.error +import six.moves.urllib.parse +import six.moves.urllib.request from django.urls import reverse from rest_framework import serializers diff --git a/lms/djangoapps/course_api/tests/test_forms.py b/lms/djangoapps/course_api/tests/test_forms.py index ed2c2e095115dfaa01c0363b0096dfa4e0670fc2..1ecaa48ebd2ce66b7df3ca430be7c2da8196e5df 100644 --- a/lms/djangoapps/course_api/tests/test_forms.py +++ b/lms/djangoapps/course_api/tests/test_forms.py @@ -1,13 +1,12 @@ """ Tests for Course API forms. """ -# pylint: disable=missing-docstring from itertools import product import ddt import six -from six.moves.urllib.parse import urlencode # pylint: disable=import-error +from six.moves.urllib.parse import urlencode from django.contrib.auth.models import AnonymousUser from django.http import QueryDict diff --git a/lms/djangoapps/course_blocks/api.py b/lms/djangoapps/course_blocks/api.py index f1b65d0d9e0f82975324bc2852b79062aec21692..569eeb947eab8f741aa74ab427f524babb4fca6d 100644 --- a/lms/djangoapps/course_blocks/api.py +++ b/lms/djangoapps/course_blocks/api.py @@ -7,6 +7,7 @@ get_course_blocks function. from django.conf import settings from edx_when import field_data +from lms.djangoapps.course_api.blocks.transformers.block_completion import BlockCompletionTransformer from openedx.core.djangoapps.content.block_structure.api import get_block_structure_manager from openedx.core.djangoapps.content.block_structure.transformers import BlockStructureTransformers from openedx.features.content_type_gating.block_transformers import ContentTypeGateTransformer @@ -57,6 +58,8 @@ def get_course_blocks( starting_block_usage_key, transformers=None, collected_block_structure=None, + allow_start_dates_in_future=False, + include_completion=False, ): """ A higher order function implemented on top of the @@ -90,7 +93,9 @@ def get_course_blocks( """ if not transformers: transformers = BlockStructureTransformers(get_course_block_access_transformers(user)) - transformers.usage_info = CourseUsageInfo(starting_block_usage_key.course_key, user) + if include_completion: + transformers += [BlockCompletionTransformer()] + transformers.usage_info = CourseUsageInfo(starting_block_usage_key.course_key, user, allow_start_dates_in_future) return get_block_structure_manager(starting_block_usage_key.course_key).get_transformed( transformers, diff --git a/lms/djangoapps/course_blocks/transformers/start_date.py b/lms/djangoapps/course_blocks/transformers/start_date.py index 06932819e29ade375aca70646a6345ac3fe0548c..900a8b74c0dd2357b966f0cea36b859901d150b5 100644 --- a/lms/djangoapps/course_blocks/transformers/start_date.py +++ b/lms/djangoapps/course_blocks/transformers/start_date.py @@ -2,6 +2,8 @@ Start Date Transformer implementation. """ +from datetime import datetime +from pytz import UTC from lms.djangoapps.courseware.access_utils import check_start_date from openedx.core.djangoapps.content.block_structure.transformer import ( @@ -71,13 +73,16 @@ class StartDateTransformer(FilteringTransformerMixin, BlockStructureTransformer) def transform_block_filters(self, usage_info, block_structure): # Users with staff access bypass the Start Date check. - if usage_info.has_staff_access: + if usage_info.has_staff_access or usage_info.allow_start_dates_in_future: return [block_structure.create_universal_filter()] + now = datetime.now(UTC) + removal_condition = lambda block_key: not check_start_date( usage_info.user, block_structure.get_xblock_field(block_key, 'days_early_for_beta'), self._get_merged_start_date(block_structure, block_key), usage_info.course_key, + now=now, ) return [block_structure.create_removal_filter(removal_condition)] diff --git a/lms/djangoapps/course_blocks/transformers/user_partitions.py b/lms/djangoapps/course_blocks/transformers/user_partitions.py index 529e76b154ed3ff8491183896f05ed4dc15c374b..78805083c749d6c87c808b5c78cb3da1c4d5bc54 100644 --- a/lms/djangoapps/course_blocks/transformers/user_partitions.py +++ b/lms/djangoapps/course_blocks/transformers/user_partitions.py @@ -20,7 +20,7 @@ from .split_test import SplitTestTransformer from .utils import get_field_on_block -class UserPartitionTransformer(FilteringTransformerMixin, BlockStructureTransformer): +class UserPartitionTransformer(BlockStructureTransformer): """ A transformer that enforces the group access rules on course blocks, by honoring their user_partitions and group_access fields, and @@ -78,13 +78,18 @@ class UserPartitionTransformer(FilteringTransformerMixin, BlockStructureTransfor merged_group_access = _MergedGroupAccess(user_partitions, xblock, merged_parent_access_list) block_structure.set_transformer_block_field(block_key, cls, 'merged_group_access', merged_group_access) - def transform_block_filters(self, usage_info, block_structure): + def transform(self, usage_info, block_structure): user = usage_info.user - result_list = SplitTestTransformer().transform_block_filters(usage_info, block_structure) + SplitTestTransformer().transform(usage_info, block_structure) + staff_access = has_access(user, 'staff', usage_info.course_key) + + # If you have staff access, you are allowed access to the entire result list + if staff_access: + return user_partitions = block_structure.get_transformer_data(self, 'user_partitions') if not user_partitions: - return [block_structure.create_universal_filter()] + return user_groups = get_user_partition_groups(usage_info.course_key, user_partitions, user, 'id') @@ -92,35 +97,38 @@ class UserPartitionTransformer(FilteringTransformerMixin, BlockStructureTransfor transformer_block_field = block_structure.get_transformer_block_field( block_key, self, 'merged_group_access' ) - access_denying_partition_id = transformer_block_field.get_access_denying_partition( + if transformer_block_field is None: + continue + + access_denying_partition_ids = transformer_block_field.get_access_denying_partitions( user_groups ) - access_denying_partition = get_partition_from_id(user_partitions, access_denying_partition_id) - - if not has_access(user, 'staff', block_key) and access_denying_partition: - user_group = user_groups.get(access_denying_partition.id) - allowed_groups = transformer_block_field.get_allowed_groups()[access_denying_partition.id] - access_denied_message = access_denying_partition.access_denied_message( - block_key, user, user_group, allowed_groups - ) - block_structure.override_xblock_field( - block_key, 'authorization_denial_reason', access_denying_partition.name - ) - block_structure.override_xblock_field( - block_key, 'authorization_denial_message', access_denied_message - ) - - group_access_filter = block_structure.create_removal_filter( - lambda block_key: ( - not has_access(user, 'staff', block_key) and - block_structure.get_transformer_block_field( - block_key, self, 'merged_group_access' - ).get_access_denying_partition(user_groups) is not None and - block_structure.get_xblock_field(block_key, 'authorization_denial_message') is None - ) - ) - result_list.append(group_access_filter) - return result_list + access_denying_reasons = [] + access_denying_messages = [] + for partition_id in access_denying_partition_ids: + access_denying_partition = get_partition_from_id(user_partitions, partition_id) + + if access_denying_partition: + user_group = user_groups.get(access_denying_partition.id) + allowed_groups = transformer_block_field.get_allowed_groups()[access_denying_partition.id] + access_denied_message = access_denying_partition.access_denied_message( + block_key, user, user_group, allowed_groups + ) + access_denying_reasons.append(access_denying_partition.name) + if access_denied_message: + access_denying_messages.append(access_denied_message) + + if access_denying_reasons and not access_denying_messages: + block_structure.remove_block(block_key, keep_descendants=False) + else: + if access_denying_reasons: + block_structure.override_xblock_field( + block_key, 'authorization_denial_reason', access_denying_reasons[0] + ) + if access_denying_messages: + block_structure.override_xblock_field( + block_key, 'authorization_denial_message', access_denying_messages[0] + ) class _MergedGroupAccess(object): @@ -243,7 +251,7 @@ class _MergedGroupAccess(object): else: return None - def get_access_denying_partition(self, user_groups): + def get_access_denying_partitions(self, user_groups): """ Arguments: dict[int: Group]: Given a user, a mapping from user @@ -251,25 +259,21 @@ class _MergedGroupAccess(object): each partition. Returns: - bool: Which partition is denying access + list of ints: Which partition is denying access """ - for partition_id, allowed_group_ids in six.iteritems(self._access): + denied_access = [] + for partition_id, allowed_group_ids in self.get_allowed_groups().items(): # If the user is not assigned to a group for this partition, - # return partition that would deny access. + # return partition as one that would deny access. if partition_id not in user_groups: - return partition_id + denied_access.append(partition_id) - # If the user belongs to one of the allowed groups for this - # partition, then move and check the next partition. - elif user_groups[partition_id].id in allowed_group_ids: - continue - - # Else, return partition that would deny access. - else: - return partition_id + # If the user does not belong to one of the allowed groups for this + # partition, then return this partition as one that would deny access + elif user_groups[partition_id].id not in allowed_group_ids: + denied_access.append(partition_id) - # The user has access for every partition, return none - return None + return denied_access def check_group_access(self, user_groups): """ @@ -281,4 +285,4 @@ class _MergedGroupAccess(object): Returns: bool: Whether said user has group access. """ - return self.get_access_denying_partition(user_groups) is None + return not self.get_access_denying_partitions(user_groups) diff --git a/lms/djangoapps/course_blocks/usage_info.py b/lms/djangoapps/course_blocks/usage_info.py index 0d347120e506bf8017b320e738645080a5b604eb..457fc00f0abd5cb781549185d2cd6b0706cf4615 100644 --- a/lms/djangoapps/course_blocks/usage_info.py +++ b/lms/djangoapps/course_blocks/usage_info.py @@ -14,13 +14,19 @@ class CourseUsageInfo(object): an instance of it in calls to BlockStructureTransformer.transform methods. ''' - def __init__(self, course_key, user): + def __init__(self, course_key, user, allow_start_dates_in_future=False): # Course identifier (opaque_keys.edx.keys.CourseKey) self.course_key = course_key # User object (django.contrib.auth.models.User) self.user = user + # Sometimes we want to allow blocks to be returned that can bypass the + # StartDateTransformer's filter to show blocks with start dates in the future. + # One use case of this is for the Dates page where we want to display + # assignments that have not yet been released. + self.allow_start_dates_in_future = allow_start_dates_in_future + # Cached value of whether the user has staff access (bool/None) self._has_staff_access = None diff --git a/lms/djangoapps/course_goals/apps.py b/lms/djangoapps/course_goals/apps.py index 3e700224b27cd6322d9ad6b41f61a0fdb4d85181..fb41462d11df6ff9c72161c237f40ab4ea69f140 100644 --- a/lms/djangoapps/course_goals/apps.py +++ b/lms/djangoapps/course_goals/apps.py @@ -18,4 +18,4 @@ class CourseGoalsConfig(AppConfig): """ Connect signal handlers. """ - from . import handlers # pylint: disable=unused-variable + from . import handlers # pylint: disable=unused-import diff --git a/lms/djangoapps/course_home_api/__init__.py b/lms/djangoapps/course_home_api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/djangoapps/course_home_api/course_metadata/__init__.py b/lms/djangoapps/course_home_api/course_metadata/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/djangoapps/course_home_api/course_metadata/v1/__init__.py b/lms/djangoapps/course_home_api/course_metadata/v1/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/djangoapps/course_home_api/course_metadata/v1/serializers.py b/lms/djangoapps/course_home_api/course_metadata/v1/serializers.py new file mode 100644 index 0000000000000000000000000000000000000000..d012390bdfeebca7406a98047cbc885daadd0d9c --- /dev/null +++ b/lms/djangoapps/course_home_api/course_metadata/v1/serializers.py @@ -0,0 +1,39 @@ +# pylint: disable=abstract-method +""" +Course Home Course Metadata Serializers. Returns Course Metadata used for all +Course Home pages. +""" + + +from django.urls import reverse +from rest_framework import serializers + + +class CourseTabSerializer(serializers.Serializer): + """ + Serializer for the Course Home Tabs + """ + tab_id = serializers.CharField() + title = serializers.SerializerMethodField() + url = serializers.SerializerMethodField() + + def get_title(self, tab): + return tab.title or tab.get('name', '') + + def get_url(self, tab): + request = self.context.get('request') + return request.build_absolute_uri(tab.link_func(self.context.get('course'), reverse)) + + +class CourseHomeMetadataSerializer(serializers.Serializer): + """ + Serializer for the Course Home Course Metadata + """ + course_id = serializers.CharField() + is_staff = serializers.BooleanField() + number = serializers.CharField() + org = serializers.CharField() + tabs = CourseTabSerializer(many=True) + title = serializers.CharField() + is_self_paced = serializers.BooleanField() + is_enrolled = serializers.BooleanField() diff --git a/lms/djangoapps/course_home_api/course_metadata/v1/tests/__init__.py b/lms/djangoapps/course_home_api/course_metadata/v1/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/djangoapps/course_home_api/course_metadata/v1/tests/test_views.py b/lms/djangoapps/course_home_api/course_metadata/v1/tests/test_views.py new file mode 100644 index 0000000000000000000000000000000000000000..e2e6f675657b80f22ae94df2577342bcdd7dfa31 --- /dev/null +++ b/lms/djangoapps/course_home_api/course_metadata/v1/tests/test_views.py @@ -0,0 +1,53 @@ +""" +Tests for the Course Home Course Metadata API in the Course Home API +""" + + +import ddt + +from django.urls import reverse + +from course_modes.models import CourseMode +from lms.djangoapps.course_home_api.tests.utils import BaseCourseHomeTests +from student.models import CourseEnrollment +from student.tests.factories import UserFactory + + +@ddt.ddt +class CourseHomeMetadataTests(BaseCourseHomeTests): + """ + Tests for the Course Home Course Metadata API + """ + @classmethod + def setUpClass(cls): + BaseCourseHomeTests.setUpClass() + cls.url = reverse('course-home-course-metadata', args=[cls.course.id]) + + def test_get_authenticated_user(self): + CourseEnrollment.enroll(self.user, self.course.id, CourseMode.VERIFIED) + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + self.assertFalse(response.data.get('is_staff')) + # 'Course', 'Wiki', 'Progress' tabs + self.assertEqual(len(response.data.get('tabs', [])), 3) + + def test_get_authenticated_staff_user(self): + self.client.logout() + staff_user = UserFactory( + username='staff', + email='staff@example.com', + password='bar', + is_staff=True + ) + self.client.login(username=staff_user.username, password='bar') + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.data['is_staff']) + # This differs for a staff user because they also receive the Instructor tab + # 'Course', 'Wiki', 'Progress', and 'Instructor' tabs + self.assertEqual(len(response.data.get('tabs', [])), 4) + + def test_get_unknown_course(self): + url = reverse('course-home-course-metadata', args=['course-v1:unknown+course+2T2020']) + response = self.client.get(url) + self.assertEqual(response.status_code, 404) diff --git a/lms/djangoapps/course_home_api/course_metadata/v1/views.py b/lms/djangoapps/course_home_api/course_metadata/v1/views.py new file mode 100644 index 0000000000000000000000000000000000000000..a9ca215e5a75229e7b5a300277a29a6c3d0b2b39 --- /dev/null +++ b/lms/djangoapps/course_home_api/course_metadata/v1/views.py @@ -0,0 +1,71 @@ +""" +General view for the Course Home that contains metadata every page needs. +""" + + +from rest_framework.generics import RetrieveAPIView +from rest_framework.response import Response + +from opaque_keys.edx.keys import CourseKey + +from student.models import CourseEnrollment +from lms.djangoapps.courseware.access import has_access +from lms.djangoapps.courseware.tabs import get_course_tab_list +from lms.djangoapps.course_api.api import course_detail +from lms.djangoapps.course_home_api.course_metadata.v1.serializers import CourseHomeMetadataSerializer + + +class CourseHomeMetadataView(RetrieveAPIView): + """ + **Use Cases** + + Request Course metadata details for the Course Home MFE that every page needs. + + **Example Requests** + + GET api/course_home/v1/course_metadata/{course_key} + + **Response Values** + + Body consists of the following fields: + + course_id: (str) The Course's id (Course Run key) + is_enrolled: (bool) Indicates if the user is enrolled in the course + is_self_paced: (bool) Indicates if the course is self paced + is_staff: (bool) Indicates if the user is staff + number: (str) The Course's number + org: (str) The Course's organization + tabs: List of Course Tabs to display. They are serialized as: + tab_id: (str) The tab's id + title: (str) The title of the tab to display + url: (str) The url to view the tab + title: (str) The Course's display title + + **Returns** + + * 200 on success with above fields. + * 404 if the course is not available or cannot be seen. + """ + + serializer_class = CourseHomeMetadataSerializer + + def get(self, request, *args, **kwargs): + course_key_string = kwargs.get('course_key_string') + course_key = CourseKey.from_string(course_key_string) + course = course_detail(request, request.user.username, course_key) + user_is_enrolled = CourseEnrollment.is_enrolled(request.user, course_key_string) + + data = { + 'course_id': course.id, + 'is_staff': has_access(request.user, 'staff', course_key).has_access, + 'number': course.display_number_with_default, + 'org': course.display_org_with_default, + 'tabs': get_course_tab_list(request.user, course), + 'title': course.display_name_with_default, + 'is_self_paced': getattr(course, 'self_paced', False), + 'is_enrolled': user_is_enrolled, + } + context = self.get_serializer_context() + context['course'] = course + serializer = self.get_serializer_class()(data, context=context) + return Response(serializer.data) diff --git a/lms/djangoapps/course_home_api/dates/__init__.py b/lms/djangoapps/course_home_api/dates/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/djangoapps/course_home_api/dates/v1/__init__.py b/lms/djangoapps/course_home_api/dates/v1/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/djangoapps/course_home_api/dates/v1/serializers.py b/lms/djangoapps/course_home_api/dates/v1/serializers.py new file mode 100644 index 0000000000000000000000000000000000000000..e246226105e45533ff317d5eef9b077bad93c648 --- /dev/null +++ b/lms/djangoapps/course_home_api/dates/v1/serializers.py @@ -0,0 +1,47 @@ +# pylint: disable=abstract-method +""" +Dates Tab Serializers. Represents the relevant dates for a Course. +""" + + +from rest_framework import serializers + +from lms.djangoapps.courseware.date_summary import VerificationDeadlineDate +from lms.djangoapps.course_home_api.mixins import DatesBannerSerializerMixin + + +class DateSummarySerializer(serializers.Serializer): + """ + Serializer for Date Summary Objects. + """ + date = serializers.DateTimeField() + date_type = serializers.CharField() + description = serializers.CharField() + learner_has_access = serializers.SerializerMethodField() + link = serializers.SerializerMethodField() + link_text = serializers.CharField() + title = serializers.CharField() + + def get_learner_has_access(self, block): + learner_is_full_access = self.context.get('learner_is_full_access', False) + block_is_verified = (getattr(block, 'contains_gated_content', False) or + isinstance(block, VerificationDeadlineDate)) + return (not block_is_verified) or learner_is_full_access + + def get_link(self, block): + if block.link: + request = self.context.get('request') + return request.build_absolute_uri(block.link) + return '' + + +class DatesTabSerializer(DatesBannerSerializerMixin, serializers.Serializer): + """ + Serializer for the Dates Tab + """ + course_date_blocks = DateSummarySerializer(many=True) + missed_deadlines = serializers.BooleanField() + missed_gated_content = serializers.BooleanField() + learner_is_full_access = serializers.BooleanField() + user_timezone = serializers.CharField() + verified_upgrade_link = serializers.URLField() diff --git a/lms/djangoapps/course_home_api/dates/v1/tests/__init__.py b/lms/djangoapps/course_home_api/dates/v1/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/djangoapps/course_home_api/dates/v1/tests/test_views.py b/lms/djangoapps/course_home_api/dates/v1/tests/test_views.py new file mode 100644 index 0000000000000000000000000000000000000000..6de10fbc583ae0f491686857405c4a9ac7ebf268 --- /dev/null +++ b/lms/djangoapps/course_home_api/dates/v1/tests/test_views.py @@ -0,0 +1,68 @@ +""" +Tests for Dates Tab API in the Course Home API +""" + +from datetime import datetime +import ddt + +from django.urls import reverse + +from course_modes.models import CourseMode +from lms.djangoapps.course_home_api.tests.utils import BaseCourseHomeTests +from lms.djangoapps.course_home_api.toggles import COURSE_HOME_MICROFRONTEND, COURSE_HOME_MICROFRONTEND_DATES_TAB +from openedx.features.content_type_gating.models import ContentTypeGatingConfig +from student.models import CourseEnrollment + + +@ddt.ddt +class DatesTabTestViews(BaseCourseHomeTests): + """ + Tests for the Dates Tab API + """ + @classmethod + def setUpClass(cls): + BaseCourseHomeTests.setUpClass() + cls.url = reverse('course-home-dates-tab', args=[cls.course.id]) + ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2017, 1, 1)) + + @COURSE_HOME_MICROFRONTEND.override(active=True) + @COURSE_HOME_MICROFRONTEND_DATES_TAB.override(active=True) + @ddt.data(CourseMode.AUDIT, CourseMode.VERIFIED) + def test_get_authenticated_enrolled_user(self, enrollment_mode): + CourseEnrollment.enroll(self.user, self.course.id, enrollment_mode) + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + + # Pulling out the date blocks to check learner has access. + date_blocks = response.data.get('course_date_blocks') + self.assertEqual(response.data.get('learner_is_full_access'), enrollment_mode == CourseMode.VERIFIED) + self.assertTrue(all(block.get('learner_has_access') for block in date_blocks)) + + @COURSE_HOME_MICROFRONTEND.override(active=True) + @COURSE_HOME_MICROFRONTEND_DATES_TAB.override(active=True) + def test_get_authenticated_user_not_enrolled(self): + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + self.assertFalse(response.data.get('learner_is_full_access')) + + def test_get_unauthenticated_user(self): + self.client.logout() + response = self.client.get(self.url) + self.assertEqual(response.status_code, 403) + + @COURSE_HOME_MICROFRONTEND.override(active=True) + @COURSE_HOME_MICROFRONTEND_DATES_TAB.override(active=True) + def test_get_unknown_course(self): + url = reverse('course-home-dates-tab', args=['course-v1:unknown+course+2T2020']) + response = self.client.get(url) + self.assertEqual(response.status_code, 404) + + @COURSE_HOME_MICROFRONTEND.override(active=True) + @COURSE_HOME_MICROFRONTEND_DATES_TAB.override(active=True) + def test_banner_data_is_returned(self): + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'missed_deadlines') + self.assertContains(response, 'missed_gated_content') + self.assertContains(response, 'content_type_gating_enabled') + self.assertContains(response, 'verified_upgrade_link') diff --git a/lms/djangoapps/course_home_api/dates/v1/views.py b/lms/djangoapps/course_home_api/dates/v1/views.py new file mode 100644 index 0000000000000000000000000000000000000000..ff544e808e07981db6c1dee663e0e3ced4137b02 --- /dev/null +++ b/lms/djangoapps/course_home_api/dates/v1/views.py @@ -0,0 +1,98 @@ +""" +Dates Tab Views +""" + +from rest_framework import status +from rest_framework.generics import RetrieveAPIView +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response + +from edx_django_utils import monitoring as monitoring_utils +from opaque_keys.edx.keys import CourseKey + +from lms.djangoapps.courseware.context_processor import user_timezone_locale_prefs +from lms.djangoapps.courseware.courses import get_course_date_blocks, get_course_with_access +from lms.djangoapps.courseware.date_summary import TodaysDate, verified_upgrade_deadline_link +from lms.djangoapps.course_home_api.dates.v1.serializers import DatesTabSerializer +from lms.djangoapps.course_home_api.toggles import course_home_mfe_dates_tab_is_active +from openedx.features.course_experience.utils import dates_banner_should_display +from openedx.features.content_type_gating.models import ContentTypeGatingConfig + + +class DatesTabView(RetrieveAPIView): + """ + **Use Cases** + + Request details for the Dates Tab + + **Example Requests** + + GET api/course_home/v1/dates/{course_key} + + **Response Values** + + Body consists of the following fields: + + course_date_blocks: List of serialized DateSummary objects. Each serialization has the following fields: + date: (datetime) The date time corresponding for the event + date_type: (str) The type of date (ex. course-start-date, assignment-due-date, etc.) + description: (str) The description for the date event + learner_has_access: (bool) Indicates if the learner has access to the date event + link: (str) An absolute link to content related to the date event + (ex. verified link or link to assignment) + title: (str) The title of the date event + missed_deadlines: (bool) Indicates whether the user missed any graded content deadlines + missed_gated_content: (bool) Indicates whether the user missed gated content + learner_is_full_access: (bool) Indicates if the user is verified in the course + user_timezone: (str) The user's preferred timezone + verified_upgrade_link: (str) The link for upgrading to the Verified track in a course + + **Returns** + + * 200 on success with above fields. + * 403 if the user is not authenticated. + * 404 if the course is not available or cannot be seen. + """ + + permission_classes = (IsAuthenticated,) + serializer_class = DatesTabSerializer + + def get(self, request, *args, **kwargs): + course_key_string = kwargs.get('course_key_string') + course_key = CourseKey.from_string(course_key_string) + + if not course_home_mfe_dates_tab_is_active(course_key): + return Response(status=status.HTTP_404_NOT_FOUND) + + # Enable NR tracing for this view based on course + monitoring_utils.set_custom_metric('course_id', course_key_string) + monitoring_utils.set_custom_metric('user_id', request.user.id) + monitoring_utils.set_custom_metric('is_staff', request.user.is_staff) + + course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) + blocks = get_course_date_blocks(course, request.user, request, include_access=True, include_past_dates=True) + missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, request.user) + + learner_is_full_access = not ContentTypeGatingConfig.enabled_for_enrollment( + user=request.user, + course_key=course_key, + ) + + # User locale settings + user_timezone_locale = user_timezone_locale_prefs(request) + user_timezone = user_timezone_locale['user_timezone'] + + data = { + 'has_ended': course.has_ended(), + 'course_date_blocks': [block for block in blocks if not isinstance(block, TodaysDate)], + 'missed_deadlines': missed_deadlines, + 'missed_gated_content': missed_gated_content, + 'learner_is_full_access': learner_is_full_access, + 'user_timezone': user_timezone, + 'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course), + } + context = self.get_serializer_context() + context['learner_is_full_access'] = learner_is_full_access + serializer = self.get_serializer_class()(data, context=context) + + return Response(serializer.data) diff --git a/lms/djangoapps/course_home_api/mixins.py b/lms/djangoapps/course_home_api/mixins.py new file mode 100644 index 0000000000000000000000000000000000000000..ab3111fd14459a5328e982b98bebb5a34d61899d --- /dev/null +++ b/lms/djangoapps/course_home_api/mixins.py @@ -0,0 +1,45 @@ +# pylint: disable=abstract-method +""" +Course Home Mixins. +""" + + +from rest_framework import serializers + +from opaque_keys.edx.keys import CourseKey + +from lms.djangoapps.courseware.date_summary import verified_upgrade_deadline_link +from openedx.features.content_type_gating.models import ContentTypeGatingConfig +from openedx.features.course_experience.utils import dates_banner_should_display + + +class DatesBannerSerializerMixin(serializers.Serializer): + """ + Serializer Mixin for displaying the dates banner. + Can be added to any serializer who's tab wants to display it. + """ + dates_banner_info = serializers.SerializerMethodField() + + def get_dates_banner_info(self, _): + """ + Serializer mixin for returning date banner info. Gets its input from + the views course_key_string url parameter and the request's user object. + """ + info = { + 'missed_deadlines': False, + 'content_type_gating_enabled': False, + } + course_key_string = self.context['view'].kwargs.get('course_key_string') + if course_key_string: + course_key = CourseKey.from_string(course_key_string) + request = self.context['request'] + missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, request.user) + info['missed_deadlines'] = missed_deadlines + info['missed_gated_content'] = missed_gated_content + info['content_type_gating_enabled'] = ContentTypeGatingConfig.enabled_for_enrollment( + user=request.user, + course_key=course_key, + ) + if info['content_type_gating_enabled']: + info['verified_upgrade_link'] = verified_upgrade_deadline_link(request.user, course_id=course_key) + return info diff --git a/lms/djangoapps/course_home_api/outline/v1/serializers.py b/lms/djangoapps/course_home_api/outline/v1/serializers.py new file mode 100644 index 0000000000000000000000000000000000000000..ec93c235e7c1b95dd40af2c93e56d3d16eda71c3 --- /dev/null +++ b/lms/djangoapps/course_home_api/outline/v1/serializers.py @@ -0,0 +1,63 @@ +""" +Outline Tab Serializers. +""" + +from rest_framework import serializers +from lms.djangoapps.course_home_api.dates.v1.serializers import DateSummarySerializer +from rest_framework.reverse import reverse + + +class CourseToolSerializer(serializers.Serializer): + """ + Serializer for Course Tool Objects + """ + analytics_id = serializers.CharField() + title = serializers.CharField() + url = serializers.SerializerMethodField() + + def get_url(self, tool): + course_key = self.context.get('course_key') + url = tool.url(course_key) + request = self.context.get('request') + return request.build_absolute_uri(url) + + +class CourseBlockSerializer(serializers.Serializer): + """ + Serializer for Course Block Objects + """ + blocks = serializers.SerializerMethodField() + + def get_blocks(self, blocks): + return { + str(block_key): { + 'id': str(block_key), + 'type': block_key.category, + 'display_name': blocks.get_xblock_field(block_key, 'display_name', block_key.category), + 'lms_web_url': reverse( + 'jump_to', + kwargs={'course_id': str(block_key.course_key), 'location': str(block_key)}, + request=self.context['request'], + ), + 'children': [str(child_key) for child_key in blocks.get_children(block_key)], + } + for block_key in blocks + } + + +class DatesWidgetSerializer(serializers.Serializer): + """ + Serializer for Dates Widget data + """ + course_date_blocks = DateSummarySerializer(many=True) + dates_tab_link = serializers.CharField() + user_timezone = serializers.CharField() + + +class OutlineTabSerializer(serializers.Serializer): + """ + Serializer for the Outline Tab + """ + course_tools = CourseToolSerializer(many=True) + course_blocks = CourseBlockSerializer() + dates_widget = DatesWidgetSerializer() diff --git a/lms/djangoapps/course_home_api/outline/v1/tests/__init__.py b/lms/djangoapps/course_home_api/outline/v1/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/djangoapps/course_home_api/outline/v1/tests/test_views.py b/lms/djangoapps/course_home_api/outline/v1/tests/test_views.py new file mode 100644 index 0000000000000000000000000000000000000000..37cd8157f903c1ea5f933b00e40e7a5a8ff157e9 --- /dev/null +++ b/lms/djangoapps/course_home_api/outline/v1/tests/test_views.py @@ -0,0 +1,60 @@ +""" +Tests for Outline Tab API in the Course Home API +""" + +import ddt + +from django.urls import reverse + +from course_modes.models import CourseMode +from lms.djangoapps.course_home_api.tests.utils import BaseCourseHomeTests +from student.models import CourseEnrollment + + +@ddt.ddt +class OutlineTabTestViews(BaseCourseHomeTests): + """ + Tests for the Outline Tab API + """ + + @classmethod + def setUpClass(cls): + BaseCourseHomeTests.setUpClass() + cls.url = reverse('course-home-outline-tab', args=[cls.course.id]) + + @ddt.data(CourseMode.AUDIT, CourseMode.VERIFIED) + def test_get_authenticated_enrolled_user(self, enrollment_mode): + CourseEnrollment.enroll(self.user, self.course.id, enrollment_mode) + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + + course_tools = response.data.get('course_tools') + self.assertTrue(course_tools) + self.assertEquals(course_tools[0]['analytics_id'], 'edx.bookmarks') + + dates_widget = response.data.get('dates_widget') + self.assertTrue(dates_widget) + date_blocks = dates_widget.get('course_date_blocks') + self.assertTrue(all((block.get('title') != "") for block in date_blocks)) + self.assertTrue(all(block.get('date') for block in date_blocks)) + + def test_get_authenticated_user_not_enrolled(self): + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + self.assertFalse(response.data.get('learner_is_verified')) + + course_tools = response.data.get('course_tools') + self.assertEqual(len(course_tools), 0) + + dates_widget = response.data.get('dates_widget') + self.assertTrue(dates_widget) + date_blocks = dates_widget.get('course_date_blocks') + self.assertTrue(all((block.get('title') != "") for block in date_blocks)) + self.assertTrue(all(block.get('date') for block in date_blocks)) + + def test_get_unauthenticated_user(self): + self.client.logout() + response = self.client.get(self.url) + self.assertEqual(response.status_code, 403) + + # TODO: write test_get_unknown_course when more data is pulled into the Outline Tab API diff --git a/lms/djangoapps/course_home_api/outline/v1/views.py b/lms/djangoapps/course_home_api/outline/v1/views.py new file mode 100644 index 0000000000000000000000000000000000000000..a5d5280e88313c2a12f023a6d94ae63a0048f542 --- /dev/null +++ b/lms/djangoapps/course_home_api/outline/v1/views.py @@ -0,0 +1,117 @@ +""" +Outline Tab Views +""" + +from rest_framework.generics import RetrieveAPIView +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response + +from edx_django_utils import monitoring as monitoring_utils +from django.urls import reverse +from opaque_keys.edx.keys import CourseKey, UsageKey + +from lms.djangoapps.course_api.blocks.transformers.blocks_api import BlocksAPITransformer +from lms.djangoapps.course_home_api.outline.v1.serializers import OutlineTabSerializer + +from lms.djangoapps.course_home_api.toggles import course_home_mfe_dates_tab_is_active +from lms.djangoapps.courseware.courses import get_course_date_blocks, get_course_with_access +from lms.djangoapps.courseware.date_summary import TodaysDate +from lms.djangoapps.courseware.context_processor import user_timezone_locale_prefs +from lms.djangoapps.course_home_api.utils import get_microfrontend_url +from openedx.core.djangoapps.content.block_structure.transformers import BlockStructureTransformers +from openedx.features.course_experience.course_tools import CourseToolsPluginManager + +from lms.djangoapps.course_blocks.api import get_course_blocks +import lms.djangoapps.course_blocks.api as course_blocks_api +from xmodule.modulestore.django import modulestore + + +class OutlineTabView(RetrieveAPIView): + """ + **Use Cases** + + Request details for the Outline Tab + + **Example Requests** + + GET api/course_home/v1/outline/{course_key} + + **Response Values** + + Body consists of the following fields: + + course_tools: List of serialized Course Tool objects. Each serialization has the following fields: + analytics_id: (str) The unique id given to the tool. + title: (str) The display title of the tool. + url: (str) The link to access the tool. + course_blocks: + blocks: List of serialized Course Block objects. Each serialization has the following fields: + id: (str) The usage ID of the block. + type: (str) The type of block. Possible values the names of any + XBlock type in the system, including custom blocks. Examples are + course, chapter, sequential, vertical, html, problem, video, and + discussion. + display_name: (str) The display name of the block. + lms_web_url: (str) The URL to the navigational container of the + xBlock on the web LMS. + children: (list) If the block has child blocks, a list of IDs of + the child blocks. + + **Returns** + + * 200 on success with above fields. + * 403 if the user is not authenticated. + * 404 if the course is not available or cannot be seen. + + """ + + permission_classes = (IsAuthenticated,) + serializer_class = OutlineTabSerializer + + def get(self, request, *args, **kwargs): + course_key_string = kwargs.get('course_key_string') + course_key = CourseKey.from_string(course_key_string) + course_usage_key = modulestore().make_course_usage_key(course_key) + + # Enable NR tracing for this view based on course + monitoring_utils.set_custom_metric('course_id', course_key_string) + monitoring_utils.set_custom_metric('user_id', request.user.id) + monitoring_utils.set_custom_metric('is_staff', request.user.is_staff) + + course_tools = CourseToolsPluginManager.get_enabled_course_tools(request, course_key) + + course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) + date_blocks = get_course_date_blocks(course, request.user, request, num_assignments=1) + + # User locale settings + user_timezone_locale = user_timezone_locale_prefs(request) + user_timezone = user_timezone_locale['user_timezone'] + + dates_tab_link = request.build_absolute_uri(reverse('dates', args=[course.id])) + if course_home_mfe_dates_tab_is_active(course.id): + dates_tab_link = get_microfrontend_url(course_key=course.id, view_name='dates') + + transformers = BlockStructureTransformers() + transformers += course_blocks_api.get_course_block_access_transformers(request.user) + transformers += [ + BlocksAPITransformer(None, None, depth=3), + ] + + course_blocks = get_course_blocks(request.user, course_usage_key, transformers, include_completion=True) + + dates_widget = { + 'course_date_blocks': [block for block in date_blocks if not isinstance(block, TodaysDate)], + 'dates_tab_link': dates_tab_link, + 'user_timezone': user_timezone, + } + + data = { + 'course_tools': course_tools, + 'course_blocks': course_blocks, + 'dates_widget': dates_widget, + } + context = self.get_serializer_context() + context['course_key'] = course_key + serializer = self.get_serializer_class()(data, context=context) + + return Response(serializer.data) diff --git a/lms/djangoapps/course_home_api/tests/__init__.py b/lms/djangoapps/course_home_api/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/djangoapps/course_home_api/tests/utils.py b/lms/djangoapps/course_home_api/tests/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..cfa98b3ccb9236f9b06dcab3216a083e848b5cae --- /dev/null +++ b/lms/djangoapps/course_home_api/tests/utils.py @@ -0,0 +1,68 @@ +""" +Base classes or util functions for use in Course Home API tests +""" + + +import unittest + +from datetime import datetime +from django.conf import settings + +from course_modes.models import CourseMode +from course_modes.tests.factories import CourseModeFactory +from lms.djangoapps.verify_student.models import VerificationDeadline +from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory +from student.tests.factories import UserFactory +from xmodule.modulestore.django import modulestore +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase +from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory + + +@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') +class BaseCourseHomeTests(SharedModuleStoreTestCase): + """ + Base class for Course Home API tests. + + Creates a course to + """ + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.store = modulestore() + cls.course = CourseFactory.create( + start=datetime(2020, 1, 1), + end=datetime(2028, 1, 1), + enrollment_start=datetime(2020, 1, 1), + enrollment_end=datetime(2028, 1, 1), + emit_signals=True, + modulestore=cls.store, + ) + chapter = ItemFactory(parent=cls.course, category='chapter') + ItemFactory(parent=chapter, category='sequential') + + CourseModeFactory(course_id=cls.course.id, mode_slug=CourseMode.AUDIT) + CourseModeFactory( + course_id=cls.course.id, + mode_slug=CourseMode.VERIFIED, + expiration_datetime=datetime(2028, 1, 1) + ) + VerificationDeadline.objects.create(course_key=cls.course.id, deadline=datetime(2028, 1, 1)) + + cls.user = UserFactory( + username='student', + email='user@example.com', + password='foo', + is_staff=False + ) + CourseOverviewFactory.create(run='1T2020') + + @classmethod + def tearDownClass(cls): + super().tearDownClass() + cls.store.delete_course(cls.course.id, cls.user.id) + + def setUp(self): + super().setUp() + self.client.login(username=self.user.username, password='foo') diff --git a/lms/djangoapps/course_home_api/toggles.py b/lms/djangoapps/course_home_api/toggles.py new file mode 100644 index 0000000000000000000000000000000000000000..bc486be81f827cbf99515d48241d2f60e7803df3 --- /dev/null +++ b/lms/djangoapps/course_home_api/toggles.py @@ -0,0 +1,19 @@ +""" +Toggles for course home experience. +""" + +from lms.djangoapps.experiments.flags import ExperimentWaffleFlag +from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag, WaffleFlagNamespace + +WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='course_home') + +COURSE_HOME_MICROFRONTEND = ExperimentWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'course_home_mfe') + +COURSE_HOME_MICROFRONTEND_DATES_TAB = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'course_home_mfe_dates_tab') + + +def course_home_mfe_dates_tab_is_active(course_key): + return ( + COURSE_HOME_MICROFRONTEND.is_enabled(course_key) and + COURSE_HOME_MICROFRONTEND_DATES_TAB.is_enabled(course_key) + ) diff --git a/lms/djangoapps/course_home_api/urls.py b/lms/djangoapps/course_home_api/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..f5e3f94e6341f0ccf231fe9c614c06bd0bea823e --- /dev/null +++ b/lms/djangoapps/course_home_api/urls.py @@ -0,0 +1,40 @@ +""" +Contains all the URLs for the Course Home +""" + + +from django.conf import settings +from django.urls import re_path + +from lms.djangoapps.course_home_api.dates.v1.views import DatesTabView +from lms.djangoapps.course_home_api.course_metadata.v1.views import CourseHomeMetadataView +from lms.djangoapps.course_home_api.outline.v1.views import OutlineTabView + +urlpatterns = [] + +# URL for Course metadata content +urlpatterns += [ + re_path( + r'v1/course_metadata/{}'.format(settings.COURSE_KEY_PATTERN), + CourseHomeMetadataView.as_view(), + name='course-home-course-metadata' + ), +] + +# Dates Tab URLs +urlpatterns += [ + re_path( + r'v1/dates/{}'.format(settings.COURSE_KEY_PATTERN), + DatesTabView.as_view(), + name='course-home-dates-tab' + ), +] + +# Outline Tab URLs +urlpatterns += [ + re_path( + r'v1/outline/{}'.format(settings.COURSE_KEY_PATTERN), + OutlineTabView.as_view(), + name='course-home-outline-tab' + ), +] diff --git a/lms/djangoapps/course_home_api/utils.py b/lms/djangoapps/course_home_api/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..ba39ea56ad62a72c1286ebb94b5369b41246bcc2 --- /dev/null +++ b/lms/djangoapps/course_home_api/utils.py @@ -0,0 +1,15 @@ +"""Utility functions for course home""" + +from django.conf import settings + + +def get_microfrontend_url(course_key, view_name=None): + """ + Takes in a course key and view name, returns the appropriate course home mfe route + """ + mfe_link = '{}/course/{}'.format(settings.LEARNING_MICROFRONTEND_URL, course_key) + + if view_name: + mfe_link += '/{}'.format(view_name) + + return mfe_link diff --git a/lms/djangoapps/course_wiki/editors.py b/lms/djangoapps/course_wiki/editors.py index 8dcd4ee82242de01752ef398c49f76fdbb665d1f..c289df47b44569e59a0939068871b0d219fd64c8 100644 --- a/lms/djangoapps/course_wiki/editors.py +++ b/lms/djangoapps/course_wiki/editors.py @@ -57,7 +57,7 @@ class CodeMirror(BaseEditor): def get_widget(self, instance=None): return CodeMirrorWidget() - class AdminMedia(object): # pylint: disable=missing-docstring + class AdminMedia(object): # pylint: disable=missing-class-docstring css = { 'all': ("wiki/markitup/skins/simple/style.css", "wiki/markitup/sets/admin/style.css",) diff --git a/lms/djangoapps/course_wiki/middleware.py b/lms/djangoapps/course_wiki/middleware.py index 5463e6f4f1bd2f73763c5a0cc6ab6117a83188e0..828103a00ffa6149af3f75a67a3598d426917926 100644 --- a/lms/djangoapps/course_wiki/middleware.py +++ b/lms/djangoapps/course_wiki/middleware.py @@ -7,7 +7,7 @@ from django.http import Http404 from django.shortcuts import redirect from django.utils.deprecation import MiddlewareMixin from six import text_type -from six.moves.urllib.parse import urlparse # pylint: disable=import-error +from six.moves.urllib.parse import urlparse from wiki.models import reverse from lms.djangoapps.courseware.access import has_access @@ -40,7 +40,7 @@ class WikiAccessMiddleware(MiddlewareMixin): # Even though we came from the course, we can't see it. So don't worry about it. pass - def process_view(self, request, view_func, view_args, view_kwargs): # pylint: disable=unused-argument + def process_view(self, request, view_func, view_args, view_kwargs): """ This function handles authentication logic for wiki urls and redirects from the "root wiki" to the "course wiki" if the user accesses the wiki from a course url diff --git a/lms/djangoapps/course_wiki/views.py b/lms/djangoapps/course_wiki/views.py index 4c0d005afed401f8c9a9ef9ef203e85f9414d915..b484fdfb4de9970c0a5c6ab662f801a51b8e512a 100644 --- a/lms/djangoapps/course_wiki/views.py +++ b/lms/djangoapps/course_wiki/views.py @@ -22,7 +22,7 @@ from openedx.features.enterprise_support.api import data_sharing_consent_require log = logging.getLogger(__name__) -def root_create(request): # pylint: disable=unused-argument +def root_create(request): """ In the edX wiki, we don't show the root_create view. Instead, we just create the root automatically if it doesn't exist. @@ -32,7 +32,7 @@ def root_create(request): # pylint: disable=unused-argument @data_sharing_consent_required -def course_wiki_redirect(request, course_id, wiki_path=""): # pylint: disable=unused-argument +def course_wiki_redirect(request, course_id, wiki_path=""): """ This redirects to whatever page on the wiki that the course designates as it's home page. A course's wiki must be an article on the root (for diff --git a/lms/djangoapps/courseware/__init__.py b/lms/djangoapps/courseware/__init__.py index 548417e4a1cabc2eb24392455aa9f7487bc15a1e..e2cad604144bd5a07d471f2f618f66385d8d66f9 100644 --- a/lms/djangoapps/courseware/__init__.py +++ b/lms/djangoapps/courseware/__init__.py @@ -1,10 +1,6 @@ -#pylint: disable=missing-docstring - - import warnings if __name__ == 'courseware': - # pylint: disable=unicode-format-string # Show the call stack that imported us wrong. msg = "Importing 'lms.djangoapps.courseware' as 'courseware' is no longer supported" warnings.warn(msg, DeprecationWarning) diff --git a/lms/djangoapps/courseware/access.py b/lms/djangoapps/courseware/access.py index 49c45106399d0a3cd4b2c73f718de3c05766ee7e..de3947e3eae5513ba49020e8e28da0e261f8c6d5 100644 --- a/lms/djangoapps/courseware/access.py +++ b/lms/djangoapps/courseware/access.py @@ -502,6 +502,7 @@ def _has_group_access(descriptor, user, course_key): # If missing_groups is empty, the user is granted access. # If missing_groups is NOT empty, we generate an error based on one of the particular groups they are missing. missing_groups = [] + block_key = descriptor.scope_ids.usage_id for partition, groups in partition_groups: user_group = partition.scheme.get_group_for_user( course_key, @@ -509,17 +510,25 @@ def _has_group_access(descriptor, user, course_key): partition, ) if user_group not in groups: - missing_groups.append((partition, user_group, groups)) + missing_groups.append(( + partition, + user_group, + groups, + partition.access_denied_message(block_key, user, user_group, groups), + partition.access_denied_fragment(descriptor, user, user_group, groups), + )) if missing_groups: - partition, user_group, allowed_groups = missing_groups[0] - block_key = descriptor.scope_ids.usage_id + # Prefer groups with explanatory messages + # False < True, so the default order and `is None` results in groups with messages coming first + ordered_groups = sorted(missing_groups, key=lambda details: (details[3] is None, details[4] is None)) + partition, user_group, allowed_groups, message, fragment = ordered_groups[0] return IncorrectPartitionGroupError( partition=partition, user_group=user_group, allowed_groups=allowed_groups, - user_message=partition.access_denied_message(block_key, user, user_group, allowed_groups), - user_fragment=partition.access_denied_fragment(descriptor, user, user_group, allowed_groups), + user_message=message, + user_fragment=fragment, ) # all checks passed. diff --git a/lms/djangoapps/courseware/access_utils.py b/lms/djangoapps/courseware/access_utils.py index 43b9a2520f5d9352284e1a359fb17905da13ab3d..17534049eab6b35c3e698ea8131aa6cb780c180e 100644 --- a/lms/djangoapps/courseware/access_utils.py +++ b/lms/djangoapps/courseware/access_utils.py @@ -65,7 +65,7 @@ def adjust_start_date(user, days_early_for_beta, start, course_key): return start -def check_start_date(user, days_early_for_beta, start, course_key, display_error_to_user=True): +def check_start_date(user, days_early_for_beta, start, course_key, display_error_to_user=True, now=None): """ Verifies whether the given user is allowed access given the start date and the Beta offset for the given course. @@ -82,10 +82,11 @@ def check_start_date(user, days_early_for_beta, start, course_key, display_error if start_dates_disabled and not masquerading_as_student: return ACCESS_GRANTED else: - now = datetime.now(UTC) if start is None or in_preview_mode() or get_course_masquerade(user, course_key): return ACCESS_GRANTED + if now is None: + now = datetime.now(UTC) effective_start = adjust_start_date(user, days_early_for_beta, start, course_key) if now > effective_start: return ACCESS_GRANTED diff --git a/lms/djangoapps/courseware/course_tools.py b/lms/djangoapps/courseware/course_tools.py index b13116cd6166e8f6552864c7f944189dd04a3088..54c0d81651c95358106646f28ed69faaa3ee1f80 100644 --- a/lms/djangoapps/courseware/course_tools.py +++ b/lms/djangoapps/courseware/course_tools.py @@ -7,12 +7,14 @@ import datetime import pytz from crum import get_current_request +from django.conf import settings from django.utils.translation import ugettext as _ - +from django.urls import reverse from course_modes.models import CourseMode from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link from openedx.features.course_experience.course_tools import CourseTool from student.models import CourseEnrollment +from openedx.core.djangoapps.content.course_overviews.models import CourseOverview class VerifiedUpgradeTool(CourseTool): @@ -73,3 +75,77 @@ class VerifiedUpgradeTool(CourseTool): """ request = get_current_request() return verified_upgrade_deadline_link(request.user, course_id=course_key) + + +class FinancialAssistanceTool(CourseTool): + """ + The financial assistance tool. + """ + @classmethod + def analytics_id(cls): + """ + Returns an id to uniquely identify this tool in analytics events. + """ + return 'edx.tool.financial_assistance' + + @classmethod + def is_enabled(cls, request, course_key): + """ + Show this link for active courses where financial assistance is available, unless upgrade deadline has passed + """ + now = datetime.datetime.now(pytz.UTC) + feature_flags = None + try: + course_overview = CourseOverview.objects.get(id=course_key) + except CourseOverview.DoesNotExist: + course_overview = None + + # hide link if there's no ENABLE_FINANCIAL_ASSISTANCE_FORM setting (ex: Edge) or if it's False + subset_name = 'FEATURES' + feature_flags = getattr(settings, subset_name) + if feature_flags is None or not feature_flags.get('ENABLE_FINANCIAL_ASSISTANCE_FORM'): + return False + + # hide link for archived courses + if course_overview is not None and course_overview.end_date is not None and now > course_overview.end_date: + return False + + # hide link if not logged in or user not enrolled in the course + if not request.user or not CourseEnrollment.is_enrolled(request.user, course_key): + return False + + enrollment = CourseEnrollment.get_enrollment(request.user, course_key) + + # hide if we're no longer in an upsell mode (already upgraded) + if enrollment.mode not in CourseMode.UPSELL_TO_VERIFIED_MODES: + return False + + # hide if there's no course_upgrade_deadline, or one with a value in the past + if enrollment.course_upgrade_deadline: + if now > enrollment.course_upgrade_deadline: + return False + else: + return False + + return bool(course_overview.eligible_for_financial_aid) + + @classmethod + def title(cls, course_key=None): + """ + Returns the title of this tool. + """ + return _('Financial Assistance') + + @classmethod + def icon_classes(cls, course_key=None): + """ + Returns the icon classes needed to represent this tool. + """ + return 'fa fa-info' + + @classmethod + def url(cls, course_key): + """ + Returns the URL for this tool for the specified course key. + """ + return reverse('financial_assistance') diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index f670eb65766462b7b741252910c22a420eb1e10c..72b69b456f9e49dafba6f6c2e05e8b1f0bfdaa1e 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -17,12 +17,13 @@ from django.http import Http404, QueryDict from django.urls import reverse from django.utils.translation import ugettext as _ from edx_django_utils.monitoring import function_trace -from edx_when.api import get_dates_for_course from fs.errors import ResourceNotFound from opaque_keys.edx.keys import UsageKey from path import Path as path from six import text_type +from openedx.core.lib.cache_utils import request_cached + import branding from course_modes.models import CourseMode from lms.djangoapps.courseware.access import has_access @@ -46,34 +47,34 @@ from lms.djangoapps.courseware.masquerade import check_content_start_date_for_ma from lms.djangoapps.courseware.model_data import FieldDataCache from lms.djangoapps.courseware.module_render import get_module from edxmako.shortcuts import render_to_string -from lms.djangoapps.certificates import api as certs_api from lms.djangoapps.courseware.access_utils import ( check_authentication, check_enrollment, ) from lms.djangoapps.courseware.courseware_access_exception import CoursewareAccessException from lms.djangoapps.courseware.exceptions import CourseAccessRedirect +from lms.djangoapps.course_blocks.api import get_course_blocks from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.enrollments.api import get_course_enrollment_details from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.lib.api.view_utils import LazySequence from openedx.features.course_duration_limits.access import AuditExpiredError -from openedx.features.course_experience import COURSE_ENABLE_UNENROLLED_ACCESS_FLAG, RELATIVE_DATES_FLAG +from openedx.features.course_experience import RELATIVE_DATES_FLAG from static_replace import replace_static_urls -from student.models import CourseEnrollment from survey.utils import SurveyRequiredAccessError, check_survey_required_and_unanswered from util.date_utils import strftime_localized from xmodule.modulestore.django import modulestore from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.x_module import STUDENT_VIEW -import lms.djangoapps.course_blocks.api as course_blocks_api -from openedx.features.content_type_gating.helpers import CONTENT_GATING_PARTITION_ID log = logging.getLogger(__name__) # Used by get_course_assignments below. You shouldn't need to use this type directly. -_Assignment = namedtuple('Assignment', ['block_key', 'title', 'url', 'date', 'requires_full_access']) +_Assignment = namedtuple( + 'Assignment', ['block_key', 'title', 'url', 'date', 'contains_gated_content', 'complete', 'past_due', + 'assignment_type'] +) def get_course(course_id, depth=0): @@ -460,25 +461,28 @@ def get_course_date_blocks(course, user, request=None, include_access=False, Return the list of blocks to display on the course info page, sorted by date. """ - block_classes = [ + blocks = [] + if RELATIVE_DATES_FLAG.is_enabled(course.id): + blocks.extend(get_course_assignment_date_blocks( + course, user, request, num_return=num_assignments, + include_access=include_access, include_past_dates=include_past_dates, + )) + + # Adding these in after the assignment blocks so in the case multiple blocks have the same date, + # these blocks will be sorted to come after the assignments. See https://openedx.atlassian.net/browse/AA-158 + default_block_classes = [ + CertificateAvailableDate, CourseEndDate, + CourseExpiredDate, CourseStartDate, TodaysDate, VerificationDeadlineDate, VerifiedUpgradeDeadlineDate, ] - if not course.self_paced and certs_api.get_active_web_certificate(course): - block_classes.insert(0, CertificateAvailableDate) - - blocks = [cls(course, user) for cls in block_classes] - if RELATIVE_DATES_FLAG.is_enabled(course.id): - blocks.append(CourseExpiredDate(course, user)) - blocks.extend(get_course_assignment_date_blocks( - course, user, request, num_return=num_assignments, - include_access=include_access, include_past_dates=include_past_dates, - )) + blocks.extend([cls(course, user) for cls in default_block_classes]) - return sorted((b for b in blocks if b.date and (b.is_enabled or include_past_dates)), key=date_block_key_fn) + blocks = filter(lambda b: b.is_allowed and b.date and (include_past_dates or b.is_enabled), blocks) + return sorted(blocks, key=date_block_key_fn) def date_block_key_fn(block): @@ -500,7 +504,11 @@ def get_course_assignment_date_blocks(course, user, request, num_return=None, for assignment in get_course_assignments(course.id, user, request, include_access=include_access): date_block = CourseAssignmentDate(course, user) date_block.date = assignment.date - date_block.requires_full_access = assignment.requires_full_access + date_block.contains_gated_content = assignment.contains_gated_content + date_block.complete = assignment.complete + date_block.assignment_type = assignment.assignment_type + date_block.past_due = assignment.past_due + date_block.link = assignment.url date_block.set_title(assignment.title, link=assignment.url) date_blocks.append(date_block) date_blocks = sorted((b for b in date_blocks if b.is_enabled or include_past_dates), key=date_block_key_fn) @@ -509,56 +517,49 @@ def get_course_assignment_date_blocks(course, user, request, num_return=None, return date_blocks +@request_cached() def get_course_assignments(course_key, user, request, include_access=False): """ Returns a list of assignment (at the subsection/sequential level) due dates for the given course. - Each returned object is a namedtuple with fields: block_key, title, url, date, requires_full_access + Each returned object is a namedtuple with fields: title, url, date, contains_gated_content, complete, past_due, + assignment_type """ store = modulestore() - all_course_dates = get_dates_for_course(course_key, user) - block_data = course_blocks_api.get_course_blocks(user, store.make_course_usage_key(course_key)) - assignments = [] - for (block_key, date_type), date in all_course_dates.items(): - if date_type != 'due' or block_key.block_type != 'sequential': - continue - - if block_key not in block_data: - continue - - block = block_data[block_key] - if not block.graded: - continue - - requires_full_access = include_access and _requires_full_access(block_data, block, user) - title = block.display_name or _('Assignment') + course_usage_key = store.make_course_usage_key(course_key) + block_data = get_course_blocks(user, course_usage_key, allow_start_dates_in_future=True, include_completion=True) - url = None - assignment_released = not block.start or block.start < datetime.now(pytz.UTC) - if assignment_released: - url = reverse('jump_to', args=[course_key, block_key]) - url = request and request.build_absolute_uri(url) - - assignments.append(_Assignment(block_key, title, url, date, requires_full_access)) + now = datetime.now(pytz.UTC) + assignments = [] + for section_key in block_data.get_children(course_usage_key): + for subsection_key in block_data.get_children(section_key): + due = block_data.get_xblock_field(subsection_key, 'due') + graded = block_data.get_xblock_field(subsection_key, 'graded', False) + if not due or not graded: + continue + + contains_gated_content = include_access and block_data.get_xblock_field( + subsection_key, 'contains_gated_content', False) + title = block_data.get_xblock_field(subsection_key, 'display_name', _('Assignment')) + + assignment_type = block_data.get_xblock_field(subsection_key, 'format', None) + + url = '' + start = block_data.get_xblock_field(subsection_key, 'start') + assignment_released = not start or start < now + if assignment_released: + url = reverse('jump_to', args=[course_key, subsection_key]) + url = request and request.build_absolute_uri(url) + + complete = block_data.get_xblock_field(subsection_key, 'complete', False) + past_due = not complete and due < now + assignments.append(_Assignment( + subsection_key, title, url, due, contains_gated_content, complete, past_due, assignment_type + )) return assignments -def _requires_full_access(block_data, block, user): - """ - Returns a boolean if any child of the block_key specified has a group_access array consisting of just full_access - """ - for child_block_key in block_data.get_children(block.location): - group_access = block_data.get_xblock_field(child_block_key, 'group_access') - # If group_access is set on the block, and the content gating is - # only full access, set the value on the CourseAssignmentDate object - if(group_access and group_access.get(CONTENT_GATING_PARTITION_ID) == [ - settings.CONTENT_TYPE_GATE_GROUP_IDS['full_access'] - ]): - return True - return False - - # TODO: Fix this such that these are pulled in as extra course-specific tabs. # arjun will address this by the end of October if no one does so prior to # then. diff --git a/lms/djangoapps/courseware/date_summary.py b/lms/djangoapps/courseware/date_summary.py index 4877e13e74b98510361500746cc3795e966fc9dc..172d153023b13fd2d3ddada02692d4b80b40117e 100644 --- a/lms/djangoapps/courseware/date_summary.py +++ b/lms/djangoapps/courseware/date_summary.py @@ -20,7 +20,8 @@ from lazy import lazy from pytz import utc from course_modes.models import CourseMode, get_cosmetic_verified_display_price -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, verified_upgrade_link_is_valid +from lms.djangoapps.certificates.api import get_active_web_certificate +from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, can_show_verified_upgrade from lms.djangoapps.verify_student.models import VerificationDeadline from lms.djangoapps.verify_student.services import IDVerificationService from openedx.core.djangoapps.catalog.utils import get_course_run_details @@ -57,6 +58,10 @@ class DateSummary(object): """ return '' + @property + def date_type(self): + return 'event' + @property def title(self): """The title of this summary.""" @@ -136,6 +141,19 @@ class DateSummary(object): absolute='{date}', ) + @lazy + def is_allowed(self): + """ + Whether or not this summary block is applicable or active for its course. + + For example, a DateSummary might only make sense for a self-paced course, and + you could restrict it here. + + You should not make time-sensitive checks here. That sort of thing belongs in + is_enabled. + """ + return True + @property def is_enabled(self): """ @@ -144,9 +162,10 @@ class DateSummary(object): By default, the summary is only shown if its date is in the future. """ - if self.date is not None: - return self.current_time.date() <= self.date.date() - return False + return ( + self.date is not None and + self.current_time.date() <= self.date.date() + ) def deadline_has_passed(self): """ @@ -226,6 +245,10 @@ class TodaysDate(DateSummary): def date(self): return self.current_time + @property + def date_type(self): + return 'todays-date' + @property def title(self): return 'current_datetime' @@ -236,11 +259,25 @@ class CourseStartDate(DateSummary): Displays the start date of the course. """ css_class = 'start-date' - title = ugettext_lazy('Course Starts') @property def date(self): - return self.course.start + if not self.course.self_paced: + return self.course.start + else: + enrollment = CourseEnrollment.get_enrollment(self.user, self.course_id) + return max(enrollment.created, self.course.start) if enrollment else self.course.start + + @property + def date_type(self): + return 'course-start-date' + + @property + def title(self): + enrollment = CourseEnrollment.get_enrollment(self.user, self.course_id) + if enrollment and self.course.end and enrollment.created > self.course.end: + return ugettext_lazy('Enrollment Date') + return ugettext_lazy('Course Starts') def register_alerts(self, request, course): """ @@ -278,10 +315,7 @@ class CourseEndDate(DateSummary): """ css_class = 'end-date' title = ugettext_lazy('Course End') - - @property - def is_enabled(self): - return self.date is not None + is_enabled = True @property def description(self): @@ -299,12 +333,16 @@ class CourseEndDate(DateSummary): weeks_to_complete = get_course_run_details(self.course.id, ['weeks_to_complete']).get('weeks_to_complete') if weeks_to_complete: course_duration = datetime.timedelta(weeks=weeks_to_complete) - if self.course.end < (self.current_time + course_duration): + if self.course.end and self.course.end < (self.current_time + course_duration): return self.course.end return None return self.course.end + @property + def date_type(self): + return 'course-end-date' + def register_alerts(self, request, course): """ Registers an alert if the end date is approaching. @@ -344,9 +382,12 @@ class CourseAssignmentDate(DateSummary): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.assignment_date = None + self.assignment_link = '' self.assignment_title = None self.assignment_title_html = None - self.requires_full_access = None + self.contains_gated_content = False + self.complete = None + self.past_due = None @property def date(self): @@ -356,6 +397,18 @@ class CourseAssignmentDate(DateSummary): def date(self, date): self.assignment_date = date + @property + def date_type(self): + return 'assignment-due-date' + + @property + def link(self): + return self.assignment_link + + @link.setter + def link(self, link): + self.assignment_link = link + @property def title(self): return self.assignment_title @@ -385,6 +438,10 @@ class CourseExpiredDate(DateSummary): return return get_user_course_expiration_date(self.user, self.course) + @property + def date_type(self): + return 'course-expired-date' + @property def description(self): return _('You lose all access to this course, including your progress.') @@ -393,6 +450,10 @@ class CourseExpiredDate(DateSummary): def title(self): return _('Audit Access Expires') + @lazy + def is_allowed(self): + return RELATIVE_DATES_FLAG.is_enabled(self.course.id) + class CertificateAvailableDate(DateSummary): """ @@ -401,21 +462,12 @@ class CertificateAvailableDate(DateSummary): css_class = 'certificate-available-date' title = ugettext_lazy('Certificate Available') - @property - def active_certificates(self): - return [ - certificate for certificate in self.course.certificates.get('certificates', []) - if certificate.get('is_active', False) - ] - - @property - def is_enabled(self): + @lazy + def is_allowed(self): return ( can_show_certificate_available_date_field(self.course) and self.has_certificate_modes and - self.date is not None and - self.current_time <= self.date and - len(self.active_certificates) > 0 + get_active_web_certificate(self.course) ) @property @@ -426,6 +478,10 @@ class CertificateAvailableDate(DateSummary): def date(self): return self.course.certificate_available_date + @property + def date_type(self): + return 'certificate-available-date' + @property def has_certificate_modes(self): return any([ @@ -476,19 +532,9 @@ class VerifiedUpgradeDeadlineDate(DateSummary): def enrollment(self): return CourseEnrollment.get_enrollment(self.user, self.course_id) - @property - def is_enabled(self): - """ - Whether or not this summary block should be shown. - - By default, the summary is only shown if it has date and the date is in the - future and the user's enrollment is in upsell modes - """ - is_enabled = super(VerifiedUpgradeDeadlineDate, self).is_enabled - if not is_enabled: - return False - - return verified_upgrade_link_is_valid(self.enrollment) + @lazy + def is_allowed(self): + return can_show_verified_upgrade(self.user, self.enrollment, self.course) @lazy def date(self): @@ -497,6 +543,10 @@ class VerifiedUpgradeDeadlineDate(DateSummary): else: return None + @property + def date_type(self): + return 'verified-upgrade-deadline' + @property def title(self): dynamic_deadline = self._dynamic_deadline() @@ -580,6 +630,7 @@ class VerificationDeadlineDate(DateSummary): Displays the date by which the user must complete the verification process. """ + is_enabled = True @property def css_class(self): @@ -633,14 +684,18 @@ class VerificationDeadlineDate(DateSummary): def date(self): return VerificationDeadline.deadline_for_course(self.course_id) + @property + def date_type(self): + return 'verification-deadline-date' + @lazy - def is_enabled(self): - if self.date is None: - return False - (mode, is_active) = CourseEnrollment.enrollment_mode_for_user(self.user, self.course_id) - if is_active and mode == 'verified': - return self.verification_status in ('expired', 'none', 'must_reverify') - return False + def is_allowed(self): + mode, is_active = CourseEnrollment.enrollment_mode_for_user(self.user, self.course_id) + return ( + is_active and + mode == 'verified' and + self.verification_status in ('expired', 'none', 'must_reverify') + ) @lazy def verification_status(self): diff --git a/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py b/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py index 1de9a61a475ba9e87291f1df2ffe156859723a6d..cc341f3b24316f5b59e268003f281f9c477e8be6 100644 --- a/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py +++ b/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py @@ -188,7 +188,7 @@ class CommandsTestBase(SharedModuleStoreTestCase): dumped_id = dump[text_type(discussion_key)]['metadata']['discussion_id'] self.assertEqual(dumped_id, "custom") - def check_export_file(self, tar_file): # pylint: disable=missing-docstring + def check_export_file(self, tar_file): # pylint: disable=missing-function-docstring names = tar_file.getnames() # Check if some of the files are present. diff --git a/lms/djangoapps/courseware/masquerade.py b/lms/djangoapps/courseware/masquerade.py index 515b7e2ebe0132a078548dee066c44d8172affb0..c679e937c4cdcfdd4a9b19cd712bb9b929cd7987 100644 --- a/lms/djangoapps/courseware/masquerade.py +++ b/lms/djangoapps/courseware/masquerade.py @@ -12,19 +12,27 @@ from django.conf import settings from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.db.models import Q +from django.utils.decorators import method_decorator from django.utils.translation import ugettext as _ -from django.views.decorators.http import require_POST +from django.views import View from opaque_keys.edx.keys import CourseKey from pytz import utc from web_fragments.fragment import Fragment from xblock.runtime import KeyValueStore +from course_modes.models import CourseMode from openedx.core.djangoapps.util.user_messages import PageLevelMessages from openedx.core.djangolib.markup import HTML +from openedx.features.content_type_gating.helpers import CONTENT_GATING_PARTITION_ID +from openedx.features.content_type_gating.helpers import FULL_ACCESS +from openedx.features.content_type_gating.helpers import LIMITED_ACCESS from student.models import CourseEnrollment from student.role_helpers import has_staff_roles from util.json_request import JsonResponse, expect_json +from xmodule.modulestore.django import modulestore +from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID from xmodule.partitions.partitions import NoSuchUserPartitionGroupError +from xmodule.partitions.partitions_service import get_all_partitions_for_course log = logging.getLogger(__name__) @@ -62,44 +70,109 @@ class CourseMasquerade(object): self.__init__(**state) -@require_POST -@login_required -@expect_json -def handle_ajax(request, course_key_string): - """ - Handle AJAX posts to update the current user's masquerade for the specified course. - The masquerade settings are stored in the Django session as a dict from course keys - to CourseMasquerade objects. - """ - course_key = CourseKey.from_string(course_key_string) - masquerade_settings = request.session.get(MASQUERADE_SETTINGS_KEY, {}) - request_json = request.json - role = request_json.get('role', 'student') - group_id = request_json.get('group_id', None) - user_partition_id = request_json.get('user_partition_id', None) if group_id is not None else None - user_name = request_json.get('user_name', None) - found_user_name = None - if user_name: - users_in_course = CourseEnrollment.objects.users_enrolled_in(course_key) - try: - found_user_name = users_in_course.get(Q(email=user_name) | Q(username=user_name)).username - except User.DoesNotExist: +@method_decorator(login_required, name='dispatch') +class MasqueradeView(View): + """ + Create an HTTP endpoint to manage masquerade settings + """ + + def get(self, request, course_key_string): + """ + Retrieve data on the active and available masquerade options + """ + course_key = CourseKey.from_string(course_key_string) + is_staff = has_staff_roles(request.user, course_key) + if not is_staff: return JsonResponse({ 'success': False, - 'error': _( - u'There is no user with the username or email address u"{user_identifier}" ' - 'enrolled in this course.' - ).format(user_identifier=user_name) }) - masquerade_settings[course_key] = CourseMasquerade( - course_key, - role=role, - user_partition_id=user_partition_id, - group_id=group_id, - user_name=found_user_name, - ) - request.session[MASQUERADE_SETTINGS_KEY] = masquerade_settings - return JsonResponse({'success': True}) + masquerade_settings = request.session.get(MASQUERADE_SETTINGS_KEY, {}) + course = masquerade_settings.get(course_key, None) + course = course or CourseMasquerade( + course_key, + role='staff', + user_partition_id=None, + group_id=None, + user_name=None, + ) + descriptor = modulestore().get_course(course_key) + partitions = get_all_partitions_for_course(descriptor, active_only=True) + data = { + 'success': True, + 'active': { + 'course_key': course_key_string, + 'group_id': course.group_id, + 'role': course.role, + 'user_name': course.user_name or ' ', + 'user_partition_id': course.user_partition_id, + }, + 'available': [ + { + 'name': 'Staff', + 'role': 'staff', + }, + { + 'name': 'Learner', + 'role': 'student', + }, + ], + } + for partition in partitions: + if partition.active: + data['available'].extend([ + { + 'group_id': group.id, + 'name': group.name, + 'role': 'student', + 'user_partition_id': partition.id, + } + for group in partition.groups + ]) + return JsonResponse(data) + + @method_decorator(expect_json) + def post(self, request, course_key_string): + """ + Handle AJAX posts to update the current user's masquerade for the specified course. + The masquerade settings are stored in the Django session as a dict from course keys + to CourseMasquerade objects. + """ + course_key = CourseKey.from_string(course_key_string) + is_staff = has_staff_roles(request.user, course_key) + if not is_staff: + return JsonResponse({ + 'success': False, + }) + masquerade_settings = request.session.get(MASQUERADE_SETTINGS_KEY, {}) + request_json = request.json + role = request_json.get('role', 'student') + group_id = request_json.get('group_id', None) + user_partition_id = request_json.get('user_partition_id', None) if group_id is not None else None + user_name = request_json.get('user_name', None) + found_user_name = None + if user_name: + users_in_course = CourseEnrollment.objects.users_enrolled_in(course_key) + try: + found_user_name = users_in_course.get(Q(email=user_name) | Q(username=user_name)).username + except User.DoesNotExist: + return JsonResponse({ + 'success': False, + 'error': _( + u'There is no user with the username or email address u"{user_identifier}" ' + 'enrolled in this course.' + ).format( + user_identifier=user_name, + ), + }) + masquerade_settings[course_key] = CourseMasquerade( + course_key, + role=role, + user_partition_id=user_partition_id, + group_id=group_id, + user_name=found_user_name, + ) + request.session[MASQUERADE_SETTINGS_KEY] = masquerade_settings + return JsonResponse({'success': True}) def setup_masquerade(request, course_key, staff_access=False, reset_masquerade_data=False): @@ -161,6 +234,83 @@ def get_masquerade_role(user, course_key): return course_masquerade.role if course_masquerade else None +def _get_masquerade_group_id(target_user_partition_id, user, course_key, course_masquerade=None): + """ + Return the masqueraded track's group ID + if it's in the specified user partition, + otherwise, return None + """ + course_masquerade = course_masquerade or get_course_masquerade(user, course_key) + if course_masquerade is not None: + user_partition_id = course_masquerade.user_partition_id + if user_partition_id == target_user_partition_id: + group_id = course_masquerade.group_id + if group_id: + return group_id + return None + + +def is_masquerading(user, course_key, course_masquerade=None): + """ + Return if the user is masquerading at all + """ + course_masquerade = course_masquerade or get_course_masquerade(user, course_key) + _is_masquerading = course_masquerade is not None + return _is_masquerading + + +def is_masquerading_as_non_audit_enrollment(user, course_key, course_masquerade=None): + """ + Return if the user is a staff member masquerading as a user + in _any_ enrollment track _except_ audit + """ + group_id = _get_masquerade_group_id(ENROLLMENT_TRACK_PARTITION_ID, user, course_key, course_masquerade) + audit_mode_id = settings.COURSE_ENROLLMENT_MODES.get(CourseMode.AUDIT, {}).get('id') + if group_id is not None: + if group_id != audit_mode_id: + return True + return False + + +def is_masquerading_as_audit_enrollment(user, course_key, course_masquerade=None): + """ + Return if the user is a staff member masquerading as a user + in the audit enrollment track + """ + group_id = _get_masquerade_group_id(ENROLLMENT_TRACK_PARTITION_ID, user, course_key, course_masquerade) + audit_mode_id = settings.COURSE_ENROLLMENT_MODES.get(CourseMode.AUDIT, {}).get('id') + _is_masquerading = group_id == audit_mode_id + return _is_masquerading + + +def is_masquerading_as_full_access(user, course_key, course_masquerade=None): + """ + Return if the user is a staff member masquerading as a user + in the Full-Access track + """ + group_id = _get_masquerade_group_id(CONTENT_GATING_PARTITION_ID, user, course_key, course_masquerade) + _is_masquerading = group_id == FULL_ACCESS.id + return _is_masquerading + + +def is_masquerading_as_limited_access(user, course_key, course_masquerade=None): + """ + Return if the user is a staff member masquerading as a user + in the Limited-Access track + """ + group_id = _get_masquerade_group_id(CONTENT_GATING_PARTITION_ID, user, course_key, course_masquerade) + _is_masquerading = group_id == LIMITED_ACCESS.id + return _is_masquerading + + +def is_masquerading_as_staff(user, course_key): + """ + Return if the user is a staff member masquerading as user + that is itself a staff user + """ + return get_masquerade_role(user, course_key) == 'staff' + + def is_masquerading_as_student(user, course_key): """ Returns true if the user is a staff member masquerading as a student. @@ -202,8 +352,8 @@ def check_content_start_date_for_masquerade_user(course_key, user, request, cour most_future_date = course_start if chapter_start and section_start: most_future_date = max(course_start, chapter_start, section_start) - is_masquerading = get_course_masquerade(user, course_key) - if now < most_future_date and is_masquerading: + _is_masquerading = get_course_masquerade(user, course_key) + if now < most_future_date and _is_masquerading: group_masquerade = is_masquerading_as_student(user, course_key) specific_student_masquerade = is_masquerading_as_specific_student(user, course_key) is_staff = has_staff_roles(user, course_key) diff --git a/lms/djangoapps/courseware/migrations/0011_csm_id_bigint.py b/lms/djangoapps/courseware/migrations/0011_csm_id_bigint.py index 03d7b7b6ea69673b9f7f8462d4ba04650923445a..5c61d76706e152dc9d869eaf0b5e4df56c54e8ac 100644 --- a/lms/djangoapps/courseware/migrations/0011_csm_id_bigint.py +++ b/lms/djangoapps/courseware/migrations/0011_csm_id_bigint.py @@ -15,6 +15,9 @@ class CsmBigInt(AlterField): level and the coursewarehistoryextended_studentmodulehistoryextended table is in a different database ''' def database_forwards(self, app_label, schema_editor, from_state, to_state): + if hasattr(schema_editor.connection, 'is_in_memory_db') and schema_editor.connection.is_in_memory_db(): + # sqlite3 doesn't support 'MODIFY', so skipping during tests + return to_model = to_state.apps.get_model(app_label, self.model_name) if schema_editor.connection.alias == 'student_module_history': if settings.FEATURES["ENABLE_CSMH_EXTENDED"]: diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 154d267ad16a5dcd5c8f8e327118be173fc00d46..5695750169bf49506057b02b5cde6ddf699b4701 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -1090,7 +1090,7 @@ def get_module_by_usage_id(request, course_id, usage_id, disable_staff_debug_inf descriptor = modulestore().get_item(usage_key) descriptor_orig_usage_key, descriptor_orig_version = modulestore().get_block_original_usage(usage_key) except ItemNotFoundError: - log.warn( + log.warning( u"Invalid location for course id %s: %s", usage_key.course_key, usage_key @@ -1236,8 +1236,8 @@ def xblock_view(request, course_id, usage_id, view_name): the second is the resource description """ if not settings.FEATURES.get('ENABLE_XBLOCK_VIEW_ENDPOINT', False): - log.warn("Attempt to use deactivated XBlock view endpoint -" - " see FEATURES['ENABLE_XBLOCK_VIEW_ENDPOINT']") + log.warning("Attempt to use deactivated XBlock view endpoint -" + " see FEATURES['ENABLE_XBLOCK_VIEW_ENDPOINT']") raise Http404 try: diff --git a/lms/djangoapps/courseware/rules.py b/lms/djangoapps/courseware/rules.py index 72a4ea903f817df633fe5f3c0bb676134261cabb..58866b397afea5c7ea49be6cacf7365506f3e22d 100644 --- a/lms/djangoapps/courseware/rules.py +++ b/lms/djangoapps/courseware/rules.py @@ -19,10 +19,12 @@ from xblock.core import XBlock from course_modes.models import CourseMode from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from student.models import CourseAccessRole, CourseEnrollment +from student.roles import CourseRole, OrgRole from xmodule.course_module import CourseDescriptor from xmodule.error_module import ErrorDescriptor from xmodule.x_module import XModule + from .access import has_access LOG = logging.getLogger(__name__) @@ -151,3 +153,27 @@ class HasStaffAccessToContent(Rule): if not is_global_staff: query &= Q(id__in=course_staff_or_instructor_courses) | Q(org__in=org_staff_or_instructor_courses) return query + + +class HasRolesRule(Rule): + def __init__(self, *roles): + self.roles = roles + + def check(self, user, instance=None): + if not user.is_authenticated: + return False + if isinstance(instance, CourseKey): + course_key = instance + elif isinstance(instance, (CourseDescriptor, CourseOverview)): + course_key = instance.id + elif isinstance(instance, (ErrorDescriptor, XModule, XBlock)): + course_key = instance.scope_ids.usage_id.course_key + else: + course_key = CourseKey.from_string(str(instance)) + + for role in self.roles: + if CourseRole(role, course_key).has_user(user): + return True + if OrgRole(role, course_key.org).has_user(user): + return True + return False diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 99b184afe96eaebc15974567920c0fb16e4c2c3e..80bec53a0add1f7552b4738414a6b064d418b89c 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -11,6 +11,8 @@ from django.utils.translation import ugettext_noop from lms.djangoapps.courseware.access import has_access from lms.djangoapps.courseware.entrance_exams import user_can_skip_entrance_exam +from lms.djangoapps.course_home_api.toggles import course_home_mfe_dates_tab_is_active +from lms.djangoapps.course_home_api.utils import get_microfrontend_url from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.lib.course_tabs import CourseTabPluginManager from openedx.features.course_experience import RELATIVE_DATES_FLAG, UNIFIED_COURSE_TAB_FLAG, default_course_url_name @@ -318,6 +320,16 @@ class DatesTab(CourseTab): view_name = "dates" is_dynamic = True + def __init__(self, tab_dict): + def link_func(course, reverse_func): + if course_home_mfe_dates_tab_is_active(course.id): + return get_microfrontend_url(course_key=course.id, view_name=self.view_name) + else: + return reverse_func(self.view_name, args=[six.text_type(course.id)]) + + tab_dict['link_func'] = link_func + super(DatesTab, self).__init__(tab_dict) + @classmethod def is_enabled(cls, course, user=None): """Returns true if this tab is enabled.""" @@ -348,6 +360,12 @@ def get_course_tab_list(user, course): if tab.type == 'static_tab' and tab.course_staff_only and \ not bool(user and has_access(user, 'staff', course, course.id)): continue + # We had initially created a CourseTab.load() for dates that ended up + # persisting the dates tab tomodulestore on Course Run creation, but + # ignoring any static dates tab here we can fix forward without + # allowing the bug to continue to surface + if tab.type == 'dates': + continue course_tab_list.append(tab) # Add in any dynamic tabs, i.e. those that are not persisted diff --git a/lms/djangoapps/courseware/tests/factories.py b/lms/djangoapps/courseware/tests/factories.py index cbf28521ecdc4c7bc1fea3882d104ce14967e135..4e0cafada1653addca12e5a38bbe441e2eff3d86 100644 --- a/lms/djangoapps/courseware/tests/factories.py +++ b/lms/djangoapps/courseware/tests/factories.py @@ -1,5 +1,4 @@ # Factories are self documenting -# pylint: disable=missing-docstring import json diff --git a/lms/djangoapps/courseware/tests/helpers.py b/lms/djangoapps/courseware/tests/helpers.py index 4a7d86e86587eaf54226e543fc5a56d90322caa3..be4da4753b89685815a31dbb79b2ca5c47c02bb3 100644 --- a/lms/djangoapps/courseware/tests/helpers.py +++ b/lms/djangoapps/courseware/tests/helpers.py @@ -22,7 +22,8 @@ from xblock.field_data import DictFieldData from edxmako.shortcuts import render_to_string from lms.djangoapps.courseware.access import has_access from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link -from lms.djangoapps.courseware.masquerade import handle_ajax, setup_masquerade +from lms.djangoapps.courseware.masquerade import MasqueradeView +from lms.djangoapps.courseware.masquerade import setup_masquerade from lms.djangoapps.lms_xblock.field_data import LmsFieldData from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.lib.url_utils import quote_slashes @@ -348,7 +349,7 @@ def masquerade_as_group_member(user, course, partition_id, group_id): user, data={"role": "student", "user_partition_id": partition_id, "group_id": group_id} ) - response = handle_ajax(request, six.text_type(course.id)) + response = MasqueradeView.as_view()(request, six.text_type(course.id)) setup_masquerade(request, course.id, True) return response.status_code @@ -413,7 +414,7 @@ def get_context_dict_from_string(data): Retrieve dictionary from string. """ # Replace tuple and un-necessary info from inside string and get the dictionary. - cleaned_data = ast.literal_eval(data.split('((\'video.html\',')[1].replace("),\n {})", '').strip()) # pylint: disable=unicode-format-string + cleaned_data = ast.literal_eval(data.split('((\'video.html\',')[1].replace("),\n {})", '').strip()) cleaned_data['metadata'] = OrderedDict( sorted(json.loads(cleaned_data['metadata']).items(), key=lambda t: t[0]) ) diff --git a/lms/djangoapps/courseware/tests/test_about.py b/lms/djangoapps/courseware/tests/test_about.py index 735a5da47e02b42e617441168700d6542e2425c8..660e1dd81ce52a0c53cac387b24717f52864fae3 100644 --- a/lms/djangoapps/courseware/tests/test_about.py +++ b/lms/djangoapps/courseware/tests/test_about.py @@ -24,7 +24,6 @@ from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from openedx.features.course_experience import COURSE_ENABLE_UNENROLLED_ACCESS_FLAG from openedx.features.course_experience.waffle import ENABLE_COURSE_ABOUT_SIDEBAR_HTML from openedx.features.course_experience.waffle import WAFFLE_NAMESPACE as COURSE_EXPERIENCE_WAFFLE_NAMESPACE -from shoppingcart.models import Order, PaidCourseRegistration from student.models import CourseEnrollment from student.tests.factories import AdminFactory, CourseEnrollmentAllowedFactory, UserFactory from track.tests import EventTrackingTestCase @@ -464,176 +463,6 @@ class AboutSidebarHTMLTestCase(SharedModuleStoreTestCase): self.assertNotContains(resp, '<section class="about-sidebar-html">') -@patch.dict(settings.FEATURES, {'ENABLE_SHOPPING_CART': True}) -@patch.dict(settings.FEATURES, {'ENABLE_PAID_COURSE_REGISTRATION': True}) -class AboutPurchaseCourseTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase): - """ - This test class runs through a suite of verifications regarding - purchaseable courses - """ - @classmethod - def setUpClass(cls): - super(AboutPurchaseCourseTestCase, cls).setUpClass() - cls.course = CourseFactory.create(org='MITx', number='buyme', display_name='Course To Buy') - - now = datetime.datetime.now(pytz.UTC) - tomorrow = now + datetime.timedelta(days=1) - nextday = tomorrow + datetime.timedelta(days=1) - - cls.closed_course = CourseFactory.create( - org='MITx', - number='closed', - display_name='Closed Course To Buy', - enrollment_start=tomorrow, - enrollment_end=nextday - ) - - def setUp(self): - super(AboutPurchaseCourseTestCase, self).setUp() - self._set_ecomm(self.course) - self._set_ecomm(self.closed_course) - - def _set_ecomm(self, course): - """ - Helper method to turn on ecommerce on the course - """ - course_mode = CourseMode( - course_id=course.id, - mode_slug=CourseMode.DEFAULT_MODE_SLUG, - mode_display_name=CourseMode.DEFAULT_MODE_SLUG, - min_price=10, - ) - course_mode.save() - - def test_anonymous_user(self): - """ - Make sure an anonymous user sees the purchase button - """ - url = reverse('about_course', args=[text_type(self.course.id)]) - resp = self.client.get(url) - self.assertContains(resp, "Add buyme to Cart <span>($10 USD)</span>") - - def test_logged_in(self): - """ - Make sure a logged in user sees the purchase button - """ - self.setup_user() - url = reverse('about_course', args=[text_type(self.course.id)]) - resp = self.client.get(url) - self.assertContains(resp, "Add buyme to Cart <span>($10 USD)</span>") - - def test_already_in_cart(self): - """ - This makes sure if a user has this course in the cart, that the expected message - appears - """ - self.setup_user() - cart = Order.get_cart_for_user(self.user) - PaidCourseRegistration.add_to_order(cart, self.course.id) - - url = reverse('about_course', args=[text_type(self.course.id)]) - resp = self.client.get(url) - self.assertContains(resp, "This course is in your") - self.assertNotContains(resp, "Add buyme to Cart <span>($10 USD)</span>") - - def test_already_enrolled(self): - """ - This makes sure that the already enrolled message appears for paywalled courses - """ - self.setup_user() - - # note that we can't call self.enroll here since that goes through - # the Django student views, which doesn't allow for enrollments - # for paywalled courses - CourseEnrollment.enroll(self.user, self.course.id) - - url = reverse('about_course', args=[text_type(self.course.id)]) - - resp = self.client.get(url) - self.assertContains(resp, "You are enrolled in this course") - self.assertContains(resp, "View Course") - self.assertNotContains(resp, "Add buyme to Cart <span>($10 USD)</span>") - - def test_closed_enrollment(self): - """ - This makes sure that paywalled courses also honor the registration - window - """ - self.setup_user() - - url = reverse('about_course', args=[text_type(self.closed_course.id)]) - resp = self.client.get(url) - self.assertContains(resp, "Enrollment is Closed") - self.assertNotContains(resp, "Add closed to Cart <span>($10 USD)</span>") - - # course price is visible ihe course_about page when the course - # mode is set to honor and it's price is set - self.assertContains(resp, '<span class="important-dates-item-text">$10</span>') - - def test_invitation_only(self): - """ - This makes sure that the invitation only restirction takes prescendence over - any purchase enablements - """ - course = CourseFactory.create(metadata={"invitation_only": True}) - self._set_ecomm(course) - self.setup_user() - - url = reverse('about_course', args=[text_type(course.id)]) - resp = self.client.get(url) - self.assertContains(resp, "Enrollment in this course is by invitation only") - - def test_enrollment_cap(self): - """ - Make sure that capped enrollments work even with - paywalled courses - """ - course = CourseFactory.create( - metadata={ - "max_student_enrollments_allowed": 1, - "display_coursenumber": "buyme", - } - ) - self._set_ecomm(course) - - self.setup_user() - url = reverse('about_course', args=[text_type(course.id)]) - resp = self.client.get(url) - self.assertContains(resp, "Add buyme to Cart <span>($10 USD)</span>") - - # note that we can't call self.enroll here since that goes through - # the Django student views, which doesn't allow for enrollments - # for paywalled courses - CourseEnrollment.enroll(self.user, course.id) - - # create a new account since the first account is already enrolled in the course - email = 'foo_second@test.com' - password = 'bar' - username = 'test_second' - self.create_account(username, - email, password) - self.activate_user(email) - self.login(email, password) - - # Get the about page again and make sure that the page says that the course is full - resp = self.client.get(url) - self.assertContains(resp, "Course is full") - self.assertNotContains(resp, "Add buyme to Cart ($10)") - - def test_free_course_display(self): - """ - Make sure other courses that don't have shopping cart enabled don't display the add-to-cart button - and don't display the course_price field if Cosmetic Price is disabled. - """ - course = CourseFactory.create(org='MITx', number='free', display_name='Course For Free') - self.setup_user() - url = reverse('about_course', args=[text_type(course.id)]) - - resp = self.client.get(url) - self.assertNotContains(resp, "Add free to Cart (Free)") - self.assertNotContains(resp, '<p class="important-dates-item-title">Price</p>') - - class CourseAboutTestCaseCCX(SharedModuleStoreTestCase, LoginEnrollmentTestCase): """ Test for unenrolled student tries to access ccx. diff --git a/lms/djangoapps/courseware/tests/test_course_info.py b/lms/djangoapps/courseware/tests/test_course_info.py index 578cd8b7dcac1b7f198f560dd45fc4866f3966e7..59b535330e7dacd905f3300b3897f3d68cc5500d 100644 --- a/lms/djangoapps/courseware/tests/test_course_info.py +++ b/lms/djangoapps/courseware/tests/test_course_info.py @@ -431,8 +431,8 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest def test_num_queries_instructor_paced(self): # TODO: decrease query count as part of REVO-28 - self.fetch_course_info_with_queries(self.instructor_paced_course, 43, 3) + self.fetch_course_info_with_queries(self.instructor_paced_course, 44, 3) def test_num_queries_self_paced(self): # TODO: decrease query count as part of REVO-28 - self.fetch_course_info_with_queries(self.self_paced_course, 43, 3) + self.fetch_course_info_with_queries(self.self_paced_course, 44, 3) diff --git a/lms/djangoapps/courseware/tests/test_course_tools.py b/lms/djangoapps/courseware/tests/test_course_tools.py index 05115b68ba69af218364b976d1afb972d5ed2325..75b7300786487c899d420e196c51fa7056bddd16 100644 --- a/lms/djangoapps/courseware/tests/test_course_tools.py +++ b/lms/djangoapps/courseware/tests/test_course_tools.py @@ -12,6 +12,7 @@ from mock import patch from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory +from lms.djangoapps.courseware.course_tools import FinancialAssistanceTool from lms.djangoapps.courseware.course_tools import VerifiedUpgradeTool from lms.djangoapps.courseware.models import DynamicUpgradeDeadlineConfiguration from openedx.core.djangoapps.content.course_overviews.models import CourseOverview @@ -103,3 +104,99 @@ class VerifiedUpgradeToolTest(SharedModuleStoreTestCase): self.course_verified_mode.expiration_datetime = None self.course_verified_mode.save() self.assertFalse(VerifiedUpgradeTool().is_enabled(self.request, self.course.id)) + + +class FinancialAssistanceToolTest(SharedModuleStoreTestCase): + """ + Tests for FinancialAssistanceTool + """ + @classmethod + def setUpClass(cls): + super(FinancialAssistanceToolTest, cls).setUpClass() + cls.now = datetime.datetime.now(pytz.UTC) + + cls.course = CourseFactory.create( + org='edX', + number='test', + display_name='Test Course', + self_paced=True, + ) + cls.course_overview = CourseOverview.get_from_id(cls.course.id) + + @override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True) + def setUp(self): + super(FinancialAssistanceToolTest, self).setUp() + + self.course_financial_mode = CourseModeFactory( + course_id=self.course.id, + mode_slug=CourseMode.VERIFIED, + expiration_datetime=self.now + datetime.timedelta(days=1), + ) + DynamicUpgradeDeadlineConfiguration.objects.create(enabled=True) + + self.request = RequestFactory().request() + crum.set_current_request(self.request) + self.addCleanup(crum.set_current_request, None) + + # baseline course enrollment, future upgrade deadline + self.enrollment = CourseEnrollmentFactory( + course_id=self.course.id, + mode=CourseMode.AUDIT, + course=self.course_overview, + ) + self.request.user = self.enrollment.user + + # enrollment where learner has upgraded + self.enrollment_upgraded = CourseEnrollmentFactory( + course_id=self.course.id, + mode=CourseMode.VERIFIED, + course=self.course_overview, + ) + + # course enrollment for mock: upgrade deadline in the past + self.enrollment_deadline_past = self.enrollment + self.enrollment_deadline_past.course_upgrade_deadline = self.now - datetime.timedelta(days=1) + self.enrollment_deadline_past.save() + + # course enrollment for mock: no upgrade deadline + self.enrollment_deadline_missing = self.enrollment + self.enrollment_deadline_missing.course_upgrade_deadline = None + self.enrollment_deadline_missing.save() + + def test_tool_visible_logged_in(self): + self.course_financial_mode.save() + self.assertTrue(FinancialAssistanceTool().is_enabled(self.request, self.course.id)) + + def test_tool_not_visible_when_not_eligible(self): + self.course_overview.eligible_for_financial_aid = False + self.course_overview.save() + self.assertFalse(FinancialAssistanceTool().is_enabled(self.request, self.course_overview.id)) + + def test_tool_not_visible_when_user_not_enrolled(self): + self.course_financial_mode.save() + self.request.user = None + self.assertFalse(FinancialAssistanceTool().is_enabled(self.request, self.course.id)) + + # mock the response from get_enrollment to use enrollment with course_upgrade_deadline in the past + @patch('lms.djangoapps.courseware.course_tools.CourseEnrollment.get_enrollment') + def test_not_visible_when_upgrade_deadline_has_passed(self, get_enrollment_mock): + get_enrollment_mock.return_value = self.enrollment_deadline_past + self.assertFalse(FinancialAssistanceTool().is_enabled(self.request, self.course.id)) + + # mock the response from get_enrollment to use enrollment with no course_upgrade_deadline + @patch('lms.djangoapps.courseware.course_tools.CourseEnrollment.get_enrollment') + def test_not_visible_when_no_upgrade_deadline(self, get_enrollment_mock): + get_enrollment_mock.return_value = self.enrollment_deadline_missing + self.assertFalse(FinancialAssistanceTool().is_enabled(self.request, self.course.id)) + + def test_tool_not_visible_when_end_date_passed(self): + self.course_overview.end_date = self.now - datetime.timedelta(days=30) + self.course_overview.save() + self.assertFalse(FinancialAssistanceTool().is_enabled(self.request, self.course_overview.id)) + + # mock the response from get_enrollment to use enrollment where learner upgraded + @patch('lms.djangoapps.courseware.course_tools.CourseEnrollment.get_enrollment') + def test_tool_not_visible_when_already_upgraded(self, get_enrollment_mock): + self.course_financial_mode.save() + get_enrollment_mock.return_value = self.enrollment_upgraded + self.assertFalse(FinancialAssistanceTool().is_enabled(self.request, self.course.id)) diff --git a/lms/djangoapps/courseware/tests/test_date_summary.py b/lms/djangoapps/courseware/tests/test_date_summary.py index 56b1556aa59895d4430535348484809bb6875804..7ea8e94914c6fe2a3ea062e0f1eb60dfadd1ec32 100644 --- a/lms/djangoapps/courseware/tests/test_date_summary.py +++ b/lms/djangoapps/courseware/tests/test_date_summary.py @@ -158,39 +158,43 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): assignment_title_html = ['<a href=', '</a>'] with self.store.bulk_operations(course.id): section = ItemFactory.create(category='chapter', parent_location=course.location) - subsection_1 = ItemFactory.create( + ItemFactory.create( category='sequential', display_name='Released', parent_location=section.location, start=now - timedelta(days=1), due=now + timedelta(days=6), graded=True, + format='Homework', ) - subsection_2 = ItemFactory.create( + ItemFactory.create( category='sequential', display_name='Not released', parent_location=section.location, start=now + timedelta(days=1), due=now + timedelta(days=7), graded=True, + format='Homework', ) - subsection_3 = ItemFactory.create( + ItemFactory.create( category='sequential', display_name='Third nearest assignment', parent_location=section.location, start=now + timedelta(days=1), due=now + timedelta(days=8), graded=True, + format='Exam', ) - subsection_4 = ItemFactory.create( + ItemFactory.create( category='sequential', display_name='Past due date', parent_location=section.location, start=now - timedelta(days=14), due=now - timedelta(days=7), graded=True, + format='Exam', ) - subsection_5 = ItemFactory.create( + ItemFactory.create( category='sequential', display_name='Not returned since we do not get non-graded subsections', parent_location=section.location, @@ -198,15 +202,16 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): due=now - timedelta(days=7), graded=False, ) - subsection_6 = ItemFactory.create( + ItemFactory.create( category='sequential', display_name='No start date', parent_location=section.location, start=None, due=now + timedelta(days=9), graded=True, + format='Speech', ) - subsection_7 = ItemFactory.create( + ItemFactory.create( category='sequential', # Setting display name to None should set the assignment title to 'Assignment' display_name=None, @@ -214,6 +219,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): start=now - timedelta(days=14), due=now + timedelta(days=10), graded=True, + format=None, ) dummy_subsection = ItemFactory.create(category='sequential', graded=True, due=now + timedelta(days=11)) @@ -222,85 +228,75 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, course.id): self.store.delete_item(dummy_subsection.location, user.id) - with patch('lms.djangoapps.courseware.courses.get_dates_for_course') as mock_get_dates: - mock_get_dates.return_value = { - (subsection_1.location, 'due'): subsection_1.due, - (subsection_1.location, 'start'): subsection_1.start, - (subsection_2.location, 'due'): subsection_2.due, - (subsection_2.location, 'start'): subsection_2.start, - (subsection_3.location, 'due'): subsection_3.due, - (subsection_3.location, 'start'): subsection_3.start, - (subsection_4.location, 'due'): subsection_4.due, - (subsection_4.location, 'start'): subsection_4.start, - (subsection_5.location, 'due'): subsection_5.due, - (subsection_5.location, 'start'): subsection_5.start, - (subsection_6.location, 'due'): subsection_6.due, - (subsection_7.location, 'due'): subsection_7.due, - (subsection_7.location, 'start'): subsection_7.start, - # Adding this in for the case where we return a block that - # doesn't actually exist in the modulestore. Should just be ignored. - (dummy_subsection.location, 'due'): dummy_subsection.due, - } - # Standard widget case where we restrict the number of assignments. - expected_blocks = ( - TodaysDate, CourseAssignmentDate, CourseAssignmentDate, CourseEndDate, VerificationDeadlineDate - ) - blocks = get_course_date_blocks(course, user, request, num_assignments=2) - self.assertEqual(len(blocks), len(expected_blocks)) - self.assertEqual(set(type(b) for b in blocks), set(expected_blocks)) - assignment_blocks = filter(lambda b: isinstance(b, CourseAssignmentDate), blocks) - for assignment in assignment_blocks: - assignment_title = str(assignment.title_html) or str(assignment.title) - self.assertNotEqual(assignment_title, 'Third nearest assignment') - self.assertNotEqual(assignment_title, 'Past due date') - self.assertNotEqual(assignment_title, 'Not returned since we do not get non-graded subsections') - # checking if it is _in_ the title instead of being the title since released assignments - # are actually links. Unreleased assignments are just the string of the title. - if 'Released' in assignment_title: - for html_tag in assignment_title_html: - self.assertIn(html_tag, assignment_title) - elif assignment_title == 'Not released': - for html_tag in assignment_title_html: - self.assertNotIn(html_tag, assignment_title) - - # No restrictions on number of assignments to return - expected_blocks = ( - CourseStartDate, TodaysDate, CourseAssignmentDate, CourseAssignmentDate, CourseAssignmentDate, - CourseAssignmentDate, CourseAssignmentDate, CourseAssignmentDate, CourseEndDate, - VerificationDeadlineDate - ) - blocks = get_course_date_blocks(course, user, request, include_past_dates=True) - self.assertEqual(len(blocks), len(expected_blocks)) - self.assertEqual(set(type(b) for b in blocks), set(expected_blocks)) - assignment_blocks = filter(lambda b: isinstance(b, CourseAssignmentDate), blocks) - for assignment in assignment_blocks: - assignment_title = str(assignment.title_html) or str(assignment.title) - self.assertNotEqual(assignment_title, 'Not returned since we do not get non-graded subsections') - # checking if it is _in_ the title instead of being the title since released assignments - # are actually links. Unreleased assignments are just the string of the title. - if 'Released' in assignment_title: - for html_tag in assignment_title_html: - self.assertIn(html_tag, assignment_title) - elif assignment_title == 'Not released': - for html_tag in assignment_title_html: - self.assertNotIn(html_tag, assignment_title) - elif assignment_title == 'Third nearest assignment': - # It's still not released - for html_tag in assignment_title_html: - self.assertNotIn(html_tag, assignment_title) - elif 'Past due date' in assignment_title: - self.assertGreater(now, assignment.date) - for html_tag in assignment_title_html: - self.assertIn(html_tag, assignment_title) - elif 'No start date' == assignment_title: - # Can't determine if it is released so it does not get a link - for html_tag in assignment_title_html: - self.assertNotIn(html_tag, assignment_title) - # This is the item with no display name where we set one ourselves. - elif 'Assignment' in assignment_title: - # Can't determine if it is released so it does not get a link - for html_tag in assignment_title_html: - self.assertIn(html_tag, assignment_title) + # Standard widget case where we restrict the number of assignments. + expected_blocks = ( + TodaysDate, CourseAssignmentDate, CourseAssignmentDate, CourseEndDate, VerificationDeadlineDate + ) + blocks = get_course_date_blocks(course, user, request, num_assignments=2) + self.assertEqual(len(blocks), len(expected_blocks)) + self.assertEqual(set(type(b) for b in blocks), set(expected_blocks)) + assignment_blocks = filter(lambda b: isinstance(b, CourseAssignmentDate), blocks) + for assignment in assignment_blocks: + assignment_title = str(assignment.title_html) or str(assignment.title) + self.assertNotEqual(assignment_title, 'Third nearest assignment') + self.assertNotEqual(assignment_title, 'Past due date') + self.assertNotEqual(assignment_title, 'Not returned since we do not get non-graded subsections') + # checking if it is _in_ the title instead of being the title since released assignments + # are actually links. Unreleased assignments are just the string of the title. + if 'Released' in assignment_title: + for html_tag in assignment_title_html: + self.assertIn(html_tag, assignment_title) + elif assignment_title == 'Not released': + for html_tag in assignment_title_html: + self.assertNotIn(html_tag, assignment_title) + + # No restrictions on number of assignments to return + expected_blocks = ( + CourseStartDate, TodaysDate, CourseAssignmentDate, CourseAssignmentDate, CourseAssignmentDate, + CourseAssignmentDate, CourseAssignmentDate, CourseAssignmentDate, CourseEndDate, + VerificationDeadlineDate + ) + blocks = get_course_date_blocks(course, user, request, include_past_dates=True) + self.assertEqual(len(blocks), len(expected_blocks)) + self.assertEqual(set(type(b) for b in blocks), set(expected_blocks)) + assignment_blocks = filter(lambda b: isinstance(b, CourseAssignmentDate), blocks) + for assignment in assignment_blocks: + assignment_title = str(assignment.title_html) or str(assignment.title) + self.assertNotEqual(assignment_title, 'Not returned since we do not get non-graded subsections') + + assignment_type = str(assignment.assignment_type) + # checking if it is _in_ the title instead of being the title since released assignments + # are actually links. Unreleased assignments are just the string of the title. + # also checking that the assignment type is returned for graded subsections + if 'Released' in assignment_title: + self.assertEqual(assignment_type, 'Homework') + for html_tag in assignment_title_html: + self.assertIn(html_tag, assignment_title) + elif assignment_title == 'Not released': + self.assertEqual(assignment_type, 'Homework') + for html_tag in assignment_title_html: + self.assertNotIn(html_tag, assignment_title) + elif assignment_title == 'Third nearest assignment': + self.assertEqual(assignment_type, 'Exam') + # It's still not released + for html_tag in assignment_title_html: + self.assertNotIn(html_tag, assignment_title) + elif 'Past due date' in assignment_title: + self.assertGreater(now, assignment.date) + self.assertEqual(assignment_type, 'Exam') + for html_tag in assignment_title_html: + self.assertIn(html_tag, assignment_title) + elif 'No start date' == assignment_title: + self.assertEqual(assignment_type, 'Speech') + # Can't determine if it is released so it does not get a link + for html_tag in assignment_title_html: + self.assertNotIn(html_tag, assignment_title) + # This is the item with no display name where we set one ourselves. + elif 'Assignment' in assignment_title: + self.assertEqual(assignment_type, None) + # Can't determine if it is released so it does not get a link + for html_tag in assignment_title_html: + self.assertIn(html_tag, assignment_title) @RELATIVE_DATES_FLAG.override(active=True) def test_enabled_block_types_with_expired_course(self): @@ -348,6 +344,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): user = create_user() block = TodaysDate(course, user) self.assertTrue(block.is_enabled) + self.assertTrue(block.is_allowed) self.assertEqual(block.date, datetime.now(utc)) self.assertEqual(block.title, 'current_datetime') @@ -524,7 +521,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): CourseEnrollmentFactory(course_id=course.id, user=user, mode=CourseMode.AUDIT) block = CertificateAvailableDate(course, user) self.assertEqual(block.date, None) - self.assertFalse(block.is_enabled) + self.assertFalse(block.is_allowed) ## CertificateAvailableDate @waffle.testutils.override_switch('certificates.auto_certificate_generation', True) @@ -536,7 +533,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): course.save() block = CertificateAvailableDate(course, verified_user) self.assertNotEqual(block.date, None) - self.assertFalse(block.is_enabled) + self.assertFalse(block.is_allowed) def test_no_certificate_available_date_for_audit_course(self): """ @@ -558,7 +555,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): # Verify Certificate Available Date is not enabled for learner. block = CertificateAvailableDate(course, audit_user) - self.assertFalse(block.is_enabled) + self.assertFalse(block.is_allowed) self.assertNotEqual(block.date, None) @waffle.testutils.override_switch('certificates.auto_certificate_generation', True) @@ -570,11 +567,14 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): CourseEnrollmentFactory(course_id=course.id, user=verified_user, mode=CourseMode.VERIFIED) course.certificate_available_date = datetime.now(utc) + timedelta(days=7) enable_course_certificates(course) - CertificateAvailableDate(course, audit_user) + expected_blocks = [ + CourseEndDate, CourseStartDate, TodaysDate, VerificationDeadlineDate, CertificateAvailableDate + ] + self.assert_block_types(course, verified_user, expected_blocks) for block in (CertificateAvailableDate(course, audit_user), CertificateAvailableDate(course, verified_user)): self.assertIsNotNone(course.certificate_available_date) self.assertEqual(block.date, course.certificate_available_date) - self.assertTrue(block.is_enabled) + self.assertTrue(block.is_allowed) ## VerificationDeadlineDate def test_no_verification_deadline(self): @@ -582,14 +582,15 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): user = create_user() CourseEnrollmentFactory(course_id=course.id, user=user, mode=CourseMode.VERIFIED) block = VerificationDeadlineDate(course, user) - self.assertFalse(block.is_enabled) + self.assertIsNone(block.date) + self.assertTrue(block.is_allowed) def test_no_verified_enrollment(self): course = create_course_run(days_till_start=-1) user = create_user() CourseEnrollmentFactory(course_id=course.id, user=user, mode=CourseMode.AUDIT) block = VerificationDeadlineDate(course, user) - self.assertFalse(block.is_enabled) + self.assertFalse(block.is_allowed) def test_verification_deadline_date_upcoming(self): with freeze_time('2015-01-02'): @@ -656,6 +657,25 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): block = VerificationDeadlineDate(course, user) self.assertEqual(block.relative_datestring, expected_date_string) + @ddt.data( + 'info', + 'openedx.course_experience.course_home', + ) + @override_waffle_flag(UNIFIED_COURSE_TAB_FLAG, active=True) + def test_dates_tab_link_render(self, url_name): + with freeze_time('2015-01-02'): + course = create_course_run() + user = create_user() + self.client.login(username=user.username, password=TEST_PASSWORD) + url = reverse(url_name, args=(course.id,)) + response = self.client.get(url, follow=True) + html_elements = [ + 'class="dates-tab-link"', + 'View all course dates</a>', + ] + for html in html_elements: + self.assertContains(response, html) + @ddt.ddt class TestDateAlerts(SharedModuleStoreTestCase): diff --git a/lms/djangoapps/courseware/tests/test_field_overrides.py b/lms/djangoapps/courseware/tests/test_field_overrides.py index 05375e8a71ff7ebefb4b04a999adc8b07568f53e..237ba3d03bd82bbcc195f6bad952cb709caaef60 100644 --- a/lms/djangoapps/courseware/tests/test_field_overrides.py +++ b/lms/djangoapps/courseware/tests/test_field_overrides.py @@ -1,9 +1,6 @@ """ Tests for `field_overrides` module. """ -# pylint: disable=missing-docstring - - import unittest from django.test.utils import override_settings diff --git a/lms/djangoapps/courseware/tests/test_i18n.py b/lms/djangoapps/courseware/tests/test_i18n.py index 64bbbd6371956b09aa546c29f107be54f5969b89..31e3318015b32565d725052192149a145d587365 100644 --- a/lms/djangoapps/courseware/tests/test_i18n.py +++ b/lms/djangoapps/courseware/tests/test_i18n.py @@ -36,7 +36,7 @@ class BaseI18nTestCase(CacheIsolationTestCase): def assert_tag_has_attr(self, content, tag, attname, value): """Assert that a tag in `content` has a certain value in a certain attribute.""" - regex_string = six.text_type(r"""<{tag} [^>]*\b{attname}=['"]([\w\d\- ]+)['"][^>]*>""") # noqa: W605,E501 pylint: disable=unicode-format-string + regex_string = six.text_type(r"""<{tag} [^>]*\b{attname}=['"]([\w\d\- ]+)['"][^>]*>""") # noqa: W605,E501 regex = regex_string.format(tag=tag, attname=attname) match = re.search(regex, content) self.assertTrue(match, u"Couldn't find desired tag '%s' with attr '%s' in %r" % (tag, attname, content)) diff --git a/lms/djangoapps/courseware/tests/test_lti_integration.py b/lms/djangoapps/courseware/tests/test_lti_integration.py index 1d79e800d29cbd6f73000c3f316db5a6108724df..1a6dc83f135598e0d5a40cd5dbf60a4cfc781506 100644 --- a/lms/djangoapps/courseware/tests/test_lti_integration.py +++ b/lms/djangoapps/courseware/tests/test_lti_integration.py @@ -6,9 +6,7 @@ from collections import OrderedDict import mock import oauthlib -import six.moves.urllib.error # pylint: disable=import-error -import six.moves.urllib.parse # pylint: disable=import-error -import six.moves.urllib.request # pylint: disable=import-error +import six from django.conf import settings from django.urls import reverse from six import text_type diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index c3033f1b401ce2b5af898759c3fff4b7a0e9c59d..005f864ea7605c065ad501f086246b7f946e0141 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -997,6 +997,7 @@ class TestXBlockView(SharedModuleStoreTestCase, LoginEnrollmentTestCase): @ddt.ddt class TestTOC(ModuleStoreTestCase): """Check the Table of Contents for a course""" + def setup_request_and_course(self, num_finds, num_sends): """ Sets up the toy course in the modulestore and the request object. @@ -1522,6 +1523,7 @@ class TestHtmlModifiers(ModuleStoreTestCase): Tests to verify that standard modifications to the output of XModule/XBlock student_view are taking place """ + def setUp(self): super(TestHtmlModifiers, self).setUp() self.course = CourseFactory.create() @@ -1712,109 +1714,12 @@ class JsonInitDataTest(ModuleStoreTestCase): self.assertEqual(html.count("</script>"), 1) -class ViewInStudioTest(ModuleStoreTestCase): - """Tests for the 'View in Studio' link visiblity.""" - - def setUp(self): - """ Set up the user and request that will be used. """ - super(ViewInStudioTest, self).setUp() - self.staff_user = GlobalStaffFactory.create() - self.request = RequestFactoryNoCsrf().get('/') - self.request.user = self.staff_user - self.request.session = {} - self.module = None - self.default_context = {'bookmarked': False, 'username': self.user.username} - - def _get_module(self, course_id, descriptor, location): - """ - Get the module from the course from which to pattern match (or not) the 'View in Studio' buttons - """ - field_data_cache = FieldDataCache.cache_for_descriptor_descendents( - course_id, - self.staff_user, - descriptor - ) - - return render.get_module( - self.staff_user, - self.request, - location, - field_data_cache, - ) - - def setup_mongo_course(self, course_edit_method='Studio'): - """ Create a mongo backed course. """ - course = CourseFactory.create( - course_edit_method=course_edit_method - ) - - descriptor = ItemFactory.create( - category='vertical', - parent_location=course.location, - ) - - child_descriptor = ItemFactory.create( - category='vertical', - parent_location=descriptor.location - ) - - self.module = self._get_module(course.id, descriptor, descriptor.location) - - # pylint: disable=attribute-defined-outside-init - self.child_module = self._get_module(course.id, child_descriptor, child_descriptor.location) - - -class MongoViewInStudioTest(ViewInStudioTest): - """Test the 'View in Studio' link visibility in a mongo backed course.""" - - def test_view_in_studio_link_studio_course(self): - """Regular Studio courses should see 'View in Studio' links.""" - self.setup_mongo_course() - result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context) - self.assertIn('View Unit in Studio', result_fragment.content) - - def test_view_in_studio_link_only_in_top_level_vertical(self): - """Regular Studio courses should not see 'View in Studio' for child verticals of verticals.""" - self.setup_mongo_course() - # Render the parent vertical, then check that there is only a single "View Unit in Studio" link. - result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context) - # The single "View Unit in Studio" link should appear before the first xmodule vertical definition. - parts = result_fragment.content.split('data-block-type="vertical"') - self.assertEqual(3, len(parts), "Did not find two vertical blocks") - self.assertIn('View Unit in Studio', parts[0]) - self.assertNotIn('View Unit in Studio', parts[1]) - self.assertNotIn('View Unit in Studio', parts[2]) - - def test_view_in_studio_link_xml_authored(self): - """Courses that change 'course_edit_method' setting can hide 'View in Studio' links.""" - self.setup_mongo_course(course_edit_method='XML') - result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context) - self.assertNotIn('View Unit in Studio', result_fragment.content) - - -class MixedViewInStudioTest(ViewInStudioTest): - """Test the 'View in Studio' link visibility in a mixed mongo backed course.""" - - MODULESTORE = TEST_DATA_MIXED_MODULESTORE - - def test_view_in_studio_link_mongo_backed(self): - """Mixed mongo courses that are mongo backed should see 'View in Studio' links.""" - self.setup_mongo_course() - result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context) - self.assertIn('View Unit in Studio', result_fragment.content) - - def test_view_in_studio_link_xml_authored(self): - """Courses that change 'course_edit_method' setting can hide 'View in Studio' links.""" - self.setup_mongo_course(course_edit_method='XML') - result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context) - self.assertNotIn('View Unit in Studio', result_fragment.content) - - @XBlock.tag("detached") class DetachedXBlock(XBlock): """ XBlock marked with the 'detached' flag. """ + def student_view(self, context=None): # pylint: disable=unused-argument """ A simple view that returns just enough to test. @@ -2100,7 +2005,7 @@ class TestAnonymousStudentId(SharedModuleStoreTestCase, LoginEnrollmentTestCase) ) -@patch('track.views.tracker', autospec=True) +@patch('track.views.eventtracker', autospec=True) class TestModuleTrackingContext(SharedModuleStoreTestCase): """ Ensure correct tracking information is included in events emitted during XBlock callback handling. @@ -2152,7 +2057,11 @@ class TestModuleTrackingContext(SharedModuleStoreTestCase): return {'content': 'test1', 'data_field': 'test2'} AsideTestType.get_event_context = get_event_context - context_info = self.handle_callback_and_get_context_info(mock_tracker, problem_display_name) + + # for different operations, there are different number of context calls. + # We are sending this `call_idx` to get the mock call that we are interested in. + context_info = self.handle_callback_and_get_context_info(mock_tracker, problem_display_name, call_idx=4) + self.assertIn('asides', context_info) self.assertIn('test_aside', context_info['asides']) self.assertIn('content', context_info['asides']['test_aside']) @@ -2160,11 +2069,15 @@ class TestModuleTrackingContext(SharedModuleStoreTestCase): self.assertIn('data_field', context_info['asides']['test_aside']) self.assertEqual(context_info['asides']['test_aside']['data_field'], 'test2') - def handle_callback_and_get_context_info(self, mock_tracker, problem_display_name=None): + def handle_callback_and_get_context_info(self, + mock_tracker, + problem_display_name=None, + call_idx=0): """ Creates a fake module, invokes the callback and extracts the 'context' metadata from the emitted problem_check event. """ + descriptor_kwargs = { 'category': 'problem', 'data': self.problem_xml @@ -2173,28 +2086,35 @@ class TestModuleTrackingContext(SharedModuleStoreTestCase): descriptor_kwargs['display_name'] = problem_display_name descriptor = ItemFactory.create(**descriptor_kwargs) + with patch('lms.djangoapps.courseware.module_render.tracker') as mock_tracker_for_context: + render.handle_xblock_callback( + self.request, + text_type(self.course.id), + quote_slashes(text_type(descriptor.location)), + 'xmodule_handler', + 'problem_check', + ) - render.handle_xblock_callback( - self.request, - text_type(self.course.id), - quote_slashes(text_type(descriptor.location)), - 'xmodule_handler', - 'problem_check', - ) + self.assertEquals(len(mock_tracker.emit.mock_calls), 1) + mock_call = mock_tracker.emit.mock_calls[0] + event = mock_call[2] + + self.assertEquals(event['name'], 'problem_check') - self.assertEqual(len(mock_tracker.send.mock_calls), 1) - mock_call = mock_tracker.send.mock_calls[0] - event = mock_call[1][0] + # for different operations, there are different number of context calls. + # We are sending this `call_idx` to get the mock call that we are interested in. + context = mock_tracker_for_context.get_tracker.mock_calls[call_idx][1][1] - self.assertEqual(event['event_type'], 'problem_check') - return event['context'] + return context def handle_callback_and_get_module_info(self, mock_tracker, problem_display_name=None): """ Creates a fake module, invokes the callback and extracts the 'module' metadata from the emitted problem_check event. """ - event = self.handle_callback_and_get_context_info(mock_tracker, problem_display_name) + event = self.handle_callback_and_get_context_info( + mock_tracker, problem_display_name, call_idx=1 + ) return event['module'] def test_missing_display_name(self, mock_tracker): @@ -2292,6 +2212,7 @@ class TestRebindModule(TestSubmittingProblems): Tests to verify the functionality of rebinding a module. Inherit from TestSubmittingProblems to get functionality that set up a course structure """ + def setUp(self): super(TestRebindModule, self).setUp() self.homework = self.add_graded_section_to_course('homework') @@ -2650,6 +2571,7 @@ class TestDisabledXBlockTypes(ModuleStoreTestCase): """ Tests that verify disabled XBlock types are not loaded. """ + def setUp(self): super(TestDisabledXBlockTypes, self).setUp() XBlockConfiguration(name='video', enabled=False).save() diff --git a/lms/djangoapps/courseware/tests/test_self_paced_overrides.py b/lms/djangoapps/courseware/tests/test_self_paced_overrides.py index c230dcb1d6ee2116c3cb1dc69b30a013b4eac8f9..d70ace2ca1c244265f7eb65bd26012347a123719 100644 --- a/lms/djangoapps/courseware/tests/test_self_paced_overrides.py +++ b/lms/djangoapps/courseware/tests/test_self_paced_overrides.py @@ -1,6 +1,4 @@ """Tests for self-paced course due date overrides.""" -# pylint: disable=missing-docstring - import datetime diff --git a/lms/djangoapps/courseware/tests/test_services.py b/lms/djangoapps/courseware/tests/test_services.py index 50281ad89a9613db190ad51de135b6aaf8d2e7b1..47ec2bff4519cbcd66ad748b3905cd28b582ef12 100644 --- a/lms/djangoapps/courseware/tests/test_services.py +++ b/lms/djangoapps/courseware/tests/test_services.py @@ -96,7 +96,8 @@ class TestUserStateService(ModuleStoreTestCase): @ddt.data( *itertools.product( [ - ({'username_or_email': 'no_user', 'block_id': 'block-v1:myOrg+123+2030_T2+type@openassessment+block@hash'}), # pylint: disable=line-too-long + ({'username_or_email': 'no_user', 'block_id': + 'block-v1:myOrg+123+2030_T2+type@openassessment+block@hash'}), ({'username_or_email': 'no_user'}), ({'block_id': 'block-v1:myOrg+1234+2030_T2+type@openassessment+block@hash'}) ], [ diff --git a/lms/djangoapps/courseware/tests/test_tabs.py b/lms/djangoapps/courseware/tests/test_tabs.py index 0516ca00cc1b75030fff2a44d6e828744e4dab65..b5d621beff5d46a65144c2d878eba9c186e3d383 100644 --- a/lms/djangoapps/courseware/tests/test_tabs.py +++ b/lms/djangoapps/courseware/tests/test_tabs.py @@ -17,6 +17,7 @@ from lms.djangoapps.courseware.courses import get_course_by_id from lms.djangoapps.courseware.tabs import ( CourseInfoTab, CoursewareTab, + DatesTab, ExternalDiscussionCourseTab, ExternalLinkCourseTab, ProgressTab, @@ -543,6 +544,7 @@ class TabListTestCase(TabTestCase): [ {'type': CoursewareTab.type}, {'type': CourseInfoTab.type, 'name': 'fake_name'}, + {'type': DatesTab.type}, # Add this even though we filter it out, for testing purposes {'type': 'discussion', 'name': 'fake_name'}, {'type': ExternalLinkCourseTab.type, 'name': 'fake_name', 'link': 'fake_link'}, {'type': ExternalLinkCourseTab.type, 'name': 'fake_name', 'link': 'fake_link'}, @@ -656,13 +658,16 @@ class CourseTabListTestCase(TabListTestCase): # enumerate the tabs with a staff user user = UserFactory(is_staff=True) CourseEnrollment.enroll(user, self.course.id) - for i, tab in enumerate(xmodule_tabs.CourseTabList.iterate_displayable(self.course, user=user)): - if getattr(tab, 'is_collection_item', False): - # a collection item was found as a result of a collection tab - self.assertTrue(getattr(self.course.tabs[i], 'is_collection', False)) - else: - # all other tabs must match the expected type - self.assertEqual(tab.type, self.course.tabs[i].type) + # Need to mock this flag as we care that orders match, and a tab not enabled will result in a failure + with patch('lms.djangoapps.courseware.tabs.RELATIVE_DATES_FLAG') as mock_flag: + mock_flag.is_enabled().return_value = True + for i, tab in enumerate(xmodule_tabs.CourseTabList.iterate_displayable(self.course, user=user)): + if getattr(tab, 'is_collection_item', False): + # a collection item was found as a result of a collection tab + self.assertTrue(getattr(self.course.tabs[i], 'is_collection', False)) + else: + # all other tabs must match the expected type + self.assertEqual(tab.type, self.course.tabs[i].type) # test including non-empty collections self.assertIn( @@ -895,3 +900,29 @@ class DiscussionLinkTestCase(TabTestCase): is_enrolled=is_enrolled, is_staff=is_staff ) + + +class DatesTabTestCase(TabListTestCase): + """Test cases for making sure no persisted dates tab is surfaced""" + + def test_singular_dates_tab(self): + user = self.create_mock_user() + self.course.tabs = self.all_valid_tab_list + self.course.save() + + # Verify that there is a dates tab in the modulestore + has_dates_tab = False + for tab in self.course.tabs: + if tab.type == 'dates': + has_dates_tab = True + self.assertTrue(has_dates_tab) + + # Verify that there is only 1 'dates' tab in the returned result from get_course_tab_list() + with patch('lms.djangoapps.courseware.tabs.RELATIVE_DATES_FLAG') as mock_flag: + mock_flag.is_enabled().return_value = True + tabs = get_course_tab_list(user, self.course) + num_dates_tabs = 0 + for tab in tabs: + if tab.type == 'dates': + num_dates_tabs += 1 + self.assertEqual(num_dates_tabs, 1) diff --git a/lms/djangoapps/courseware/tests/test_video_mongo.py b/lms/djangoapps/courseware/tests/test_video_mongo.py index 2c8b9b47fa650233959fd675c4b9d1f7f9c9d40b..7f6955c6b63550063d6ddf17d4c501dc59cc994e 100644 --- a/lms/djangoapps/courseware/tests/test_video_mongo.py +++ b/lms/djangoapps/courseware/tests/test_video_mongo.py @@ -1326,7 +1326,6 @@ class TestEditorSavedMethod(BaseTestVideoXBlock): } # path to subs_3_yD_cEKoCk.srt.sjson file self.file_name = 'subs_3_yD_cEKoCk.srt.sjson' - # pylint: disable=no-value-for-parameter self.test_dir = path(__file__).abspath().dirname().dirname().dirname().dirname().dirname() self.file_path = self.test_dir + '/common/test/data/uploads/' + self.file_name diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 27c1452a6660e50a33ba6168ea3f44dbffdf328c..851eb4bac878d703d80b1a63ed66cca2978e3964 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -4,18 +4,24 @@ Tests courseware views.py """ +import html import itertools import json import unittest from datetime import datetime, timedelta -from pytz import utc from uuid import uuid4 -import crum -import ddt import six +from markupsafe import escape +from mock import MagicMock, PropertyMock, call, create_autospec, patch +from pytz import UTC, utc +from six import text_type +from six.moves import range +from six.moves.urllib.parse import quote, urlencode + from completion.test_utils import CompletionWaffleTestMixin from crum import set_current_request +import ddt from django.conf import settings from django.contrib.auth.models import AnonymousUser from django.http import Http404, HttpResponseBadRequest @@ -24,33 +30,17 @@ from django.test.client import Client from django.test.utils import override_settings from django.urls import reverse, reverse_lazy from freezegun import freeze_time -from markupsafe import escape from milestones.tests.utils import MilestonesTestCaseMixin -from mock import MagicMock, PropertyMock, call, create_autospec, patch +from opaque_keys.edx.keys import CourseKey, UsageKey from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator -from pytz import UTC -from six import text_type -from six.moves import range -from six.moves.html_parser import HTMLParser # pylint: disable=import-error -from six.moves.urllib.parse import quote, urlencode # pylint: disable=import-error from web_fragments.fragment import Fragment from xblock.core import XBlock from xblock.fields import Scope, String - import lms.djangoapps.courseware.views.views as views -import shoppingcart from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory from course_modes.models import CourseMode from course_modes.tests.factories import CourseModeFactory -from lms.djangoapps.courseware.access_utils import check_course_open_for_learner -from lms.djangoapps.courseware.model_data import FieldDataCache, set_score -from lms.djangoapps.courseware.module_render import get_module, handle_xblock_callback -from lms.djangoapps.courseware.tests.factories import GlobalStaffFactory, RequestFactoryNoCsrf, StudentModuleFactory -from lms.djangoapps.courseware.tests.helpers import get_expiration_banner_text -from lms.djangoapps.courseware.testutils import RenderXBlockTestMixin -from lms.djangoapps.courseware.url_helpers import get_redirect_url -from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateClient from lms.djangoapps.certificates import api as certs_api from lms.djangoapps.certificates.models import ( CertificateGenerationConfiguration, @@ -60,17 +50,23 @@ from lms.djangoapps.certificates.models import ( from lms.djangoapps.certificates.tests.factories import CertificateInvalidationFactory, GeneratedCertificateFactory from lms.djangoapps.commerce.models import CommerceConfiguration from lms.djangoapps.commerce.utils import EcommerceService -from lms.djangoapps.courseware.views.index import show_courseware_mfe_link +from lms.djangoapps.courseware.access_utils import check_course_open_for_learner +from lms.djangoapps.courseware.model_data import FieldDataCache, set_score +from lms.djangoapps.courseware.module_render import get_module, handle_xblock_callback +from lms.djangoapps.courseware.tests.factories import GlobalStaffFactory, RequestFactoryNoCsrf, StudentModuleFactory +from lms.djangoapps.courseware.tests.helpers import get_expiration_banner_text +from lms.djangoapps.courseware.testutils import RenderXBlockTestMixin from lms.djangoapps.courseware.toggles import ( COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW, - REDIRECT_TO_COURSEWARE_MICROFRONTEND, + REDIRECT_TO_COURSEWARE_MICROFRONTEND ) -from lms.djangoapps.courseware.url_helpers import get_microfrontend_url +from lms.djangoapps.courseware.url_helpers import get_microfrontend_url, get_redirect_url +from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateClient +from lms.djangoapps.courseware.views.index import show_courseware_mfe_link from lms.djangoapps.grades.config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT from lms.djangoapps.grades.config.waffle import waffle as grades_waffle from lms.djangoapps.verify_student.models import VerificationDeadline from lms.djangoapps.verify_student.services import IDVerificationService -from opaque_keys.edx.keys import CourseKey, UsageKey from openedx.core.djangoapps.catalog.tests.factories import CourseFactory as CatalogCourseFactory from openedx.core.djangoapps.catalog.tests.factories import CourseRunFactory, ProgramFactory from openedx.core.djangoapps.content.course_overviews.models import CourseOverview @@ -101,7 +97,6 @@ from xmodule.course_module import COURSE_VISIBILITY_PRIVATE, COURSE_VISIBILITY_P from xmodule.graders import ShowCorrectness from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore - from xmodule.modulestore.tests.django_utils import ( TEST_DATA_MIXED_MODULESTORE, TEST_DATA_SPLIT_MODULESTORE, @@ -273,8 +268,8 @@ class IndexQueryTestCase(ModuleStoreTestCase): NUM_PROBLEMS = 20 @ddt.data( - (ModuleStoreEnum.Type.mongo, 10, 170), - (ModuleStoreEnum.Type.split, 4, 168), + (ModuleStoreEnum.Type.mongo, 10, 167), + (ModuleStoreEnum.Type.split, 4, 165), ) @ddt.unpack def test_index_query_counts(self, store_type, expected_mongo_query_count, expected_mysql_query_count): @@ -507,31 +502,6 @@ class ViewsTestCase(BaseViewsTestCase): self.assertEqual(response.status_code, 302) self.assertRedirects(response, '/courses/{}/about'.format(six.text_type(self.course_key))) - @unittest.skipUnless(settings.FEATURES.get('ENABLE_SHOPPING_CART'), "Shopping Cart not enabled in settings") - @patch.dict(settings.FEATURES, {'ENABLE_PAID_COURSE_REGISTRATION': True}) - def test_course_about_in_cart(self): - in_cart_span = '<span class="add-to-cart">' - # don't mock this course due to shopping cart existence checking - course = CourseFactory.create(org="new", number="unenrolled", display_name="course") - - self.client.logout() - response = self.client.get(reverse('about_course', args=[six.text_type(course.id)])) - self.assertEqual(response.status_code, 200) - self.assertNotContains(response, in_cart_span) - - # authenticated user with nothing in cart - self.assertTrue(self.client.login(username=self.user.username, password=TEST_PASSWORD)) - response = self.client.get(reverse('about_course', args=[six.text_type(course.id)])) - self.assertEqual(response.status_code, 200) - self.assertNotContains(response, in_cart_span) - - # now add the course to the cart - cart = shoppingcart.models.Order.get_cart_for_user(self.user) - shoppingcart.models.PaidCourseRegistration.add_to_order(cart, course.id) - response = self.client.get(reverse('about_course', args=[six.text_type(course.id)])) - self.assertEqual(response.status_code, 200) - self.assertContains(response, in_cart_span) - def assert_enrollment_link_present(self, is_anonymous): """ Prepare ecommerce checkout data and assert if the ecommerce link is contained in the response. @@ -568,20 +538,6 @@ class ViewsTestCase(BaseViewsTestCase): else: self.assertEqual(EcommerceService().is_enabled(AnonymousUser()), False) - @ddt.data(True, False) - @unittest.skipUnless(settings.FEATURES.get('ENABLE_SHOPPING_CART'), 'Shopping Cart not enabled in settings') - @patch.dict(settings.FEATURES, {'ENABLE_PAID_COURSE_REGISTRATION': True}) - def test_ecommerce_checkout_shopping_cart_enabled(self, is_anonymous): - """ - Two scenarios are being validated here -- authenticated/known user and unauthenticated/anonymous user - For a known user we expect the checkout link to point to Otto in a scenario where the CommerceConfiguration - is active and the course mode is PROFESSIONAL. - """ - if not is_anonymous: - self.assert_enrollment_link_present(is_anonymous=is_anonymous) - else: - self.assertEqual(EcommerceService().is_enabled(AnonymousUser()), False) - def test_user_groups(self): # deprecated function mock_user = MagicMock() @@ -734,7 +690,7 @@ class ViewsTestCase(BaseViewsTestCase): 'location': six.text_type(usage_key), }) response = self.client.get(url) - response_content = HTMLParser().unescape(response.content.decode('utf-8')) + response_content = html.unescape(response.content.decode('utf-8')) # We have update the state 4 times: twice to change content, and twice # to set the scores. We'll check that the identifying content from each is @@ -2571,34 +2527,6 @@ class TestIndexView(ModuleStoreTestCase): expected_should_show_enroll_button ) - @RELATIVE_DATES_FLAG.override(active=True) - def test_reset_deadlines_banner_is_present_when_viewing_courseware(self): - user = UserFactory() - course = CourseFactory.create(self_paced=True) - with self.store.bulk_operations(course.id): - chapter = ItemFactory.create(parent=course, category='chapter') - section = ItemFactory.create( - parent=chapter, category='sequential', - display_name="Sequence", - due=datetime.today() - timedelta(1), - ) - - CourseOverview.load_from_module_store(course.id) - CourseEnrollmentFactory(user=user, course_id=course.id, mode=CourseMode.VERIFIED) - self.client.login(username=user.username, password='test') - response = self.client.get( - reverse( - 'courseware_section', - kwargs={ - 'course_id': six.text_type(course.id), - 'chapter': chapter.url_name, - 'section': section.url_name, - } - ) + '?activate_block_id=test_block_id' - ) - - self.assertContains(response, '<div class="reset-deadlines-banner">') - @ddt.ddt class TestIndexViewCompleteOnView(ModuleStoreTestCase, CompletionWaffleTestMixin): @@ -3148,9 +3076,10 @@ class DatesTabTestCase(ModuleStoreTestCase): super(DatesTabTestCase, self).setUp() now = datetime.now(utc) - self.course = CourseFactory.create(start=now + timedelta(days=-1)) + self.course = CourseFactory.create(start=now + timedelta(days=-1), self_paced=True) self.course.end = now + timedelta(days=3) + ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1)) CourseModeFactory(course_id=self.course.id, mode_slug=CourseMode.AUDIT) CourseModeFactory( course_id=self.course.id, @@ -3164,6 +3093,7 @@ class DatesTabTestCase(ModuleStoreTestCase): self.user = UserFactory() self.client.login(username=self.user.username, password=TEST_PASSWORD) + ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2017, 1, 1)) def _get_response(self, course): """ Returns the HTML for the progress page """ @@ -3181,55 +3111,71 @@ class DatesTabTestCase(ModuleStoreTestCase): display_name='Released', parent_location=section.location, start=now - timedelta(days=1), - due=now, # Setting this today so it'll show the 'Due Today' pill + due=now + timedelta(days=1), # Setting this to tomorrow so it'll show the 'Due Next' pill graded=True, + format='Homework', ) + vertical = ItemFactory.create(category='vertical', parent_location=subsection.location) + ItemFactory.create(category='problem', parent_location=vertical.location) - with patch('lms.djangoapps.courseware.courses.get_dates_for_course') as mock_get_dates: - with patch('lms.djangoapps.courseware.views.views.get_enrollment') as mock_get_enrollment: - mock_get_dates.return_value = { - (subsection.location, 'due'): subsection.due, - (subsection.location, 'start'): subsection.start, - } - mock_get_enrollment.return_value = { - 'mode': enrollment.mode - } - response = self._get_response(self.course) - self.assertContains(response, subsection.display_name) - # Show the Verification Deadline for everyone - self.assertContains(response, 'Verification Deadline') - # Make sure pill exists for assignment due today - self.assertContains(response, '<div class="pill due">') - # No pills for verified enrollments - self.assertNotContains(response, '<div class="pill verified">') - - enrollment.delete() - subsection.due = now + timedelta(days=1) - enrollment = CourseEnrollmentFactory(course_id=self.course.id, user=self.user, mode=CourseMode.AUDIT) - mock_get_dates.return_value = { - (subsection.location, 'due'): subsection.due, - (subsection.location, 'start'): subsection.start, - } - mock_get_enrollment.return_value = { - 'mode': enrollment.mode - } + with patch('lms.djangoapps.courseware.views.views.get_enrollment') as mock_get_enrollment: + mock_get_enrollment.return_value = { + 'mode': enrollment.mode + } + response = self._get_response(self.course) + self.assertContains(response, subsection.display_name) + # Show the Verification Deadline for verified only + self.assertContains(response, 'Verification Deadline') + # Make sure pill exists for today's date + self.assertContains(response, '<div class="pill today">') + # Make sure pill exists for next due assignment + self.assertContains(response, '<div class="pill due-next">') + # No pills for verified enrollments + self.assertNotContains(response, '<div class="pill verified">') + # Make sure the assignment type is rendered + self.assertContains(response, 'Homework:') + + enrollment.delete() + enrollment = CourseEnrollmentFactory(course_id=self.course.id, user=self.user, mode=CourseMode.AUDIT) + mock_get_enrollment.return_value = { + 'mode': enrollment.mode + } - expected_calls = [ - call('course_id', text_type(self.course.id)), - call('user_id', self.user.id), - call('is_staff', self.user.is_staff), - ] - - response = self._get_response(self.course) - - mock_set_custom_metric.assert_has_calls(expected_calls, any_order=True) - self.assertContains(response, subsection.display_name) - # Show the Verification Deadline for everyone - self.assertContains(response, 'Verification Deadline') - # Pill doesn't exist for assignment due tomorrow - self.assertNotContains(response, '<div class="pill due">') - # Should have verified pills for audit enrollments - self.assertContains(response, '<div class="pill verified">') + expected_calls = [ + call('course_id', text_type(self.course.id)), + call('user_id', self.user.id), + call('is_staff', self.user.is_staff), + ] + + response = self._get_response(self.course) + + mock_set_custom_metric.assert_has_calls(expected_calls, any_order=True) + self.assertContains(response, subsection.display_name) + # Don't show the Verification Deadline for audit + self.assertNotContains(response, 'Verification Deadline') + # Pill doesn't exist for assignment due tomorrow + self.assertNotContains(response, '<div class="pill due-next">') + # Should have verified pills for audit enrollments + self.assertContains(response, '<div class="pill verified">') + # Make sure the assignment type is rendered + self.assertContains(response, 'Homework:') + + @RELATIVE_DATES_FLAG.override(active=True) + def test_reset_deadlines_banner_displays(self): + CourseEnrollmentFactory(course_id=self.course.id, user=self.user, mode=CourseMode.VERIFIED) + now = datetime.now(utc) + with self.store.bulk_operations(self.course.id): + section = ItemFactory.create(category='chapter', parent_location=self.course.location) + ItemFactory.create( + category='sequential', + display_name='Released', + parent_location=section.location, + start=now - timedelta(days=1), + due=now - timedelta(days=1), # Setting this to tomorrow so it'll show the 'Due Next' pill + graded=True, + ) + response = self._get_response(self.course) + self.assertContains(response, 'div class="dates-banner-text"') class TestShowCoursewareMFE(TestCase): diff --git a/lms/djangoapps/courseware/testutils.py b/lms/djangoapps/courseware/testutils.py index b4a2f371d0c09eb760e1e8e7fc8f2b23fc308b2b..a7613585eb26220d2979efe060abb3444d2b25f3 100644 --- a/lms/djangoapps/courseware/testutils.py +++ b/lms/djangoapps/courseware/testutils.py @@ -9,7 +9,7 @@ from datetime import datetime, timedelta import ddt import six from mock import patch -from six.moves.urllib.parse import urlencode # pylint: disable=import-error +from six.moves.urllib.parse import urlencode from lms.djangoapps.courseware.field_overrides import OverrideModulestoreFieldData from lms.djangoapps.courseware.url_helpers import get_redirect_url diff --git a/lms/djangoapps/courseware/url_helpers.py b/lms/djangoapps/courseware/url_helpers.py index eb0e06fd79f5b1f4cc5e45b0decfa95f1c83406d..ed5c358a611474fc48e5843123db55fc3d456e1d 100644 --- a/lms/djangoapps/courseware/url_helpers.py +++ b/lms/djangoapps/courseware/url_helpers.py @@ -6,7 +6,7 @@ Module to define url helpers functions import six from django.conf import settings from django.urls import reverse -from six.moves.urllib.parse import urlencode # pylint: disable=import-error +from six.moves.urllib.parse import urlencode from xmodule.modulestore.django import modulestore from xmodule.modulestore.search import navigation_index, path_to_location diff --git a/lms/djangoapps/courseware/utils.py b/lms/djangoapps/courseware/utils.py index a378ace954fb2af9f46e4ce168ebeb672802d4e7..983b321e4a67b16dc9f9951c0602d958e92642c2 100644 --- a/lms/djangoapps/courseware/utils.py +++ b/lms/djangoapps/courseware/utils.py @@ -3,10 +3,13 @@ import datetime +from django.conf import settings from lms.djangoapps.commerce.utils import EcommerceService from pytz import utc from course_modes.models import CourseMode +from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID +from xmodule.partitions.partitions_service import PartitionService def verified_upgrade_deadline_link(user, course=None, course_id=None): @@ -32,17 +35,38 @@ def verified_upgrade_deadline_link(user, course=None, course_id=None): return EcommerceService().upgrade_url(user, course_id) -def verified_upgrade_link_is_valid(enrollment=None): +def can_show_verified_upgrade(user, enrollment, course=None): """ - Return whether this enrollment can be upgraded. + Return whether this user can be shown upgrade message. Arguments: + user (:class:`.AuthUser`): The user from the request.user property enrollment (:class:`.CourseEnrollment`): The enrollment under consideration. If None, then the enrollment is considered to be upgradeable. + course (:class:`.ModulestoreCourse`): Optional passed in modulestore course. + If provided, it is expected to correspond to `enrollment.course.id`. + If not provided, the course will be loaded from the modulestore. + We use the course to retrieve user partitions when calculating whether + the upgrade link will be shown. """ # Return `true` if user is not enrolled in course if enrollment is None: return False + partition_service = PartitionService(enrollment.course.id, course=course) + enrollment_track_partition = partition_service.get_user_partition(ENROLLMENT_TRACK_PARTITION_ID) + group = partition_service.get_group(user, enrollment_track_partition) + current_mode = None + if group: + try: + current_mode = [ + mode.get('slug') for mode in settings.COURSE_ENROLLMENT_MODES.values() if mode['id'] == group.id + ].pop() + except IndexError: + pass + upgradable_mode = not current_mode or current_mode in CourseMode.UPSELL_TO_VERIFIED_MODES + + if not upgradable_mode: + return False upgrade_deadline = enrollment.upgrade_deadline diff --git a/lms/djangoapps/courseware/views/index.py b/lms/djangoapps/courseware/views/index.py index 123e63368be7c264a7f00807d25e27bf150e9e62..d13fdd3c9dc8b5b46afae4dc80dc5644c65635cf 100644 --- a/lms/djangoapps/courseware/views/index.py +++ b/lms/djangoapps/courseware/views/index.py @@ -8,12 +8,8 @@ View for Courseware Index import logging import six -import six.moves.urllib as urllib # pylint: disable=import-error -import six.moves.urllib.error # pylint: disable=import-error -import six.moves.urllib.parse # pylint: disable=import-error -import six.moves.urllib.request # pylint: disable=import-error +from six.moves import urllib from django.conf import settings -from django.contrib.auth.models import User from django.contrib.auth.views import redirect_to_login from django.db import transaction from django.http import Http404 @@ -49,12 +45,9 @@ from openedx.features.course_experience import ( RELATIVE_DATES_FLAG, ) from openedx.features.course_experience.urls import COURSE_HOME_VIEW_NAME -from openedx.features.course_experience.utils import reset_deadlines_banner_should_display from openedx.features.course_experience.views.course_sock import CourseSockFragmentView from openedx.features.enterprise_support.api import data_sharing_consent_required -from shoppingcart.models import CourseRegistrationCode from student.models import CourseEnrollment -from student.views import is_course_blocked from util.views import ensure_valid_course_key from xmodule.course_module import COURSE_VISIBILITY_PUBLIC from xmodule.modulestore.django import modulestore @@ -188,7 +181,7 @@ class CoursewareIndex(View): # Set the user in the request to the effective user. self.request.user = self.effective_user - def _redirect_to_learning_mfe(self, request): + def _redirect_to_learning_mfe(self): """ Redirect to the new courseware micro frontend, unless this is a time limited exam. @@ -203,17 +196,33 @@ class CoursewareIndex(View): if self.is_staff: return - url = get_microfrontend_url( - self.course_key, - self.section.location - ) - raise Redirect(url) + raise Redirect(self.microfrontend_url) + + @property + def microfrontend_url(self): + """ + Return absolute URL to this section in the courseware micro-frontend. + """ + try: + unit_key = UsageKey.from_string(self.request.GET.get('activate_block_id', '')) + # `activate_block_id` is typically a Unit (a.k.a. Vertical), + # but it can technically be any block type. Do a check to + # make sure it's really a Unit before we use it for the MFE. + if unit_key.block_type != 'vertical': + unit_key = None + except InvalidKeyError: + unit_key = None + url = get_microfrontend_url( + self.course_key, + self.section.location if self.section else None, + unit_key + ) + return url def render(self, request): """ Render the index page. """ - self._redirect_if_needed_to_pay_for_course() self._prefetch_and_bind_course(request) if self.course.has_children_at_depth(CONTENT_DEPTH): @@ -225,7 +234,7 @@ class CoursewareIndex(View): self._redirect_if_not_requested_section() self._save_positions() self._prefetch_and_bind_section() - self._redirect_to_learning_mfe(request) + self._redirect_to_learning_mfe() check_content_start_date_for_masquerade_user(self.course_key, self.effective_user, request, self.course.start, self.chapter.start, self.section.start) @@ -289,31 +298,6 @@ class CoursewareIndex(View): except ValueError: raise Http404(u"Position {} is not an integer!".format(self.position)) - def _redirect_if_needed_to_pay_for_course(self): - """ - Redirect to dashboard if the course is blocked due to non-payment. - """ - redeemed_registration_codes = [] - - if self.request.user.is_authenticated: - self.real_user = User.objects.prefetch_related("groups").get(id=self.real_user.id) - redeemed_registration_codes = CourseRegistrationCode.objects.filter( - course_id=self.course_key, - registrationcoderedemption__redeemed_by=self.real_user - ) - - if is_course_blocked(self.request, redeemed_registration_codes, self.course_key): - # registration codes may be generated via Bulk Purchase Scenario - # we have to check only for the invoice generated registration codes - # that their invoice is valid or not - # TODO Update message to account for the fact that the user is not authenticated. - log.warning( - u'User %s cannot access the course %s because payment has not yet been received', - self.real_user, - six.text_type(self.course_key), - ) - raise CourseAccessRedirect(reverse('dashboard')) - def _reset_section_to_exam_if_required(self): """ Check to see if an Entrance Exam is required for the user. @@ -439,7 +423,6 @@ class CoursewareIndex(View): Returns and creates the rendering context for the courseware. Also returns the table of contents for the courseware. """ - from lms.urls import RESET_COURSE_DEADLINES_NAME course_url_name = default_course_url_name(self.course.id) course_url = reverse(course_url_name, kwargs={'course_id': six.text_type(self.course.id)}) @@ -449,15 +432,6 @@ class CoursewareIndex(View): ) staff_access = self.is_staff - allow_anonymous = check_public_access(self.course, [COURSE_VISIBILITY_PUBLIC]) - display_reset_dates_banner = False - if not allow_anonymous and RELATIVE_DATES_FLAG.is_enabled(self.course.id): - display_reset_dates_banner = reset_deadlines_banner_should_display(self.course_key, request) - - reset_deadlines_url = reverse(RESET_COURSE_DEADLINES_NAME) if display_reset_dates_banner else None - - reset_deadlines_redirect_url_base = COURSE_HOME_VIEW_NAME if reset_deadlines_url else None - courseware_context = { 'csrf': csrf(self.request)['csrf_token'], 'course': self.course, @@ -479,11 +453,6 @@ class CoursewareIndex(View): 'sequence_title': None, 'disable_accordion': COURSE_OUTLINE_PAGE_FLAG.is_enabled(self.course.id), 'show_search': show_search, - 'relative_dates_is_enabled': RELATIVE_DATES_FLAG.is_enabled(self.course.id), - 'display_reset_dates_banner': display_reset_dates_banner, - 'reset_deadlines_url': reset_deadlines_url, - 'reset_deadlines_redirect_url_base': reset_deadlines_redirect_url_base, - 'reset_deadlines_redirect_url_id_dict': {'course_id': str(self.course.id)}, } courseware_context.update( get_experiment_user_metadata_context( @@ -506,7 +475,7 @@ class CoursewareIndex(View): ) courseware_context['course_sock_fragment'] = CourseSockFragmentView().render_to_fragment( - request, course=self.course_overview) + request, course=self.course) # entrance exam data self._add_entrance_exam_to_context(courseware_context) @@ -537,22 +506,7 @@ class CoursewareIndex(View): # Courseware MFE link if show_courseware_mfe_link(request.user, staff_access, self.course.id): - if self.section: - try: - unit_key = UsageKey.from_string(request.GET.get('activate_block_id', '')) - # `activate_block_id` is typically a Unit (a.k.a. Vertical), - # but it can technically be any block type. Do a check to - # make sure it's really a Unit before we use it for the MFE. - if unit_key.block_type != 'vertical': - unit_key = None - except InvalidKeyError: - unit_key = None - - courseware_context['microfrontend_link'] = get_microfrontend_url( - self.course.id, self.section.location, unit_key - ) - else: - courseware_context['microfrontend_link'] = get_microfrontend_url(self.course.id) + courseware_context['microfrontend_link'] = self.microfrontend_url else: courseware_context['microfrontend_link'] = None diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 421fe1afb8676cfb1d5a1947bec71e593e225ad6..1e868140555361240c1750d292d7120e7648b296 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -5,15 +5,12 @@ Courseware views functions import json import logging -import requests -from requests.exceptions import Timeout, ConnectionError from collections import OrderedDict, namedtuple from datetime import datetime import bleach -import six.moves.urllib.error # pylint: disable=import-error -import six.moves.urllib.parse # pylint: disable=import-error -import six.moves.urllib.request # pylint: disable=import-error +import requests +import six from django.conf import settings from django.contrib.auth.decorators import login_required from django.contrib.auth.models import AnonymousUser, User @@ -30,6 +27,7 @@ from django.utils.http import urlquote_plus from django.utils.text import slugify from django.utils.translation import ugettext from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import ugettext_noop from django.views.decorators.cache import cache_control from django.views.decorators.clickjacking import xframe_options_exempt from django.views.decorators.csrf import ensure_csrf_cookie @@ -37,12 +35,12 @@ from django.views.decorators.http import require_GET, require_http_methods, requ from django.views.generic import View from edx_django_utils import monitoring as monitoring_utils from edx_django_utils.monitoring import set_custom_metrics_for_course_key -from edxnotes.helpers import is_feature_enabled from ipware.ip import get_ip from markupsafe import escape from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey, UsageKey from pytz import UTC +from requests.exceptions import ConnectionError, Timeout # pylint: disable=redefined-builtin from rest_framework import status from rest_framework.decorators import api_view, throttle_classes from rest_framework.response import Response @@ -50,11 +48,16 @@ from rest_framework.throttling import UserRateThrottle from six import text_type from web_fragments.fragment import Fragment -import shoppingcart import survey.views from course_modes.models import CourseMode, get_course_prices +from edxmako.shortcuts import marketing_link, render_to_response, render_to_string +from edxnotes.helpers import is_feature_enabled +from lms.djangoapps.ccx.custom_exception import CCXLocatorValidationException +from lms.djangoapps.certificates import api as certs_api +from lms.djangoapps.certificates.models import CertificateStatuses +from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.courseware.access import has_access, has_ccx_coach_role -from lms.djangoapps.courseware.access_utils import check_course_open_for_learner +from lms.djangoapps.courseware.access_utils import check_course_open_for_learner, check_public_access from lms.djangoapps.courseware.courses import ( can_self_enroll_in_course, course_open_for_self_enrollment, @@ -70,21 +73,18 @@ from lms.djangoapps.courseware.courses import ( sort_by_start_date ) from lms.djangoapps.courseware.date_summary import verified_upgrade_deadline_link +from lms.djangoapps.courseware.exceptions import CourseAccessRedirect, Redirect from lms.djangoapps.courseware.masquerade import setup_masquerade from lms.djangoapps.courseware.model_data import FieldDataCache from lms.djangoapps.courseware.models import BaseStudentModuleHistory, StudentModule from lms.djangoapps.courseware.permissions import ( - MASQUERADE_AS_STUDENT, VIEW_COURSE_HOME, VIEW_COURSEWARE, VIEW_XQA_INTERFACE, + MASQUERADE_AS_STUDENT, + VIEW_COURSE_HOME, + VIEW_COURSEWARE, + VIEW_XQA_INTERFACE ) from lms.djangoapps.courseware.url_helpers import get_redirect_url from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateClient -from edxmako.shortcuts import marketing_link, render_to_response, render_to_string -from lms.djangoapps.ccx.custom_exception import CCXLocatorValidationException -from lms.djangoapps.certificates import api as certs_api -from lms.djangoapps.certificates.models import CertificateStatuses -from lms.djangoapps.commerce.utils import EcommerceService -from lms.djangoapps.courseware.access_utils import check_public_access -from lms.djangoapps.courseware.exceptions import CourseAccessRedirect, Redirect from lms.djangoapps.experiments.utils import get_experiment_user_metadata_context from lms.djangoapps.grades.api import CourseGradeFactory from lms.djangoapps.instructor.enrollment import uses_shib @@ -108,20 +108,21 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_ from openedx.core.djangoapps.util.user_messages import PageLevelMessages from openedx.core.djangoapps.zendesk_proxy.utils import create_zendesk_ticket from openedx.core.djangolib.markup import HTML, Text +from openedx.core.lib.mobile_utils import is_request_from_mobile_app +from openedx.features.content_type_gating.models import ContentTypeGatingConfig from openedx.features.course_duration_limits.access import generate_course_expired_fragment from openedx.features.course_experience import ( COURSE_ENABLE_UNENROLLED_ACCESS_FLAG, - UNIFIED_COURSE_TAB_FLAG, - course_home_url_name, RELATIVE_DATES_FLAG, + UNIFIED_COURSE_TAB_FLAG, + course_home_url_name ) from openedx.features.course_experience.course_tools import CourseToolsPluginManager -from openedx.features.course_experience.utils import reset_deadlines_banner_should_display +from openedx.features.course_experience.utils import dates_banner_should_display from openedx.features.course_experience.views.course_dates import CourseDatesFragmentView from openedx.features.course_experience.waffle import ENABLE_COURSE_ABOUT_SIDEBAR_HTML from openedx.features.course_experience.waffle import waffle as course_experience_waffle from openedx.features.enterprise_support.api import data_sharing_consent_required -from shoppingcart.utils import is_shopping_cart_enabled from student.models import CourseEnrollment, UserTestGroup from track import segment from util.cache import cache, cache_if_anonymous @@ -289,11 +290,11 @@ def yt_video_metadata(request): :return: youtube video metadata """ video_id = request.GET.get('id', None) - metadata, status_code = load_metadata_from_youtube(video_id) + metadata, status_code = load_metadata_from_youtube(video_id, request) return Response(metadata, status=status_code, content_type='application/json') -def load_metadata_from_youtube(video_id): +def load_metadata_from_youtube(video_id, request): """ Get metadata about a YouTube video. @@ -306,9 +307,24 @@ def load_metadata_from_youtube(video_id): yt_api_key = settings.YOUTUBE_API_KEY yt_metadata_url = settings.YOUTUBE['METADATA_URL'] yt_timeout = settings.YOUTUBE.get('TEST_TIMEOUT', 1500) / 1000 # converting milli seconds to seconds + + headers = {} + http_referer = None + + try: + # This raises an attribute error if called from the xblock yt_video_metadata handler, which passes + # a webob request instead of a django request. + http_referer = request.META.get('HTTP_REFERER') + except AttributeError: + # So here, let's assume it's a webob request and access the referer the webob way. + http_referer = request.referer + + if http_referer: + headers['Referer'] = http_referer + payload = {'id': video_id, 'part': 'contentDetails', 'key': yt_api_key} try: - res = requests.get(yt_metadata_url, params=payload, timeout=yt_timeout) + res = requests.get(yt_metadata_url, params=payload, timeout=yt_timeout, headers=headers) status_code = res.status_code if res.status_code == 200: try: @@ -736,19 +752,6 @@ class CourseTabView(EdxFragmentView): else: masquerade = None - display_reset_dates_banner = False - if RELATIVE_DATES_FLAG.is_enabled(course.id): - course_overview = CourseOverview.get_from_id(course.id) - end_date = getattr(course_overview, 'end_date', None) - if (not end_date or timezone.now() < end_date and CourseEnrollment.objects.filter( - course=course_overview, user=request.user, mode=CourseMode.VERIFIED - ).exists()): - display_reset_dates_banner = True - - reset_deadlines_url = reverse(RESET_COURSE_DEADLINES_NAME) if display_reset_dates_banner else None - - reset_deadlines_redirect_url_base = COURSE_HOME_VIEW_NAME if reset_deadlines_url else None - context = { 'course': course, 'tab': tab, @@ -759,10 +762,6 @@ class CourseTabView(EdxFragmentView): 'uses_bootstrap': uses_bootstrap, 'uses_pattern_library': not uses_bootstrap, 'disable_courseware_js': True, - 'display_reset_dates_banner': display_reset_dates_banner, - 'reset_deadlines_url': reset_deadlines_url, - 'reset_deadlines_redirect_url_base': reset_deadlines_redirect_url_base, - 'reset_deadlines_redirect_url_id_dict': {'course_id': str(course.id)} } # Avoid Multiple Mathjax loading on the 'user_profile' if 'profile_page_context' in kwargs: @@ -866,7 +865,7 @@ class EnrollStaffView(View): Either enrolls the user in course or redirects user to course about page depending upon the option (Enroll, Don't Enroll) chosen by the user. """ - _next = six.moves.urllib.parse.quote_plus(request.GET.get('next', 'info'), safe='/:?=') # pylint: disable=redundant-keyword-arg + _next = six.moves.urllib.parse.quote_plus(request.GET.get('next', 'info'), safe='/:?=') course_key = CourseKey.from_string(course_id) enroll = 'enroll' in request.POST if enroll: @@ -921,21 +920,6 @@ def course_about(request, course_id): ) or settings.FEATURES.get('ENABLE_LMS_MIGRATION') ) - # Note: this is a flow for payment for course registration, not the Verified Certificate flow. - in_cart = False - reg_then_add_to_cart_link = "" - - _is_shopping_cart_enabled = is_shopping_cart_enabled() - if _is_shopping_cart_enabled: - if request.user.is_authenticated: - cart = shoppingcart.models.Order.get_cart_for_user(request.user) - in_cart = shoppingcart.models.PaidCourseRegistration.contained_in_order(cart, course_key) or \ - shoppingcart.models.CourseRegCodeItem.contained_in_order(cart, course_key) - - reg_then_add_to_cart_link = "{reg_url}?course_id={course_id}&enrollment_action=add_to_cart".format( - reg_url=reverse('register_user'), course_id=six.moves.urllib.parse.quote(str(course_id)) - ) - # If the ecommerce checkout flow is enabled and the mode of the course is # professional or no id professional, we construct links for the enrollment # button to add the course to the ecommerce basket. @@ -958,9 +942,6 @@ def course_about(request, course_id): registration_price, course_price = get_course_prices(course) - # Determine which checkout workflow to use -- LMS shoppingcart or Otto basket - can_add_course_to_cart = _is_shopping_cart_enabled and registration_price and not ecommerce_checkout_link - # Used to provide context to message to student if enrollment not allowed can_enroll = bool(request.user.has_perm(ENROLL_IN_COURSE, course)) invitation_only = course.invitation_only @@ -1001,12 +982,10 @@ def course_about(request, course_id): 'course_target': course_target, 'is_cosmetic_price_enabled': settings.FEATURES.get('ENABLE_COSMETIC_DISPLAY_PRICE'), 'course_price': course_price, - 'in_cart': in_cart, 'ecommerce_checkout': ecommerce_checkout, 'ecommerce_checkout_link': ecommerce_checkout_link, 'ecommerce_bulk_checkout_link': ecommerce_bulk_checkout_link, 'single_paid_mode': single_paid_mode, - 'reg_then_add_to_cart_link': reg_then_add_to_cart_link, 'show_courseware_link': show_courseware_link, 'is_course_full': is_course_full, 'can_enroll': can_enroll, @@ -1016,8 +995,6 @@ def course_about(request, course_id): # We do not want to display the internal courseware header, which is used when the course is found in the # context. This value is therefor explicitly set to render the appropriate header. 'disable_courseware_header': True, - 'can_add_course_to_cart': can_add_course_to_cart, - 'cart_link': reverse('shoppingcart.views.show_cart'), 'pre_requisite_courses': pre_requisite_courses, 'course_image_urls': overview.image_urls, 'reviews_fragment_view': reviews_fragment_view, @@ -1061,6 +1038,8 @@ def dates(request, course_id): Display the course's dates.html, or 404 if there is no such course. Assumes the course_id is in a valid format. """ + from lms.urls import COURSE_DATES_NAME, RESET_COURSE_DEADLINES_NAME + course_key = CourseKey.from_string(course_id) # Enable NR tracing for this view based on course @@ -1069,26 +1048,51 @@ def dates(request, course_id): monitoring_utils.set_custom_metric('is_staff', request.user.is_staff) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) + + masquerade = None + can_masquerade = request.user.has_perm(MASQUERADE_AS_STUDENT, course) + if can_masquerade: + masquerade, masquerade_user = setup_masquerade( + request, + course.id, + can_masquerade, + reset_masquerade_data=True, + ) + request.user = masquerade_user + course_date_blocks = get_course_date_blocks(course, request.user, request, include_access=True, include_past_dates=True) - enrollment = get_enrollment(request.user.username, course_id) - learner_is_verified = False + + learner_is_full_access = not ContentTypeGatingConfig.enabled_for_enrollment(request.user, course_key) # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] user_language = user_timezone_locale['user_language'] - if enrollment: - learner_is_verified = enrollment.get('mode') == 'verified' + missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, request.user) context = { 'course': course, - 'course_date_blocks': [block for block in course_date_blocks if block.title != 'current_datetime'], + 'course_date_blocks': course_date_blocks, 'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course), - 'learner_is_verified': learner_is_verified, + 'learner_is_full_access': learner_is_full_access, 'user_timezone': user_timezone, 'user_language': user_language, + 'supports_preview_menu': True, + 'can_masquerade': can_masquerade, + 'masquerade': masquerade, + 'on_dates_tab': True, + 'content_type_gating_enabled': ContentTypeGatingConfig.enabled_for_enrollment( + user=request.user, + course_key=course_key, + ), + 'missed_deadlines': missed_deadlines, + 'missed_gated_content': missed_gated_content, + 'reset_deadlines_url': reverse(RESET_COURSE_DEADLINES_NAME), + 'reset_deadlines_redirect_url_base': COURSE_DATES_NAME, + 'reset_deadlines_redirect_url_id_dict': {'course_id': str(course.id)}, + 'has_ended': course.has_ended(), } return render_to_response('courseware/dates.html', context) @@ -1632,7 +1636,7 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True): Returns an HttpResponse with HTML content for the xBlock with the given usage_key. The returned HTML is a chromeless rendering of the xBlock (excluding content of the containing courseware). """ - from lms.urls import RENDER_XBLOCK_NAME, RESET_COURSE_DEADLINES_NAME + from lms.urls import COURSE_DATES_NAME, RESET_COURSE_DEADLINES_NAME from openedx.features.course_experience.urls import COURSE_HOME_VIEW_NAME usage_key = UsageKey.from_string(usage_key_string) @@ -1671,9 +1675,7 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True): 'mark-completed-on-view-after-delay': completion_service.get_complete_on_view_delay_ms() } - display_reset_dates_banner = False - if RELATIVE_DATES_FLAG.is_enabled(course.id): - display_reset_dates_banner = reset_deadlines_banner_should_display(course_key, request) + missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, request.user) context = { 'fragment': block.render('student_view', context=student_view_context), @@ -1687,9 +1689,17 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True): 'edx_notes_enabled': is_feature_enabled(course, request.user), 'staff_access': bool(request.user.has_perm(VIEW_XQA_INTERFACE, course)), 'xqa_server': settings.FEATURES.get('XQA_SERVER', 'http://your_xqa_server.com'), - 'display_reset_dates_banner': display_reset_dates_banner, + 'missed_deadlines': missed_deadlines, + 'missed_gated_content': missed_gated_content, + 'has_ended': course.has_ended(), 'web_app_course_url': reverse(COURSE_HOME_VIEW_NAME, args=[course.id]), + 'on_courseware_page': True, + 'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course), 'is_learning_mfe': request.META.get('HTTP_REFERER', '').startswith(settings.LEARNING_MICROFRONTEND_URL), + 'is_mobile_app': is_request_from_mobile_app(request), + 'reset_deadlines_url': reverse(RESET_COURSE_DEADLINES_NAME), + 'reset_deadlines_redirect_url_base': COURSE_DATES_NAME, + 'reset_deadlines_redirect_url_id_dict': {'course_id': str(course.id)} } return render_to_response('courseware/courseware-chromeless.html', context) @@ -1704,19 +1714,20 @@ FINANCIAL_ASSISTANCE_HEADER = _( ' Note that you must complete a separate application for each course you take.\n We plan to use this' ' information to evaluate your application for financial assistance and to further develop our' ' financial assistance program.' -).format( - percent_sign="%", - platform_name=configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) -).split('\n') +) + + +def _get_fa_header(header): + return header.\ + format(percent_sign="%", + platform_name=configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME)).split('\n') -FA_INCOME_LABEL = _('Annual Household Income') -FA_REASON_FOR_APPLYING_LABEL = 'Tell us about your current financial situation. Why do you need assistance?' -FA_GOALS_LABEL = 'Tell us about your learning or professional goals. How will a Verified Certificate in ' \ - 'this course help you achieve these goals?' +FA_INCOME_LABEL = ugettext_noop('Annual Household Income') +FA_REASON_FOR_APPLYING_LABEL = ugettext_noop('Tell us about your current financial situation. Why do you need assistance?') +FA_GOALS_LABEL = ugettext_noop('Tell us about your learning or professional goals. How will a Verified Certificate in this course help you achieve these goals?') -FA_EFFORT_LABEL = 'Tell us about your plans for this course. What steps will you take to help you complete ' \ - 'the course work and receive a certificate?' +FA_EFFORT_LABEL = ugettext_noop('Tell us about your plans for this course. What steps will you take to help you complete the course work and receive a certificate?') FA_SHORT_ANSWER_INSTRUCTIONS = _('Use between 1250 and 2500 characters or so in your response.') @@ -1725,7 +1736,7 @@ FA_SHORT_ANSWER_INSTRUCTIONS = _('Use between 1250 and 2500 characters or so in def financial_assistance(_request): """Render the initial financial assistance page.""" return render_to_response('financial-assistance/financial-assistance.html', { - 'header_text': FINANCIAL_ASSISTANCE_HEADER + 'header_text': _get_fa_header(FINANCIAL_ASSISTANCE_HEADER) }) @@ -1779,7 +1790,7 @@ def financial_assistance_request(request): ('Username', username), ('Full Name', legal_name), ('Course ID', course_id), - ('Annual Household Income', income), + (FA_INCOME_LABEL, income), ('Country', country), ('Allowed for marketing purposes', 'Yes' if marketing_permission else 'No'), (FA_REASON_FOR_APPLYING_LABEL, '\n' + reason_for_applying + '\n\n'), @@ -1810,7 +1821,7 @@ def financial_assistance_form(request): {'name': _(income), 'value': income} for income in incomes ] return render_to_response('financial-assistance/apply.html', { - 'header_text': FINANCIAL_ASSISTANCE_HEADER, + 'header_text': _get_fa_header(FINANCIAL_ASSISTANCE_HEADER), 'student_faq_url': marketing_link('FAQ'), 'dashboard_url': reverse('dashboard'), 'account_settings_url': reverse('account_settings'), @@ -1840,7 +1851,7 @@ def financial_assistance_form(request): { 'name': 'income', 'type': 'select', - 'label': FA_INCOME_LABEL, + 'label': _(FA_INCOME_LABEL), 'placeholder': '', 'defaultValue': '', 'required': True, @@ -1850,7 +1861,7 @@ def financial_assistance_form(request): { 'name': 'reason_for_applying', 'type': 'textarea', - 'label': _(FA_REASON_FOR_APPLYING_LABEL), # pylint: disable=translation-of-non-string + 'label': _(FA_REASON_FOR_APPLYING_LABEL), 'placeholder': '', 'defaultValue': '', 'required': True, @@ -1863,7 +1874,7 @@ def financial_assistance_form(request): { 'name': 'goals', 'type': 'textarea', - 'label': _(FA_GOALS_LABEL), # pylint: disable=translation-of-non-string + 'label': _(FA_GOALS_LABEL), 'placeholder': '', 'defaultValue': '', 'required': True, @@ -1876,7 +1887,7 @@ def financial_assistance_form(request): { 'name': 'effort', 'type': 'textarea', - 'label': _(FA_EFFORT_LABEL), # pylint: disable=translation-of-non-string + 'label': _(FA_EFFORT_LABEL), 'placeholder': '', 'defaultValue': '', 'required': True, diff --git a/lms/djangoapps/dashboard/decisions/0001-sysadmin-dashboard.rst b/lms/djangoapps/dashboard/decisions/0001-sysadmin-dashboard.rst new file mode 100644 index 0000000000000000000000000000000000000000..a8e76e09d47666d814a2208fed10f4804e221074 --- /dev/null +++ b/lms/djangoapps/dashboard/decisions/0001-sysadmin-dashboard.rst @@ -0,0 +1,46 @@ +1. Sysadmin Dashboard +--------------------- + +Status +------ + +Accepted + +Context +------- +When operating an Open edX installation, it is convenient to allow admins and course staff to perform some tasks from +the web browser instead of requiring access to django managment commands. These tasks include + +- creating user accounts +- importing courses (from git) +- deleting courses +- gathering cross-course enrollment data + +The SysAdmin Dashboard feature has remained functionally unchanged since 2015, but it has never been documented. +This ADR serves to captures the decisions that went into it, so that we may being the process of moving it out of +edx-platofrm and into a pluggable django app. + +Decision +-------- + +The users tab provides Web based user management (create and delete user accounts), a listing of courses loaded, +and user statistics. There is also a button to repair the external authentication map, a task relevant to open +edX installations using Shibboleth and certificate-based authentication. + +The courses tabs manages adding/updating courses from git, deleting courses, and provides course listing information, +including commit hash, date and author for course imported from git. + +The Staffing tab provides a view of staffing and enrollment in courses that include an option to download the data +as a csv. + +The Gitlogs tab provides a view into the import log of courses from git repositories. It is convenient for allowing +course teams to see what may be wrong wit their xml. This is the only view that allows permits access by course +staff, so they can review their own course import logs. + +Consequences +------------ + +The Sysadmin dashboard is little used outside of MIT and difficult to maintain. Many of its features have been +replicated elsewhere in edx-platform. It coudld be refactored as a pluggable app, but some of it's features rely on +internal edX APIs. In a subsequent ADR, we will identify the APIs that would be necessary for extracting the Sysadmin +Dashboard. diff --git a/lms/djangoapps/dashboard/git_import.py b/lms/djangoapps/dashboard/git_import.py index 59ceee1d24f68e351b293b0ee457ecaa67469f58..547e645dc525a20f419c542ec9fb285f24fed74e 100644 --- a/lms/djangoapps/dashboard/git_import.py +++ b/lms/djangoapps/dashboard/git_import.py @@ -335,7 +335,7 @@ def add_repo(repo, rdir_in, branch=None): mdb = mongoengine.connect(mongo_db['db'], host=mongouri) else: mdb = mongoengine.connect(mongo_db['db'], host=mongo_db['host'], port=mongo_db['port']) - except mongoengine.connection.ConnectionError: + except mongoengine.connection.ConnectionFailure: log.exception('Unable to connect to mongodb to save log, please ' 'check MONGODB_LOG settings') cil = CourseImportLog( diff --git a/lms/djangoapps/dashboard/tests/test_sysadmin.py b/lms/djangoapps/dashboard/tests/test_sysadmin.py index 4f42623eb272d2d4fad02e645358788b72d209ca..f89aca55bbf46e5271a6befdc670343099a831e4 100644 --- a/lms/djangoapps/dashboard/tests/test_sysadmin.py +++ b/lms/djangoapps/dashboard/tests/test_sysadmin.py @@ -128,7 +128,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase): try: mongoengine.connect(TEST_MONGODB_LOG['db']) CourseImportLog.objects.all().delete() - except mongoengine.connection.ConnectionError: + except mongoengine.connection.ConnectionFailure: pass def _setstaff_login(self): @@ -193,7 +193,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase): # Make sure we don't have any git hashes on the page response = self.client.get(reverse('sysadmin_courses')) - self.assertNotRegexpMatches(response.content.decode('utf-8'), table_re) + self.assertNotRegex(response.content.decode('utf-8'), table_re) # Now add the course and make sure it does match response = self._add_edx4edx() diff --git a/lms/djangoapps/discussion/apps.py b/lms/djangoapps/discussion/apps.py index cc75cdb8767e75227bab7458f99290fc7a997163..edb82d5174fbbc7487e43f338b16ef01a9aae1b3 100644 --- a/lms/djangoapps/discussion/apps.py +++ b/lms/djangoapps/discussion/apps.py @@ -39,4 +39,4 @@ class DiscussionConfig(AppConfig): """ Connect handlers to send notifications about discussions. """ - from .signals import handlers # pylint: disable=unused-variable + from .signals import handlers # pylint: disable=unused-import diff --git a/lms/djangoapps/discussion/config/waffle.py b/lms/djangoapps/discussion/config/waffle.py index e672926703ef4fb9c7ebe47c81d0016fe39fb85b..381cbb86b755b58e053fdfea2cba09101b3ca79b 100644 --- a/lms/djangoapps/discussion/config/waffle.py +++ b/lms/djangoapps/discussion/config/waffle.py @@ -4,7 +4,6 @@ Discussion settings and flags. from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace -USE_BOOTSTRAP = 'use_bootstrap' ENABLE_FORUM_DAILY_DIGEST = 'enable_forum_daily_digest' @@ -14,12 +13,6 @@ def waffle_flags(): """ namespace = WaffleFlagNamespace(name='edx_discussions') return { - # Waffle flag to enable the use of Bootstrap - USE_BOOTSTRAP: WaffleFlag( - namespace, - USE_BOOTSTRAP, - flag_undefined_default=True - ), # By default, enable forum notifications. Can be disabled platform wide. ENABLE_FORUM_DAILY_DIGEST: WaffleFlag( namespace, @@ -29,11 +22,6 @@ def waffle_flags(): } -def use_bootstrap_flag_enabled(): - """Returns whether use of bootstrap is enabled.""" - return waffle_flags()[USE_BOOTSTRAP].is_enabled() - - def is_forum_daily_digest_enabled(): """Returns whether forum notification features should be visible""" return waffle_flags()[ENABLE_FORUM_DAILY_DIGEST].is_enabled() diff --git a/lms/djangoapps/discussion/django_comment_client/base/__init__.py b/lms/djangoapps/discussion/django_comment_client/base/__init__.py index 6fb9c4756bdc8309dddc33bfbf4d931e0d383e06..ce2d4e380c1ccd7f2dab7cbe289fb151231ec60e 100644 --- a/lms/djangoapps/discussion/django_comment_client/base/__init__.py +++ b/lms/djangoapps/discussion/django_comment_client/base/__init__.py @@ -1,5 +1,3 @@ -# pylint: disable=missing-docstring # This import registers the ForumThreadViewedEventTransformer - from . import event_transformers diff --git a/lms/djangoapps/discussion/django_comment_client/base/views.py b/lms/djangoapps/discussion/django_comment_client/base/views.py index c28065d27518e25af8dcc1918f398a29c1acdc7f..505cda2841ece54cd2f5187f6a75d6b67e2d6adb 100644 --- a/lms/djangoapps/discussion/django_comment_client/base/views.py +++ b/lms/djangoapps/discussion/django_comment_client/base/views.py @@ -1,4 +1,3 @@ -# pylint: disable=missing-docstring,unused-argument """Views for discussion forums.""" @@ -10,7 +9,6 @@ import time import eventtracking import six -import six.moves.urllib.parse # pylint: disable=import-error from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.core import exceptions @@ -783,7 +781,7 @@ def upload(request, course_id): # ajax upload file to a question or answer result = _('Good') file_url = file_storage.url(new_file_name) parsed_url = six.moves.urllib.parse.urlparse(file_url) - file_url = six.moves.urllib.parse.urlunparse( # pylint: disable=too-many-function-args + file_url = six.moves.urllib.parse.urlunparse( six.moves.urllib.parse.ParseResult( parsed_url.scheme, parsed_url.netloc, diff --git a/lms/djangoapps/discussion/django_comment_client/middleware.py b/lms/djangoapps/discussion/django_comment_client/middleware.py index fd76a9060e0a780ca74ad3c542c725660e25ce13..300a3f11112e9a451040a004f09e8235705bc941 100644 --- a/lms/djangoapps/discussion/django_comment_client/middleware.py +++ b/lms/djangoapps/discussion/django_comment_client/middleware.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - import json import logging diff --git a/lms/djangoapps/discussion/django_comment_client/permissions.py b/lms/djangoapps/discussion/django_comment_client/permissions.py index ca346e94bb1d37e8a75e0f80463e8d6b9ef50118..99fd8e6a05a2e6094d8f0645843dfbfb3ddccca1 100644 --- a/lms/djangoapps/discussion/django_comment_client/permissions.py +++ b/lms/djangoapps/discussion/django_comment_client/permissions.py @@ -1,4 +1,3 @@ -# pylint: disable=missing-docstring """ Module for checking permissions with the comment_client backend """ diff --git a/lms/djangoapps/discussion/django_comment_client/settings.py b/lms/djangoapps/discussion/django_comment_client/settings.py index d28d60efa6c0f4e43c82ed9a184a754016170c35..68613436d6d5fd3c30432edc1ab80a424689edca 100644 --- a/lms/djangoapps/discussion/django_comment_client/settings.py +++ b/lms/djangoapps/discussion/django_comment_client/settings.py @@ -1,4 +1,4 @@ -# pylint: disable=missing-docstring +# pylint: disable=missing-module-docstring from django.conf import settings diff --git a/lms/djangoapps/discussion/django_comment_client/tests/factories.py b/lms/djangoapps/discussion/django_comment_client/tests/factories.py index 43090c099fb4361efe69f169788794ec33b81f58..f77c3236e6d2b264a05db8643fe3fe96146eeff4 100644 --- a/lms/djangoapps/discussion/django_comment_client/tests/factories.py +++ b/lms/djangoapps/discussion/django_comment_client/tests/factories.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - from factory.django import DjangoModelFactory from openedx.core.djangoapps.django_comment_common.models import Permission, Role diff --git a/lms/djangoapps/discussion/django_comment_client/tests/mock_cs_server/test_mock_cs_server.py b/lms/djangoapps/discussion/django_comment_client/tests/mock_cs_server/test_mock_cs_server.py index 15277906e30c1f40b46e2979bbe5bfc11dc576fd..c9db7b598835939672322394af6f3f92ff870362 100644 --- a/lms/djangoapps/discussion/django_comment_client/tests/mock_cs_server/test_mock_cs_server.py +++ b/lms/djangoapps/discussion/django_comment_client/tests/mock_cs_server/test_mock_cs_server.py @@ -1,12 +1,8 @@ -# pylint: disable=missing-docstring - - import json import threading import unittest import pytest -import six.moves.urllib.request # pylint: disable=import-error from lms.djangoapps.discussion.django_comment_client.tests.mock_cs_server.mock_cs_server import MockCommentServiceServer diff --git a/lms/djangoapps/discussion/django_comment_client/tests/test_middleware.py b/lms/djangoapps/discussion/django_comment_client/tests/test_middleware.py index 778b71e767be0922c1bfb627c32e7f8721650489..3f77e1ce0c7080dbec5716d522998386b758dc2a 100644 --- a/lms/djangoapps/discussion/django_comment_client/tests/test_middleware.py +++ b/lms/djangoapps/discussion/django_comment_client/tests/test_middleware.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - import json import django.http diff --git a/lms/djangoapps/discussion/django_comment_client/tests/test_utils.py b/lms/djangoapps/discussion/django_comment_client/tests/test_utils.py index 1c9a45ffd91b3f717b27e0e0017c36c54cdcdafb..9d00c4793dde294b0c98b8a569ef1b98062fbf80 100644 --- a/lms/djangoapps/discussion/django_comment_client/tests/test_utils.py +++ b/lms/djangoapps/discussion/django_comment_client/tests/test_utils.py @@ -4,9 +4,11 @@ import datetime import json +import sys import ddt import mock +import pytest import six from django.test import RequestFactory, TestCase from django.urls import reverse @@ -949,6 +951,74 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase): } ) + @pytest.mark.skipif( + sys.version_info < (3, 7), + reason="Python 3.7 sorted dict insertion is considered" + ) + def test_sort_intermediates(self): + self.create_discussion("Chapter B", "Discussion 2") + self.create_discussion("Chapter C", "Discussion") + self.create_discussion("Chapter A", "Discussion 1") + self.create_discussion("Chapter B", "Discussion 1") + self.create_discussion("Chapter A", "Discussion 2") + + self.assert_category_map_equals( + { + "children": [("Chapter A", TYPE_SUBCATEGORY), ("Chapter B", TYPE_SUBCATEGORY), + ("Chapter C", TYPE_SUBCATEGORY)], + "entries": {}, + "subcategories": { + "Chapter A": { + "children": [("Discussion 1", TYPE_ENTRY), ("Discussion 2", TYPE_ENTRY)], + "entries": { + "Discussion 1": { + "id": "discussion3", + "sort_key": None, + "is_divided": False, + }, + "Discussion 2": { + "id": "discussion5", + "sort_key": None, + "is_divided": False, + } + }, + "subcategories": {}, + }, + "Chapter B": { + "children": [("Discussion 2", TYPE_ENTRY), ("Discussion 1", TYPE_ENTRY)], + "entries": { + "Discussion 2": { + "id": "discussion1", + "sort_key": None, + "is_divided": False, + }, + "Discussion 1": { + "id": "discussion4", + "sort_key": None, + "is_divided": False, + } + }, + "subcategories": {}, + }, + "Chapter C": { + "entries": { + "Discussion": { + "id": "discussion2", + "sort_key": None, + "is_divided": False, + } + }, + "children": [("Discussion", TYPE_ENTRY)], + "subcategories": {}, + } + }, + } + ) + + @pytest.mark.skipif( + sys.version_info >= (3, 7), + reason="Python 3.7 sorted dict insertion is not considered" + ) def test_sort_intermediates(self): self.create_discussion("Chapter B", "Discussion 2") self.create_discussion("Chapter C", "Discussion") diff --git a/lms/djangoapps/discussion/django_comment_client/tests/unicode.py b/lms/djangoapps/discussion/django_comment_client/tests/unicode.py index a750b6ba0b61fd9e4c1cf427a3186bfec7013780..017a0371ec22c5f95330a0102b1fc03cc405ed18 100644 --- a/lms/djangoapps/discussion/django_comment_client/tests/unicode.py +++ b/lms/djangoapps/discussion/django_comment_client/tests/unicode.py @@ -1,4 +1,3 @@ -# pylint: disable=missing-docstring # coding=utf-8 diff --git a/lms/djangoapps/discussion/management/commands/assign_role.py b/lms/djangoapps/discussion/management/commands/assign_role.py index f306f1da909d3a831c68bc39b463cc32f24c194c..00f6273c843233a2cea8402e276f9d0fc5a47181 100644 --- a/lms/djangoapps/discussion/management/commands/assign_role.py +++ b/lms/djangoapps/discussion/management/commands/assign_role.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - from django.contrib.auth.models import User from django.core.management.base import BaseCommand diff --git a/lms/djangoapps/discussion/management/commands/assign_roles_for_course.py b/lms/djangoapps/discussion/management/commands/assign_roles_for_course.py index 5c589431f062c67ba8130a25a7eea0ace8ddc6b0..e721279053330ee5279c406d2ea9ba3c8d44bb4b 100644 --- a/lms/djangoapps/discussion/management/commands/assign_roles_for_course.py +++ b/lms/djangoapps/discussion/management/commands/assign_roles_for_course.py @@ -1,4 +1,3 @@ -# pylint: disable=missing-docstring """ This must be run only after seed_permissions_roles.py! diff --git a/lms/djangoapps/discussion/management/commands/get_discussion_link.py b/lms/djangoapps/discussion/management/commands/get_discussion_link.py index b5b756bfb6a81a74eea74971e1f48490a70d0aba..d669b6777130ecd16ad33153ee493806012f5390 100644 --- a/lms/djangoapps/discussion/management/commands/get_discussion_link.py +++ b/lms/djangoapps/discussion/management/commands/get_discussion_link.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - from django.core.management.base import BaseCommand, CommandError from opaque_keys.edx.keys import CourseKey diff --git a/lms/djangoapps/discussion/management/commands/reload_forum_users.py b/lms/djangoapps/discussion/management/commands/reload_forum_users.py index 7b25b9ec8c7071fb4e515903d3c72f3577395c1b..401360582999518f40e31e60612eb53e3f58d2fb 100644 --- a/lms/djangoapps/discussion/management/commands/reload_forum_users.py +++ b/lms/djangoapps/discussion/management/commands/reload_forum_users.py @@ -1,4 +1,3 @@ -# pylint: disable=missing-docstring,broad-except """ Reload forum (comment client) users from existing users. """ diff --git a/lms/djangoapps/discussion/management/commands/seed_permissions_roles.py b/lms/djangoapps/discussion/management/commands/seed_permissions_roles.py index 6dc624093f879e1193f52ce554d4e5d572b5da93..54e194e06227f67cf91803b72cf92c1fad011286 100644 --- a/lms/djangoapps/discussion/management/commands/seed_permissions_roles.py +++ b/lms/djangoapps/discussion/management/commands/seed_permissions_roles.py @@ -1,4 +1,3 @@ -# pylint: disable=missing-docstring """ Management command to seed default permissions and roles. """ diff --git a/lms/djangoapps/discussion/management/commands/show_permissions.py b/lms/djangoapps/discussion/management/commands/show_permissions.py index 88930cf9bdf4a203bc110f53d5cd58806702beda..bd091c8168ac15cbc923a415d8744ee4795e12fb 100644 --- a/lms/djangoapps/discussion/management/commands/show_permissions.py +++ b/lms/djangoapps/discussion/management/commands/show_permissions.py @@ -1,4 +1,4 @@ -# pylint: disable=missing-docstring,too-many-format-args +# pylint: disable=missing-module-docstring,too-many-format-args from django.contrib.auth.models import User diff --git a/lms/djangoapps/discussion/notification_prefs/__init__.py b/lms/djangoapps/discussion/notification_prefs/__init__.py index ea3cc6902102381fe3470ba3918e04282a76469f..daed38e2b050c2718ead04b8eee70a1692be5a99 100644 --- a/lms/djangoapps/discussion/notification_prefs/__init__.py +++ b/lms/djangoapps/discussion/notification_prefs/__init__.py @@ -1,2 +1 @@ -# pylint: disable=missing-docstring NOTIFICATION_PREF_KEY = "notification_pref" diff --git a/lms/djangoapps/discussion/notification_prefs/tests.py b/lms/djangoapps/discussion/notification_prefs/tests.py index 6efe5e3f900673440d04ec41f047ea0824a80c9d..d86d8871c6b0c6025796fd3dba5e9de6d0ec5dfd 100644 --- a/lms/djangoapps/discussion/notification_prefs/tests.py +++ b/lms/djangoapps/discussion/notification_prefs/tests.py @@ -1,4 +1,4 @@ -# pylint: disable=missing-docstring,consider-iterating-dictionary +# pylint: disable=consider-iterating-dictionary, missing-module-docstring import json diff --git a/lms/djangoapps/discussion/notification_prefs/views.py b/lms/djangoapps/discussion/notification_prefs/views.py index a91996e623f1fb9e643864cbde451ff8517ccea0..20e631bbf60122c5c2364a85106be0d084e5fde7 100644 --- a/lms/djangoapps/discussion/notification_prefs/views.py +++ b/lms/djangoapps/discussion/notification_prefs/views.py @@ -1,4 +1,3 @@ -# pylint: disable=missing-docstring """ Views to support notification preferences. """ @@ -96,7 +95,7 @@ class UsernameCipher(object): try: unpadded = unpadder.update(decrypted) + unpadder.finalize() - if len(unpadded) == 0: # pylint: disable=len-as-condition + if len(unpadded) == 0: raise UsernameDecryptionException("padding") return unpadded except ValueError: @@ -173,7 +172,7 @@ def ajax_status(request): @require_GET -def set_subscription(request, token, subscribe): # pylint: disable=unused-argument +def set_subscription(request, token, subscribe): """ A view that disables or re-enables notifications for a user who may not be authenticated diff --git a/lms/djangoapps/discussion/notifier_api/serializers.py b/lms/djangoapps/discussion/notifier_api/serializers.py index 3bcb68b8fa7cfb1b2f024a5d192a2c0f4312316f..4d1dbbb5bebc652020cea2c59dc9ebf9b09c942c 100644 --- a/lms/djangoapps/discussion/notifier_api/serializers.py +++ b/lms/djangoapps/discussion/notifier_api/serializers.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - import six from django.contrib.auth.models import User from django.http import Http404 diff --git a/lms/djangoapps/discussion/plugins.py b/lms/djangoapps/discussion/plugins.py index c9ea2101eb47944a6470b5d14efc4297bb566986..5fc8beb19b5a3991503943b0b4e225971c34599c 100644 --- a/lms/djangoapps/discussion/plugins.py +++ b/lms/djangoapps/discussion/plugins.py @@ -8,7 +8,6 @@ from django.utils.translation import ugettext_noop import lms.djangoapps.discussion.django_comment_client.utils as utils from lms.djangoapps.courseware.tabs import EnrolledTab -from lms.djangoapps.discussion.config.waffle import use_bootstrap_flag_enabled from xmodule.tabs import TabFragmentViewMixin @@ -38,4 +37,4 @@ class DiscussionTab(TabFragmentViewMixin, EnrolledTab): """ Returns true if this tab is rendered with Bootstrap. """ - return use_bootstrap_flag_enabled() + return True diff --git a/lms/djangoapps/discussion/rest_api/api.py b/lms/djangoapps/discussion/rest_api/api.py index 20c251c51a1ab1b3c35701a553c4f16c102137d7..5bbea6df41d7a1fc28e24e5f6bf57c22de4454ba 100644 --- a/lms/djangoapps/discussion/rest_api/api.py +++ b/lms/djangoapps/discussion/rest_api/api.py @@ -14,7 +14,7 @@ from django.urls import reverse from opaque_keys import InvalidKeyError from opaque_keys.edx.locator import CourseKey from rest_framework.exceptions import PermissionDenied -from six.moves.urllib.parse import urlencode, urlunparse # pylint: disable=import-error +from six.moves.urllib.parse import urlencode, urlunparse from lms.djangoapps.courseware.courses import get_course_with_access from lms.djangoapps.courseware.exceptions import CourseAccessRedirect diff --git a/lms/djangoapps/discussion/rest_api/forms.py b/lms/djangoapps/discussion/rest_api/forms.py index 85a879a7b97c83cc926a6ab7b42078fbc425cd6c..266ac129180cbbd2ea3230648bbc140e8238a295 100644 --- a/lms/djangoapps/discussion/rest_api/forms.py +++ b/lms/djangoapps/discussion/rest_api/forms.py @@ -3,9 +3,9 @@ Discussion API forms """ -import six.moves.urllib.error # pylint: disable=import-error -import six.moves.urllib.parse # pylint: disable=import-error -import six.moves.urllib.request # pylint: disable=import-error +import six.moves.urllib.error +import six.moves.urllib.parse +import six.moves.urllib.request from django.core.exceptions import ValidationError from django.forms import BooleanField, CharField, ChoiceField, Form, IntegerField from opaque_keys import InvalidKeyError @@ -173,7 +173,6 @@ class CourseDiscussionRolesForm(CourseDiscussionSettingsForm): def clean_rolename(self): """Validate the 'rolename' value.""" - # pylint: disable=too-many-function-args rolename = six.moves.urllib.parse.unquote(self.cleaned_data.get('rolename')) course_id = self.cleaned_data.get('course_key') if course_id and rolename: diff --git a/lms/djangoapps/discussion/rest_api/serializers.py b/lms/djangoapps/discussion/rest_api/serializers.py index ecc840f1530d94a5574883c224f4b49fae1ea206..414c9bdc372a0ddca281d725af8fd26696854d67 100644 --- a/lms/djangoapps/discussion/rest_api/serializers.py +++ b/lms/djangoapps/discussion/rest_api/serializers.py @@ -7,7 +7,7 @@ from django.contrib.auth.models import User as DjangoUser from django.core.exceptions import ValidationError from django.urls import reverse from rest_framework import serializers -from six.moves.urllib.parse import urlencode, urlunparse # pylint: disable=import-error +from six.moves.urllib.parse import urlencode, urlunparse from lms.djangoapps.discussion.django_comment_client.utils import ( course_discussion_division_enabled, diff --git a/lms/djangoapps/discussion/rest_api/tests/test_api.py b/lms/djangoapps/discussion/rest_api/tests/test_api.py index 530228ce1c8f2ed5da55f1973888a93b7fb82045..c993890b728c2718166609bad8d861efcc8a1f26 100644 --- a/lms/djangoapps/discussion/rest_api/tests/test_api.py +++ b/lms/djangoapps/discussion/rest_api/tests/test_api.py @@ -16,7 +16,7 @@ from opaque_keys.edx.locator import CourseLocator from pytz import UTC from rest_framework.exceptions import PermissionDenied from six.moves import range -from six.moves.urllib.parse import parse_qs, urlencode, urlparse, urlunparse # pylint: disable=import-error +from six.moves.urllib.parse import parse_qs, urlencode, urlparse, urlunparse from common.test.utils import MockSignalHandlerMixin, disable_signal from lms.djangoapps.courseware.tests.factories import BetaTesterFactory, StaffFactory diff --git a/lms/djangoapps/discussion/rest_api/tests/test_forms.py b/lms/djangoapps/discussion/rest_api/tests/test_forms.py index 8afb23ee86f86a50d89d83b5cec6f2cbb9aacb93..9df8aee20a160f0bb72a5524529d3792c466c7ef 100644 --- a/lms/djangoapps/discussion/rest_api/tests/test_forms.py +++ b/lms/djangoapps/discussion/rest_api/tests/test_forms.py @@ -9,7 +9,7 @@ from unittest import TestCase import ddt from django.http import QueryDict from opaque_keys.edx.locator import CourseLocator -from six.moves.urllib.parse import urlencode # pylint: disable=import-error +from six.moves.urllib.parse import urlencode from lms.djangoapps.discussion.rest_api.forms import CommentListGetForm, ThreadListGetForm from openedx.core.djangoapps.util.test_forms import FormTestMixin diff --git a/lms/djangoapps/discussion/rest_api/tests/test_serializers.py b/lms/djangoapps/discussion/rest_api/tests/test_serializers.py index 8e88d100fbc08936ae7855076427839021220b2d..a4b8d1a601995add4e0a8601a4fbf01e6fcbc6ee 100644 --- a/lms/djangoapps/discussion/rest_api/tests/test_serializers.py +++ b/lms/djangoapps/discussion/rest_api/tests/test_serializers.py @@ -10,7 +10,7 @@ import httpretty import mock import six from django.test.client import RequestFactory -from six.moves.urllib.parse import urlparse # pylint: disable=import-error +from six.moves.urllib.parse import urlparse from lms.djangoapps.discussion.django_comment_client.tests.utils import ForumsEnableMixin from lms.djangoapps.discussion.rest_api.serializers import CommentSerializer, ThreadSerializer, get_context diff --git a/lms/djangoapps/discussion/rest_api/tests/test_views.py b/lms/djangoapps/discussion/rest_api/tests/test_views.py index f6250916503040a274e18c633109c022f2c28003..8029dd1173360386677dabd755e2df78aad4c3af 100644 --- a/lms/djangoapps/discussion/rest_api/tests/test_views.py +++ b/lms/djangoapps/discussion/rest_api/tests/test_views.py @@ -16,7 +16,7 @@ from rest_framework.parsers import JSONParser from rest_framework.test import APIClient, APITestCase from six import text_type from six.moves import range -from six.moves.urllib.parse import urlparse # pylint: disable=import-error +from six.moves.urllib.parse import urlparse from common.test.utils import disable_signal from course_modes.models import CourseMode diff --git a/lms/djangoapps/discussion/rest_api/tests/utils.py b/lms/djangoapps/discussion/rest_api/tests/utils.py index 172e04e8396a01a7e445af1113935591f06aa39e..0620ffe032baeea972718abe581eaaed430edfbb 100644 --- a/lms/djangoapps/discussion/rest_api/tests/utils.py +++ b/lms/djangoapps/discussion/rest_api/tests/utils.py @@ -522,7 +522,7 @@ class ProfileImageTestMixin(object): self.assertTrue(storage.exists(name)) with closing(Image.open(storage.path(name))) as img: self.assertEqual(img.size, (size, size)) - self.assertEqual(img.format, 'JPEG') # pylint: disable=no-member + self.assertEqual(img.format, 'JPEG') else: self.assertFalse(storage.exists(name)) diff --git a/lms/djangoapps/discussion/rest_api/views.py b/lms/djangoapps/discussion/rest_api/views.py index c743ad98441c2dc9c5dc37d7de11cec332daba1c..a9df8f5cc4142e6df1fc32c7b7873a915d8ccd04 100644 --- a/lms/djangoapps/discussion/rest_api/views.py +++ b/lms/djangoapps/discussion/rest_api/views.py @@ -614,6 +614,7 @@ class ReplaceUsernamesView(APIView): {"current_username_2": "desired_username_2"} ] } + """ authentication_classes = (JwtAuthentication,) diff --git a/lms/djangoapps/discussion/static/discussion/js/spec/discussion_board_view_spec.js b/lms/djangoapps/discussion/static/discussion/js/spec/discussion_board_view_spec.js index e63caf4a25cf567bd1daab60dc60fa7061b6b6f1..9905bc08041abdf26a0a69f3ba8c14749073d662 100644 --- a/lms/djangoapps/discussion/static/discussion/js/spec/discussion_board_view_spec.js +++ b/lms/djangoapps/discussion/static/discussion/js/spec/discussion_board_view_spec.js @@ -1,4 +1,4 @@ -/* globals Discussion, DiscussionCourseSettings */ +/* globals Discussion, DiscussionCourseSettings, DiscussionUser, DiscussionUtil */ (function(define) { 'use strict'; define( @@ -26,10 +26,33 @@ discussion: discussion, courseSettings: courseSettings }); + window.ENABLE_FORUM_DAILY_DIGEST = true; + window.user = new DiscussionUser({ + id: 99 + }); return discussionBoardView; }; + describe('goHome view', function() { + it('Ensure no ajax request when digests are unavailable', function() { + var discussionBoardView = createDiscussionBoardView(); + spyOn(DiscussionUtil, 'safeAjax').and.callThrough(); + window.ENABLE_FORUM_DAILY_DIGEST = false; + + discussionBoardView.goHome(); + expect(DiscussionUtil.safeAjax).not.toHaveBeenCalled(); + }); + it('Verify the ajax request when digests are available', function() { + var discussionBoardView = createDiscussionBoardView(); + discussionBoardView.render(); + spyOn(DiscussionUtil, 'safeAjax').and.callThrough(); + + discussionBoardView.goHome(); + expect(DiscussionUtil.safeAjax).toHaveBeenCalled(); + }); + }); + describe('Thread List View', function() { it('should ensure the mode is all', function() { var discussionBoardView = createDiscussionBoardView().render(), diff --git a/lms/djangoapps/discussion/static/discussion/js/views/discussion_board_view.js b/lms/djangoapps/discussion/static/discussion/js/views/discussion_board_view.js index 73cd76b665d4a059d203362a8d054273e32f5b0e..1e55ae459f8c68d84a91d3d2187af869cdd5c374 100644 --- a/lms/djangoapps/discussion/static/discussion/js/views/discussion_board_view.js +++ b/lms/djangoapps/discussion/static/discussion/js/views/discussion_board_view.js @@ -133,13 +133,22 @@ }, goHome: function() { - var url = DiscussionUtil.urlFor('notifications_status', window.user.get('id')); HtmlUtils.append(this.$('.forum-content').empty(), HtmlUtils.template(discussionHomeTemplate)({})); this.$('.forum-nav-thread-list a').removeClass('is-active').find('.sr') - .remove(); + .remove(); + this.setupForumDigestSettings(window.user.get('id')); + }, + setupForumDigestSettings: function(userId) { + if (window.ENABLE_FORUM_DAILY_DIGEST === false) { + return; + } this.$('input.email-setting').bind('click', this.discussionThreadListView.updateEmailNotifications); + this.getUserNotificationSettings(userId); + }, + + getUserNotificationSettings: function(userId) { DiscussionUtil.safeAjax({ - url: url, + url: DiscussionUtil.urlFor('notifications_status', userId), type: 'GET', success: function(response) { $('input.email-setting').prop('checked', response.status); diff --git a/lms/djangoapps/discussion/tasks.py b/lms/djangoapps/discussion/tasks.py index 3420288367270ed3fc98b3f263ba1143c15c1030..a0101e85b466d7fa6a460d7e5f76c79025a38864 100644 --- a/lms/djangoapps/discussion/tasks.py +++ b/lms/djangoapps/discussion/tasks.py @@ -17,7 +17,7 @@ from edx_ace.recipient import Recipient from edx_ace.utils import date from eventtracking import tracker from opaque_keys.edx.keys import CourseKey -from six.moves.urllib.parse import urljoin # pylint: disable=import-error +from six.moves.urllib.parse import urljoin import openedx.core.djangoapps.django_comment_common.comment_client as cc from lms.djangoapps.discussion.django_comment_client.utils import ( diff --git a/lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html b/lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html index 5bdcdb9074fc7bdb43ac13e05b67e81a8aadd6e7..71c88ae73fec3a2b3bd928563433f24fb3321739 100644 --- a/lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html +++ b/lms/djangoapps/discussion/templates/discussion/edx_ace/responsenotification/email/body.html @@ -7,9 +7,12 @@ <tr> <td> <p> - {% blocktrans trimmed %} - {{ comment_username }} replied to <b>{{ thread_title }}</b>: + {% filter force_escape %} + {% blocktrans trimmed asvar replied_to_text %} + {{ comment_username }} replied to {% endblocktrans %} + {% endfilter %} + {{ replied_to_text }} <b>{{ thread_title }}</b>: </p> <div style="border-left: 1px solid rgba(0,0,0,0.25); padding: 1px 1px 1px 15px; @@ -18,7 +21,9 @@ {{ comment_body }} </div> - {% trans "View discussion" as course_cta_text %} + {% filter force_escape %} + {% blocktrans asvar course_cta_text %}View discussion{% endblocktrans %} + {% endfilter %} {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text course_cta_url=post_link%} {% block google_analytics_pixel %} diff --git a/lms/djangoapps/discussion/tests/test_tasks.py b/lms/djangoapps/discussion/tests/test_tasks.py index 4161792a98e7a186830b3022bc41fb5e0c90d3e7..5f828b102af0375a9b5b5e74fa3ada9d9a695c11 100644 --- a/lms/djangoapps/discussion/tests/test_tasks.py +++ b/lms/djangoapps/discussion/tests/test_tasks.py @@ -232,7 +232,6 @@ class TaskTestCase(ModuleStoreTestCase): with emulate_http_request( site=message.context['site'], user=self.thread_author ): - # pylint: disable=unsupported-membership-test rendered_email = EmailRenderer().render(get_channel_for_message(ChannelType.EMAIL, message), message) assert self.comment['body'] in rendered_email.body_html assert self.comment_author.username in rendered_email.body_html diff --git a/lms/djangoapps/discussion/tests/test_views.py b/lms/djangoapps/discussion/tests/test_views.py index 0fe34381fe1b5fb608333643a324fbc7a31017f5..5c3274b01a38098da992981442fb95125076c4ba 100644 --- a/lms/djangoapps/discussion/tests/test_views.py +++ b/lms/djangoapps/discussion/tests/test_views.py @@ -72,8 +72,6 @@ log = logging.getLogger(__name__) QUERY_COUNT_TABLE_BLACKLIST = WAFFLE_TABLES -# pylint: disable=missing-docstring - class ViewsExceptionTestCase(UrlResetMixin, ModuleStoreTestCase): @@ -769,8 +767,10 @@ class ForumFormDiscussionContentGroupTestCase(ForumsEnableMixin, ContentGroupTes self.thread_list = [ {"thread_id": "test_general_thread_id"}, {"thread_id": "test_global_group_thread_id", "commentable_id": self.global_module.discussion_id}, - {"thread_id": "test_alpha_group_thread_id", "group_id": self.alpha_module.group_access[0][0], "commentable_id": self.alpha_module.discussion_id}, # pylint: disable=line-too-long - {"thread_id": "test_beta_group_thread_id", "group_id": self.beta_module.group_access[0][0], "commentable_id": self.beta_module.discussion_id} # pylint: disable=line-too-long + {"thread_id": "test_alpha_group_thread_id", "group_id": self.alpha_module.group_access[0][0], + "commentable_id": self.alpha_module.discussion_id}, + {"thread_id": "test_beta_group_thread_id", "group_id": self.beta_module.group_access[0][0], + "commentable_id": self.beta_module.discussion_id} ] def assert_has_access(self, response, expected_discussion_threads): @@ -1633,7 +1633,7 @@ class ForumDiscussionXSSTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTe @ddt.data('"><script>alert(1)</script>', '<script>alert(1)</script>', '</script><script>alert(1)</script>') @patch('student.models.cc.User.from_django_user') - def test_forum_discussion_xss_prevent(self, malicious_code, mock_user, mock_req): # pylint: disable=unused-argument + def test_forum_discussion_xss_prevent(self, malicious_code, mock_user, mock_req): """ Test that XSS attack is prevented """ diff --git a/lms/djangoapps/discussion/views.py b/lms/djangoapps/discussion/views.py index aac52ce560ae096efd3c20bd0c13dec70190fbbd..e9f8188838adcc67320214590acf53142450b7f7 100644 --- a/lms/djangoapps/discussion/views.py +++ b/lms/djangoapps/discussion/views.py @@ -30,7 +30,7 @@ import openedx.core.djangoapps.django_comment_common.comment_client as cc from lms.djangoapps.courseware.access import has_access from lms.djangoapps.courseware.courses import get_course_with_access from lms.djangoapps.courseware.views.views import CourseTabView -from lms.djangoapps.discussion.config.waffle import is_forum_daily_digest_enabled, use_bootstrap_flag_enabled +from lms.djangoapps.discussion.config.waffle import is_forum_daily_digest_enabled from lms.djangoapps.discussion.django_comment_client.base.views import track_thread_viewed_event from lms.djangoapps.discussion.django_comment_client.constants import TYPE_ENTRY from lms.djangoapps.discussion.django_comment_client.permissions import has_permission @@ -423,7 +423,6 @@ def _create_base_discussion_view_context(request, course_key): user_info = cc_user.to_dict() course = get_course_with_access(user, 'load', course_key, check_if_enrolled=True) course_settings = make_course_settings(course, user) - uses_bootstrap = use_bootstrap_flag_enabled() return { 'csrf': csrf(request)['csrf_token'], 'course': course, @@ -440,8 +439,7 @@ def _create_base_discussion_view_context(request, course_key): ), 'course_settings': course_settings, 'disable_courseware_js': True, - 'uses_bootstrap': uses_bootstrap, - 'uses_pattern_library': not uses_bootstrap, + 'uses_bootstrap': True, } @@ -697,6 +695,8 @@ class DiscussionBoardFragmentView(EdxFragmentView): """ Component implementation of the discussion board. """ + _uses_pattern_library = False + def render_to_fragment( self, request, @@ -760,7 +760,7 @@ class DiscussionBoardFragmentView(EdxFragmentView): log.warning('Forum is in maintenance mode') html = render_to_string('discussion/maintenance_fragment.html', { 'disable_courseware_js': True, - 'uses_pattern_library': True, + 'uses_bootstrap': True, }) fragment = Fragment(html) self.add_fragment_resource_urls(fragment) @@ -774,7 +774,7 @@ class DiscussionBoardFragmentView(EdxFragmentView): ) html = render_to_string('discussion/discussion_private_fragment.html', { 'disable_courseware_js': True, - 'uses_pattern_library': True, + 'uses_bootstrap': True, }) fragment = Fragment(html) self.add_fragment_resource_urls(fragment) @@ -809,15 +809,11 @@ class DiscussionBoardFragmentView(EdxFragmentView): the files are loaded individually, but in production just the single bundle is loaded. """ is_right_to_left = get_language_bidi() - if use_bootstrap_flag_enabled(): - css_file = BOOTSTRAP_DISCUSSION_CSS_PATH - if is_right_to_left: - css_file = css_file.replace('.css', '-rtl.css') - return [css_file] - elif is_right_to_left: - return self.get_css_dependencies('style-discussion-main-rtl') - else: - return self.get_css_dependencies('style-discussion-main') + + css_file = BOOTSTRAP_DISCUSSION_CSS_PATH + if is_right_to_left: + css_file = css_file.replace('.css', '-rtl.css') + return [css_file] @expect_json diff --git a/lms/djangoapps/edxnotes/helpers.py b/lms/djangoapps/edxnotes/helpers.py index 9a79a7a923dade4d306694f558492dc1f2887189..437018a6f4d44249d30401646b40ab867ef5c222 100644 --- a/lms/djangoapps/edxnotes/helpers.py +++ b/lms/djangoapps/edxnotes/helpers.py @@ -11,7 +11,7 @@ from uuid import uuid4 import requests import six -from six.moves.urllib.parse import urlencode, urlparse, parse_qs # pylint: disable=import-error +from six.moves.urllib.parse import urlencode, urlparse, parse_qs from dateutil.parser import parse as dateutil_parse from django.conf import settings from django.core.exceptions import ImproperlyConfigured @@ -449,7 +449,7 @@ def generate_uid(): """ Generates unique id. """ - return uuid4().int # pylint: disable=no-member + return uuid4().int def is_feature_enabled(course, user): diff --git a/lms/djangoapps/edxnotes/tests.py b/lms/djangoapps/edxnotes/tests.py index 8fce8bc8d767ec084b3f47b0a20618233bf55abf..ae3fb317edc9217a46b0670deb51d89f74878cb1 100644 --- a/lms/djangoapps/edxnotes/tests.py +++ b/lms/djangoapps/edxnotes/tests.py @@ -12,7 +12,7 @@ import ddt import jwt import six from six import text_type -from six.moves.urllib.parse import urlparse, parse_qs # pylint: disable=import-error +from six.moves.urllib.parse import urlparse, parse_qs from django.conf import settings from django.contrib.auth.models import AnonymousUser from django.core.exceptions import ImproperlyConfigured diff --git a/lms/djangoapps/edxnotes/views.py b/lms/djangoapps/edxnotes/views.py index 600a11d8fa329124d838aeae303fd3c370abb622..755167339262260ffeeac87a711cb30d328f44ee 100644 --- a/lms/djangoapps/edxnotes/views.py +++ b/lms/djangoapps/edxnotes/views.py @@ -180,7 +180,6 @@ def notes(request, course_id): return HttpResponse(json.dumps(notes_info, cls=NoteJSONEncoder), content_type="application/json") -# pylint: disable=unused-argument @login_required def get_token(request, course_id): """ diff --git a/lms/djangoapps/email_marketing/signals.py b/lms/djangoapps/email_marketing/signals.py index 76271d45c9e5fcf66942e2db5ea70a361c2bfc44..5ac4ac95dddaacb379666dcaf8fd8cfe02edcdfe 100644 --- a/lms/djangoapps/email_marketing/signals.py +++ b/lms/djangoapps/email_marketing/signals.py @@ -116,6 +116,7 @@ def add_email_marketing_cookies(sender, response=None, user=None, max_age=365 * 24 * 60 * 60, # set for 1 year domain=settings.SESSION_COOKIE_DOMAIN, path='/', + secure=request.is_secure() ) log.info(u"sailthru_hid cookie:%s successfully retrieved for user %s", cookie, user.email) diff --git a/lms/djangoapps/experiments/flags.py b/lms/djangoapps/experiments/flags.py index 254cb81beffb2c10c262868aaaaafc3eb44c5186..7b5a5ee92329a70f649dfc7d79621204693883bc 100644 --- a/lms/djangoapps/experiments/flags.py +++ b/lms/djangoapps/experiments/flags.py @@ -124,7 +124,7 @@ class ExperimentWaffleFlag(CourseWaffleFlag): if not request: return 0 - if not request.user.id: + if not hasattr(request, 'user') or not request.user.id: # We need username for stable bucketing and id for tracking, so just skip anonymous (not-logged-in) users return 0 diff --git a/lms/djangoapps/experiments/tests/test_views.py b/lms/djangoapps/experiments/tests/test_views.py index 616cf58201fa74862bbdf08ce79e0d95f49c579c..e1615701e1af85c6f1e0113f49bbfd846c9efc08 100644 --- a/lms/djangoapps/experiments/tests/test_views.py +++ b/lms/djangoapps/experiments/tests/test_views.py @@ -5,9 +5,9 @@ Tests for experimentation views import unittest -import six.moves.urllib.error # pylint: disable=import-error -import six.moves.urllib.parse # pylint: disable=import-error -import six.moves.urllib.request # pylint: disable=import-error +import six.moves.urllib.error +import six.moves.urllib.parse +import six.moves.urllib.request from django.conf import settings from django.core.handlers.wsgi import WSGIRequest from django.test.utils import override_settings diff --git a/lms/djangoapps/experiments/utils.py b/lms/djangoapps/experiments/utils.py index 3e4420e33fd89917a7c893650243b03190ea6de3..f04d81362a3f9c533c72aca3a71fbf03f1f66c54 100644 --- a/lms/djangoapps/experiments/utils.py +++ b/lms/djangoapps/experiments/utils.py @@ -13,7 +13,7 @@ from opaque_keys.edx.keys import CourseKey from course_modes.models import format_course_price, get_cosmetic_verified_display_price, CourseMode from lms.djangoapps.courseware.access import has_staff_access_to_preview_mode -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, verified_upgrade_link_is_valid +from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, can_show_verified_upgrade from entitlements.models import CourseEntitlement from lms.djangoapps.commerce.utils import EcommerceService from openedx.core.djangoapps.catalog.utils import get_programs @@ -78,37 +78,36 @@ def check_and_get_upgrade_link_and_date(user, enrollment=None, course=None): otherwise, returns None for both the link and date. """ if enrollment is None and course is None: - logger.warn(u'Must specify either an enrollment or a course') + logger.warning(u'Must specify either an enrollment or a course') return (None, None, None) if enrollment: - if course is None: - course = enrollment.course - elif enrollment.course_id != course.id: - logger.warn(u'{} refers to a different course than {} which was supplied. Enrollment course id={}, ' - u'repr={!r}, deprecated={}. Course id={}, repr={!r}, deprecated={}.' - .format(enrollment, - course, - enrollment.course_id, - enrollment.course_id, - enrollment.course_id.deprecated, - course.id, - course.id, - course.id.deprecated - ) - ) + if course and enrollment.course_id != course.id: + logger.warning(u'{} refers to a different course than {} which was supplied. Enrollment course id={}, ' + u'repr={!r}, deprecated={}. Course id={}, repr={!r}, deprecated={}.' + .format(enrollment, + course, + enrollment.course_id, + enrollment.course_id, + enrollment.course_id.deprecated, + course.id, + course.id, + course.id.deprecated + ) + ) return (None, None, None) if enrollment.user_id != user.id: - logger.warn(u'{} refers to a different user than {} which was supplied. Enrollment user id={}, repr={!r}. ' - u'User id={}, repr={!r}.'.format(enrollment, - user, - enrollment.user_id, - enrollment.user_id, - user.id, - user.id, - ) - ) + logger.warning(u'{} refers to a different user than {} which was supplied. ' + u'Enrollment user id={}, repr={!r}. ' + u'User id={}, repr={!r}.'.format(enrollment, + user, + enrollment.user_id, + enrollment.user_id, + user.id, + user.id, + ) + ) return (None, None, None) if enrollment is None: @@ -116,9 +115,9 @@ def check_and_get_upgrade_link_and_date(user, enrollment=None, course=None): if enrollment is None: return (None, None, None) - if user.is_authenticated and verified_upgrade_link_is_valid(enrollment): + if user.is_authenticated and can_show_verified_upgrade(user, enrollment, course): return ( - verified_upgrade_deadline_link(user, course), + verified_upgrade_deadline_link(user, enrollment.course), enrollment.upgrade_deadline, enrollment.course_upgrade_deadline, ) @@ -227,7 +226,7 @@ def is_enrolled_in_course_run(course_run, enrollment_course_ids): course_run_key = CourseKey.from_string(key) return course_run_key in enrollment_course_ids except InvalidKeyError: - logger.warn( + logger.warning( u'Unable to determine if user was enrolled since the course key {} is invalid'.format(key) ) return False # Invalid course run key. Assume user is not enrolled. diff --git a/lms/djangoapps/experiments/views_custom.py b/lms/djangoapps/experiments/views_custom.py index ba3ba252f401d9e9ef08b3b6165f630663021e7b..23f4ede8635e4a3d1d631e5f4a850aed18d2abe2 100644 --- a/lms/djangoapps/experiments/views_custom.py +++ b/lms/djangoapps/experiments/views_custom.py @@ -23,7 +23,7 @@ from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiv from openedx.core.lib.api.permissions import ApiKeyHeaderPermissionIsAuthenticated from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin -from lms.djangoapps.courseware.utils import verified_upgrade_link_is_valid +from lms.djangoapps.courseware.utils import can_show_verified_upgrade from course_modes.models import get_cosmetic_verified_display_price from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.experiments.stable_bucketing import stable_bucketing_hash_group @@ -135,7 +135,7 @@ class Rev934(DeveloperErrorViewMixin, APIView): enrollment = CourseEnrollment.objects.select_related( 'course' ).get(user_id=user.id, course_id=course.id) - user_upsell = verified_upgrade_link_is_valid(enrollment) + user_upsell = can_show_verified_upgrade(user, enrollment) except CourseEnrollment.DoesNotExist: user_upsell = True diff --git a/lms/djangoapps/gating/apps.py b/lms/djangoapps/gating/apps.py index efb4b92a326d6c051a5f4e1226c7742898732b81..26281c86386295352be26fd08bd7fdcf3d4a2b45 100644 --- a/lms/djangoapps/gating/apps.py +++ b/lms/djangoapps/gating/apps.py @@ -14,4 +14,4 @@ class GatingConfig(AppConfig): def ready(self): # Import signals to wire up the signal handlers contained within - from gating import signals # pylint: disable=unused-variable + from gating import signals # pylint: disable=unused-import diff --git a/lms/djangoapps/grades/apps.py b/lms/djangoapps/grades/apps.py index bd2caff9ac3c7c6b86b7753bd76a11ec8fb7c1f7..7abbaff757451881be704b802dbaad9bc20a8394 100644 --- a/lms/djangoapps/grades/apps.py +++ b/lms/djangoapps/grades/apps.py @@ -41,7 +41,7 @@ class GradesConfig(AppConfig): """ # Can't import models at module level in AppConfigs, and models get # included from the signal handlers - from .signals import handlers # pylint: disable=unused-variable + from .signals import handlers # pylint: disable=unused-import if settings.FEATURES.get('ENABLE_SPECIAL_EXAMS'): from .services import GradesService set_runtime_service('grades', GradesService()) diff --git a/lms/djangoapps/grades/config/waffle.py b/lms/djangoapps/grades/config/waffle.py index f209bf1aaaa35daa47e1257e946dd1a345fdec6f..e23e6f757104a44d9947214d29604f4f337bdb09 100644 --- a/lms/djangoapps/grades/config/waffle.py +++ b/lms/djangoapps/grades/config/waffle.py @@ -34,17 +34,20 @@ def waffle_flags(): namespace = WaffleFlagNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Grades: ') return { # By default, enable rejected exam grade overrides. Can be disabled on a course-by-course basis. + # TODO: After removing this flag, add a migration to remove waffle flag in a follow-up deployment. REJECTED_EXAM_OVERRIDES_GRADE: CourseWaffleFlag( namespace, REJECTED_EXAM_OVERRIDES_GRADE, flag_undefined_default=True, ), + # TODO: After removing this flag, add a migration to remove waffle flag in a follow-up deployment. ENFORCE_FREEZE_GRADE_AFTER_COURSE_END: CourseWaffleFlag( namespace, ENFORCE_FREEZE_GRADE_AFTER_COURSE_END, flag_undefined_default=True, ), # Have this course override flag so we can selectively turn off the gradebook for courses. + # TODO: After removing this flag, add a migration to remove waffle flag in a follow-up deployment. WRITABLE_GRADEBOOK: CourseWaffleFlag( namespace, WRITABLE_GRADEBOOK, diff --git a/lms/djangoapps/grades/migrations/0018_add_waffle_flag_defaults.py b/lms/djangoapps/grades/migrations/0018_add_waffle_flag_defaults.py new file mode 100644 index 0000000000000000000000000000000000000000..7b1876e9df9fbfa0e81900e1c4686611a02b568f --- /dev/null +++ b/lms/djangoapps/grades/migrations/0018_add_waffle_flag_defaults.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +from django.db import migrations + +from lms.djangoapps.grades.config.waffle import ( + ENFORCE_FREEZE_GRADE_AFTER_COURSE_END, + REJECTED_EXAM_OVERRIDES_GRADE, + WRITABLE_GRADEBOOK, + waffle_flags, +) + + +def create_flag(apps, schema_editor): + Flag = apps.get_model('waffle', 'Flag') + # Replacement for flag_undefined_default=True on flag definition + Flag.objects.get_or_create( + name=waffle_flags()[REJECTED_EXAM_OVERRIDES_GRADE].namespaced_flag_name, defaults={'everyone': True} + ) + Flag.objects.get_or_create( + name=waffle_flags()[ENFORCE_FREEZE_GRADE_AFTER_COURSE_END].namespaced_flag_name, defaults={'everyone': True} + ) + Flag.objects.get_or_create( + name=waffle_flags()[WRITABLE_GRADEBOOK].namespaced_flag_name, defaults={'everyone': True} + ) + + +class Migration(migrations.Migration): + dependencies = [ + ('grades', '0017_delete_manual_psgoverride_table'), + ('waffle', '0001_initial'), + ] + + operations = [ + # Do not remove the flags for rollback. We don't want to lose originals if + # they already existed, and it won't hurt if they are created. + migrations.RunPython(create_flag, reverse_code=migrations.RunPython.noop), + ] diff --git a/lms/djangoapps/grades/rest_api/v1/tests/test_views.py b/lms/djangoapps/grades/rest_api/v1/tests/test_views.py index 287697e8eeb63d845fbcfeed123f9f48fd8289ee..9c89bf4d9458a9f10413229cf6f407a88f72dbc2 100644 --- a/lms/djangoapps/grades/rest_api/v1/tests/test_views.py +++ b/lms/djangoapps/grades/rest_api/v1/tests/test_views.py @@ -100,7 +100,7 @@ class SingleUserGradesTests(GradeViewTestMixin, AuthAndScopesTestMixin, APITestC """ Test that a request for an invalid course key returns an error. """ - def mock_from_string(*args, **kwargs): # pylint: disable=unused-argument + def mock_from_string(*args, **kwargs): """Mocked function to always raise an exception""" raise InvalidKeyError('foo', 'bar') diff --git a/lms/djangoapps/grades/tests/integration/test_problems.py b/lms/djangoapps/grades/tests/integration/test_problems.py index c2e589866d59f28c04eeeced969ab0481e4a1c9c..ae1815b0927191ea17ec6baff89d4e51449f7541 100644 --- a/lms/djangoapps/grades/tests/integration/test_problems.py +++ b/lms/djangoapps/grades/tests/integration/test_problems.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - import datetime import itertools diff --git a/lms/djangoapps/grades/tests/test_course_grade.py b/lms/djangoapps/grades/tests/test_course_grade.py index 7520cc03f3234b49ee1ef39d3913b64f7a68a1fa..6920621fdc7aa6a0669aba7182b901479273c2fc 100644 --- a/lms/djangoapps/grades/tests/test_course_grade.py +++ b/lms/djangoapps/grades/tests/test_course_grade.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - import ddt import six from crum import set_current_request diff --git a/lms/djangoapps/grades/tests/test_course_grade_factory.py b/lms/djangoapps/grades/tests/test_course_grade_factory.py index dc41c26978b44d7dc6a1c928ddfa8bc9e89bdad7..fe1b193870a20f64aed3091fa215717e8d065576 100644 --- a/lms/djangoapps/grades/tests/test_course_grade_factory.py +++ b/lms/djangoapps/grades/tests/test_course_grade_factory.py @@ -202,12 +202,12 @@ class TestCourseGradeFactory(GradeTestBase): 'Homework': { 'category': 'Homework', 'percent': 0.25, - 'detail': 'Homework = 25.00% of a possible 100.00%', # pylint: disable=unicode-format-string + 'detail': 'Homework = 25.00% of a possible 100.00%', }, 'NoCredit': { 'category': 'NoCredit', 'percent': 0.0, - 'detail': 'NoCredit = 0.00% of a possible 0.00%', # pylint: disable=unicode-format-string + 'detail': 'NoCredit = 0.00% of a possible 0.00%', } }, 'percent': 0.25, diff --git a/lms/djangoapps/instructor/message_types.py b/lms/djangoapps/instructor/message_types.py index 51429e29aa4e3962a327e94e35ec0a76af7067ba..ca96316eaa171a195a854870b4adfa67050c12ab 100644 --- a/lms/djangoapps/instructor/message_types.py +++ b/lms/djangoapps/instructor/message_types.py @@ -16,7 +16,7 @@ class AccountCreationAndEnrollment(BaseMessageType): def __init__(self, *args, **kwargs): super(AccountCreationAndEnrollment, self).__init__(*args, **kwargs) - self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + self.options['transactional'] = True class AddBetaTester(BaseMessageType): @@ -27,7 +27,7 @@ class AddBetaTester(BaseMessageType): def __init__(self, *args, **kwargs): super(AddBetaTester, self).__init__(*args, **kwargs) - self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + self.options['transactional'] = True class AllowedEnroll(BaseMessageType): @@ -38,7 +38,7 @@ class AllowedEnroll(BaseMessageType): def __init__(self, *args, **kwargs): super(AllowedEnroll, self).__init__(*args, **kwargs) - self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + self.options['transactional'] = True class AllowedUnenroll(BaseMessageType): @@ -49,7 +49,7 @@ class AllowedUnenroll(BaseMessageType): def __init__(self, *args, **kwargs): super(AllowedUnenroll, self).__init__(*args, **kwargs) - self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + self.options['transactional'] = True class EnrollEnrolled(BaseMessageType): @@ -60,7 +60,7 @@ class EnrollEnrolled(BaseMessageType): def __init__(self, *args, **kwargs): super(EnrollEnrolled, self).__init__(*args, **kwargs) - self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + self.options['transactional'] = True class EnrolledUnenroll(BaseMessageType): @@ -71,7 +71,7 @@ class EnrolledUnenroll(BaseMessageType): def __init__(self, *args, **kwargs): super(EnrolledUnenroll, self).__init__(*args, **kwargs) - self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + self.options['transactional'] = True class RemoveBetaTester(BaseMessageType): @@ -82,4 +82,4 @@ class RemoveBetaTester(BaseMessageType): def __init__(self, *args, **kwargs): super(RemoveBetaTester, self).__init__(*args, **kwargs) - self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + self.options['transactional'] = True diff --git a/lms/djangoapps/instructor/permissions.py b/lms/djangoapps/instructor/permissions.py index e1d75a235b6fe12b5e81b4ac021fe8122c77edde..e766dedc0b6c55825006589d93d3627f4c68cca4 100644 --- a/lms/djangoapps/instructor/permissions.py +++ b/lms/djangoapps/instructor/permissions.py @@ -4,7 +4,8 @@ Permissions for the instructor dashboard and associated actions from bridgekeeper import perms from bridgekeeper.rules import is_staff -from lms.djangoapps.courseware.rules import HasAccessRule +from lms.djangoapps.courseware.rules import HasAccessRule, HasRolesRule + ALLOW_STUDENT_TO_BYPASS_ENTRANCE_EXAM = 'instructor.allow_student_to_bypass_entrance_exam' ASSIGN_TO_COHORTS = 'instructor.assign_to_cohorts' @@ -16,6 +17,18 @@ GENERATE_CERTIFICATE_EXCEPTIONS = 'instructor.generate_certificate_exceptions' GENERATE_BULK_CERTIFICATE_EXCEPTIONS = 'instructor.generate_bulk_certificate_exceptions' GIVE_STUDENT_EXTENSION = 'instructor.give_student_extension' VIEW_ISSUED_CERTIFICATES = 'instructor.view_issued_certificates' +CAN_RESEARCH = 'instructor.research' +CAN_ENROLL = 'instructor.enroll' +CAN_BETATEST = 'instructor.enroll_beta' +ENROLLMENT_REPORT = 'instructor.enrollment_report' +EXAM_RESULTS = 'instructor.view_exam_results' +OVERRIDE_GRADES = 'instructor.override_grades' +SHOW_TASKS = 'instructor.show_tasks' +VIEW_COUPONS = 'instructor.view_coupons' +EMAIL = 'instructor.email' +RESCORE_EXAMS = 'instructor.rescore_exams' +VIEW_REGISTRATION = 'instructor.view_registration' +VIEW_DASHBOARD = 'instructor.dashboard' perms[ALLOW_STUDENT_TO_BYPASS_ENTRANCE_EXAM] = HasAccessRule('staff') @@ -27,4 +40,23 @@ perms[ENABLE_CERTIFICATE_GENERATION] = is_staff perms[GENERATE_CERTIFICATE_EXCEPTIONS] = is_staff perms[GENERATE_BULK_CERTIFICATE_EXCEPTIONS] = is_staff perms[GIVE_STUDENT_EXTENSION] = HasAccessRule('staff') -perms[VIEW_ISSUED_CERTIFICATES] = HasAccessRule('staff') +perms[VIEW_ISSUED_CERTIFICATES] = HasAccessRule('staff') | HasRolesRule('data_researcher') +# only global staff or those with the data_researcher role can access the data download tab +# HasAccessRule('staff') also includes course staff +perms[CAN_RESEARCH] = is_staff | HasRolesRule('data_researcher') +perms[CAN_ENROLL] = HasAccessRule('staff') +perms[CAN_BETATEST] = HasAccessRule('instructor') +perms[ENROLLMENT_REPORT] = HasAccessRule('staff') | HasRolesRule('data_researcher') +perms[VIEW_COUPONS] = HasAccessRule('staff') | HasRolesRule('data_researcher') +perms[EXAM_RESULTS] = HasAccessRule('staff') +perms[OVERRIDE_GRADES] = HasAccessRule('staff') +perms[SHOW_TASKS] = HasAccessRule('staff') | HasRolesRule('data_researcher') +perms[EMAIL] = HasAccessRule('staff') +perms[RESCORE_EXAMS] = HasAccessRule('instructor') +perms[VIEW_REGISTRATION] = HasAccessRule('staff') +perms[VIEW_DASHBOARD] = \ + HasRolesRule( + 'staff', + 'instructor', + 'data_researcher' +) | HasAccessRule('staff') | HasAccessRule('instructor') diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py index e75fc2b49687efe975102f32dedfabcd5127ad8f..756ea921747693d2958a6140496fb8f4ad56f23a 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -22,15 +22,14 @@ from django.core import mail from django.core.files.uploadedfile import SimpleUploadedFile from django.http import HttpRequest, HttpResponse from django.test import RequestFactory, TestCase -from django.test.utils import override_settings from django.urls import reverse as django_reverse from django.utils.translation import ugettext as _ -from edx_when.api import get_overrides_for_user +from edx_when.api import get_dates_for_course, get_overrides_for_user, set_date_for_block from mock import Mock, NonCallableMock, patch from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locator import UsageKey from pytz import UTC -from six import text_type, unichr # pylint: disable=redefined-builtin +from six import text_type, unichr from six.moves import range, zip from testfixtures import LogCapture @@ -72,17 +71,6 @@ from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from openedx.core.lib.teams_config import TeamsConfig from openedx.core.lib.xblock_utils import grade_histogram from openedx.features.course_experience import RELATIVE_DATES_FLAG -from shoppingcart.models import ( - Coupon, - CouponRedemption, - CourseRegistrationCode, - CourseRegistrationCodeInvoiceItem, - Invoice, - InvoiceTransaction, - Order, - PaidCourseRegistration, - RegistrationCodeRedemption -) from student.models import ( ALLOWEDTOENROLL_TO_ENROLLED, ALLOWEDTOENROLL_TO_UNENROLLED, @@ -115,8 +103,6 @@ EXPECTED_CSV_HEADER = ( '"code","redeem_code_url","course_id","company_name","created_by","redeemed_by","invoice_id","purchaser",' '"customer_reference_number","internal_reference"' ) -EXPECTED_COUPON_CSV_HEADER = u'"Coupon Code","Course Id","% Discount","Description","Expiration Date",' \ - u'"Is Active","Code Redeemed Count","Total Discounted Seats","Total Discounted Amount"' # ddt data for test cases involving reports REPORTS_DATA = ( @@ -172,35 +158,27 @@ EXECUTIVE_SUMMARY_DATA = ( INSTRUCTOR_GET_ENDPOINTS = set([ 'get_anon_ids', - 'get_coupon_codes', 'get_issued_certificates', - 'get_sale_order_records', - 'get_sale_records', ]) INSTRUCTOR_POST_ENDPOINTS = set([ - 'active_registration_codes', 'add_users_to_cohorts', 'bulk_beta_modify_access', 'calculate_grades_csv', 'change_due_date', 'export_ora2_data', - 'generate_registration_codes', 'get_enrollment_report', 'get_exec_summary_report', 'get_grading_config', 'get_problem_responses', 'get_proctored_exam_results', - 'get_registration_codes', 'get_student_enrollment_status', 'get_student_progress_url', 'get_students_features', 'get_students_who_may_enroll', - 'get_user_invoice_preference', 'list_background_email_tasks', 'list_course_role_members', 'list_email_content', 'list_entrance_exam_instructor_tasks', - 'list_financial_report_downloads', 'list_forum_members', 'list_instructor_tasks', 'list_report_downloads', @@ -212,11 +190,9 @@ INSTRUCTOR_POST_ENDPOINTS = set([ 'reset_due_date', 'reset_student_attempts', 'reset_student_attempts_for_entrance_exam', - 'sale_validation', 'show_student_extensions', 'show_unit_extensions', 'send_email', - 'spent_registration_codes', 'students_update_enrollment', 'update_forum_role_membership', 'override_problem_score', @@ -249,25 +225,25 @@ def reverse(endpoint, args=None, kwargs=None, is_dashboard_endpoint=True): @common_exceptions_400 -def view_success(request): # pylint: disable=unused-argument +def view_success(request): "A dummy view for testing that returns a simple HTTP response" return HttpResponse('success') @common_exceptions_400 -def view_user_doesnotexist(request): # pylint: disable=unused-argument +def view_user_doesnotexist(request): "A dummy view that raises a User.DoesNotExist exception" raise User.DoesNotExist() @common_exceptions_400 -def view_alreadyrunningerror(request): # pylint: disable=unused-argument +def view_alreadyrunningerror(request): "A dummy view that raises an AlreadyRunningError exception" raise AlreadyRunningError() @common_exceptions_400 -def view_alreadyrunningerror_unicode(request): # pylint: disable=unused-argument +def view_alreadyrunningerror_unicode(request): """ A dummy view that raises an AlreadyRunningError exception with unicode message """ @@ -275,7 +251,7 @@ def view_alreadyrunningerror_unicode(request): # pylint: disable=unused-argumen @common_exceptions_400 -def view_queue_connection_error(request): # pylint: disable=unused-argument +def view_queue_connection_error(request): """ A dummy view that raises a QueueConnectionError exception. """ @@ -299,24 +275,24 @@ class TestCommonExceptions400(TestCase): def test_user_doesnotexist(self): self.request.is_ajax.return_value = False - resp = view_user_doesnotexist(self.request) # pylint: disable=assignment-from-no-return + resp = view_user_doesnotexist(self.request) self.assertContains(resp, "User does not exist", status_code=400) def test_user_doesnotexist_ajax(self): self.request.is_ajax.return_value = True - resp = view_user_doesnotexist(self.request) # pylint: disable=assignment-from-no-return + resp = view_user_doesnotexist(self.request) self.assertContains(resp, "User does not exist", status_code=400) @ddt.data(True, False) def test_alreadyrunningerror(self, is_ajax): self.request.is_ajax.return_value = is_ajax - resp = view_alreadyrunningerror(self.request) # pylint: disable=assignment-from-no-return + resp = view_alreadyrunningerror(self.request) self.assertContains(resp, "Requested task is already running", status_code=400) @ddt.data(True, False) def test_alreadyrunningerror_with_unicode(self, is_ajax): self.request.is_ajax.return_value = is_ajax - resp = view_alreadyrunningerror_unicode(self.request) # pylint: disable=assignment-from-no-return + resp = view_alreadyrunningerror_unicode(self.request) self.assertContains( resp, u'Text with unicode chárácters', @@ -329,7 +305,7 @@ class TestCommonExceptions400(TestCase): Tests that QueueConnectionError exception is handled in common_exception_400. """ self.request.is_ajax.return_value = is_ajax - resp = view_queue_connection_error(self.request) # pylint: disable=assignment-from-no-return + resp = view_queue_connection_error(self.request) self.assertContains( resp, 'Error occured. Please try again later', @@ -465,7 +441,6 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest ('list_instructor_tasks', {}), ('list_background_email_tasks', {}), ('list_report_downloads', {}), - ('list_financial_report_downloads', {}), ('calculate_grades_csv', {}), ('get_students_features', {}), ('get_enrollment_report', {}), @@ -1062,32 +1037,6 @@ class TestInstructorAPIBulkAccountCreationAndEnrollment(SharedModuleStoreTestCas for enrollment in manual_enrollments: self.assertEqual(enrollment.enrollment.mode, CourseMode.HONOR) - @patch.dict(settings.FEATURES, {'ALLOW_AUTOMATED_SIGNUPS': True}) - def test_default_shopping_cart_enrollment_mode_for_white_label(self): - """ - Test that enrollment mode for white label courses (paid courses) is DEFAULT_SHOPPINGCART_MODE_SLUG. - """ - # Login white label course instructor - self.client.login(username=self.white_label_course_instructor.username, password='test') - - csv_content = b"test_student_wl@example.com,test_student_wl,Test Student,USA" - uploaded_file = SimpleUploadedFile("temp.csv", csv_content) - response = self.client.post(self.white_label_course_url, {'students_list': uploaded_file}) - - self.assertEqual(response.status_code, 200) - data = json.loads(response.content.decode('utf-8')) - self.assertEqual(len(data['row_errors']), 0) - self.assertEqual(len(data['warnings']), 0) - self.assertEqual(len(data['general_errors']), 0) - - manual_enrollments = ManualEnrollmentAudit.objects.all() - self.assertEqual(manual_enrollments.count(), 1) - self.assertEqual(manual_enrollments[0].state_transition, UNENROLLED_TO_ENROLLED) - - # Verify enrollment modes to be CourseMode.DEFAULT_SHOPPINGCART_MODE_SLUG - for enrollment in manual_enrollments: - self.assertEqual(enrollment.enrollment.mode, CourseMode.DEFAULT_SHOPPINGCART_MODE_SLUG) - @ddt.ddt class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTestCase): @@ -2612,24 +2561,6 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment self.instructor = InstructorFactory(course_key=self.course.id) CourseDataResearcherRole(self.course.id).add_users(self.instructor) self.client.login(username=self.instructor.username, password='test') - self.cart = Order.get_cart_for_user(self.instructor) - self.coupon_code = 'abcde' - self.coupon = Coupon(code=self.coupon_code, description='testing code', course_id=self.course.id, - percentage_discount=10, created_by=self.instructor, is_active=True) - self.coupon.save() - - # Create testing invoice 1 - self.sale_invoice_1 = Invoice.objects.create( - total_amount=1234.32, company_name='Test1', company_contact_name='TestName', company_contact_email='Test@company.com', - recipient_name='Testw', recipient_email='test1@test.com', customer_reference_number='2Fwe23S', - internal_reference="A", course_id=self.course.id, is_valid=True - ) - self.invoice_item = CourseRegistrationCodeInvoiceItem.objects.create( - invoice=self.sale_invoice_1, - qty=1, - unit_price=1234.32, - course_id=self.course.id - ) self.students = [UserFactory() for _ in range(6)] for student in self.students: @@ -2641,292 +2572,6 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment email=student.email, course_id=self.course.id ) - def register_with_redemption_code(self, user, code): - """ - enroll user using a registration code - """ - redeem_url = reverse('register_code_redemption', args=[code], is_dashboard_endpoint=False) - self.client.login(username=user.username, password='test') - response = self.client.get(redeem_url) - self.assertEqual(response.status_code, 200) - # check button text - self.assertContains(response, 'Activate Course Enrollment') - - response = self.client.post(redeem_url) - self.assertEqual(response.status_code, 200) - - def test_invalidate_sale_record(self): - """ - Testing the sale invalidating scenario. - """ - for i in range(2): - course_registration_code = CourseRegistrationCode( - code='sale_invoice{}'.format(i), - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice_1, - invoice_item=self.invoice_item, - mode_slug='honor' - ) - course_registration_code.save() - - data = {'invoice_number': self.sale_invoice_1.id, 'event_type': "invalidate"} - url = reverse('sale_validation', kwargs={'course_id': text_type(self.course.id)}) - self.assert_request_status_code(200, url, method="POST", data=data) - - #Now try to fetch data against not existing invoice number - test_data_1 = {'invoice_number': 100, 'event_type': "invalidate"} - self.assert_request_status_code(404, url, method="POST", data=test_data_1) - - # Now invalidate the same invoice number and expect an Bad request - response = self.assert_request_status_code(400, url, method="POST", data=data) - self.assertContains( - response, - "The sale associated with this invoice has already been invalidated.", - status_code=400, - ) - - # now re_validate the invoice number - data['event_type'] = "re_validate" - self.assert_request_status_code(200, url, method="POST", data=data) - - # Now re_validate the same active invoice number and expect an Bad request - response = self.assert_request_status_code(400, url, method="POST", data=data) - self.assertContains(response, "This invoice is already active.", status_code=400) - - test_data_2 = {'invoice_number': self.sale_invoice_1.id} - response = self.assert_request_status_code(400, url, method="POST", data=test_data_2) - self.assertContains(response, "Missing required event_type parameter", status_code=400) - - test_data_3 = {'event_type': "re_validate"} - response = self.assert_request_status_code(400, url, method="POST", data=test_data_3) - self.assertContains(response, "Missing required invoice_number parameter", status_code=400) - - # submitting invalid invoice number - data['invoice_number'] = 'testing' - response = self.assert_request_status_code(400, url, method="POST", data=data) - self.assertContains( - response, - u"invoice_number must be an integer, {value} provided".format(value=data['invoice_number']), - status_code=400, - ) - - def test_get_sale_order_records_features_csv(self): - """ - Test that the response from get_sale_order_records is in csv format. - """ - # add the coupon code for the course - coupon = Coupon( - code='test_code', description='test_description', course_id=self.course.id, - percentage_discount='10', created_by=self.instructor, is_active=True - ) - coupon.save() - self.cart.order_type = 'business' - self.cart.save() - self.cart.add_billing_details(company_name='Test Company', company_contact_name='Test', - company_contact_email='test@123', recipient_name='R1', - recipient_email='', customer_reference_number='PO#23') - - paid_course_reg_item = PaidCourseRegistration.add_to_order( - self.cart, - self.course.id, - mode_slug=CourseMode.HONOR - ) - # update the quantity of the cart item paid_course_reg_item - resp = self.client.post( - reverse('shoppingcart.views.update_user_cart', is_dashboard_endpoint=False), - {'ItemId': paid_course_reg_item.id, 'qty': '4'} - ) - self.assertEqual(resp.status_code, 200) - # apply the coupon code to the item in the cart - resp = self.client.post( - reverse('shoppingcart.views.use_code', is_dashboard_endpoint=False), - {'code': coupon.code} - ) - self.assertEqual(resp.status_code, 200) - self.cart.purchase() - # get the updated item - item = self.cart.orderitem_set.all().select_subclasses()[0] - # get the redeemed coupon information - coupon_redemption = CouponRedemption.objects.select_related('coupon').filter(order=self.cart) - - sale_order_url = reverse('get_sale_order_records', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(sale_order_url) - self.assertEqual(response['Content-Type'], 'text/csv') - self.assertIn('36', response.content.decode('utf-8').split('\r\n')[1]) - self.assertIn(str(item.unit_cost), response.content.decode('utf-8').split('\r\n')[1],) - self.assertIn(str(item.list_price), response.content.decode('utf-8').split('\r\n')[1],) - self.assertIn(item.status, response.content.decode('utf-8').split('\r\n')[1],) - self.assertIn(coupon_redemption[0].coupon.code, response.content.decode('utf-8').split('\r\n')[1],) - - def test_coupon_redeem_count_in_ecommerce_section(self): - """ - Test that checks the redeem count in the instructor_dashboard coupon section - """ - # add the coupon code for the course - coupon = Coupon( - code='test_code', description='test_description', course_id=self.course.id, - percentage_discount='10', created_by=self.instructor, is_active=True - ) - coupon.save() - - # Coupon Redeem Count only visible for Financial Admins. - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - - PaidCourseRegistration.add_to_order(self.cart, self.course.id) - # apply the coupon code to the item in the cart - resp = self.client.post( - reverse('shoppingcart.views.use_code', is_dashboard_endpoint=False), - {'code': coupon.code} - ) - self.assertEqual(resp.status_code, 200) - - # URL for instructor dashboard - instructor_dashboard = reverse( - 'instructor_dashboard', - kwargs={'course_id': text_type(self.course.id)}, - is_dashboard_endpoint=False - ) - # visit the instructor dashboard page and - # check that the coupon redeem count should be 0 - resp = self.client.get(instructor_dashboard) - self.assertContains(resp, 'Number Redeemed') - self.assertContains(resp, '<td>0</td>') - - # now make the payment of your cart items - self.cart.purchase() - # visit the instructor dashboard page and - # check that the coupon redeem count should be 1 - resp = self.client.get(instructor_dashboard) - - self.assertContains(resp, 'Number Redeemed') - self.assertContains(resp, '<td>1</td>') - - def test_get_sale_records_features_csv(self): - """ - Test that the response from get_sale_records is in csv format. - """ - for i in range(2): - course_registration_code = CourseRegistrationCode( - code='sale_invoice{}'.format(i), - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice_1, - invoice_item=self.invoice_item, - mode_slug='honor' - ) - course_registration_code.save() - - url = reverse( - 'get_sale_records', - kwargs={'course_id': text_type(self.course.id)} - ) - response = self.client.post(url + '/csv', {}) - self.assertEqual(response['Content-Type'], 'text/csv') - - def test_get_sale_records_features_json(self): - """ - Test that the response from get_sale_records is in json format. - """ - for i in range(5): - course_registration_code = CourseRegistrationCode( - code='sale_invoice{}'.format(i), - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice_1, - invoice_item=self.invoice_item, - mode_slug='honor' - ) - course_registration_code.save() - - url = reverse('get_sale_records', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(url, {}) - res_json = json.loads(response.content.decode('utf-8')) - self.assertIn('sale', res_json) - - for res in res_json['sale']: - self.validate_sale_records_response( - res, - course_registration_code, - self.sale_invoice_1, - 0, - invoice_item=self.invoice_item - ) - - def test_get_sale_records_features_with_multiple_invoices(self): - """ - Test that the response from get_sale_records is in json format for multiple invoices - """ - for i in range(5): - course_registration_code = CourseRegistrationCode( - code='qwerty{}'.format(i), - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice_1, - invoice_item=self.invoice_item, - mode_slug='honor' - ) - course_registration_code.save() - - # Create test invoice 2 - sale_invoice_2 = Invoice.objects.create( - total_amount=1234.32, company_name='Test1', company_contact_name='TestName', company_contact_email='Test@company.com', - recipient_name='Testw_2', recipient_email='test2@test.com', customer_reference_number='2Fwe23S', - internal_reference="B", course_id=self.course.id - ) - - invoice_item_2 = CourseRegistrationCodeInvoiceItem.objects.create( - invoice=sale_invoice_2, - qty=1, - unit_price=1234.32, - course_id=self.course.id - ) - - for i in range(5): - course_registration_code = CourseRegistrationCode( - code='xyzmn{}'.format(i), course_id=text_type(self.course.id), - created_by=self.instructor, invoice=sale_invoice_2, invoice_item=invoice_item_2, mode_slug='honor' - ) - course_registration_code.save() - - url = reverse('get_sale_records', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(url, {}) - res_json = json.loads(response.content.decode('utf-8')) - self.assertIn('sale', res_json) - - self.validate_sale_records_response( - res_json['sale'][0], - course_registration_code, - self.sale_invoice_1, - 0, - invoice_item=self.invoice_item - ) - self.validate_sale_records_response( - res_json['sale'][1], - course_registration_code, - sale_invoice_2, - 0, - invoice_item=invoice_item_2 - ) - - def validate_sale_records_response(self, res, course_registration_code, invoice, used_codes, invoice_item): - """ - validate sale records attribute values with the response object - """ - self.assertEqual(res['total_amount'], invoice.total_amount) - self.assertEqual(res['recipient_email'], invoice.recipient_email) - self.assertEqual(res['recipient_name'], invoice.recipient_name) - self.assertEqual(res['company_name'], invoice.company_name) - self.assertEqual(res['company_contact_name'], invoice.company_contact_name) - self.assertEqual(res['company_contact_email'], invoice.company_contact_email) - self.assertEqual(res['internal_reference'], invoice.internal_reference) - self.assertEqual(res['customer_reference_number'], invoice.customer_reference_number) - self.assertEqual(res['invoice_number'], invoice.id) - self.assertEqual(res['created_by'], course_registration_code.created_by.username) - self.assertEqual(res['course_id'], text_type(invoice_item.course_id)) - self.assertEqual(res['total_used_codes'], used_codes) - self.assertEqual(res['total_codes'], 5) - def test_get_problem_responses_invalid_location(self): """ Test whether get_problem_responses returns an appropriate status @@ -3145,148 +2790,6 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment decorated_func(request, text_type(self.course.id)) self.assertTrue(func.called) - def test_enrollment_report_features_csv(self): - """ - test to generate enrollment report. - enroll users, admin staff using registration codes. - """ - InvoiceTransaction.objects.create( - invoice=self.sale_invoice_1, - amount=self.sale_invoice_1.total_amount, - status='completed', - created_by=self.instructor, - last_modified_by=self.instructor - ) - course_registration_code = CourseRegistrationCode.objects.create( - code='abcde', - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice_1, - invoice_item=self.invoice_item, - mode_slug='honor' - ) - - admin_user = AdminFactory() - admin_cart = Order.get_cart_for_user(admin_user) - PaidCourseRegistration.add_to_order(admin_cart, self.course.id) - admin_cart.purchase() - - # create a new user/student and enroll - # in the course using a registration code - # and then validates the generated detailed enrollment report - test_user = UserFactory() - self.register_with_redemption_code(test_user, course_registration_code.code) - - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - UserProfileFactory.create(user=self.students[0], meta='{"company": "asdasda"}') - - self.client.login(username=self.instructor.username, password='test') - url = reverse('get_enrollment_report', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(url, {}) - self.assertContains(response, 'The detailed enrollment report is being created.') - - def test_bulk_purchase_detailed_report(self): - """ - test to generate detailed enrollment report. - 1 Purchase registration codes. - 2 Enroll users via registration code. - 3 Validate generated enrollment report. - """ - paid_course_reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course.id) - # update the quantity of the cart item paid_course_reg_item - resp = self.client.post( - reverse('shoppingcart.views.update_user_cart', is_dashboard_endpoint=False), - {'ItemId': paid_course_reg_item.id, 'qty': '4'} - ) - self.assertEqual(resp.status_code, 200) - # apply the coupon code to the item in the cart - resp = self.client.post( - reverse('shoppingcart.views.use_code', is_dashboard_endpoint=False), - {'code': self.coupon_code} - ) - self.assertEqual(resp.status_code, 200) - self.cart.purchase() - - course_reg_codes = CourseRegistrationCode.objects.filter(order=self.cart) - self.register_with_redemption_code(self.instructor, course_reg_codes[0].code) - - test_user = UserFactory() - test_user_cart = Order.get_cart_for_user(test_user) - PaidCourseRegistration.add_to_order(test_user_cart, self.course.id) - test_user_cart.purchase() - InvoiceTransaction.objects.create( - invoice=self.sale_invoice_1, - amount=-self.sale_invoice_1.total_amount, - status='refunded', - created_by=self.instructor, - last_modified_by=self.instructor - ) - course_registration_code = CourseRegistrationCode.objects.create( - code='abcde', - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice_1, - invoice_item=self.invoice_item, - mode_slug='honor' - ) - - test_user1 = UserFactory() - self.register_with_redemption_code(test_user1, course_registration_code.code) - - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - self.client.login(username=self.instructor.username, password='test') - - url = reverse('get_enrollment_report', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(url, {}) - self.assertContains(response, 'The detailed enrollment report is being created.') - - def test_create_registration_code_without_invoice_and_order(self): - """ - test generate detailed enrollment report, - used a registration codes which has been created via invoice or bulk - purchase scenario. - """ - course_registration_code = CourseRegistrationCode.objects.create( - code='abcde', - course_id=text_type(self.course.id), - created_by=self.instructor, - mode_slug='honor' - ) - test_user1 = UserFactory() - self.register_with_redemption_code(test_user1, course_registration_code.code) - - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - self.client.login(username=self.instructor.username, password='test') - - url = reverse('get_enrollment_report', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(url, {}) - self.assertContains(response, 'The detailed enrollment report is being created.') - - def test_invoice_payment_is_still_pending_for_registration_codes(self): - """ - test generate enrollment report - enroll a user in a course using registration code - whose invoice has not been paid yet - """ - course_registration_code = CourseRegistrationCode.objects.create( - code='abcde', - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice_1, - invoice_item=self.invoice_item, - mode_slug='honor' - ) - - test_user1 = UserFactory() - self.register_with_redemption_code(test_user1, course_registration_code.code) - - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - self.client.login(username=self.instructor.username, password='test') - - url = reverse('get_enrollment_report', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(url, {}) - self.assertContains(response, 'The detailed enrollment report is being created.') - @patch('lms.djangoapps.instructor.views.api.anonymous_id_for_user', Mock(return_value='42')) @patch('lms.djangoapps.instructor.views.api.unique_id_for_user', Mock(return_value='41')) def test_get_anon_ids(self): @@ -4397,11 +3900,18 @@ def get_extended_due(course, unit, user): for override in dates: if text_type(override['location']) == location: return override['actual_date'] - print(unit.location) - print(dates) return None +def get_date_for_block(course, unit, user): + """ + Gets the due date for the given user on the given unit (overridden or original). + Returns `None` if there is no date set. + (Differs from edx-when's get_date_for_block only in that we skip the cache. + """ + return get_dates_for_course(course.id, user=user, use_cached=False).get((unit.location, 'due'), None) + + class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase): """ Test data dumps for reporting. @@ -4538,6 +4048,28 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase): get_extended_due(self.course, self.week1, self.user1) ) + @RELATIVE_DATES_FLAG.override(True) + def test_reset_date_only_in_edx_when(self): + # Start with a unit that only has a date in edx-when + self.assertEqual(get_date_for_block(self.course, self.week3, self.user1), None) + original_due = datetime.datetime(2010, 4, 1, tzinfo=UTC) + set_date_for_block(self.course.id, self.week3.location, 'due', original_due) + self.assertEqual(get_date_for_block(self.course, self.week3, self.user1), original_due) + + # set override, confirm it took + override = datetime.datetime(2010, 7, 1, tzinfo=UTC) + set_date_for_block(self.course.id, self.week3.location, 'due', override, user=self.user1) + self.assertEqual(get_date_for_block(self.course, self.week3, self.user1), override) + + # Now test that we noticed the edx-when date + url = reverse('reset_due_date', kwargs={'course_id': text_type(self.course.id)}) + response = self.client.post(url, { + 'student': self.user1.username, + 'url': text_type(self.week3.location), + }) + self.assertContains(response, 'Successfully reset due date for student') + self.assertEqual(get_date_for_block(self.course, self.week3, self.user1), original_due) + def test_show_unit_extensions(self): self.test_change_due_date() url = reverse('show_unit_extensions', @@ -4792,448 +4324,6 @@ class TestCourseIssuedCertificatesData(SharedModuleStoreTestCase): ) -@override_settings(REGISTRATION_CODE_LENGTH=8) -class TestCourseRegistrationCodes(SharedModuleStoreTestCase): - """ - Test data dumps for E-commerce Course Registration Codes. - """ - @classmethod - def setUpClass(cls): - super(TestCourseRegistrationCodes, cls).setUpClass() - cls.course = CourseFactory.create() - cls.url = reverse( - 'generate_registration_codes', - kwargs={'course_id': text_type(cls.course.id)} - ) - - def setUp(self): - """ - Fixtures. - """ - super(TestCourseRegistrationCodes, self).setUp() - - CourseModeFactory.create(course_id=self.course.id, min_price=50) - self.instructor = InstructorFactory(course_key=self.course.id) - self.client.login(username=self.instructor.username, password='test') - CourseSalesAdminRole(self.course.id).add_users(self.instructor) - - data = { - 'total_registration_codes': 12, 'company_name': 'Test Group', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 122.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', - 'address_line_2': '', 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': '' - } - - response = self.client.post(self.url, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - for i in range(5): - order = Order(user=self.instructor, status='purchased') - order.save() - - # Spent(used) Registration Codes - for i in range(5): - i += 1 - registration_code_redemption = RegistrationCodeRedemption( - registration_code_id=i, - redeemed_by=self.instructor - ) - registration_code_redemption.save() - - @override_settings(FINANCE_EMAIL='finance@example.com') - def test_finance_email_in_recipient_list_when_generating_registration_codes(self): - """ - Test to verify that the invoice will also be sent to the FINANCE_EMAIL when - generating registration codes - """ - url_reg_code = reverse('generate_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - data = { - 'total_registration_codes': 5, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 121.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': 'True' - } - - response = self.client.post(url_reg_code, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - # check for the last mail.outbox, The FINANCE_EMAIL has been appended at the - # very end, when generating registration codes - self.assertEqual(mail.outbox[-1].to[0], 'finance@example.com') - - def test_user_invoice_copy_preference(self): - """ - Test to remember user invoice copy preference - """ - url_reg_code = reverse('generate_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - data = { - 'total_registration_codes': 5, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 121.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': 'True' - } - - # user invoice copy preference will be saved in api user preference; model - response = self.client.post(url_reg_code, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - - # get user invoice copy preference. - url_user_invoice_preference = reverse('get_user_invoice_preference', - kwargs={'course_id': text_type(self.course.id)}) - - response = self.client.post(url_user_invoice_preference, data) - result = json.loads(response.content.decode('utf-8')) - self.assertEqual(result['invoice_copy'], True) - - # updating the user invoice copy preference during code generation flow - data['invoice'] = '' - response = self.client.post(url_reg_code, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - - # get user invoice copy preference. - url_user_invoice_preference = reverse('get_user_invoice_preference', - kwargs={'course_id': text_type(self.course.id)}) - - response = self.client.post(url_user_invoice_preference, data) - result = json.loads(response.content.decode('utf-8')) - self.assertEqual(result['invoice_copy'], False) - - def test_generate_course_registration_codes_csv(self): - """ - Test to generate a response of all the generated course registration codes - """ - url = reverse('generate_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - data = { - 'total_registration_codes': 15, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 122.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': '' - } - - response = self.client.post(url, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - self.assertEqual(len(body.split('\n')), 17) - - def test_generate_course_registration_with_redeem_url_codes_csv(self): - """ - Test to generate a response of all the generated course registration codes - """ - url = reverse('generate_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - data = { - 'total_registration_codes': 15, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 122.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': '' - } - - response = self.client.post(url, data, **{'HTTP_HOST': 'localhost'}) - - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - self.assertEqual(len(body.split('\n')), 17) - rows = body.split('\n') - index = 1 - while index < len(rows): - if rows[index]: - row_data = rows[index].split(',') - code = row_data[0].replace('"', '') - self.assertTrue(row_data[1].startswith('"http') - and row_data[1].endswith('/shoppingcart/register/redeem/{0}/"'.format(code))) - index += 1 - - @patch('lms.djangoapps.instructor.views.api.random_code_generator', - Mock(side_effect=['first', 'second', 'third', 'fourth'])) - def test_generate_course_registration_codes_matching_existing_coupon_code(self): - """ - Test the generated course registration code is already in the Coupon Table - """ - url = reverse('generate_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - coupon = Coupon(code='first', course_id=text_type(self.course.id), created_by=self.instructor) - coupon.save() - data = { - 'total_registration_codes': 3, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 122.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': '' - } - - response = self.client.post(url, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - self.assertEqual(len(body.split('\n')), 5) # 1 for headers, 1 for new line at the end and 3 for the actual data - - @patch('lms.djangoapps.instructor.views.api.random_code_generator', - Mock(side_effect=['first', 'first', 'second', 'third'])) - def test_generate_course_registration_codes_integrity_error(self): - """ - Test for the Integrity error against the generated code - """ - url = reverse('generate_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - data = { - 'total_registration_codes': 2, 'company_name': 'Test Group', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 122.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': '' - } - - response = self.client.post(url, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - self.assertEqual(len(body.split('\n')), 4) - - def test_spent_course_registration_codes_csv(self): - """ - Test to generate a response of all the spent course registration codes - """ - url = reverse('spent_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - data = {'spent_company_name': ''} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - - self.assertEqual(len(body.split('\n')), 7) - - generate_code_url = reverse( - 'generate_registration_codes', kwargs={'course_id': text_type(self.course.id)} - ) - - data = { - 'total_registration_codes': 9, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com', - 'unit_price': 122.45, 'company_contact_email': 'Test@company.com', 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': '' - } - - response = self.client.post(generate_code_url, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - - for i in range(9): - order = Order(user=self.instructor, status='purchased') - order.save() - - # Spent(used) Registration Codes - for i in range(9): - i += 13 - registration_code_redemption = RegistrationCodeRedemption( - registration_code_id=i, - redeemed_by=self.instructor - ) - registration_code_redemption.save() - - data = {'spent_company_name': 'Group Alpha'} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - self.assertEqual(len(body.split('\n')), 11) - - def test_active_course_registration_codes_csv(self): - """ - Test to generate a response of all the active course registration codes - """ - url = reverse('active_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - data = {'active_company_name': ''} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - self.assertEqual(len(body.split('\n')), 9) - - generate_code_url = reverse( - 'generate_registration_codes', kwargs={'course_id': text_type(self.course.id)} - ) - - data = { - 'total_registration_codes': 9, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 122.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': '' - } - - response = self.client.post(generate_code_url, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - - data = {'active_company_name': 'Group Alpha'} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - self.assertEqual(len(body.split('\n')), 11) - - def test_get_all_course_registration_codes_csv(self): - """ - Test to generate a response of all the course registration codes - """ - url = reverse( - 'get_registration_codes', kwargs={'course_id': text_type(self.course.id)} - ) - - data = {'download_company_name': ''} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - self.assertEqual(len(body.split('\n')), 14) - - generate_code_url = reverse( - 'generate_registration_codes', kwargs={'course_id': text_type(self.course.id)} - ) - - data = { - 'total_registration_codes': 9, 'company_name': 'Group Alpha', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 122.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': '' - } - - response = self.client.post(generate_code_url, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - - data = {'download_company_name': 'Group Alpha'} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - self.assertEqual(len(body.split('\n')), 11) - - def test_get_codes_with_sale_invoice(self): - """ - Test to generate a response of all the course registration codes - """ - generate_code_url = reverse( - 'generate_registration_codes', kwargs={'course_id': text_type(self.course.id)} - ) - - data = { - 'total_registration_codes': 5.5, 'company_name': 'Group Invoice', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 122.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': True - } - - response = self.client.post(generate_code_url, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - - url = reverse('get_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - data = {'download_company_name': 'Group Invoice'} - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_CSV_HEADER)) - - def test_with_invalid_unit_price(self): - """ - Test to generate a response of all the course registration codes - """ - generate_code_url = reverse( - 'generate_registration_codes', kwargs={'course_id': text_type(self.course.id)} - ) - - data = { - 'total_registration_codes': 10, 'company_name': 'Group Invoice', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 'invalid', 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': True - } - - response = self.client.post(generate_code_url, data, **{'HTTP_HOST': 'localhost'}) - self.assertContains(response, 'Could not parse amount as', status_code=400) - - def test_get_historical_coupon_codes(self): - """ - Test to download a response of all the active coupon codes - """ - get_coupon_code_url = reverse( - 'get_coupon_codes', kwargs={'course_id': text_type(self.course.id)} - ) - for i in range(10): - coupon = Coupon( - code='test_code{0}'.format(i), description='test_description', course_id=self.course.id, - percentage_discount='{0}'.format(i), created_by=self.instructor, is_active=True - ) - coupon.save() - - #now create coupons with the expiration dates - for i in range(5): - coupon = Coupon( - code='coupon{0}'.format(i), description='test_description', course_id=self.course.id, - percentage_discount='{0}'.format(i), created_by=self.instructor, is_active=True, - expiration_date=datetime.datetime.now(UTC) + datetime.timedelta(days=2) - ) - coupon.save() - - response = self.client.post(get_coupon_code_url) - self.assertEqual(response.status_code, 200, response.content) - # filter all the coupons - for coupon in Coupon.objects.all(): - self.assertIn( - '"{coupon_code}","{course_id}","{discount}","{description}","{expiration_date}","{is_active}",' - '"{code_redeemed_count}","{total_discounted_seats}","{total_discounted_amount}"'.format( - coupon_code=coupon.code, - course_id=coupon.course_id, - discount=coupon.percentage_discount, - description=coupon.description, - expiration_date=coupon.display_expiry_date, - is_active=coupon.is_active, - code_redeemed_count="0", - total_discounted_seats="0", - total_discounted_amount="0", - ), response.content.decode("utf-8") - ) - - self.assertEqual(response['Content-Type'], 'text/csv') - body = response.content.decode('utf-8').replace('\r', '') - self.assertTrue(body.startswith(EXPECTED_COUPON_CSV_HEADER)) - - class TestBulkCohorting(SharedModuleStoreTestCase): """ Test adding users to cohorts in bulk via CSV upload. diff --git a/lms/djangoapps/instructor/tests/test_ecommerce.py b/lms/djangoapps/instructor/tests/test_ecommerce.py deleted file mode 100644 index 00faa943aa892589e8a3ca17fe3dc1c1c377e4e7..0000000000000000000000000000000000000000 --- a/lms/djangoapps/instructor/tests/test_ecommerce.py +++ /dev/null @@ -1,412 +0,0 @@ -""" -Unit tests for Ecommerce feature flag in new instructor dashboard. -""" - - -import datetime - -import pytz -import six -from django.urls import reverse -from six import text_type - -from course_modes.models import CourseMode -from course_modes.tests.factories import CourseModeFactory -from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin -from shoppingcart.models import Coupon, CourseRegistrationCode -from student.roles import CourseFinanceAdminRole -from student.tests.factories import AdminFactory -from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory - - -class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase): - """ - Check for E-commerce view on the new instructor dashboard - """ - - @classmethod - def setUpClass(cls): - super(TestECommerceDashboardViews, cls).setUpClass() - cls.course = CourseFactory.create() - - # URL for instructor dash - cls.url = reverse('instructor_dashboard', kwargs={'course_id': text_type(cls.course.id)}) - cls.ecommerce_link = '<button type="button" class="btn-link e-commerce" data-section="e-commerce">E-Commerce</button>' - - def setUp(self): - super(TestECommerceDashboardViews, self).setUp() - - # Create instructor account - self.instructor = AdminFactory.create() - self.client.login(username=self.instructor.username, password="test") - mode = CourseModeFactory( - course_id=text_type(self.course.id), mode_slug='honor', - mode_display_name='honor', min_price=10, currency='usd' - ) - mode.save() - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - - def test_pass_e_commerce_tab_in_instructor_dashboard(self): - """ - Test Pass E-commerce Tab is in the Instructor Dashboard - """ - response = self.client.get(self.url) - self.assertContains(response, self.ecommerce_link) - # Coupons should show up for White Label sites with priced honor modes. - self.assertContains(response, 'Coupon Code List') - - def test_reports_section_under_e_commerce_tab(self): - """ - Test reports section, under E-commerce Tab, is in the Instructor Dashboard - """ - self.use_site(site=self.site_other) - self.client.login(username=self.instructor.username, password="test") - response = self.client.get(self.url) - self.assertContains(response, self.ecommerce_link) - self.assertContains(response, 'Create Enrollment Report') - - def test_reports_section_not_under_e_commerce_tab(self): - """ - Test reports section, under E-commerce Tab, should not be available in the Instructor Dashboard with default - value - """ - response = self.client.get(self.url) - self.assertContains(response, self.ecommerce_link) - self.assertNotContains(response, 'Create Enrollment Report') - - def test_user_has_finance_admin_rights_in_e_commerce_tab(self): - response = self.client.get(self.url) - self.assertContains(response, self.ecommerce_link) - - # Order/Invoice sales csv button text should render in e-commerce page - self.assertContains(response, 'Total Credit Card Purchases') - self.assertContains(response, 'Download All Credit Card Purchases') - self.assertContains(response, 'Download All Invoices') - - # removing the course finance_admin role of login user - CourseFinanceAdminRole(self.course.id).remove_users(self.instructor) - - # Order/Invoice sales csv button text should not be visible in e-commerce page if the user is not finance admin - url = reverse('instructor_dashboard', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(url) - self.assertNotContains(response, 'Download All Invoices') - - def test_user_view_course_price(self): - """ - test to check if the user views the set price button and price in - the instructor dashboard - """ - response = self.client.get(self.url) - self.assertContains(response, self.ecommerce_link) - - # Total amount html should render in e-commerce page, total amount will be 0 - course_honor_mode = CourseMode.mode_for_course(self.course.id, 'honor') - - price = course_honor_mode.min_price - self.assertContains(response, 'Course price per seat: <span>$' + str(price) + '</span>') - self.assertNotContains(response, '+ Set Price</a></span>') - - # removing the course finance_admin role of login user - CourseFinanceAdminRole(self.course.id).remove_users(self.instructor) - - # total amount should not be visible in e-commerce page if the user is not finance admin - url = reverse('instructor_dashboard', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.get(url) - self.assertNotContains(response, '+ Set Price</a></span>') - - def test_update_course_price_check(self): - price = 200 - # course B - course2 = CourseFactory.create(org='EDX', display_name='test_course', number='100') - mode = CourseModeFactory( - course_id=text_type(course2.id), mode_slug='honor', - mode_display_name='honor', min_price=30, currency='usd' - ) - mode.save() - # course A update - CourseMode.objects.filter(course_id=self.course.id).update(min_price=price) - - set_course_price_url = reverse('set_course_mode_price', kwargs={'course_id': text_type(self.course.id)}) - data = {'course_price': price, 'currency': 'usd'} - response = self.client.post(set_course_price_url, data) - self.assertContains(response, 'CourseMode price updated successfully') - - # Course A updated total amount should be visible in e-commerce page if the user is finance admin - url = reverse('instructor_dashboard', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.get(url) - - self.assertContains(response, 'Course price per seat: <span>$' + str(price) + '</span>') - - def test_user_admin_set_course_price(self): - """ - test to set the course price related functionality. - test al the scenarios for setting a new course price - """ - set_course_price_url = reverse('set_course_mode_price', kwargs={'course_id': text_type(self.course.id)}) - data = {'course_price': '12%', 'currency': 'usd'} - - # Value Error course price should be a numeric value - response = self.client.post(set_course_price_url, data) - self.assertContains(response, "Please Enter the numeric value for the course price", status_code=400) - - # validation check passes and course price is successfully added - data['course_price'] = 100 - response = self.client.post(set_course_price_url, data) - self.assertContains(response, "CourseMode price updated successfully") - - course_honor_mode = CourseMode.objects.get(mode_slug='honor') - course_honor_mode.delete() - # Course Mode not exist with mode slug honor - response = self.client.post(set_course_price_url, data) - self.assertContains( - response, - u"CourseMode with the mode slug({mode_slug}) DoesNotExist".format(mode_slug='honor'), - status_code=400, - ) - - def test_add_coupon(self): - """ - Test Add Coupon Scenarios. Handle all the HttpResponses return by add_coupon view - """ - # URL for add_coupon - add_coupon_url = reverse('add_coupon', kwargs={'course_id': text_type(self.course.id)}) - expiration_date = datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=2) - - data = { - 'code': 'A2314', 'course_id': text_type(self.course.id), - 'description': 'ADSADASDSAD', 'created_by': self.instructor, 'discount': 5, - 'expiration_date': '{month}/{day}/{year}'.format( - month=expiration_date.month, day=expiration_date.day, year=expiration_date.year - ) - } - response = self.client.post(add_coupon_url, data) - self.assertContains( - response, - u"coupon with the coupon code ({code}) added successfully".format(code=data['code']), - ) - - #now add the coupon with the wrong value in the expiration_date - # server will through the ValueError Exception in the expiration_date field - data = { - 'code': '213454', 'course_id': text_type(self.course.id), - 'description': 'ADSADASDSAD', 'created_by': self.instructor, 'discount': 5, - 'expiration_date': expiration_date.strftime('"%d/%m/%Y') - } - response = self.client.post(add_coupon_url, data) - self.assertContains( - response, - "Please enter the date in this format i-e month/day/year", - status_code=400, - ) - - data = { - 'code': 'A2314', 'course_id': text_type(self.course.id), - 'description': 'asdsasda', 'created_by': self.instructor, 'discount': 99 - } - response = self.client.post(add_coupon_url, data) - self.assertContains( - response, - u"coupon with the coupon code ({code}) already exist".format(code='A2314'), - status_code=400, - ) - - response = self.client.post(self.url) - self.assertContains(response, '<td>ADSADASDSAD</td>') - self.assertContains(response, '<td>A2314</td>') - self.assertNotContains(response, '<td>111</td>') - - data = { - 'code': 'A2345314', 'course_id': text_type(self.course.id), - 'description': 'asdsasda', 'created_by': self.instructor, 'discount': 199 - } - response = self.client.post(add_coupon_url, data) - self.assertContains( - response, - "Please Enter the Coupon Discount Value Less than or Equal to 100", - status_code=400, - ) - - data['discount'] = '25%' - response = self.client.post(add_coupon_url, data=data) - self.assertContains(response, 'Please Enter the Integer Value for Coupon Discount', status_code=400) - - course_registration = CourseRegistrationCode( - code='Vs23Ws4j', course_id=text_type(self.course.id), created_by=self.instructor, - mode_slug='honor' - ) - course_registration.save() - - data['code'] = 'Vs23Ws4j' - response = self.client.post(add_coupon_url, data) - msg = u"The code ({code}) that you have tried to define is already in use as a registration code" - self.assertContains(response, msg.format(code=data['code']), status_code=400) - - def test_delete_coupon(self): - """ - Test Delete Coupon Scenarios. Handle all the HttpResponses return by remove_coupon view - """ - coupon = Coupon( - code='AS452', description='asdsadsa', course_id=text_type(self.course.id), - percentage_discount=10, created_by=self.instructor - ) - - coupon.save() - - response = self.client.post(self.url) - self.assertContains(response, '<td>AS452</td>') - - # URL for remove_coupon - delete_coupon_url = reverse('remove_coupon', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(delete_coupon_url, {'id': coupon.id}) - self.assertContains( - response, - u'coupon with the coupon id ({coupon_id}) updated successfully'.format(coupon_id=coupon.id), - ) - - coupon.is_active = False - coupon.save() - - response = self.client.post(delete_coupon_url, {'id': coupon.id}) - self.assertContains( - response, - u'coupon with the coupon id ({coupon_id}) is already inactive'.format(coupon_id=coupon.id), - status_code=400, - ) - - response = self.client.post(delete_coupon_url, {'id': 24454}) - self.assertContains( - response, - u'coupon with the coupon id ({coupon_id}) DoesNotExist'.format(coupon_id=24454), - status_code=400, - ) - - response = self.client.post(delete_coupon_url, {'id': ''}) - self.assertContains(response, 'coupon id is None', status_code=400) - - def test_get_coupon_info(self): - """ - Test Edit Coupon Info Scenarios. Handle all the HttpResponses return by edit_coupon_info view - """ - coupon = Coupon( - code='AS452', description='asdsadsa', course_id=text_type(self.course.id), - percentage_discount=10, created_by=self.instructor, - expiration_date=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=2) - ) - coupon.save() - # URL for edit_coupon_info - edit_url = reverse('get_coupon_info', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(edit_url, {'id': coupon.id}) - self.assertContains( - response, - u'coupon with the coupon id ({coupon_id}) updated successfully'.format(coupon_id=coupon.id), - ) - self.assertContains(response, coupon.display_expiry_date) - - response = self.client.post(edit_url, {'id': 444444}) - self.assertContains( - response, - u'coupon with the coupon id ({coupon_id}) DoesNotExist'.format(coupon_id=444444), - status_code=400, - ) - - response = self.client.post(edit_url, {'id': ''}) - self.assertContains(response, 'coupon id not found"', status_code=400) - - coupon.is_active = False - coupon.save() - - response = self.client.post(edit_url, {'id': coupon.id}) - self.assertContains( - response, - u"coupon with the coupon id ({coupon_id}) is already inactive".format(coupon_id=coupon.id), - status_code=400, - ) - - def test_update_coupon(self): - """ - Test Update Coupon Info Scenarios. Handle all the HttpResponses return by update_coupon view - """ - coupon = Coupon( - code='AS452', description='asdsadsa', course_id=text_type(self.course.id), - percentage_discount=10, created_by=self.instructor - ) - coupon.save() - response = self.client.post(self.url) - self.assertContains(response, '<td>AS452</td>') - data = { - 'coupon_id': coupon.id, 'code': 'AS452', 'discount': '10', 'description': 'updated_description', - 'course_id': text_type(coupon.course_id) - } - # URL for update_coupon - update_coupon_url = reverse('update_coupon', kwargs={'course_id': text_type(self.course.id)}) - response = self.client.post(update_coupon_url, data=data) - self.assertContains( - response, - u'coupon with the coupon id ({coupon_id}) updated Successfully'.format(coupon_id=coupon.id), - ) - - response = self.client.post(self.url) - self.assertContains(response, '<td>updated_description</td>') - - data['coupon_id'] = 1000 # Coupon Not Exist with this ID - response = self.client.post(update_coupon_url, data=data) - self.assertContains( - response, - u'coupon with the coupon id ({coupon_id}) DoesNotExist'.format(coupon_id=1000), - status_code=400, - ) - - data['coupon_id'] = '' # Coupon id is not provided - response = self.client.post(update_coupon_url, data=data) - self.assertContains(response, 'coupon id not found', status_code=400) - - def test_verified_course(self): - """Verify the e-commerce panel shows up for verified courses as well, without Coupons """ - # Change honor mode to verified. - original_mode = CourseMode.objects.get(course_id=self.course.id, mode_slug='honor') - original_mode.delete() - new_mode = CourseModeFactory( - course_id=six.text_type(self.course.id), mode_slug='verified', - mode_display_name='verified', min_price=10, currency='usd' - ) - new_mode.save() - - # Get the response value, ensure the Coupon section is not included. - response = self.client.get(self.url) - self.assertContains(response, self.ecommerce_link) - # Coupons should show up for White Label sites with priced honor modes. - self.assertNotContains(response, 'Coupons List') - - def test_coupon_code_section_not_under_e_commerce_tab(self): - """ - Test Coupon Creation UI, under E-commerce Tab, should not be available in the Instructor Dashboard with - e-commerce course - """ - # Setup e-commerce course - CourseMode.objects.filter(course_id=self.course.id).update(sku='test_sku') - - response = self.client.get(self.url) - self.assertContains(response, self.ecommerce_link) - self.assertNotContains(response, 'Coupon Code List') - - def test_enrollment_codes_section_not_under_e_commerce_tab(self): - """ - Test Enrollment Codes UI, under E-commerce Tab, should not be available in the Instructor Dashboard with - e-commerce course - """ - # Setup e-commerce course - CourseMode.objects.filter(course_id=self.course.id).update(sku='test_sku') - - response = self.client.get(self.url) - self.assertContains(response, self.ecommerce_link) - self.assertNotContains(response, '<h3 class="hd hd-3">Enrollment Codes</h3>') - - def test_enrollment_codes_section_visible_for_non_ecommerce_course(self): - """ - Test Enrollment Codes UI, under E-commerce Tab, should be available in the Instructor Dashboard with non - e-commerce course - """ - response = self.client.get(self.url) - self.assertContains(response, self.ecommerce_link) - self.assertContains(response, '<h3 class="hd hd-3">Enrollment Codes</h3>') diff --git a/lms/djangoapps/instructor/tests/test_registration_codes.py b/lms/djangoapps/instructor/tests/test_registration_codes.py deleted file mode 100644 index 111def9e92c5e39c0d1a24d5d9382e8c217288c1..0000000000000000000000000000000000000000 --- a/lms/djangoapps/instructor/tests/test_registration_codes.py +++ /dev/null @@ -1,306 +0,0 @@ -""" -Test for the registration code status information. -""" - - -import json - -import six -from django.test.utils import override_settings -from django.urls import reverse -from django.utils.translation import ugettext as _ -from six import text_type -from six.moves import range - -from course_modes.models import CourseMode -from course_modes.tests.factories import CourseModeFactory -from lms.djangoapps.courseware.tests.factories import InstructorFactory -from shoppingcart.models import ( - CourseRegCodeItem, - CourseRegistrationCode, - CourseRegistrationCodeInvoiceItem, - Invoice, - Order, - RegistrationCodeRedemption -) -from student.models import CourseEnrollment -from student.roles import CourseSalesAdminRole -from student.tests.factories import UserFactory -from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory - - -@override_settings(REGISTRATION_CODE_LENGTH=8) -class TestCourseRegistrationCodeStatus(SharedModuleStoreTestCase): - """ - Test registration code status. - """ - - @classmethod - def setUpClass(cls): - super(TestCourseRegistrationCodeStatus, cls).setUpClass() - cls.course = CourseFactory.create() - - def setUp(self): - super(TestCourseRegistrationCodeStatus, self).setUp() - CourseModeFactory.create(course_id=self.course.id, min_price=50) - self.instructor = InstructorFactory(course_key=self.course.id) - self.client.login(username=self.instructor.username, password='test') - CourseSalesAdminRole(self.course.id).add_users(self.instructor) - - # create testing invoice - self.sale_invoice = Invoice.objects.create( - total_amount=1234.32, company_name='Test1', company_contact_name='TestName', - company_contact_email='Test@company.com', recipient_name='Testw', recipient_email='test1@test.com', - customer_reference_number='2Fwe23S', internal_reference="A", course_id=self.course.id, is_valid=True - ) - self.invoice_item = CourseRegistrationCodeInvoiceItem.objects.create( - invoice=self.sale_invoice, - qty=1, - unit_price=1234.32, - course_id=self.course.id - ) - self.lookup_code_url = reverse('look_up_registration_code', - kwargs={'course_id': text_type(self.course.id)}) - - self.registration_code_detail_url = reverse('registration_code_details', - kwargs={'course_id': text_type(self.course.id)}) - - url = reverse('generate_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - data = { - 'total_registration_codes': 12, - 'company_name': 'Test Group', - 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', - 'unit_price': 122.45, - 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', - 'address_line_1': 'Portland Street', - 'address_line_2': '', - 'address_line_3': '', - 'city': '', - 'state': '', - 'zip': '', - 'country': '', - 'customer_reference_number': '123A23F', - 'internal_reference': '', - 'invoice': '' - } - - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200, response.content) - - def test_look_up_invalid_registration_code(self): - """ - Verify the view returns HTTP status 400 if an invalid registration code is passed. - Also, verify the data returned includes a message indicating the error, - and the is_registration_code_valid is set to False. - """ - data = { - 'registration_code': 'invalid_reg_code' - } - response = self.client.get(self.lookup_code_url, data) - self.assertEqual(response.status_code, 400) - json_dict = json.loads(response.content.decode('utf-8')) - message = _(u'The enrollment code ({code}) was not found for the {course_name} course.').format( - course_name=self.course.display_name, code=data['registration_code'] - ) - self.assertEqual(message, json_dict['message']) - self.assertFalse(json_dict['is_registration_code_valid']) - self.assertFalse(json_dict['is_registration_code_redeemed']) - - def test_look_up_valid_registration_code(self): - """ - test lookup for the valid registration code - and that registration code has been redeemed by user - and then mark the registration code as in_valid - when marking as invalidate, it also lookup for - registration redemption entry and also delete - that redemption entry and un_enroll the student - who used that registration code for their enrollment. - """ - for i in range(2): - CourseRegistrationCode.objects.create( - code='reg_code{}'.format(i), - course_id=six.text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice, - invoice_item=self.invoice_item, - mode_slug=CourseMode.DEFAULT_MODE_SLUG - ) - - reg_code = CourseRegistrationCode.objects.all()[0] - student = UserFactory() - enrollment = CourseEnrollment.enroll(student, self.course.id) - - RegistrationCodeRedemption.objects.create( - registration_code=reg_code, - redeemed_by=student, - course_enrollment=enrollment - ) - - data = { - 'registration_code': reg_code.code - } - response = self.client.get(self.lookup_code_url, data) - self.assertEqual(response.status_code, 200) - json_dict = json.loads(response.content.decode('utf-8')) - self.assertTrue(json_dict['is_registration_code_valid']) - self.assertTrue(json_dict['is_registration_code_redeemed']) - - # now mark that registration code as invalid - data = { - 'registration_code': reg_code.code, - 'action_type': 'invalidate_registration_code' - } - response = self.client.post(self.registration_code_detail_url, data) - self.assertEqual(response.status_code, 200) - - json_dict = json.loads(response.content.decode('utf-8')) - message = _('This enrollment code has been canceled. It can no longer be used.') - self.assertEqual(message, json_dict['message']) - - # now check that the registration code should be marked as invalid in the db. - reg_code = CourseRegistrationCode.objects.get(code=reg_code.code) - self.assertEqual(reg_code.is_valid, False) - - redemption = RegistrationCodeRedemption.get_registration_code_redemption(reg_code.code, self.course.id) - self.assertIsNone(redemption) - - # now the student course enrollment should be false. - enrollment = CourseEnrollment.get_enrollment(student, self.course.id) - self.assertEqual(enrollment.is_active, False) - - def test_lookup_valid_redeemed_registration_code(self): - """ - test to lookup for the valid and redeemed registration code - and then mark that registration code as un_redeemed - which will unenroll the user and delete the redemption - entry from the database. - """ - student = UserFactory() - self.client.login(username=student.username, password='test') - cart = Order.get_cart_for_user(student) - cart.order_type = 'business' - cart.save() - CourseRegCodeItem.add_to_order(cart, self.course.id, 2) - cart.purchase() - - reg_code = CourseRegistrationCode.objects.filter(order=cart)[0] - - enrollment = CourseEnrollment.enroll(student, self.course.id) - - RegistrationCodeRedemption.objects.create( - registration_code=reg_code, - redeemed_by=student, - course_enrollment=enrollment - ) - self.client.login(username=self.instructor.username, password='test') - data = { - 'registration_code': reg_code.code - } - response = self.client.get(self.lookup_code_url, data) - self.assertEqual(response.status_code, 200) - json_dict = json.loads(response.content.decode('utf-8')) - self.assertTrue(json_dict['is_registration_code_valid']) - self.assertTrue(json_dict['is_registration_code_redeemed']) - - # now mark the registration code as unredeemed - # this will unenroll the user and removed the redemption entry from - # the database. - - data = { - 'registration_code': reg_code.code, - 'action_type': 'unredeem_registration_code' - } - response = self.client.post(self.registration_code_detail_url, data) - self.assertEqual(response.status_code, 200) - - json_dict = json.loads(response.content.decode('utf-8')) - message = _('This enrollment code has been marked as unused.') - self.assertEqual(message, json_dict['message']) - - redemption = RegistrationCodeRedemption.get_registration_code_redemption(reg_code.code, self.course.id) - self.assertIsNone(redemption) - - # now the student course enrollment should be false. - enrollment = CourseEnrollment.get_enrollment(student, self.course.id) - self.assertEqual(enrollment.is_active, False) - - def test_apply_invalid_reg_code_when_updating_code_information(self): - """ - test to apply an invalid registration code - when updating the registration code information. - """ - data = { - 'registration_code': 'invalid_registration_code', - 'action_type': 'unredeem_registration_code' - } - response = self.client.post(self.registration_code_detail_url, data) - self.assertEqual(response.status_code, 400) - - json_dict = json.loads(response.content.decode('utf-8')) - message = _(u'The enrollment code ({code}) was not found for the {course_name} course.').format( - course_name=self.course.display_name, code=data['registration_code'] - ) - self.assertEqual(message, json_dict['message']) - - def test_mark_registration_code_as_valid(self): - """ - test to mark the invalid registration code - as valid - """ - for i in range(2): - CourseRegistrationCode.objects.create( - code='reg_code{}'.format(i), - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice, - invoice_item=self.invoice_item, - mode_slug=CourseMode.DEFAULT_MODE_SLUG, - is_valid=False - ) - - reg_code = CourseRegistrationCode.objects.all()[0] - data = { - 'registration_code': reg_code.code, - 'action_type': 'validate_registration_code' - } - response = self.client.post(self.registration_code_detail_url, data) - self.assertEqual(response.status_code, 200) - - json_dict = json.loads(response.content.decode('utf-8')) - message = _('The enrollment code has been restored.') - self.assertEqual(message, json_dict['message']) - - # now check that the registration code should be marked as valid in the db. - reg_code = CourseRegistrationCode.objects.get(code=reg_code.code) - self.assertEqual(reg_code.is_valid, True) - - def test_returns_error_when_unredeeming_already_unredeemed_registration_code_redemption(self): - """ - test to mark the already unredeemed registration code as unredeemed. - """ - for i in range(2): - CourseRegistrationCode.objects.create( - code='reg_code{}'.format(i), - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice, - invoice_item=self.invoice_item, - mode_slug=CourseMode.DEFAULT_MODE_SLUG, - ) - - reg_code = CourseRegistrationCode.objects.all()[0] - data = { - 'registration_code': reg_code.code, - 'action_type': 'unredeem_registration_code' - } - response = self.client.post(self.registration_code_detail_url, data) - self.assertEqual(response.status_code, 400) - - json_dict = json.loads(response.content.decode('utf-8')) - message = _(u'The redemption does not exist against enrollment code ({code}).').format(code=reg_code.code) - self.assertEqual(message, json_dict['message']) diff --git a/lms/djangoapps/instructor/tests/test_tools.py b/lms/djangoapps/instructor/tests/test_tools.py index bad04525a02cf2cb27fdb7fe5609e6d2de084d07..9febba7ccc993b8aff7a1081fff5a22a3cb6301a 100644 --- a/lms/djangoapps/instructor/tests/test_tools.py +++ b/lms/djangoapps/instructor/tests/test_tools.py @@ -15,6 +15,7 @@ from django.test import TestCase from opaque_keys.edx.keys import CourseKey from pytz import UTC +from edx_when.api import set_dates_for_course from edx_when.field_data import DateLookupFieldData from openedx.core.djangoapps.course_date_signals import handlers from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory @@ -43,7 +44,6 @@ class TestHandleDashboardError(unittest.TestCase): Test handle_dashboard_error decorator. """ def test_error(self): - # pylint: disable=unused-argument @tools.handle_dashboard_error def view(request, course_id): """ @@ -55,7 +55,6 @@ class TestHandleDashboardError(unittest.TestCase): self.assertEqual(response, {'error': 'Oh noes!'}) def test_no_error(self): - # pylint: disable=unused-argument @tools.handle_dashboard_error def view(request, course_id): """ @@ -139,17 +138,19 @@ class TestGetUnitsWithDueDate(ModuleStoreTestCase): """ Fixtures. """ - super(TestGetUnitsWithDueDate, self).setUp() + super().setUp() - due = datetime.datetime(2010, 5, 12, 2, 42, tzinfo=UTC) course = CourseFactory.create() - week1 = ItemFactory.create(due=due, parent=course) - week2 = ItemFactory.create(due=due, parent=course) + week1 = ItemFactory.create(parent=course) + week2 = ItemFactory.create(parent=course) + child = ItemFactory.create(parent=week1) - ItemFactory.create( - parent=week1, - due=due - ) + due = datetime.datetime(2010, 5, 12, 2, 42, tzinfo=UTC) + set_dates_for_course(course.id, [ + (week1.location, {'due': due}), + (week2.location, {'due': due}), + (child.location, {'due': due}), + ]) self.course = course self.week1 = week1 @@ -244,13 +245,21 @@ class TestSetDueDateExtension(ModuleStoreTestCase): block.fields['due']._del_cached_value(block) # pylint: disable=protected-access def test_set_due_date_extension(self): - extended = datetime.datetime(2013, 12, 25, 0, 0, tzinfo=UTC) - tools.set_due_date_extension(self.course, self.week1, self.user, extended) - tools.set_due_date_extension(self.course, self.assignment, self.user, extended) + # First, extend the leaf assignment date + extended_hw = datetime.datetime(2013, 10, 25, 0, 0, tzinfo=UTC) + tools.set_due_date_extension(self.course, self.assignment, self.user, extended_hw) + self._clear_field_data_cache() + self.assertEqual(self.week1.due, self.due) + self.assertEqual(self.homework.due, self.due) + self.assertEqual(self.assignment.due, extended_hw) + + # Now, extend the whole section that the assignment was in. Both it and all under it should change + extended_week = datetime.datetime(2013, 12, 25, 0, 0, tzinfo=UTC) + tools.set_due_date_extension(self.course, self.week1, self.user, extended_week) self._clear_field_data_cache() - self.assertEqual(self.week1.due, extended) - self.assertEqual(self.homework.due, extended) - self.assertEqual(self.assignment.due, extended) + self.assertEqual(self.week1.due, extended_week) + self.assertEqual(self.homework.due, extended_week) + self.assertEqual(self.assignment.due, extended_week) def test_set_due_date_extension_invalid_date(self): extended = datetime.datetime(2009, 1, 1, 0, 0, tzinfo=UTC) diff --git a/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py b/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py index 3bbfdbf54ffa749a8d16c42abf4abd67ae8e8ad4..3a140a057b2b69001127df2ef14c5701081708c1 100644 --- a/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py +++ b/lms/djangoapps/instructor/tests/views/test_instructor_dashboard.py @@ -4,12 +4,12 @@ Unit tests for instructor_dashboard.py. import datetime +import re import ddt import six from django.conf import settings from django.contrib.sites.models import Site -from django.test.client import RequestFactory from django.test.utils import override_settings from django.urls import reverse from mock import patch @@ -20,18 +20,17 @@ from six.moves import range from common.test.utils import XssTestMixin from course_modes.models import CourseMode +from edxmako.shortcuts import render_to_response from lms.djangoapps.courseware.tabs import get_course_tab_list from lms.djangoapps.courseware.tests.factories import StaffFactory, StudentModuleFactory, UserFactory from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase -from edxmako.shortcuts import render_to_response from lms.djangoapps.grades.config.waffle import WRITABLE_GRADEBOOK, waffle_flags from lms.djangoapps.instructor.views.gradebook_api import calculate_page_info from openedx.core.djangoapps.site_configuration.models import SiteConfiguration from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag -from shoppingcart.models import CourseRegCodeItem, Order, PaidCourseRegistration from student.models import CourseEnrollment from student.roles import CourseFinanceAdminRole -from student.tests.factories import AdminFactory, CourseEnrollmentFactory +from student.tests.factories import AdminFactory, CourseAccessRoleFactory, CourseEnrollmentFactory from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls @@ -118,6 +117,72 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT student = UserFactory.create() self.assertFalse(has_instructor_tab(student, self.course)) + researcher = UserFactory.create() + CourseAccessRoleFactory( + course_id=self.course.id, + user=researcher, + role='data_researcher', + org=self.course.id.org + ) + self.assertTrue(has_instructor_tab(researcher, self.course)) + + org_researcher = UserFactory.create() + CourseAccessRoleFactory( + course_id=None, + user=org_researcher, + role='data_researcher', + org=self.course.id.org + ) + self.assertTrue(has_instructor_tab(org_researcher, self.course)) + + @ddt.data( + ('staff', False), + ('instructor', False), + ('data_researcher', True), + ('global_staff', True), + ) + @ddt.unpack + def test_data_download(self, access_role, can_access): + """ + Verify that the Data Download tab only shows up for certain roles + """ + download_section = '<li class="nav-item"><button type="button" class="btn-link data_download" '\ + 'data-section="data_download">Data Download</button></li>' + user = UserFactory.create(is_staff=access_role == 'global_staff') + CourseAccessRoleFactory( + course_id=self.course.id, + user=user, + role=access_role, + org=self.course.id.org + ) + self.client.login(username=user.username, password="test") + response = self.client.get(self.url) + if can_access: + self.assertContains(response, download_section) + else: + self.assertNotContains(response, download_section) + + @override_settings(ANALYTICS_DASHBOARD_URL='http://example.com') + @override_settings(ANALYTICS_DASHBOARD_NAME='Example') + def test_data_download_only(self): + """ + Verify that only the data download tab is visible for data researchers. + """ + user = UserFactory.create() + CourseAccessRoleFactory( + course_id=self.course.id, + user=user, + role='data_researcher', + org=self.course.id.org + ) + self.client.login(username=user.username, password="test") + response = self.client.get(self.url) + matches = re.findall( + rb'<li class="nav-item"><button type="button" class="btn-link .*" data-section=".*">.*', + response.content + ) + assert len(matches) == 1 + @ddt.data( ("How to defeat the Road Runner", "2017", "001", "ACME"), ) @@ -179,7 +244,8 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT } ) response = self.client.get(url) - reason_field = '<textarea rows="2" id="reason-field-id" name="reason-field" placeholder="Reason" spellcheck="false"></textarea>' # pylint: disable=line-too-long + reason_field = '<textarea rows="2" id="reason-field-id" name="reason-field" ' \ + 'placeholder="Reason" spellcheck="false"></textarea>' if enbale_reason_field: self.assertContains(response, reason_field) else: @@ -302,15 +368,6 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT ) self.assertContains(response, 'View Gradebook') - def test_default_currency_in_the_html_response(self): - """ - Test that checks the default currency_symbol ($) in the response - """ - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - total_amount = PaidCourseRegistration.get_total_amount_of_purchased_item(self.course.id) - response = self.client.get(self.url) - self.assertContains(response, '${amount}'.format(amount=total_amount)) - def test_course_name_xss(self): """Test that the instructor dashboard correctly escapes course names with script tags. @@ -318,16 +375,6 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT response = self.client.get(self.url) self.assert_no_xss(response, '<script>alert("XSS")</script>') - @override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs']) - def test_override_currency_settings_in_the_html_response(self): - """ - Test that checks the default currency_symbol ($) in the response - """ - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - total_amount = PaidCourseRegistration.get_total_amount_of_purchased_item(self.course.id) - response = self.client.get(self.url) - self.assertContains(response, '{currency}{amount}'.format(currency='Rs', amount=total_amount)) - @patch.dict(settings.FEATURES, {'DISPLAY_ANALYTICS_ENROLLMENTS': False}) @override_settings(ANALYTICS_DASHBOARD_URL='') def test_no_enrollments(self): @@ -406,41 +453,14 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssT Test analytics dashboard message is shown """ response = self.client.get(self.url) - analytics_section = '<li class="nav-item"><button type="button" class="btn-link instructor_analytics" data-section="instructor_analytics">Analytics</button></li>' # pylint: disable=line-too-long + analytics_section = '<li class="nav-item"><button type="button" class="btn-link instructor_analytics"' \ + ' data-section="instructor_analytics">Analytics</button></li>' self.assertContains(response, analytics_section) # link to dashboard shown expected_message = self.get_dashboard_analytics_message() self.assertIn(expected_message, response.content.decode(response.charset)) - def add_course_to_user_cart(self, cart, course_key): - """ - adding course to user cart - """ - reg_item = PaidCourseRegistration.add_to_order(cart, course_key) - return reg_item - - @patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True}) - def test_total_credit_cart_sales_amount(self): - """ - Test to check the total amount for all the credit card purchases. - """ - student = UserFactory.create() - self.client.login(username=student.username, password="test") - student_cart = Order.get_cart_for_user(student) - item = self.add_course_to_user_cart(student_cart, self.course.id) - resp = self.client.post(reverse('shoppingcart.views.update_user_cart'), {'ItemId': item.id, 'qty': 4}) - self.assertEqual(resp.status_code, 200) - student_cart.purchase() - - self.client.login(username=self.instructor.username, password="test") - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - single_purchase_total = PaidCourseRegistration.get_total_amount_of_purchased_item(self.course.id) - bulk_purchase_total = CourseRegCodeItem.get_total_amount_of_purchased_item(self.course.id) - total_amount = single_purchase_total + bulk_purchase_total - response = self.client.get(self.url) - self.assertContains(response, '{currency}{amount}'.format(currency='$', amount=total_amount)) - @ddt.data( (True, True, True), (True, False, False), diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index ca3a1f3d38ed3ba7e7ce708fcf8eb52015275a64..369e06d2a26591839f04f9ddb74aca035d822418 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -8,20 +8,17 @@ Many of these GETs may become PUTs in the future. import csv -import decimal import json import logging import random import re import string -import time import six import unicodecsv from django.conf import settings from django.contrib.auth.models import User from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist, PermissionDenied, ValidationError -from django.core.mail.message import EmailMessage from django.core.validators import validate_email from django.db import IntegrityError, transaction from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotFound @@ -35,9 +32,11 @@ from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.http import require_http_methods, require_POST from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser +from edx_when.api import get_date_for_block from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey, UsageKey -from rest_framework import permissions, status +from rest_framework import status +from rest_framework.permissions import IsAuthenticated, IsAdminUser from rest_framework.response import Response from rest_framework.views import APIView from six import StringIO, text_type @@ -49,7 +48,7 @@ import instructor_analytics.csvs import instructor_analytics.distributions from bulk_email.api import is_bulk_email_feature_enabled from bulk_email.models import CourseEmail -from edxmako.shortcuts import render_to_string +from course_modes.models import CourseMode from lms.djangoapps.certificates import api as certs_api from lms.djangoapps.certificates.models import ( CertificateInvalidation, @@ -91,18 +90,10 @@ from openedx.core.djangoapps.django_comment_common.models import ( Role ) from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.djangoapps.user_api.preferences.api import get_user_preference, set_user_preference +from openedx.core.djangoapps.user_api.preferences.api import get_user_preference from openedx.core.djangolib.markup import HTML, Text from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin -from shoppingcart.models import ( - Coupon, - CourseMode, - CourseRegistrationCode, - CourseRegistrationCodeInvoiceItem, - Invoice, - RegistrationCodeRedemption -) from student import auth from student.models import ( ALLOWEDTOENROLL_TO_ENROLLED, @@ -135,18 +126,8 @@ from util.json_request import JsonResponse, JsonResponseBadRequest from util.views import require_global_staff from xmodule.modulestore.django import modulestore -from ..permissions import ( - ALLOW_STUDENT_TO_BYPASS_ENTRANCE_EXAM, - ASSIGN_TO_COHORTS, - EDIT_COURSE_ACCESS, - EDIT_FORUM_ROLES, - EDIT_INVOICE_VALIDATION, - ENABLE_CERTIFICATE_GENERATION, - GENERATE_BULK_CERTIFICATE_EXCEPTIONS, - GENERATE_CERTIFICATE_EXCEPTIONS, - GIVE_STUDENT_EXTENSION, - VIEW_ISSUED_CERTIFICATES -) +from .. import permissions + from .tools import ( dump_module_extensions, dump_student_extensions, @@ -173,7 +154,7 @@ def common_exceptions_400(func): (decorator without arguments) """ - def wrapped(request, *args, **kwargs): # pylint: disable=missing-docstring + def wrapped(request, *args, **kwargs): use_json = (request.is_ajax() or request.META.get("HTTP_ACCEPT", "").startswith("application/json")) try: @@ -207,8 +188,8 @@ def require_post_params(*args, **kwargs): required_params += [(key, kwargs[key]) for key in kwargs] # required_params = e.g. [('action', 'enroll or unenroll'), ['emails', None]] - def decorator(func): # pylint: disable=missing-docstring - def wrapped(*args, **kwargs): # pylint: disable=missing-docstring + def decorator(func): + def wrapped(*args, **kwargs): request = args[0] error_response_data = { @@ -231,36 +212,6 @@ def require_post_params(*args, **kwargs): return decorator -def require_level(level, perm=None): - """ - Decorator with argument that requires an access level of the requesting - user. If the requirement is not satisfied, returns an - HttpResponseForbidden (403). - - Assumes that request is in args[0]. - Assumes that course_id is in kwargs['course_id']. - - `level` is in ['instructor', 'staff'] - if `level` is 'staff', instructors will also be allowed, even - if they are not in the staff group. - """ - if level not in ['instructor', 'staff']: - raise ValueError(u"unrecognized level '{}'".format(level)) - - def decorator(func): # pylint: disable=missing-docstring - def wrapped(*args, **kwargs): - request = args[0] - course = get_course_by_id(CourseKey.from_string(kwargs['course_id'])) - - if has_access(request.user, level, course) and \ - ((perm and request.user.has_perm(perm, course.id)) or not perm): - return func(*args, **kwargs) - else: - return HttpResponseForbidden() - return wrapped - return decorator - - def require_course_permission(permission): """ Decorator with argument that requires a specific permission of the requesting @@ -270,7 +221,7 @@ def require_course_permission(permission): Assumes that request is in args[0]. Assumes that course_id is in kwargs['course_id']. """ - def decorator(func): # pylint: disable=missing-docstring + def decorator(func): def wrapped(*args, **kwargs): request = args[0] course = get_course_by_id(CourseKey.from_string(kwargs['course_id'])) @@ -291,7 +242,7 @@ def require_sales_admin(func): If the user does not have privileges for this operation, this will return HttpResponseForbidden (403). """ - def wrapped(request, course_id): # pylint: disable=missing-docstring + def wrapped(request, course_id): try: course_key = CourseKey.from_string(course_id) @@ -316,7 +267,7 @@ def require_finance_admin(func): If the user does not have privileges for this operation, this will return HttpResponseForbidden (403). """ - def wrapped(request, course_id): # pylint: disable=missing-docstring + def wrapped(request, course_id): try: course_key = CourseKey.from_string(course_id) @@ -342,7 +293,7 @@ COUNTRY_INDEX = 3 @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.CAN_ENROLL) def register_and_enroll_students(request, course_id): # pylint: disable=too-many-statements """ Create new account and Enroll students in this course. @@ -658,7 +609,7 @@ def create_and_enroll_user(email, username, name, country, password, course_id, @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.CAN_ENROLL) @require_post_params(action="enroll or unenroll", identifiers="stringified list of emails and/or usernames") def students_update_enrollment(request, course_id): """ @@ -826,7 +777,7 @@ def students_update_enrollment(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('instructor') +@require_course_permission(permissions.CAN_BETATEST) @common_exceptions_400 @require_post_params( identifiers="stringified list of emails and/or usernames", @@ -910,7 +861,7 @@ def bulk_beta_modify_access(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_course_permission(EDIT_COURSE_ACCESS) +@require_course_permission(permissions.EDIT_COURSE_ACCESS) @require_post_params( unique_student_identifier="email or username of user to change access", rolename="'instructor', 'staff', 'beta', or 'ccx_coach'", @@ -991,7 +942,7 @@ def modify_access(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('instructor') +@require_course_permission(permissions.EDIT_COURSE_ACCESS) @require_post_params(rolename="'instructor', 'staff', or 'beta'") def list_course_role_members(request, course_id): """ @@ -1045,7 +996,7 @@ def list_course_role_members(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff', perm='student.can_research') +@require_course_permission(permissions.CAN_RESEARCH) @common_exceptions_400 def get_problem_responses(request, course_id): """ @@ -1085,15 +1036,17 @@ def get_problem_responses(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.CAN_RESEARCH) def get_grading_config(request, course_id): """ Respond with json which contains a html formatted grade summary. """ course_id = CourseKey.from_string(course_id) - course = get_course_with_access( - request.user, 'staff', course_id, depth=None - ) + # course = get_course_with_access( + # request.user, 'staff', course_id, depth=None + # ) + course = get_course_by_id(course_id) + grading_config_summary = instructor_analytics.basic.dump_grading_context(course) response_payload = { @@ -1105,8 +1058,8 @@ def get_grading_config(request, course_id): @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff', perm='student.can_research') -def get_sale_records(request, course_id, csv=False): # pylint: disable=unused-argument, redefined-outer-name +@require_course_permission(permissions.CAN_RESEARCH) +def get_sale_records(request, course_id, csv=False): # pylint: disable=redefined-outer-name """ return the summary of all sales records for a particular course """ @@ -1134,116 +1087,10 @@ def get_sale_records(request, course_id, csv=False): # pylint: disable=unused-a return instructor_analytics.csvs.create_csv_response("e-commerce_sale_invoice_records.csv", header, datarows) -@ensure_csrf_cookie -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff', perm='student.can_research') -def get_sale_order_records(request, course_id): # pylint: disable=unused-argument - """ - return the summary of all sales records for a particular course - """ - course_id = CourseKey.from_string(course_id) - query_features = [ - ('id', 'Order Id'), - ('company_name', 'Company Name'), - ('company_contact_name', 'Company Contact Name'), - ('company_contact_email', 'Company Contact Email'), - ('logged_in_username', 'Login Username'), - ('logged_in_email', 'Login User Email'), - ('purchase_time', 'Date of Sale'), - ('customer_reference_number', 'Customer Reference Number'), - ('recipient_name', 'Recipient Name'), - ('recipient_email', 'Recipient Email'), - ('bill_to_street1', 'Street 1'), - ('bill_to_street2', 'Street 2'), - ('bill_to_city', 'City'), - ('bill_to_state', 'State'), - ('bill_to_postalcode', 'Postal Code'), - ('bill_to_country', 'Country'), - ('order_type', 'Order Type'), - ('status', 'Order Item Status'), - ('coupon_code', 'Coupon Code'), - ('list_price', 'List Price'), - ('unit_cost', 'Unit Price'), - ('quantity', 'Quantity'), - ('total_discount', 'Total Discount'), - ('total_amount', 'Total Amount Paid'), - ] - - db_columns = [x[0] for x in query_features] - csv_columns = [x[1] for x in query_features] - sale_data = instructor_analytics.basic.sale_order_record_features(course_id, db_columns) - __, datarows = instructor_analytics.csvs.format_dictlist(sale_data, db_columns) - return instructor_analytics.csvs.create_csv_response("e-commerce_sale_order_records.csv", csv_columns, datarows) - - -@require_course_permission(EDIT_INVOICE_VALIDATION) -@require_POST -def sale_validation(request, course_id): - """ - This method either invalidate or re validate the sale against the invoice number depending upon the event type - """ - try: - invoice_number = request.POST["invoice_number"] - except KeyError: - return HttpResponseBadRequest("Missing required invoice_number parameter") - try: - invoice_number = int(invoice_number) - except ValueError: - return HttpResponseBadRequest( - u"invoice_number must be an integer, {value} provided".format( - value=invoice_number - ) - ) - try: - event_type = request.POST["event_type"] - except KeyError: - return HttpResponseBadRequest("Missing required event_type parameter") - - course_id = CourseKey.from_string(course_id) - try: - obj_invoice = CourseRegistrationCodeInvoiceItem.objects.select_related('invoice').get( - invoice_id=invoice_number, - course_id=course_id - ) - obj_invoice = obj_invoice.invoice - except CourseRegistrationCodeInvoiceItem.DoesNotExist: # Check for old type invoices - return HttpResponseNotFound(_(u"Invoice number '{num}' does not exist.").format(num=invoice_number)) - - if event_type == "invalidate": - return invalidate_invoice(obj_invoice) - else: - return re_validate_invoice(obj_invoice) - - -def invalidate_invoice(obj_invoice): - """ - This method invalidate the sale against the invoice number - """ - if not obj_invoice.is_valid: - return HttpResponseBadRequest(_("The sale associated with this invoice has already been invalidated.")) - obj_invoice.is_valid = False - obj_invoice.save() - message = _(u'Invoice number {0} has been invalidated.').format(obj_invoice.id) - return JsonResponse({'message': message}) - - -def re_validate_invoice(obj_invoice): - """ - This method re-validate the sale against the invoice number - """ - if obj_invoice.is_valid: - return HttpResponseBadRequest(_("This invoice is already active.")) - - obj_invoice.is_valid = True - obj_invoice.save() - message = _(u'The registration codes for invoice {0} have been re-activated.').format(obj_invoice.id) - return JsonResponse({'message': message}) - - @transaction.non_atomic_requests @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_course_permission(VIEW_ISSUED_CERTIFICATES) +@require_course_permission(permissions.VIEW_ISSUED_CERTIFICATES) def get_issued_certificates(request, course_id): """ Responds with JSON if CSV is not required. contains a list of issued certificates. @@ -1284,7 +1131,7 @@ def get_issued_certificates(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff', perm='student.can_research') +@require_course_permission(permissions.CAN_RESEARCH) @common_exceptions_400 def get_students_features(request, course_id, csv=False): # pylint: disable=redefined-outer-name """ @@ -1381,7 +1228,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.CAN_RESEARCH) @common_exceptions_400 def get_students_who_may_enroll(request, course_id): """ @@ -1428,7 +1275,7 @@ def _cohorts_csv_validator(file_storage, file_to_validate): @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) @require_POST -@require_course_permission(ASSIGN_TO_COHORTS) +@require_course_permission(permissions.ASSIGN_TO_COHORTS) @common_exceptions_400 def add_users_to_cohorts(request, course_id): """ @@ -1474,7 +1321,7 @@ class CohortCSV(DeveloperErrorViewMixin, APIView): BearerAuthenticationAllowInactiveUser, SessionAuthenticationAllowInactiveUser, ) - permission_classes = (permissions.IsAuthenticated, permissions.IsAdminUser) + permission_classes = (IsAuthenticated, IsAdminUser) def post(self, request, course_key_string): """ @@ -1496,40 +1343,11 @@ class CohortCSV(DeveloperErrorViewMixin, APIView): return Response(status=status.HTTP_204_NO_CONTENT) -@ensure_csrf_cookie -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') -def get_coupon_codes(request, course_id): # pylint: disable=unused-argument - """ - Respond with csv which contains a summary of all Active Coupons. - """ - course_id = CourseKey.from_string(course_id) - coupons = Coupon.objects.filter(course_id=course_id) - - query_features = [ - ('code', _('Coupon Code')), - ('course_id', _('Course Id')), - ('percentage_discount', _('% Discount')), # pylint: disable=unicode-format-string - ('description', _('Description')), - ('expiration_date', _('Expiration Date')), - ('is_active', _('Is Active')), - ('code_redeemed_count', _('Code Redeemed Count')), - ('total_discounted_seats', _('Total Discounted Seats')), - ('total_discounted_amount', _('Total Discounted Amount')), - ] - db_columns = [x[0] for x in query_features] - csv_columns = [x[1] for x in query_features] - - coupons_list = instructor_analytics.basic.coupon_codes_features(db_columns, coupons, course_id) - __, data_rows = instructor_analytics.csvs.format_dictlist(coupons_list, db_columns) - return instructor_analytics.csvs.create_csv_response('Coupons.csv', csv_columns, data_rows) - - @transaction.non_atomic_requests @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.ENROLLMENT_REPORT) @require_finance_admin @common_exceptions_400 def get_enrollment_report(request, course_id): @@ -1548,7 +1366,7 @@ def get_enrollment_report(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.ENROLLMENT_REPORT) @require_finance_admin @common_exceptions_400 def get_exec_summary_report(request, course_id): @@ -1567,7 +1385,7 @@ def get_exec_summary_report(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.ENROLLMENT_REPORT) @common_exceptions_400 def get_course_survey_results(request, course_id): """ @@ -1585,7 +1403,7 @@ def get_course_survey_results(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.EXAM_RESULTS) @common_exceptions_400 def get_proctored_exam_results(request, course_id): """ @@ -1599,340 +1417,10 @@ def get_proctored_exam_results(request, course_id): return JsonResponse({"status": success_status}) -def save_registration_code(user, course_id, mode_slug, invoice=None, order=None, invoice_item=None): - """ - recursive function that generate a new code every time and saves in the Course Registration Table - if validation check passes - - Args: - user (User): The user creating the course registration codes. - course_id (str): The string representation of the course ID. - mode_slug (str): The Course Mode Slug associated with any enrollment made by these codes. - invoice (Invoice): (Optional) The associated invoice for this code. - order (Order): (Optional) The associated order for this code. - invoice_item (CourseRegistrationCodeInvoiceItem) : (Optional) The associated CourseRegistrationCodeInvoiceItem - - Returns: - The newly created CourseRegistrationCode. - - """ - code = random_code_generator() - - # check if the generated code is in the Coupon Table - matching_coupons = Coupon.objects.filter(code=code, is_active=True) - if matching_coupons: - return save_registration_code( - user, course_id, mode_slug, invoice=invoice, order=order, invoice_item=invoice_item - ) - - course_registration = CourseRegistrationCode( - code=code, - course_id=six.text_type(course_id), - created_by=user, - invoice=invoice, - order=order, - mode_slug=mode_slug, - invoice_item=invoice_item - ) - try: - with transaction.atomic(): - course_registration.save() - return course_registration - except IntegrityError: - return save_registration_code( - user, course_id, mode_slug, invoice=invoice, order=order, invoice_item=invoice_item - ) - - -def registration_codes_csv(file_name, codes_list, csv_type=None): - """ - Respond with the csv headers and data rows - given a dict of codes list - :param file_name: - :param codes_list: - :param csv_type: - """ - # csv headers - query_features = [ - 'code', 'redeem_code_url', 'course_id', 'company_name', 'created_by', - 'redeemed_by', 'invoice_id', 'purchaser', 'customer_reference_number', 'internal_reference', 'is_valid' - ] - - registration_codes = instructor_analytics.basic.course_registration_features(query_features, codes_list, csv_type) - header, data_rows = instructor_analytics.csvs.format_dictlist(registration_codes, query_features) - return instructor_analytics.csvs.create_csv_response(file_name, header, data_rows) - - -def random_code_generator(): - """ - generate a random alphanumeric code of length defined in - REGISTRATION_CODE_LENGTH settings - """ - code_length = getattr(settings, 'REGISTRATION_CODE_LENGTH', 8) - return generate_random_string(code_length) - - @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') -@require_POST -def get_registration_codes(request, course_id): - """ - Respond with csv which contains a summary of all Registration Codes. - """ - course_id = CourseKey.from_string(course_id) - - #filter all the course registration codes - registration_codes = CourseRegistrationCode.objects.filter( - course_id=course_id - ).order_by('invoice_item__invoice__company_name') - - company_name = request.POST['download_company_name'] - if company_name: - registration_codes = registration_codes.filter(invoice_item__invoice__company_name=company_name) - - csv_type = 'download' - return registration_codes_csv("Registration_Codes.csv", registration_codes, csv_type) - - -@ensure_csrf_cookie -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_sales_admin -@require_POST -def generate_registration_codes(request, course_id): - """ - Respond with csv which contains a summary of all Generated Codes. - """ - course_id = CourseKey.from_string(course_id) - invoice_copy = False - - # covert the course registration code number into integer - try: - course_code_number = int(request.POST['total_registration_codes']) - except ValueError: - course_code_number = int(float(request.POST['total_registration_codes'])) - - company_name = request.POST['company_name'] - company_contact_name = request.POST['company_contact_name'] - company_contact_email = request.POST['company_contact_email'] - unit_price = request.POST['unit_price'] - - try: - unit_price = ( - decimal.Decimal(unit_price) - ).quantize( - decimal.Decimal('.01'), - rounding=decimal.ROUND_DOWN - ) - except decimal.InvalidOperation: - return HttpResponse( - status=400, - content=_(u"Could not parse amount as a decimal") - ) - - recipient_name = request.POST['recipient_name'] - recipient_email = request.POST['recipient_email'] - address_line_1 = request.POST['address_line_1'] - address_line_2 = request.POST['address_line_2'] - address_line_3 = request.POST['address_line_3'] - city = request.POST['city'] - state = request.POST['state'] - zip_code = request.POST['zip'] - country = request.POST['country'] - internal_reference = request.POST['internal_reference'] - customer_reference_number = request.POST['customer_reference_number'] - recipient_list = [recipient_email] - if request.POST.get('invoice', False): - recipient_list.append(request.user.email) - invoice_copy = True - - sale_price = unit_price * course_code_number - set_user_preference(request.user, INVOICE_KEY, invoice_copy) - sale_invoice = Invoice.objects.create( - total_amount=sale_price, - company_name=company_name, - company_contact_email=company_contact_email, - company_contact_name=company_contact_name, - course_id=course_id, - recipient_name=recipient_name, - recipient_email=recipient_email, - address_line_1=address_line_1, - address_line_2=address_line_2, - address_line_3=address_line_3, - city=city, - state=state, - zip=zip_code, - country=country, - internal_reference=internal_reference, - customer_reference_number=customer_reference_number - ) - - invoice_item = CourseRegistrationCodeInvoiceItem.objects.create( - invoice=sale_invoice, - qty=course_code_number, - unit_price=unit_price, - course_id=course_id - ) - - course = get_course_by_id(course_id, depth=0) - paid_modes = CourseMode.paid_modes_for_course(course_id) - - if len(paid_modes) != 1: - msg = ( - u"Generating Code Redeem Codes for Course '{course_id}', which must have a single paid course mode. " - u"This is a configuration issue. Current course modes with payment options: {paid_modes}" - ).format(course_id=course_id, paid_modes=paid_modes) - log.error(msg) - return HttpResponse( - status=500, - content=_(u"Unable to generate redeem codes because of course misconfiguration.") - ) - - course_mode = paid_modes[0] - course_price = course_mode.min_price - - registration_codes = [] - for __ in range(course_code_number): - generated_registration_code = save_registration_code( - request.user, course_id, course_mode.slug, invoice=sale_invoice, order=None, invoice_item=invoice_item - ) - registration_codes.append(generated_registration_code) - - site_name = configuration_helpers.get_value('SITE_NAME', 'localhost') - quantity = course_code_number - discount = (float(quantity * course_price) - float(sale_price)) - course_url = '{base_url}{course_about}'.format( - base_url=configuration_helpers.get_value('SITE_NAME', settings.SITE_NAME), - course_about=reverse('about_course', kwargs={'course_id': text_type(course_id)}) - ) - dashboard_url = '{base_url}{dashboard}'.format( - base_url=configuration_helpers.get_value('SITE_NAME', settings.SITE_NAME), - dashboard=reverse('dashboard') - ) - - from_address = configuration_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL) - context = { - 'invoice': sale_invoice, - 'site_name': site_name, - 'course': course, - 'course_price': course_price, - 'sub_total': course_price * quantity, - 'discount': discount, - 'sale_price': sale_price, - 'quantity': quantity, - 'registration_codes': registration_codes, - 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], - 'course_url': course_url, - 'platform_name': configuration_helpers.get_value('platform_name', settings.PLATFORM_NAME), - 'dashboard_url': dashboard_url, - 'contact_email': from_address, - 'corp_address': configuration_helpers.get_value('invoice_corp_address', settings.INVOICE_CORP_ADDRESS), - 'payment_instructions': configuration_helpers.get_value( - 'invoice_payment_instructions', - settings. INVOICE_PAYMENT_INSTRUCTIONS, - ), - 'date': time.strftime("%m/%d/%Y") - } - # composes registration codes invoice email - subject = u'Confirmation and Invoice for {course_name}'.format(course_name=course.display_name) - message = render_to_string('emails/registration_codes_sale_email.txt', context) - - invoice_attachment = render_to_string('emails/registration_codes_sale_invoice_attachment.txt', context) - - #send_mail(subject, message, from_address, recipient_list, fail_silently=False) - csv_file = StringIO() - csv_writer = csv.writer(csv_file) - for registration_code in registration_codes: - full_redeem_code_url = 'http://{base_url}{redeem_code_url}'.format( - base_url=configuration_helpers.get_value('SITE_NAME', settings.SITE_NAME), - redeem_code_url=reverse('register_code_redemption', kwargs={'registration_code': registration_code.code}) - ) - csv_writer.writerow([registration_code.code, full_redeem_code_url]) - finance_email = configuration_helpers.get_value('finance_email', settings.FINANCE_EMAIL) - if finance_email: - # append the finance email into the recipient_list - recipient_list.append(finance_email) - - # send a unique email for each recipient, don't put all email addresses in a single email - for recipient in recipient_list: - email = EmailMessage() - email.subject = subject - email.body = message - email.from_email = from_address - email.to = [recipient] - email.attach(u'RegistrationCodes.csv', csv_file.getvalue(), 'text/csv') - email.attach(u'Invoice.txt', invoice_attachment, 'text/plain') - email.send() - - return registration_codes_csv("Registration_Codes.csv", registration_codes) - - -@ensure_csrf_cookie -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') -@require_POST -def active_registration_codes(request, course_id): - """ - Respond with csv which contains a summary of all Active Registration Codes. - """ - course_id = CourseKey.from_string(course_id) - - # find all the registration codes in this course - registration_codes_list = CourseRegistrationCode.objects.filter( - course_id=course_id - ).order_by('invoice_item__invoice__company_name') - - company_name = request.POST['active_company_name'] - if company_name: - registration_codes_list = registration_codes_list.filter(invoice_item__invoice__company_name=company_name) - # find the redeemed registration codes if any exist in the db - code_redemption_set = RegistrationCodeRedemption.objects.select_related( - 'registration_code', 'registration_code__invoice_item__invoice' - ).filter(registration_code__course_id=course_id) - if code_redemption_set.exists(): - redeemed_registration_codes = [code.registration_code.code for code in code_redemption_set] - # exclude the redeemed registration codes from the registration codes list and you will get - # all the registration codes that are active - registration_codes_list = registration_codes_list.exclude(code__in=redeemed_registration_codes) - - return registration_codes_csv("Active_Registration_Codes.csv", registration_codes_list) - - -@ensure_csrf_cookie -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') -@require_POST -def spent_registration_codes(request, course_id): - """ - Respond with csv which contains a summary of all Spent(used) Registration Codes. - """ - course_id = CourseKey.from_string(course_id) - - # find the redeemed registration codes if any exist in the db - code_redemption_set = RegistrationCodeRedemption.objects.select_related('registration_code').filter( - registration_code__course_id=course_id - ) - spent_codes_list = [] - if code_redemption_set.exists(): - redeemed_registration_codes = [code.registration_code.code for code in code_redemption_set] - # filter the Registration Codes by course id and the redeemed codes and - # you will get a list of all the spent(Redeemed) Registration Codes - spent_codes_list = CourseRegistrationCode.objects.filter( - course_id=course_id, code__in=redeemed_registration_codes - ).order_by('invoice_item__invoice__company_name').select_related('invoice_item__invoice') - - company_name = request.POST['spent_company_name'] - if company_name: - spent_codes_list = spent_codes_list.filter(invoice_item__invoice__company_name=company_name) - - csv_type = 'spent' - return registration_codes_csv("Spent_Registration_Codes.csv", spent_codes_list, csv_type) - - -@ensure_csrf_cookie -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff', perm='student.can_research') -def get_anon_ids(request, course_id): # pylint: disable=unused-argument +@require_course_permission(permissions.CAN_RESEARCH) +def get_anon_ids(request, course_id): """ Respond with 2-column CSV output of user-id, anonymized-user-id """ @@ -1969,7 +1457,7 @@ def get_anon_ids(request, course_id): # pylint: disable=unused-argument @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.CAN_ENROLL) @require_post_params( unique_student_identifier="email or username of student for whom to get enrollment status" ) @@ -2026,7 +1514,7 @@ def get_student_enrollment_status(request, course_id): @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) @common_exceptions_400 -@require_level('staff') +@require_course_permission(permissions.ENROLLMENT_REPORT) @require_post_params( unique_student_identifier="email or username of student for whom to get progress url" ) @@ -2057,7 +1545,7 @@ def get_student_progress_url(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.GIVE_STUDENT_EXTENSION) @require_post_params( problem_to_reset="problem urlname to reset" ) @@ -2144,7 +1632,7 @@ def reset_student_attempts(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.GIVE_STUDENT_EXTENSION) @common_exceptions_400 def reset_student_attempts_for_entrance_exam(request, course_id): """ @@ -2219,7 +1707,7 @@ def reset_student_attempts_for_entrance_exam(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.OVERRIDE_GRADES) @require_post_params(problem_to_reset="problem urlname to reset") @common_exceptions_400 def rescore_problem(request, course_id): @@ -2295,7 +1783,7 @@ def rescore_problem(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.OVERRIDE_GRADES) @require_post_params(problem_to_reset="problem urlname to reset", score='overriding score') @common_exceptions_400 def override_problem_score(request, course_id): @@ -2352,7 +1840,7 @@ def override_problem_score(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('instructor') +@require_course_permission(permissions.RESCORE_EXAMS) @common_exceptions_400 def rescore_entrance_exam(request, course_id): """ @@ -2409,8 +1897,8 @@ def rescore_entrance_exam(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') -def list_background_email_tasks(request, course_id): # pylint: disable=unused-argument +@require_course_permission(permissions.EMAIL) +def list_background_email_tasks(request, course_id): """ List background email tasks. """ @@ -2431,8 +1919,8 @@ def list_background_email_tasks(request, course_id): # pylint: disable=unused-a @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') -def list_email_content(request, course_id): # pylint: disable=unused-argument +@require_course_permission(permissions.EMAIL) +def list_email_content(request, course_id): """ List the content of bulk emails sent """ @@ -2450,7 +1938,7 @@ def list_email_content(request, course_id): # pylint: disable=unused-argument @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.SHOW_TASKS) def list_instructor_tasks(request, course_id): """ List instructor tasks. @@ -2496,7 +1984,7 @@ def list_instructor_tasks(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.SHOW_TASKS) def list_entrance_exam_instructor_tasks(request, course_id): """ List entrance exam related instructor tasks. @@ -2538,7 +2026,7 @@ def list_entrance_exam_instructor_tasks(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.CAN_RESEARCH) def list_report_downloads(request, course_id): """ List grade CSV files that are available for download for this course. @@ -2562,7 +2050,7 @@ def list_report_downloads(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff', perm='student.can_research') +@require_course_permission(permissions.CAN_RESEARCH) @require_finance_admin def list_financial_report_downloads(_request, course_id): """ @@ -2584,7 +2072,7 @@ def list_financial_report_downloads(_request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff', perm='student.can_research') +@require_course_permission(permissions.CAN_RESEARCH) @common_exceptions_400 def export_ora2_data(request, course_id): """ @@ -2602,7 +2090,7 @@ def export_ora2_data(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff', perm='student.can_research') +@require_course_permission(permissions.CAN_RESEARCH) @common_exceptions_400 def calculate_grades_csv(request, course_id): """ @@ -2620,7 +2108,7 @@ def calculate_grades_csv(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff', perm='student.can_research') +@require_course_permission(permissions.CAN_RESEARCH) @common_exceptions_400 def problem_grade_report(request, course_id): """ @@ -2641,7 +2129,7 @@ def problem_grade_report(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.CAN_ENROLL) @require_post_params('rolename') def list_forum_members(request, course_id): """ @@ -2713,7 +2201,7 @@ def list_forum_members(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.EMAIL) @require_post_params(send_to="sending to whom", subject="subject line", message="message text") @common_exceptions_400 def send_email(request, course_id): @@ -2789,7 +2277,7 @@ def send_email(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_course_permission(EDIT_FORUM_ROLES) +@require_course_permission(permissions.EDIT_FORUM_ROLES) @require_post_params( unique_student_identifier="email or username of user to change access", rolename="the forum role", @@ -2853,7 +2341,7 @@ def update_forum_role_membership(request, course_id): @require_POST -def get_user_invoice_preference(request, course_id): # pylint: disable=unused-argument +def get_user_invoice_preference(request, course_id): """ Gets invoice copy user's preferences. """ @@ -2882,7 +2370,7 @@ def _display_unit(unit): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_course_permission(GIVE_STUDENT_EXTENSION) +@require_course_permission(permissions.GIVE_STUDENT_EXTENSION) @require_post_params('student', 'url', 'due_datetime') def change_due_date(request, course_id): """ @@ -2906,7 +2394,7 @@ def change_due_date(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_course_permission(GIVE_STUDENT_EXTENSION) +@require_course_permission(permissions.GIVE_STUDENT_EXTENSION) @require_post_params('student', 'url') def reset_due_date(request, course_id): """ @@ -2917,14 +2405,16 @@ def reset_due_date(request, course_id): unit = find_unit(course, request.POST.get('url')) reason = strip_tags(request.POST.get('reason', '')) + original_due_date = get_date_for_block(course_id, unit.location) + set_due_date_extension(course, unit, student, None, request.user, reason=reason) - if not getattr(unit, "due", None): + if not original_due_date: # It's possible the normal due date was deleted after an extension was granted: return JsonResponse( _("Successfully removed invalid due date extension (unit has no due date).") ) - original_due_date_str = unit.due.strftime(u'%Y-%m-%d %H:%M') + original_due_date_str = original_due_date.strftime(u'%Y-%m-%d %H:%M') return JsonResponse(_( u'Successfully reset due date for student {0} for {1} ' u'to {2}').format(student.profile.name, _display_unit(unit), @@ -2935,7 +2425,7 @@ def reset_due_date(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.GIVE_STUDENT_EXTENSION) @require_post_params('url') def show_unit_extensions(request, course_id): """ @@ -2950,7 +2440,7 @@ def show_unit_extensions(request, course_id): @require_POST @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.GIVE_STUDENT_EXTENSION) @require_post_params('student') def show_student_extensions(request, course_id): """ @@ -3002,7 +2492,7 @@ def _instructor_dash_url(course_key, section=None): @require_global_staff @require_POST -def generate_example_certificates(request, course_id=None): # pylint: disable=unused-argument +def generate_example_certificates(request, course_id=None): """Start generating a set of example certificates. Example certificates are used to verify that certificates have @@ -3017,7 +2507,7 @@ def generate_example_certificates(request, course_id=None): # pylint: disable=u return redirect(_instructor_dash_url(course_key, section='certificates')) -@require_course_permission(ENABLE_CERTIFICATE_GENERATION) +@require_course_permission(permissions.ENABLE_CERTIFICATE_GENERATION) @require_POST def enable_certificate_generation(request, course_id=None): """Enable/disable self-generated certificates for a course. @@ -3037,7 +2527,7 @@ def enable_certificate_generation(request, course_id=None): @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_course_permission(ALLOW_STUDENT_TO_BYPASS_ENTRANCE_EXAM) +@require_course_permission(permissions.ALLOW_STUDENT_TO_BYPASS_ENTRANCE_EXAM) @require_POST def mark_student_can_skip_entrance_exam(request, course_id): """ @@ -3223,7 +2713,7 @@ def remove_certificate_exception(course_key, student): ) try: - generated_certificate = GeneratedCertificate.objects.get( # pylint: disable=no-member + generated_certificate = GeneratedCertificate.objects.get( user=student, course_id=course_key ) @@ -3301,7 +2791,7 @@ def get_student(username_or_email, course_key): @transaction.non_atomic_requests @ensure_csrf_cookie @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_course_permission(GENERATE_CERTIFICATE_EXCEPTIONS) +@require_course_permission(permissions.GENERATE_CERTIFICATE_EXCEPTIONS) @require_POST @common_exceptions_400 def generate_certificate_exceptions(request, course_id, generate_for=None): @@ -3343,7 +2833,7 @@ def generate_certificate_exceptions(request, course_id, generate_for=None): @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_course_permission(GENERATE_BULK_CERTIFICATE_EXCEPTIONS) +@require_course_permission(permissions.GENERATE_BULK_CERTIFICATE_EXCEPTIONS) @require_POST def generate_bulk_certificate_exceptions(request, course_id): """ diff --git a/lms/djangoapps/instructor/views/api_urls.py b/lms/djangoapps/instructor/views/api_urls.py index 250e4525a54219be1e605fe4e484b92bc167df4c..d8df317da9ebeecbd6dc9165de2eafc84c5e9384 100644 --- a/lms/djangoapps/instructor/views/api_urls.py +++ b/lms/djangoapps/instructor/views/api_urls.py @@ -18,10 +18,6 @@ urlpatterns = [ url(r'^get_students_features(?P<csv>/csv)?$', api.get_students_features, name='get_students_features'), url(r'^get_issued_certificates/$', api.get_issued_certificates, name='get_issued_certificates'), url(r'^get_students_who_may_enroll$', api.get_students_who_may_enroll, name='get_students_who_may_enroll'), - url(r'^get_user_invoice_preference$', api.get_user_invoice_preference, name='get_user_invoice_preference'), - url(r'^get_sale_records(?P<csv>/csv)?$', api.get_sale_records, name='get_sale_records'), - url(r'^get_sale_order_records$', api.get_sale_order_records, name='get_sale_order_records'), - url(r'^sale_validation_url$', api.sale_validation, name='sale_validation'), url(r'^get_anon_ids$', api.get_anon_ids, name='get_anon_ids'), url(r'^get_student_enrollment_status$', api.get_student_enrollment_status, name="get_student_enrollment_status"), url(r'^get_student_progress_url$', api.get_student_progress_url, name='get_student_progress_url'), @@ -54,25 +50,12 @@ urlpatterns = [ url(r'^calculate_grades_csv$', api.calculate_grades_csv, name='calculate_grades_csv'), url(r'^problem_grade_report$', api.problem_grade_report, name='problem_grade_report'), - # Financial Report downloads.. - url(r'^list_financial_report_downloads$', api.list_financial_report_downloads, - name='list_financial_report_downloads'), - - # Registration Codes.. - url(r'^get_registration_codes$', api.get_registration_codes, name='get_registration_codes'), - url(r'^generate_registration_codes$', api.generate_registration_codes, name='generate_registration_codes'), - url(r'^active_registration_codes$', api.active_registration_codes, name='active_registration_codes'), - url(r'^spent_registration_codes$', api.spent_registration_codes, name='spent_registration_codes'), - # Reports.. url(r'^get_enrollment_report$', api.get_enrollment_report, name='get_enrollment_report'), url(r'^get_exec_summary_report$', api.get_exec_summary_report, name='get_exec_summary_report'), url(r'^get_course_survey_results$', api.get_course_survey_results, name='get_course_survey_results'), url(r'^export_ora2_data', api.export_ora2_data, name='export_ora2_data'), - # Coupon Codes.. - url(r'^get_coupon_codes', api.get_coupon_codes, name='get_coupon_codes'), - # spoc gradebook url(r'^gradebook$', gradebook_api.spoc_gradebook, name='spoc_gradebook'), diff --git a/lms/djangoapps/instructor/views/coupons.py b/lms/djangoapps/instructor/views/coupons.py deleted file mode 100644 index 2b0e5723b567497c6a0d45e90cd90cf083b76757..0000000000000000000000000000000000000000 --- a/lms/djangoapps/instructor/views/coupons.py +++ /dev/null @@ -1,171 +0,0 @@ -""" -E-commerce Tab Instructor Dashboard Coupons Operations views -""" - - -import datetime -import logging - -import pytz -from django.contrib.auth.decorators import login_required -from django.core.exceptions import ObjectDoesNotExist -from django.utils.translation import ugettext as _ -from django.views.decorators.http import require_POST -from opaque_keys.edx.locator import CourseKey -from six import text_type - -from shoppingcart.models import Coupon, CourseRegistrationCode -from util.json_request import JsonResponse - -log = logging.getLogger(__name__) - - -@require_POST -@login_required -def remove_coupon(request, course_id): # pylint: disable=unused-argument - """ - remove the coupon against the coupon id - set the coupon is_active flag to false - """ - coupon_id = request.POST.get('id', None) - if not coupon_id: - return JsonResponse({ - 'message': _('coupon id is None') - }, status=400) # status code 400: Bad Request - - try: - coupon = Coupon.objects.get(id=coupon_id) - except ObjectDoesNotExist: - return JsonResponse({ - 'message': _(u'coupon with the coupon id ({coupon_id}) DoesNotExist').format(coupon_id=coupon_id) - }, status=400) # status code 400: Bad Request - if not coupon.is_active: - return JsonResponse({ - 'message': _(u'coupon with the coupon id ({coupon_id}) is already inactive').format(coupon_id=coupon_id) - }, status=400) # status code 400: Bad Request - coupon.is_active = False - coupon.save() - return JsonResponse({ - 'message': _(u'coupon with the coupon id ({coupon_id}) updated successfully').format(coupon_id=coupon_id) - }) # status code 200: OK by default - - -@require_POST -@login_required -def add_coupon(request, course_id): - """ - add coupon in the Coupons Table - """ - code = request.POST.get('code') - - # check if the code is already in the Coupons Table and active - try: - course_id = CourseKey.from_string(course_id) - coupon = Coupon.objects.get(is_active=True, code=code, course_id=course_id) - except Coupon.DoesNotExist: - # check if the coupon code is in the CourseRegistrationCode Table - course_registration_code = CourseRegistrationCode.objects.filter(code=code) - if course_registration_code: - return JsonResponse( - {'message': _(u"The code ({code}) that you have tried to define is already in use as a registration code").format(code=code)}, - status=400) # status code 400: Bad Request - - description = request.POST.get('description') - course_id = request.POST.get('course_id') - try: - discount = int(request.POST.get('discount')) - except ValueError: - return JsonResponse({ - 'message': _("Please Enter the Integer Value for Coupon Discount") - }, status=400) # status code 400: Bad Request - - if discount > 100 or discount < 0: - return JsonResponse({ - 'message': _("Please Enter the Coupon Discount Value Less than or Equal to 100") - }, status=400) # status code 400: Bad Request - expiration_date = None - if request.POST.get('expiration_date'): - expiration_date = request.POST.get('expiration_date') - try: - expiration_date = datetime.datetime.strptime(expiration_date, "%m/%d/%Y").replace(tzinfo=pytz.UTC) + datetime.timedelta(days=1) - except ValueError: - return JsonResponse({ - 'message': _("Please enter the date in this format i-e month/day/year") - }, status=400) # status code 400: Bad Request - - coupon = Coupon( - code=code, description=description, - course_id=course_id, - percentage_discount=discount, - created_by_id=request.user.id, - expiration_date=expiration_date - ) - coupon.save() - return JsonResponse( - {'message': _(u"coupon with the coupon code ({code}) added successfully").format(code=code)} - ) - - if coupon: - return JsonResponse( - {'message': _(u"coupon with the coupon code ({code}) already exists for this course").format(code=code)}, - status=400) # status code 400: Bad Request - - -@require_POST -@login_required -def update_coupon(request, course_id): # pylint: disable=unused-argument - """ - update the coupon object in the database - """ - coupon_id = request.POST.get('coupon_id', None) - if not coupon_id: - return JsonResponse({'message': _("coupon id not found")}, status=400) # status code 400: Bad Request - - try: - coupon = Coupon.objects.get(pk=coupon_id) - except ObjectDoesNotExist: - return JsonResponse( - {'message': _(u"coupon with the coupon id ({coupon_id}) DoesNotExist").format(coupon_id=coupon_id)}, - status=400) # status code 400: Bad Request - - description = request.POST.get('description') - coupon.description = description - coupon.save() - return JsonResponse( - {'message': _(u"coupon with the coupon id ({coupon_id}) updated Successfully").format(coupon_id=coupon_id)} - ) - - -@require_POST -@login_required -def get_coupon_info(request, course_id): # pylint: disable=unused-argument - """ - get the coupon information to display in the pop up form - """ - coupon_id = request.POST.get('id', None) - if not coupon_id: - return JsonResponse({ - 'message': _("coupon id not found") - }, status=400) # status code 400: Bad Request - - try: - coupon = Coupon.objects.get(id=coupon_id) - except ObjectDoesNotExist: - return JsonResponse({ - 'message': _(u"coupon with the coupon id ({coupon_id}) DoesNotExist").format(coupon_id=coupon_id) - }, status=400) # status code 400: Bad Request - - if not coupon.is_active: - return JsonResponse({ - 'message': _(u"coupon with the coupon id ({coupon_id}) is already inactive").format(coupon_id=coupon_id) - }, status=400) # status code 400: Bad Request - - expiry_date = coupon.display_expiry_date - return JsonResponse({ - 'coupon_code': coupon.code, - 'coupon_description': coupon.description, - 'coupon_course_id': text_type(coupon.course_id), - 'coupon_discount': coupon.percentage_discount, - 'expiry_date': expiry_date, - 'message': _(u'coupon with the coupon id ({coupon_id}) updated successfully').format(coupon_id=coupon_id) - }) # status code 200: OK by default diff --git a/lms/djangoapps/instructor/views/gradebook_api.py b/lms/djangoapps/instructor/views/gradebook_api.py index 32f0ed3197f4f7c833fd9f6ea282a1e95ba3ab41..ca8a4f0293cb5c6f8d24c5e0240a959e0f0f9173 100644 --- a/lms/djangoapps/instructor/views/gradebook_api.py +++ b/lms/djangoapps/instructor/views/gradebook_api.py @@ -6,7 +6,6 @@ which is currently use by ccx and instructor apps. import math -import six from django.contrib.auth.models import User from django.db import transaction from django.urls import reverse @@ -16,9 +15,11 @@ from opaque_keys.edx.keys import CourseKey from lms.djangoapps.courseware.courses import get_course_with_access from edxmako.shortcuts import render_to_response from lms.djangoapps.grades.api import CourseGradeFactory -from lms.djangoapps.instructor.views.api import require_level +from lms.djangoapps.instructor.views.api import require_course_permission from xmodule.modulestore.django import modulestore +from .. import permissions + # Grade book: max students per page MAX_STUDENTS_PER_PAGE_GRADE_BOOK = 20 @@ -101,7 +102,7 @@ def get_grade_book_page(request, course, course_key): @transaction.non_atomic_requests @cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') +@require_course_permission(permissions.OVERRIDE_GRADES) def spoc_gradebook(request, course_id): """ Show the gradebook for this course: @@ -114,7 +115,7 @@ def spoc_gradebook(request, course_id): return render_to_response('courseware/gradebook.html', { 'page': page, - 'page_url': reverse('spoc_gradebook', kwargs={'course_id': six.text_type(course_key)}), + 'page_url': reverse('spoc_gradebook', kwargs={'course_id': str(course_key)}), 'students': student_info, 'course': course, 'course_id': course_key, diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index aa87e18c5f6c3b903db8fc1bda9e72716352c6d5..21d1a20d6d0446f15f91a24b0f6ccfb14a9df917 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -6,7 +6,7 @@ Instructor Dashboard Views import datetime import logging import uuid -from functools import reduce # pylint: disable=redefined-builtin +from functools import reduce import pytz import six @@ -25,7 +25,7 @@ from mock import patch from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey from six import text_type -from six.moves.urllib.parse import urljoin # pylint: disable=import-error +from six.moves.urllib.parse import urljoin from xblock.field_data import DictFieldData from xblock.fields import ScopeIds @@ -65,6 +65,7 @@ from xmodule.modulestore.django import modulestore from xmodule.tabs import CourseTab from .tools import get_units_with_due_date, title_or_url +from .. import permissions log = logging.getLogger(__name__) @@ -84,7 +85,7 @@ class InstructorDashboardTab(CourseTab): """ Returns true if the specified user has staff access. """ - return bool(user and has_access(user, 'staff', course, course.id)) + return bool(user and user.is_authenticated and user.has_perm(permissions.VIEW_DASHBOARD, course.id)) def show_analytics_dashboard_message(course_key): @@ -120,27 +121,30 @@ def instructor_dashboard_2(request, course_id): 'sales_admin': CourseSalesAdminRole(course_key).has_user(request.user), 'staff': bool(has_access(request.user, 'staff', course)), 'forum_admin': has_forum_access(request.user, course_key, FORUM_ROLE_ADMINISTRATOR), - 'data_researcher': request.user.has_perm('student.can_research', course_key), + 'data_researcher': request.user.has_perm(permissions.CAN_RESEARCH, course_key), } - if not access['staff']: + if not request.user.has_perm(permissions.VIEW_DASHBOARD, course_key): raise Http404() is_white_label = CourseMode.is_white_label(course_key) reports_enabled = configuration_helpers.get_value('SHOW_ECOMMERCE_REPORTS', False) - sections = [ - _section_course_info(course, access), - _section_membership(course, access), - _section_cohort_management(course, access), - _section_discussions_management(course, access), - _section_student_admin(course, access), - _section_data_download(course, access), - ] + sections = [] + if access['staff']: + sections.extend([ + _section_course_info(course, access), + _section_membership(course, access), + _section_cohort_management(course, access), + _section_discussions_management(course, access), + _section_student_admin(course, access), + ]) + if access['data_researcher']: + sections.append(_section_data_download(course, access)) analytics_dashboard_message = None - if show_analytics_dashboard_message(course_key): + if show_analytics_dashboard_message(course_key) and (access['staff'] or access['instructor']): # Construct a URL to the external analytics dashboard analytics_dashboard_url = '{0}/courses/{1}'.format(settings.ANALYTICS_DASHBOARD_URL, six.text_type(course_key)) link_start = HTML(u"<a href=\"{}\" rel=\"noopener\" target=\"_blank\">").format(analytics_dashboard_url) @@ -170,7 +174,7 @@ def instructor_dashboard_2(request, course_id): sections.insert(3, _section_extensions(course)) # Gate access to course email by feature flag & by course-specific authorization - if is_bulk_email_feature_enabled(course_key): + if is_bulk_email_feature_enabled(course_key) and (access['staff'] or access['instructor']): sections.append(_section_send_email(course, access)) # Gate access to Ecommerce tab @@ -207,7 +211,7 @@ def instructor_dashboard_2(request, course_id): openassessment_blocks = [ block for block in openassessment_blocks if block.parent is not None ] - if len(openassessment_blocks) > 0: + if len(openassessment_blocks) > 0 and access['staff']: sections.append(_section_open_response_assessment(request, course, openassessment_blocks, access)) disable_buttons = not _is_small_course(course_key) @@ -504,7 +508,8 @@ def _section_course_info(course, access): try: sorted_cutoffs = sorted(list(course.grade_cutoffs.items()), key=lambda i: i[1], reverse=True) - advance = lambda memo, letter_score_tuple: u"{}: {}, ".format(letter_score_tuple[0], letter_score_tuple[1]) + memo # pylint: disable=line-too-long + advance = lambda memo, letter_score_tuple: u"{}: {}, ".format(letter_score_tuple[0], letter_score_tuple[1]) \ + + memo section_data['grade_cutoffs'] = reduce(advance, sorted_cutoffs, "")[:-2] except Exception: # pylint: disable=broad-except section_data['grade_cutoffs'] = "Not Available" diff --git a/lms/djangoapps/instructor/views/registration_codes.py b/lms/djangoapps/instructor/views/registration_codes.py deleted file mode 100644 index 57348574e484dc65db834161463e29d7c785980a..0000000000000000000000000000000000000000 --- a/lms/djangoapps/instructor/views/registration_codes.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -E-commerce Tab Instructor Dashboard Query Registration Code Status. -""" - - -import logging - -import six -from django.urls import reverse -from django.utils.translation import ugettext as _ -from django.views.decorators.cache import cache_control -from django.views.decorators.http import require_GET, require_POST -from opaque_keys.edx.locator import CourseKey - -from lms.djangoapps.courseware.courses import get_course_by_id -from lms.djangoapps.instructor.enrollment import get_email_params, send_mail_to_student -from lms.djangoapps.instructor.views.api import require_level -from shoppingcart.models import CourseRegistrationCode, RegistrationCodeRedemption -from student.models import CourseEnrollment -from util.json_request import JsonResponse - -log = logging.getLogger(__name__) - - -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') -@require_GET -def look_up_registration_code(request, course_id): - """ - Look for the registration_code in the database. - and check if it is still valid, allowed to redeem or not. - """ - course_key = CourseKey.from_string(course_id) - code = request.GET.get('registration_code') - course = get_course_by_id(course_key, depth=0) - try: - registration_code = CourseRegistrationCode.objects.get(code=code) - except CourseRegistrationCode.DoesNotExist: - return JsonResponse({ - 'is_registration_code_exists': False, - 'is_registration_code_valid': False, - 'is_registration_code_redeemed': False, - 'message': _(u'The enrollment code ({code}) was not found for the {course_name} course.').format( - code=code, course_name=course.display_name - ) - }, status=400) # status code 200: OK by default - - reg_code_already_redeemed = RegistrationCodeRedemption.is_registration_code_redeemed(code) - - registration_code_detail_url = reverse('registration_code_details', kwargs={'course_id': six.text_type(course_id)}) - - return JsonResponse({ - 'is_registration_code_exists': True, - 'is_registration_code_valid': registration_code.is_valid, - 'is_registration_code_redeemed': reg_code_already_redeemed, - 'registration_code_detail_url': registration_code_detail_url - }) # status code 200: OK by default - - -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_level('staff') -@require_POST -def registration_code_details(request, course_id): - """ - Post handler to mark the registration code as - 1) valid - 2) invalid - 3) Unredeem. - - """ - course_key = CourseKey.from_string(course_id) - code = request.POST.get('registration_code') - action_type = request.POST.get('action_type') - course = get_course_by_id(course_key, depth=0) - action_type_messages = { - 'invalidate_registration_code': _('This enrollment code has been canceled. It can no longer be used.'), - 'unredeem_registration_code': _('This enrollment code has been marked as unused.'), - 'validate_registration_code': _('The enrollment code has been restored.') - } - try: - registration_code = CourseRegistrationCode.objects.get(code=code) - except CourseRegistrationCode.DoesNotExist: - return JsonResponse({ - 'message': _(u'The enrollment code ({code}) was not found for the {course_name} course.').format( - code=code, course_name=course.display_name - )}, status=400) - - if action_type == 'invalidate_registration_code': - registration_code.is_valid = False - registration_code.save() - if RegistrationCodeRedemption.is_registration_code_redeemed(code): - code_redemption = RegistrationCodeRedemption.get_registration_code_redemption(code, course_key) - delete_redemption_entry(request, code_redemption, course_key) - - if action_type == 'validate_registration_code': - registration_code.is_valid = True - registration_code.save() - - if action_type == 'unredeem_registration_code': - code_redemption = RegistrationCodeRedemption.get_registration_code_redemption(code, course_key) - if code_redemption is None: - return JsonResponse({ - 'message': _(u'The redemption does not exist against enrollment code ({code}).').format( - code=code)}, status=400) - - delete_redemption_entry(request, code_redemption, course_key) - - return JsonResponse({'message': action_type_messages[action_type]}) - - -def delete_redemption_entry(request, code_redemption, course_key): - """ - delete the redemption entry from the table and - unenroll the user who used the registration code - for the enrollment and send him/her the unenrollment email. - """ - user = code_redemption.redeemed_by - email_address = code_redemption.redeemed_by.email - full_name = code_redemption.redeemed_by.profile.name - CourseEnrollment.unenroll(user, course_key, skip_refund=True) - - course = get_course_by_id(course_key, depth=0) - email_params = get_email_params(course, True, secure=request.is_secure()) - email_params['message_type'] = 'enrolled_unenroll' - email_params['email_address'] = email_address - email_params['full_name'] = full_name - send_mail_to_student(email_address, email_params) - - # remove the redemption entry from the database. - log.info(u'deleting redemption entry (%s) from the database.', code_redemption.id) - code_redemption.delete() diff --git a/lms/djangoapps/instructor/views/tools.py b/lms/djangoapps/instructor/views/tools.py index 70c8f7a0a87bf4a0c2d365c06f43c7bb13a084a9..7cbc0987f59c5e34284896f41687d0f26a742a23 100644 --- a/lms/djangoapps/instructor/views/tools.py +++ b/lms/djangoapps/instructor/views/tools.py @@ -17,6 +17,7 @@ from pytz import UTC from six import string_types, text_type from six.moves import zip +from openedx.core.djangoapps.schedules.models import Schedule from student.models import get_user_by_username_or_email, CourseEnrollment @@ -127,13 +128,19 @@ def get_units_with_due_date(course): """ units = [] + # Pass in a schedule here so that we get back any relative dates in the course, but actual value + # doesn't matter, since we don't care about the dates themselves, just whether they exist. + # Thus we don't save or care about this temporary schedule object. + schedule = Schedule(start_date=course.start) + course_dates = api.get_dates_for_course(course.id, schedule=schedule) + def visit(node): """ Visit a node. Checks to see if node has a due date and appends to `units` if it does. Otherwise recurses into children to search for nodes with due dates. """ - if getattr(node, 'due', None): + if (node.location, 'due') in course_dates: units.append(node) else: for child in node.get_children(): @@ -166,15 +173,35 @@ def set_due_date_extension(course, unit, student, due_date, actor=None, reason=' if not mode: raise DashboardError(_("Could not find student enrollment in the course.")) - if due_date: - try: - api.set_date_for_block(course.id, unit.location, 'due', due_date, user=student, reason=reason, actor=actor) - except api.MissingDateError: - raise DashboardError(_(u"Unit {0} has no due date to extend.").format(unit.location)) - except api.InvalidDateError: - raise DashboardError(_("An extended due date must be later than the original due date.")) - else: - api.set_date_for_block(course.id, unit.location, 'due', None, user=student, reason=reason, actor=actor) + # We normally set dates at the subsection level. But technically dates can be anywhere down the tree (and + # usually are in self paced courses, where the subsection date gets propagated down). + # So find all children that we need to set the date on, then set those dates. + course_dates = api.get_dates_for_course(course.id, user=student) + blocks_to_set = {unit} # always include the requested unit, even if it doesn't appear to have a due date now + + def visit(node): + """ + Visit a node. Checks to see if node has a due date and appends to + `blocks_to_set` if it does. And recurses into children to search for + nodes with due dates. + """ + if (node.location, 'due') in course_dates: + blocks_to_set.add(node) + for child in node.get_children(): + visit(child) + visit(unit) + + for block in blocks_to_set: + if due_date: + try: + api.set_date_for_block(course.id, block.location, 'due', due_date, user=student, reason=reason, + actor=actor) + except api.MissingDateError: + raise DashboardError(_(u"Unit {0} has no due date to extend.").format(unit.location)) + except api.InvalidDateError: + raise DashboardError(_("An extended due date must be later than the original due date.")) + else: + api.set_date_for_block(course.id, block.location, 'due', None, user=student, reason=reason, actor=actor) def dump_module_extensions(course, unit): diff --git a/lms/djangoapps/instructor_analytics/tests/test_basic.py b/lms/djangoapps/instructor_analytics/tests/test_basic.py index ef1d8d2b861be3ea7c4f8d9a566c3f5a1bd76c5e..779344c12b02be0ee3591f4e2441134d76aea4cc 100644 --- a/lms/djangoapps/instructor_analytics/tests/test_basic.py +++ b/lms/djangoapps/instructor_analytics/tests/test_basic.py @@ -37,16 +37,6 @@ from lms.djangoapps.instructor_analytics.basic import ( sale_record_features ) from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory -from shoppingcart.models import ( - Coupon, - CouponRedemption, - CourseRegCodeItem, - CourseRegistrationCode, - CourseRegistrationCodeInvoiceItem, - Invoice, - Order, - RegistrationCodeRedemption -) from student.models import CourseEnrollment, CourseEnrollmentAllowed from student.roles import CourseSalesAdminRole from student.tests.factories import UserFactory @@ -296,362 +286,3 @@ class TestAnalyticsBasic(ModuleStoreTestCase): self.assertEqual(len(proctored_exam_attempts), 3) for proctored_exam_attempt in proctored_exam_attempts: self.assertEqual(set(proctored_exam_attempt.keys()), set(query_features)) - - -@patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True}) -class TestCourseSaleRecordsAnalyticsBasic(ModuleStoreTestCase): - """ Test basic course sale records analytics functions. """ - def setUp(self): - """ - Fixtures. - """ - super(TestCourseSaleRecordsAnalyticsBasic, self).setUp() - self.course = CourseFactory.create() - self.cost = 40 - self.course_mode = CourseMode( - course_id=self.course.id, mode_slug="honor", - mode_display_name="honor cert", min_price=self.cost - ) - self.course_mode.save() - self.instructor = InstructorFactory(course_key=self.course.id) - self.client.login(username=self.instructor.username, password='test') - - def test_course_sale_features(self): - - query_features = [ - 'company_name', 'company_contact_name', 'company_contact_email', 'total_codes', 'total_used_codes', - 'total_amount', 'created', 'customer_reference_number', 'recipient_name', 'recipient_email', - 'created_by', 'internal_reference', 'invoice_number', 'codes', 'course_id' - ] - - #create invoice - sale_invoice = Invoice.objects.create( - total_amount=1234.32, company_name='Test1', company_contact_name='TestName', - company_contact_email='test@company.com', recipient_name='Testw_1', recipient_email='test2@test.com', - customer_reference_number='2Fwe23S', internal_reference="ABC", course_id=self.course.id - ) - invoice_item = CourseRegistrationCodeInvoiceItem.objects.create( - invoice=sale_invoice, - qty=1, - unit_price=1234.32, - course_id=self.course.id - ) - for i in range(5): - course_code = CourseRegistrationCode( - code="test_code{}".format(i), course_id=text_type(self.course.id), - created_by=self.instructor, invoice=sale_invoice, invoice_item=invoice_item, mode_slug='honor' - ) - course_code.save() - - course_sale_records_list = sale_record_features(self.course.id, query_features) - - for sale_record in course_sale_records_list: - self.assertEqual(sale_record['total_amount'], sale_invoice.total_amount) - self.assertEqual(sale_record['recipient_email'], sale_invoice.recipient_email) - self.assertEqual(sale_record['recipient_name'], sale_invoice.recipient_name) - self.assertEqual(sale_record['company_name'], sale_invoice.company_name) - self.assertEqual(sale_record['company_contact_name'], sale_invoice.company_contact_name) - self.assertEqual(sale_record['company_contact_email'], sale_invoice.company_contact_email) - self.assertEqual(sale_record['internal_reference'], sale_invoice.internal_reference) - self.assertEqual(sale_record['customer_reference_number'], sale_invoice.customer_reference_number) - self.assertEqual(sale_record['invoice_number'], sale_invoice.id) - self.assertEqual(sale_record['created_by'], self.instructor) - self.assertEqual(sale_record['total_used_codes'], 0) - self.assertEqual(sale_record['total_codes'], 5) - - def test_course_sale_no_codes(self): - - query_features = [ - 'company_name', 'company_contact_name', 'company_contact_email', 'total_codes', 'total_used_codes', - 'total_amount', 'created', 'customer_reference_number', 'recipient_name', 'recipient_email', - 'created_by', 'internal_reference', 'invoice_number', 'codes', 'course_id' - ] - - #create invoice - sale_invoice = Invoice.objects.create( - total_amount=0.00, company_name='Test1', company_contact_name='TestName', - company_contact_email='test@company.com', recipient_name='Testw_1', recipient_email='test2@test.com', - customer_reference_number='2Fwe23S', internal_reference="ABC", course_id=self.course.id - ) - CourseRegistrationCodeInvoiceItem.objects.create( - invoice=sale_invoice, - qty=0, - unit_price=0.00, - course_id=self.course.id - ) - - course_sale_records_list = sale_record_features(self.course.id, query_features) - - for sale_record in course_sale_records_list: - self.assertEqual(sale_record['total_amount'], sale_invoice.total_amount) - self.assertEqual(sale_record['recipient_email'], sale_invoice.recipient_email) - self.assertEqual(sale_record['recipient_name'], sale_invoice.recipient_name) - self.assertEqual(sale_record['company_name'], sale_invoice.company_name) - self.assertEqual(sale_record['company_contact_name'], sale_invoice.company_contact_name) - self.assertEqual(sale_record['company_contact_email'], sale_invoice.company_contact_email) - self.assertEqual(sale_record['internal_reference'], sale_invoice.internal_reference) - self.assertEqual(sale_record['customer_reference_number'], sale_invoice.customer_reference_number) - self.assertEqual(sale_record['invoice_number'], sale_invoice.id) - self.assertEqual(sale_record['created_by'], None) - self.assertEqual(sale_record['total_used_codes'], 0) - self.assertEqual(sale_record['total_codes'], 0) - - def test_sale_order_features_with_discount(self): - """ - Test Order Sales Report CSV - """ - query_features = [ - ('id', 'Order Id'), - ('company_name', 'Company Name'), - ('company_contact_name', 'Company Contact Name'), - ('company_contact_email', 'Company Contact Email'), - ('total_amount', 'Total Amount'), - ('total_codes', 'Total Codes'), - ('total_used_codes', 'Total Used Codes'), - ('logged_in_username', 'Login Username'), - ('logged_in_email', 'Login User Email'), - ('purchase_time', 'Date of Sale'), - ('customer_reference_number', 'Customer Reference Number'), - ('recipient_name', 'Recipient Name'), - ('recipient_email', 'Recipient Email'), - ('bill_to_street1', 'Street 1'), - ('bill_to_street2', 'Street 2'), - ('bill_to_city', 'City'), - ('bill_to_state', 'State'), - ('bill_to_postalcode', 'Postal Code'), - ('bill_to_country', 'Country'), - ('order_type', 'Order Type'), - ('status', 'Order Item Status'), - ('coupon_code', 'Coupon Code'), - ('unit_cost', 'Unit Price'), - ('list_price', 'List Price'), - ('codes', 'Registration Codes'), - ('course_id', 'Course Id') - ] - # add the coupon code for the course - coupon = Coupon( - code='test_code', - description='test_description', - course_id=self.course.id, - percentage_discount='10', - created_by=self.instructor, - is_active=True - ) - coupon.save() - order = Order.get_cart_for_user(self.instructor) - order.order_type = 'business' - order.save() - order.add_billing_details( - company_name='Test Company', - company_contact_name='Test', - company_contact_email='test@123', - recipient_name='R1', recipient_email='', - customer_reference_number='PO#23' - ) - CourseRegCodeItem.add_to_order(order, self.course.id, 4) - # apply the coupon code to the item in the cart - resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': coupon.code}) - self.assertEqual(resp.status_code, 200) - order.purchase() - - # get the updated item - item = order.orderitem_set.all().select_subclasses()[0] - # get the redeemed coupon information - coupon_redemption = CouponRedemption.objects.select_related('coupon').filter(order=order) - - db_columns = [x[0] for x in query_features] - sale_order_records_list = sale_order_record_features(self.course.id, db_columns) - - for sale_order_record in sale_order_records_list: - self.assertEqual(sale_order_record['recipient_email'], order.recipient_email) - self.assertEqual(sale_order_record['recipient_name'], order.recipient_name) - self.assertEqual(sale_order_record['company_name'], order.company_name) - self.assertEqual(sale_order_record['company_contact_name'], order.company_contact_name) - self.assertEqual(sale_order_record['company_contact_email'], order.company_contact_email) - self.assertEqual(sale_order_record['customer_reference_number'], order.customer_reference_number) - self.assertEqual(sale_order_record['unit_cost'], item.unit_cost) - self.assertEqual(sale_order_record['list_price'], item.list_price) - self.assertEqual(sale_order_record['status'], item.status) - self.assertEqual(sale_order_record['coupon_code'], coupon_redemption[0].coupon.code) - - def test_sale_order_features_without_discount(self): - """ - Test Order Sales Report CSV - """ - query_features = [ - ('id', 'Order Id'), - ('company_name', 'Company Name'), - ('company_contact_name', 'Company Contact Name'), - ('company_contact_email', 'Company Contact Email'), - ('total_amount', 'Total Amount'), - ('total_codes', 'Total Codes'), - ('total_used_codes', 'Total Used Codes'), - ('logged_in_username', 'Login Username'), - ('logged_in_email', 'Login User Email'), - ('purchase_time', 'Date of Sale'), - ('customer_reference_number', 'Customer Reference Number'), - ('recipient_name', 'Recipient Name'), - ('recipient_email', 'Recipient Email'), - ('bill_to_street1', 'Street 1'), - ('bill_to_street2', 'Street 2'), - ('bill_to_city', 'City'), - ('bill_to_state', 'State'), - ('bill_to_postalcode', 'Postal Code'), - ('bill_to_country', 'Country'), - ('order_type', 'Order Type'), - ('status', 'Order Item Status'), - ('coupon_code', 'Coupon Code'), - ('unit_cost', 'Unit Price'), - ('list_price', 'List Price'), - ('codes', 'Registration Codes'), - ('course_id', 'Course Id'), - ('quantity', 'Quantity'), - ('total_discount', 'Total Discount'), - ('total_amount', 'Total Amount Paid'), - ] - # add the coupon code for the course - order = Order.get_cart_for_user(self.instructor) - order.order_type = 'business' - order.save() - order.add_billing_details( - company_name='Test Company', - company_contact_name='Test', - company_contact_email='test@123', - recipient_name='R1', recipient_email='', - customer_reference_number='PO#23' - ) - CourseRegCodeItem.add_to_order(order, self.course.id, 4) - order.purchase() - - # get the updated item - item = order.orderitem_set.all().select_subclasses()[0] - - db_columns = [x[0] for x in query_features] - sale_order_records_list = sale_order_record_features(self.course.id, db_columns) - - for sale_order_record in sale_order_records_list: - self.assertEqual(sale_order_record['recipient_email'], order.recipient_email) - self.assertEqual(sale_order_record['recipient_name'], order.recipient_name) - self.assertEqual(sale_order_record['company_name'], order.company_name) - self.assertEqual(sale_order_record['company_contact_name'], order.company_contact_name) - self.assertEqual(sale_order_record['company_contact_email'], order.company_contact_email) - self.assertEqual(sale_order_record['customer_reference_number'], order.customer_reference_number) - self.assertEqual(sale_order_record['unit_cost'], item.unit_cost) - # Make sure list price is not None and matches the unit price since no discount was applied. - self.assertIsNotNone(sale_order_record['list_price']) - self.assertEqual(sale_order_record['list_price'], item.unit_cost) - self.assertEqual(sale_order_record['status'], item.status) - self.assertEqual(sale_order_record['coupon_code'], 'N/A') - self.assertEqual(sale_order_record['total_amount'], item.unit_cost * item.qty) - self.assertEqual(sale_order_record['total_discount'], 0) - self.assertEqual(sale_order_record['quantity'], item.qty) - - -class TestCourseRegistrationCodeAnalyticsBasic(ModuleStoreTestCase): - """ Test basic course registration codes analytics functions. """ - - def setUp(self): - """ - Fixtures. - """ - super(TestCourseRegistrationCodeAnalyticsBasic, self).setUp() - self.course = CourseFactory.create() - self.instructor = InstructorFactory(course_key=self.course.id) - self.client.login(username=self.instructor.username, password='test') - CourseSalesAdminRole(self.course.id).add_users(self.instructor) - - # Create a paid course mode. - mode = CourseModeFactory.create(course_id=self.course.id, min_price=1) - - url = reverse('generate_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - data = { - 'total_registration_codes': 12, 'company_name': 'Test Group', 'unit_price': 122.45, - 'company_contact_name': 'TestName', 'company_contact_email': 'test@company.com', 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', 'address_line_2': '', - 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': '' - } - - response = self.client.post(url, data, **{'HTTP_HOST': 'localhost'}) - self.assertEqual(response.status_code, 200, response.content) - - def test_course_registration_features(self): - query_features = [ - 'code', 'redeem_code_url', 'course_id', 'company_name', 'created_by', - 'redeemed_by', 'invoice_id', 'purchaser', 'customer_reference_number', 'internal_reference' - ] - order = Order(user=self.instructor, status='purchased') - order.save() - - registration_code_redemption = RegistrationCodeRedemption( - registration_code_id=1, redeemed_by=self.instructor - ) - registration_code_redemption.save() - registration_codes = CourseRegistrationCode.objects.all() - course_registration_list = course_registration_features(query_features, registration_codes, csv_type='download') - self.assertEqual(len(course_registration_list), len(registration_codes)) - for course_registration in course_registration_list: - self.assertEqual(set(course_registration.keys()), set(query_features)) - self.assertIn(course_registration['code'], [registration_code.code for registration_code in registration_codes]) - self.assertIn( - course_registration['course_id'], - [text_type(registration_code.course_id) for registration_code in registration_codes] - ) - self.assertIn( - course_registration['company_name'], - [ - registration_code.invoice_item.invoice.company_name - for registration_code in registration_codes - ] - ) - self.assertIn( - course_registration['invoice_id'], - [ - registration_code.invoice_item.invoice_id - for registration_code in registration_codes - ] - ) - - def test_coupon_codes_features(self): - query_features = [ - 'course_id', 'percentage_discount', 'code_redeemed_count', 'description', 'expiration_date', - 'total_discounted_amount', 'total_discounted_seats' - ] - for i in range(10): - coupon = Coupon( - code='test_code{0}'.format(i), - description='test_description', - course_id=self.course.id, percentage_discount='{0}'.format(i), - created_by=self.instructor, - is_active=True - ) - coupon.save() - #now create coupons with the expiration dates - for i in range(5): - coupon = Coupon( - code='coupon{0}'.format(i), description='test_description', course_id=self.course.id, - percentage_discount='{0}'.format(i), created_by=self.instructor, is_active=True, - expiration_date=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=2) - ) - coupon.save() - - active_coupons = Coupon.objects.filter( - Q(course_id=self.course.id), - Q(is_active=True), - Q(expiration_date__gt=datetime.datetime.now(pytz.UTC)) | - Q(expiration_date__isnull=True) - ) - active_coupons_list = coupon_codes_features(query_features, active_coupons, self.course.id) - self.assertEqual(len(active_coupons_list), len(active_coupons)) - for active_coupon in active_coupons_list: - self.assertEqual(set(active_coupon.keys()), set(query_features)) - self.assertIn(active_coupon['percentage_discount'], [coupon.percentage_discount for coupon in active_coupons]) - self.assertIn(active_coupon['description'], [coupon.description for coupon in active_coupons]) - if active_coupon['expiration_date']: - self.assertIn(active_coupon['expiration_date'], [coupon.display_expiry_date for coupon in active_coupons]) - self.assertIn( - active_coupon['course_id'], - [text_type(coupon.course_id) for coupon in active_coupons] - ) diff --git a/lms/djangoapps/instructor_task/config/waffle.py b/lms/djangoapps/instructor_task/config/waffle.py index 6d353b4622cb6f117372458e8dd0d10420eae225..134ece89523ea93e8e433c98f598e4e9fa159cfc 100644 --- a/lms/djangoapps/instructor_task/config/waffle.py +++ b/lms/djangoapps/instructor_task/config/waffle.py @@ -3,23 +3,36 @@ This module contains various configuration settings via waffle switches for the instructor_task app. """ +from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag, WaffleFlagNamespace, WaffleSwitchNamespace -from openedx.core.djangoapps.waffle_utils import WaffleFlagNamespace, WaffleSwitchNamespace - -WAFFLE_NAMESPACE = u'instructor_task' +WAFFLE_NAMESPACE = 'instructor_task' INSTRUCTOR_TASK_WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name=WAFFLE_NAMESPACE) WAFFLE_SWITCHES = WaffleSwitchNamespace(name=WAFFLE_NAMESPACE) # Waffle switches -OPTIMIZE_GET_LEARNERS_FOR_COURSE = u'optimize_get_learners_for_course' -GENERATE_GRADE_REPORT_VERIFIED_ONLY = u'generate_grade_report_for_verified_only' +OPTIMIZE_GET_LEARNERS_FOR_COURSE = 'optimize_get_learners_for_course' + +# Course override flags +GENERATE_PROBLEM_GRADE_REPORT_VERIFIED_ONLY = 'generate_problem_grade_report_verified_only' +GENERATE_COURSE_GRADE_REPORT_VERIFIED_ONLY = 'generate_course_grade_report_verified_only' def waffle_flags(): """ Returns the namespaced, cached, audited Waffle flags dictionary for Grades. """ - return {} + return { + GENERATE_PROBLEM_GRADE_REPORT_VERIFIED_ONLY: CourseWaffleFlag( + waffle_namespace=INSTRUCTOR_TASK_WAFFLE_FLAG_NAMESPACE, + flag_name=GENERATE_PROBLEM_GRADE_REPORT_VERIFIED_ONLY, + flag_undefined_default=False, + ), + GENERATE_COURSE_GRADE_REPORT_VERIFIED_ONLY: CourseWaffleFlag( + waffle_namespace=INSTRUCTOR_TASK_WAFFLE_FLAG_NAMESPACE, + flag_name=GENERATE_COURSE_GRADE_REPORT_VERIFIED_ONLY, + flag_undefined_default=False, + ), + } def optimize_get_learners_switch_enabled(): @@ -29,9 +42,19 @@ def optimize_get_learners_switch_enabled(): return WAFFLE_SWITCHES.is_enabled(OPTIMIZE_GET_LEARNERS_FOR_COURSE) -def generate_grade_report_for_verified_only(): +def problem_grade_report_verified_only(course_id): + """ + Returns True if problem grade reports should only + return rows for verified students in the given course, + False otherwise. + """ + return waffle_flags()[GENERATE_PROBLEM_GRADE_REPORT_VERIFIED_ONLY].is_enabled(course_id) + + +def course_grade_report_verified_only(course_id): """ - Returns True if waffle switch is enabled that indicates generate grading reports only for - verified learners. + Returns True if problem grade reports should only + return rows for verified students in the given course, + False otherwise. """ - return WAFFLE_SWITCHES.is_enabled(GENERATE_GRADE_REPORT_VERIFIED_ONLY) + return waffle_flags()[GENERATE_COURSE_GRADE_REPORT_VERIFIED_ONLY].is_enabled(course_id) diff --git a/lms/djangoapps/instructor_task/tasks_helper/certs.py b/lms/djangoapps/instructor_task/tasks_helper/certs.py index 714a32b2d7d608263738fb3891cffa192a5f9fa8..047beacf6a3e064cbc0d8f4396b6d853ba2db4de 100644 --- a/lms/djangoapps/instructor_task/tasks_helper/certs.py +++ b/lms/djangoapps/instructor_task/tasks_helper/certs.py @@ -134,7 +134,7 @@ def invalidate_generated_certificates(course_id, enrolled_students, certificate_ :param enrolled_students: (queryset or list) students enrolled in the course :param certificate_statuses: certificates statuses for whom to remove generated certificate """ - certificates = GeneratedCertificate.objects.filter( # pylint: disable=no-member + certificates = GeneratedCertificate.objects.filter( user__in=enrolled_students, course_id=course_id, status__in=certificate_statuses, diff --git a/lms/djangoapps/instructor_task/tasks_helper/grades.py b/lms/djangoapps/instructor_task/tasks_helper/grades.py index 8ad22e7f1598d7f5efedee2ff5a0cb57202da99d..7beead617f07d170ccb811ce5eadfde8bd84c911 100644 --- a/lms/djangoapps/instructor_task/tasks_helper/grades.py +++ b/lms/djangoapps/instructor_task/tasks_helper/grades.py @@ -29,11 +29,13 @@ from lms.djangoapps.grades.api import prefetch_course_and_subsection_grades from lms.djangoapps.instructor_analytics.basic import list_problem_responses from lms.djangoapps.instructor_analytics.csvs import format_dictlist from lms.djangoapps.instructor_task.config.waffle import ( - generate_grade_report_for_verified_only, - optimize_get_learners_switch_enabled + course_grade_report_verified_only, + optimize_get_learners_switch_enabled, + problem_grade_report_verified_only ) from lms.djangoapps.teams.models import CourseTeamMembership from lms.djangoapps.verify_student.services import IDVerificationService +from openedx.core.lib.cache_utils import get_cache from openedx.core.djangoapps.content.block_structure.api import get_course_in_cache from openedx.core.djangoapps.course_groups.cohorts import bulk_cache_cohorts, get_cohort, is_course_cohorted from openedx.core.djangoapps.user_api.course_tag.api import BulkCourseTags @@ -220,6 +222,7 @@ class _CourseGradeReportContext(object): self.action_name = action_name self.course_id = course_id self.task_progress = TaskProgress(self.action_name, total=None, start_time=time()) + self.report_for_verified_only = course_grade_report_verified_only(self.course_id) @lazy def course(self): @@ -311,7 +314,7 @@ class _ProblemGradeReportContext(object): self.task_input = _task_input self.action_name = action_name self.course_id = course_id - self.report_for_verified_only = generate_grade_report_for_verified_only() + self.report_for_verified_only = problem_grade_report_verified_only(self.course_id) self.task_progress = TaskProgress(self.action_name, total=None, start_time=time()) self.file_name = 'problem_grade_report' @@ -560,11 +563,9 @@ class CourseGradeReport(object): **filter_kwargs ).select_related('profile') yield users - course_id = context.course_id task_log_message = u'{}, Task type: {}'.format(context.task_info_string, context.action_name) - report_for_verified_only = generate_grade_report_for_verified_only() - return get_enrolled_learners_for_course(course_id=course_id, verified_only=report_for_verified_only) + return get_enrolled_learners_for_course(course_id=course_id, verified_only=context.report_for_verified_only) def _user_grades(self, course_grade, context): """ @@ -811,6 +812,9 @@ class ProblemGradeReport(GradeReportBase): """ for users in self._batch_users(context): yield self._rows_for_users(context, users) + # Clear the CourseEnrollment caches after each batch of users has been processed + get_cache('get_enrollment').clear() + get_cache(CourseEnrollment.MODE_CACHE_NAMESPACE).clear() class ProblemResponses(object): diff --git a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py index 3622ed095692e56a42a560b37dfea142261c2592..7cbfd0271eab6f09a734f1a4bed282c77ca9fd7e 100644 --- a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py +++ b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py @@ -26,7 +26,7 @@ from mock import ANY, MagicMock, Mock, patch from pytz import UTC from six import text_type from six.moves import range, zip -from six.moves.urllib.parse import quote # pylint: disable=import-error +from six.moves.urllib.parse import quote from waffle.testutils import override_switch import openedx.core.djangoapps.user_api.course_tag.api as course_tag_api @@ -73,15 +73,6 @@ from openedx.core.djangoapps.credit.tests.factories import CreditCourseFactory from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme from openedx.core.djangoapps.util.testing import ContentGroupTestCase, TestConditionalContent from openedx.core.lib.teams_config import TeamsConfig -from shoppingcart.models import ( - Coupon, - CourseRegistrationCode, - CourseRegistrationCodeInvoiceItem, - Invoice, - InvoiceTransaction, - Order, - PaidCourseRegistration -) from student.models import ALLOWEDTOENROLL_TO_ENROLLED, CourseEnrollment, CourseEnrollmentAllowed, ManualEnrollmentAudit from student.tests.factories import CourseEnrollmentFactory, UserFactory from survey.models import SurveyAnswer, SurveyForm @@ -90,7 +81,6 @@ from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls from xmodule.partitions.partitions import Group, UserPartition -from ..config.waffle import GENERATE_GRADE_REPORT_VERIFIED_ONLY from ..models import ReportStore from ..tasks_helper.utils import UPDATE_STATUS_FAILED, UPDATE_STATUS_SUCCEEDED @@ -98,7 +88,6 @@ _TEAMS_CONFIG = TeamsConfig({ 'max_size': 2, 'topics': [{'id': 'topic', 'name': 'Topic', 'description': 'A Topic'}], }) -SWITCH_GENERATE_GRADE_REPORT_VERIFIED_ONLY = '.'.join(['instructor_task', GENERATE_GRADE_REPORT_VERIFIED_ONLY]) class InstructorGradeReportTestCase(TestReportMixin, InstructorTaskCourseTestCase): @@ -420,7 +409,7 @@ class TestInstructorGradeReport(InstructorGradeReportTestCase): RequestCache.clear_all_namespaces() - expected_query_count = 45 + expected_query_count = 46 with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): with check_mongo_calls(mongo_count): with self.assertNumQueries(expected_query_count): @@ -668,209 +657,6 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase): self.assertIn("report_name", result) -@ddt.ddt -@patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True}) -class TestInstructorDetailedEnrollmentReport(TestReportMixin, InstructorTaskCourseTestCase): - """ - Tests that CSV detailed enrollment generation works. - """ - def setUp(self): - super(TestInstructorDetailedEnrollmentReport, self).setUp() - self.course = CourseFactory.create() - CourseModeFactory.create( - course_id=self.course.id, - min_price=50, - mode_slug=CourseMode.DEFAULT_SHOPPINGCART_MODE_SLUG - ) - - # create testing invoice 1 - self.instructor = InstructorFactory(course_key=self.course.id) - self.sale_invoice_1 = Invoice.objects.create( - total_amount=1234.32, company_name='Test1', company_contact_name='TestName', - company_contact_email='Test@company.com', - recipient_name='Testw', recipient_email='test1@test.com', customer_reference_number='2Fwe23S', - internal_reference="A", course_id=self.course.id, is_valid=True - ) - self.invoice_item = CourseRegistrationCodeInvoiceItem.objects.create( - invoice=self.sale_invoice_1, - qty=1, - unit_price=1234.32, - course_id=self.course.id - ) - - def test_success(self): - self.create_student('student', 'student@example.com') - task_input = {'features': []} - with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): - result = upload_enrollment_report(None, None, self.course.id, task_input, 'generating_enrollment_report') - - self.assertDictContainsSubset({'attempted': 1, 'succeeded': 1, 'failed': 0}, result) - - def test_student_paid_course_enrollment_report(self): - """ - test to check the paid user enrollment csv report status - and enrollment source. - """ - student = UserFactory() - student_cart = Order.get_cart_for_user(student) - PaidCourseRegistration.add_to_order(student_cart, self.course.id) - student_cart.purchase() - - task_input = {'features': []} - with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): - result = upload_enrollment_report(None, None, self.course.id, task_input, 'generating_enrollment_report') - self.assertDictContainsSubset({'attempted': 1, 'succeeded': 1, 'failed': 0}, result) - self._verify_cell_data_in_csv(student.username, 'Enrollment Source', 'Credit Card - Individual') - self._verify_cell_data_in_csv(student.username, 'Payment Status', 'purchased') - - def test_student_manually_enrolled_in_detailed_enrollment_source(self): - """ - test to check the manually enrolled user enrollment report status - and enrollment source. - """ - student = UserFactory() - enrollment = CourseEnrollment.enroll(student, self.course.id) - ManualEnrollmentAudit.create_manual_enrollment_audit( - self.instructor, student.email, ALLOWEDTOENROLL_TO_ENROLLED, - 'manually enrolling unenrolled user', enrollment - ) - - task_input = {'features': []} - with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): - result = upload_enrollment_report(None, None, self.course.id, task_input, 'generating_enrollment_report') - - enrollment_source = u'manually enrolled by username: {username}'.format( - username=self.instructor.username) - self.assertDictContainsSubset({'attempted': 1, 'succeeded': 1, 'failed': 0}, result) - self._verify_cell_data_in_csv(student.username, 'Enrollment Source', enrollment_source) - self._verify_cell_data_in_csv( - student.username, - 'Manual (Un)Enrollment Reason', - 'manually enrolling unenrolled user' - ) - self._verify_cell_data_in_csv(student.username, 'Payment Status', 'TBD') - - def test_student_used_enrollment_code_for_course_enrollment(self): - """ - test to check the user enrollment source and payment status in the - enrollment detailed report - """ - student = UserFactory() - self.client.login(username=student.username, password='test') - student_cart = Order.get_cart_for_user(student) - paid_course_reg_item = PaidCourseRegistration.add_to_order(student_cart, self.course.id) - # update the quantity of the cart item paid_course_reg_item - resp = self.client.post(reverse('shoppingcart.views.update_user_cart'), - {'ItemId': paid_course_reg_item.id, 'qty': '4'}) - self.assertEqual(resp.status_code, 200) - student_cart.purchase() - - course_reg_codes = CourseRegistrationCode.objects.filter(order=student_cart) - redeem_url = reverse('register_code_redemption', args=[course_reg_codes[0].code]) - response = self.client.get(redeem_url) - self.assertEqual(response.status_code, 200) - # check button text - self.assertContains(response, 'Activate Course Enrollment') - - response = self.client.post(redeem_url) - self.assertEqual(response.status_code, 200) - - task_input = {'features': []} - with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): - result = upload_enrollment_report(None, None, self.course.id, task_input, 'generating_enrollment_report') - self.assertDictContainsSubset({'attempted': 1, 'succeeded': 1, 'failed': 0}, result) - self._verify_cell_data_in_csv(student.username, 'Enrollment Source', 'Used Registration Code') - self._verify_cell_data_in_csv(student.username, 'Payment Status', 'purchased') - - def test_student_used_invoice_unpaid_enrollment_code_for_course_enrollment(self): - """ - test to check the user enrollment source and payment status in the - enrollment detailed report - """ - student = UserFactory() - self.client.login(username=student.username, password='test') - - course_registration_code = CourseRegistrationCode( - code='abcde', - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice_1, - invoice_item=self.invoice_item, - mode_slug=CourseMode.DEFAULT_SHOPPINGCART_MODE_SLUG - ) - course_registration_code.save() - - redeem_url = reverse('register_code_redemption', args=['abcde']) - response = self.client.get(redeem_url) - self.assertEqual(response.status_code, 200) - # check button text - self.assertContains(response, 'Activate Course Enrollment') - - response = self.client.post(redeem_url) - self.assertEqual(response.status_code, 200) - - task_input = {'features': []} - with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): - result = upload_enrollment_report(None, None, self.course.id, task_input, 'generating_enrollment_report') - self.assertDictContainsSubset({'attempted': 1, 'succeeded': 1, 'failed': 0}, result) - self._verify_cell_data_in_csv(student.username, 'Enrollment Source', 'Used Registration Code') - self._verify_cell_data_in_csv(student.username, 'Payment Status', 'Invoice Outstanding') - - def test_student_used_invoice_paid_enrollment_code_for_course_enrollment(self): - """ - test to check the user enrollment source and payment status in the - enrollment detailed report - """ - student = UserFactory() - self.client.login(username=student.username, password='test') - invoice_transaction = InvoiceTransaction( - invoice=self.sale_invoice_1, - amount=self.sale_invoice_1.total_amount, - status='completed', - created_by=self.instructor, - last_modified_by=self.instructor - ) - invoice_transaction.save() - course_registration_code = CourseRegistrationCode( - code='abcde', - course_id=text_type(self.course.id), - created_by=self.instructor, - invoice=self.sale_invoice_1, - invoice_item=self.invoice_item, - mode_slug=CourseMode.DEFAULT_SHOPPINGCART_MODE_SLUG - ) - course_registration_code.save() - - redeem_url = reverse('register_code_redemption', args=['abcde']) - response = self.client.get(redeem_url) - self.assertEqual(response.status_code, 200) - # check button text - self.assertContains(response, 'Activate Course Enrollment') - - response = self.client.post(redeem_url) - self.assertEqual(response.status_code, 200) - - task_input = {'features': []} - with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): - result = upload_enrollment_report(None, None, self.course.id, task_input, 'generating_enrollment_report') - self.assertDictContainsSubset({'attempted': 1, 'succeeded': 1, 'failed': 0}, result) - self._verify_cell_data_in_csv(student.username, 'Enrollment Source', 'Used Registration Code') - self._verify_cell_data_in_csv(student.username, 'Payment Status', 'Invoice Paid') - - def _verify_cell_data_in_csv(self, username, column_header, expected_cell_content): - """ - Verify that the last ReportStore CSV contains the expected content. - """ - report_store = ReportStore.from_config(config_name='FINANCIAL_REPORTS') - report_csv_filename = report_store.links_for(self.course.id)[0][0] - report_path = report_store.path_to(self.course.id, report_csv_filename) - with report_store.storage.open(report_path) as csv_file: - # Expand the dict reader generator so we don't lose it's content - for row in unicodecsv.DictReader(csv_file): - if row.get('Username') == username: - self.assertEqual(row[column_header], expected_cell_content) - - @ddt.ddt class TestProblemGradeReport(TestReportMixin, InstructorTaskModuleTestCase): """ @@ -943,23 +729,26 @@ class TestProblemGradeReport(TestReportMixin, InstructorTaskModuleTestCase): ]) @patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task') - @override_switch(SWITCH_GENERATE_GRADE_REPORT_VERIFIED_ONLY, True) def test_single_problem_verified_student_only(self, _get_current_task): - student_verified = self.create_student(u'user_verified', mode='verified') - vertical = ItemFactory.create( - parent_location=self.problem_section.location, - category='vertical', - metadata={'graded': True}, - display_name='Problem Vertical' - ) - self.define_option_problem(u'Problem1', parent=vertical) + with patch( + 'lms.djangoapps.instructor_task.tasks_helper.grades.problem_grade_report_verified_only', + return_value=True, + ): + student_verified = self.create_student(u'user_verified', mode='verified') + vertical = ItemFactory.create( + parent_location=self.problem_section.location, + category='vertical', + metadata={'graded': True}, + display_name='Problem Vertical' + ) + self.define_option_problem(u'Problem1', parent=vertical) - self.submit_student_answer(self.student_1.username, u'Problem1', ['Option 1']) - self.submit_student_answer(student_verified.username, u'Problem1', ['Option 1']) - result = ProblemGradeReport.generate(None, None, self.course.id, None, 'graded') - self.assertDictContainsSubset( - {'action_name': 'graded', 'attempted': 1, 'succeeded': 1, 'failed': 0}, result - ) + self.submit_student_answer(self.student_1.username, u'Problem1', ['Option 1']) + self.submit_student_answer(student_verified.username, u'Problem1', ['Option 1']) + result = ProblemGradeReport.generate(None, None, self.course.id, None, 'graded') + self.assertDictContainsSubset( + {'action_name': 'graded', 'attempted': 1, 'succeeded': 1, 'failed': 0}, result + ) @patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task') def test_inactive_enrollment_included(self, _get_current_task): @@ -1258,34 +1047,6 @@ class TestExecutiveSummaryReport(TestReportMixin, InstructorTaskCourseTestCase): self.instructor = InstructorFactory(course_key=self.course.id) self.student1 = UserFactory() self.student2 = UserFactory() - self.student1_cart = Order.get_cart_for_user(self.student1) - self.student2_cart = Order.get_cart_for_user(self.student2) - - self.sale_invoice_1 = Invoice.objects.create( - total_amount=1234.32, company_name='Test1', company_contact_name='TestName', - company_contact_email='Test@company.com', - recipient_name='Testw', recipient_email='test1@test.com', customer_reference_number='2Fwe23S', - internal_reference="A", course_id=self.course.id, is_valid=True - ) - InvoiceTransaction.objects.create( - invoice=self.sale_invoice_1, - amount=self.sale_invoice_1.total_amount, - status='completed', - created_by=self.instructor, - last_modified_by=self.instructor - ) - self.invoice_item = CourseRegistrationCodeInvoiceItem.objects.create( - invoice=self.sale_invoice_1, - qty=10, - unit_price=1234.32, - course_id=self.course.id - ) - for i in range(5): - coupon = Coupon( - code='coupon{0}'.format(i), description='test_description', course_id=self.course.id, - percentage_discount='{0}'.format(i), created_by=self.instructor, is_active=True, - ) - coupon.save() def test_successfully_generate_executive_summary_report(self): """ @@ -1300,66 +1061,6 @@ class TestExecutiveSummaryReport(TestReportMixin, InstructorTaskCourseTestCase): ReportStore.from_config(config_name='FINANCIAL_REPORTS') self.assertDictContainsSubset({'attempted': 1, 'succeeded': 1, 'failed': 0}, result) - def students_purchases(self): - """ - Students purchases the courses using enrollment - and coupon codes. - """ - self.client.login(username=self.student1.username, password='test') - paid_course_reg_item = PaidCourseRegistration.add_to_order(self.student1_cart, self.course.id) - # update the quantity of the cart item paid_course_reg_item - resp = self.client.post(reverse('shoppingcart.views.update_user_cart'), { - 'ItemId': paid_course_reg_item.id, 'qty': '4' - }) - self.assertEqual(resp.status_code, 200) - # apply the coupon code to the item in the cart - resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': 'coupon1'}) - self.assertEqual(resp.status_code, 200) - - self.student1_cart.purchase() - - course_reg_codes = CourseRegistrationCode.objects.filter(order=self.student1_cart) - redeem_url = reverse('register_code_redemption', args=[course_reg_codes[0].code]) - response = self.client.get(redeem_url) - self.assertEqual(response.status_code, 200) - # check button text - self.assertContains(response, 'Activate Course Enrollment') - - response = self.client.post(redeem_url) - self.assertEqual(response.status_code, 200) - - self.client.login(username=self.student2.username, password='test') - PaidCourseRegistration.add_to_order(self.student2_cart, self.course.id) - - # apply the coupon code to the item in the cart - resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': 'coupon1'}) - self.assertEqual(resp.status_code, 200) - - self.student2_cart.purchase() - - @patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True}) - def test_generate_executive_summary_report(self): - """ - test to generate executive summary report - and then test the report authenticity. - """ - self.students_purchases() - task_input = {'features': []} - with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): - result = upload_exec_summary_report( - None, None, self.course.id, - task_input, 'generating executive summary report' - ) - report_store = ReportStore.from_config(config_name='FINANCIAL_REPORTS') - expected_data = [ - 'Gross Revenue Collected', '$1481.82', - 'Gross Revenue Pending', '$0.00', - 'Average Price per Seat', '$296.36', - 'Number of seats purchased using coupon codes', '<td>2</td>' - ] - self.assertDictContainsSubset({'attempted': 1, 'succeeded': 1, 'failed': 0}, result) - self._verify_html_file_report(report_store, expected_data) - def _verify_html_file_report(self, report_store, expected_data): """ Verify grade report data. @@ -2008,28 +1709,31 @@ class TestGradeReport(TestReportMixin, InstructorTaskModuleTestCase): ) @patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task') - @override_switch(SWITCH_GENERATE_GRADE_REPORT_VERIFIED_ONLY, True) def test_course_grade_with_verified_student_only(self, _get_current_task): """ Tests that course grade report has expected data when it is generated only for verified learners. """ - student_1 = self.create_student(u'user_honor') - student_verified = self.create_student(u'user_verified', mode='verified') - vertical = ItemFactory.create( - parent_location=self.problem_section.location, - category='vertical', - metadata={'graded': True}, - display_name='Problem Vertical' - ) - self.define_option_problem(u'Problem1', parent=vertical) + with patch( + 'lms.djangoapps.instructor_task.tasks_helper.grades.course_grade_report_verified_only', + return_value=True, + ): + student_1 = self.create_student(u'user_honor') + student_verified = self.create_student(u'user_verified', mode='verified') + vertical = ItemFactory.create( + parent_location=self.problem_section.location, + category='vertical', + metadata={'graded': True}, + display_name='Problem Vertical' + ) + self.define_option_problem(u'Problem1', parent=vertical) - self.submit_student_answer(student_1.username, u'Problem1', ['Option 1']) - self.submit_student_answer(student_verified.username, u'Problem1', ['Option 1']) - result = CourseGradeReport.generate(None, None, self.course.id, None, 'graded') - self.assertDictContainsSubset( - {'action_name': 'graded', 'attempted': 1, 'succeeded': 1, 'failed': 0}, result - ) + self.submit_student_answer(student_1.username, u'Problem1', ['Option 1']) + self.submit_student_answer(student_verified.username, u'Problem1', ['Option 1']) + result = CourseGradeReport.generate(None, None, self.course.id, None, 'graded') + self.assertDictContainsSubset( + {'action_name': 'graded', 'attempted': 1, 'succeeded': 1, 'failed': 0}, result + ) @ddt.data(True, False) def test_fast_generation(self, create_non_zero_grade): diff --git a/lms/djangoapps/learner_dashboard/programs.py b/lms/djangoapps/learner_dashboard/programs.py index f7e0914a88f386336976555a551f0eaf5892a155..4ec9df392d9a92404bf447e3f49cecc804ea1118 100644 --- a/lms/djangoapps/learner_dashboard/programs.py +++ b/lms/djangoapps/learner_dashboard/programs.py @@ -31,6 +31,8 @@ class ProgramsFragmentView(EdxFragmentView): """ A fragment to program listing. """ + _uses_pattern_library = False + def render_to_fragment(self, request, **kwargs): """ Render the program listing fragment. @@ -82,6 +84,8 @@ class ProgramDetailsFragmentView(EdxFragmentView): """ Render the program details fragment. """ + _uses_pattern_library = False + def render_to_fragment(self, request, program_uuid, **kwargs): """View details about a specific program.""" programs_config = kwargs.get('programs_config') or ProgramsApiConfig.current() diff --git a/lms/djangoapps/learner_dashboard/tests/test_programs.py b/lms/djangoapps/learner_dashboard/tests/test_programs.py index 18463a33fd81731ce4c7f428d520ce9d7da33f76..2d27052c01c96f12b567b07d30c57d5d11bfc63c 100644 --- a/lms/djangoapps/learner_dashboard/tests/test_programs.py +++ b/lms/djangoapps/learner_dashboard/tests/test_programs.py @@ -10,7 +10,7 @@ from uuid import uuid4 import mock import six -from six.moves.urllib.parse import urljoin # pylint: disable=import-error +from six.moves.urllib.parse import urljoin from bs4 import BeautifulSoup from django.conf import settings from django.test import override_settings diff --git a/lms/djangoapps/learner_dashboard/views.py b/lms/djangoapps/learner_dashboard/views.py index dd0beedeefdb788b63380346ac2b5283f576ce13..e77f970c08d596b28d2db330d497cdca3cded8c4 100644 --- a/lms/djangoapps/learner_dashboard/views.py +++ b/lms/djangoapps/learner_dashboard/views.py @@ -22,7 +22,7 @@ def program_listing(request): 'nav_hidden': True, 'show_dashboard_tabs': True, 'show_program_listing': programs_config.enabled, - 'uses_pattern_library': True, + 'uses_bootstrap': True, } return render_to_response('learner_dashboard/programs.html', context) @@ -43,7 +43,7 @@ def program_details(request, program_uuid): 'show_dashboard_tabs': True, 'nav_hidden': True, 'disable_courseware_js': True, - 'uses_pattern_library': True, + 'uses_bootstrap': True, } return render_to_response('learner_dashboard/program_details.html', context) diff --git a/lms/djangoapps/lms_xblock/field_data.py b/lms/djangoapps/lms_xblock/field_data.py index dff09c79d3f2a5cc9fefec72e4cb112f261d913e..6866c32187bc8fc8bf63a5ae5a3248d875dd2ae6 100644 --- a/lms/djangoapps/lms_xblock/field_data.py +++ b/lms/djangoapps/lms_xblock/field_data.py @@ -17,7 +17,7 @@ class LmsFieldData(SplitFieldData): def __init__(self, authored_data, student_data): # Make sure that we don't repeatedly nest LmsFieldData instances if isinstance(authored_data, LmsFieldData): - authored_data = authored_data._authored_data # pylint: disable=protected-access + authored_data = authored_data._authored_data else: authored_data = ReadOnlyFieldData(authored_data) diff --git a/lms/djangoapps/lms_xblock/test/test_runtime.py b/lms/djangoapps/lms_xblock/test/test_runtime.py index a3563e24d254394e4b193a14380a47476ad41b0e..91aba728acdd5dc1f863b645a27294dced918e92 100644 --- a/lms/djangoapps/lms_xblock/test/test_runtime.py +++ b/lms/djangoapps/lms_xblock/test/test_runtime.py @@ -9,7 +9,7 @@ from django.test import TestCase from mock import Mock, patch from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locations import BlockUsageLocator, CourseLocator -from six.moves.urllib.parse import urlparse # pylint: disable=import-error +from six.moves.urllib.parse import urlparse from xblock.exceptions import NoSuchServiceError from xblock.fields import ScopeIds diff --git a/lms/djangoapps/lti_provider/apps.py b/lms/djangoapps/lti_provider/apps.py index 9360bbaf075bb2b0f42b5cf4535e51468adb54b1..bb5a66f5ad60fdaf7b9d53705f3448aa236998a8 100644 --- a/lms/djangoapps/lti_provider/apps.py +++ b/lms/djangoapps/lti_provider/apps.py @@ -15,4 +15,4 @@ class LtiProviderConfig(AppConfig): def ready(self): # Import the tasks module to ensure that signal handlers are registered. - from . import signals # pylint: disable=unused-variable + from . import signals # pylint: disable=unused-import diff --git a/lms/djangoapps/lti_provider/outcomes.py b/lms/djangoapps/lti_provider/outcomes.py index 65e6c3c7d9a94f389669ab4b84dfddea1fdfd822..8efcbe4353eb60a47aba5f68e1c8a420beb110d5 100644 --- a/lms/djangoapps/lti_provider/outcomes.py +++ b/lms/djangoapps/lti_provider/outcomes.py @@ -37,7 +37,7 @@ def store_outcome_parameters(request_params, user, lti_consumer): # the LTI consumer that the request comes from then we may be able # to figure out the result service URL. As it stands, though, this # is a badly-formed LTI request - log.warn( + log.warning( u"Outcome Service: lis_outcome_service_url parameter missing " u"from scored assignment; we will be unable to return a score. " u"Request parameters: %s", @@ -168,7 +168,8 @@ def sign_and_send_replace_result(assignment, xml): consumer_key, consumer_secret, signature_method='HMAC-SHA1', - force_include_body=True + force_include_body=True, + decoding=None, ) headers = {'content-type': 'application/xml'} diff --git a/lms/djangoapps/mailing/management/commands/mailchimp_sync_course.py b/lms/djangoapps/mailing/management/commands/mailchimp_sync_course.py index cf736855c136c4573636dbbb4e71197ba0d98903..02d73c1c2884cc1b7e558ea072a6d1a66ec7af19 100644 --- a/lms/djangoapps/mailing/management/commands/mailchimp_sync_course.py +++ b/lms/djangoapps/mailing/management/commands/mailchimp_sync_course.py @@ -135,7 +135,7 @@ def get_student_data(students, exclude=None): """ # To speed the query, we won't retrieve the full User object, only # two of its values. The namedtuple simulates the User object. - FakeUser = namedtuple('Fake', 'id username is_anonymous') # pylint: disable=invalid-name + FakeUser = namedtuple('Fake', 'id username is_anonymous') exclude = exclude if exclude else set() diff --git a/lms/djangoapps/mobile_api/models.py b/lms/djangoapps/mobile_api/models.py index 3775cd58bbe2d37d62d924cb458fc2646cc44b70..8fe88fc9d1b5ebd9cc41d0870051a61ab2821200 100644 --- a/lms/djangoapps/mobile_api/models.py +++ b/lms/djangoapps/mobile_api/models.py @@ -91,7 +91,7 @@ class AppVersionConfig(models.Model): super(AppVersionConfig, self).save(*args, **kwargs) -class IgnoreMobileAvailableFlagConfig(ConfigurationModel): # pylint: disable=W5101 +class IgnoreMobileAvailableFlagConfig(ConfigurationModel): """ Configuration for the mobile_available flag. Default is false. diff --git a/lms/djangoapps/mobile_api/users/tests.py b/lms/djangoapps/mobile_api/users/tests.py index e06de0309fc61a1f7c50770f52d79d28f9dbd637..e93a7fb42fc19a534faec760938078ff2d1c6aa9 100644 --- a/lms/djangoapps/mobile_api/users/tests.py +++ b/lms/djangoapps/mobile_api/users/tests.py @@ -16,7 +16,7 @@ from django.utils.timezone import now from milestones.tests.utils import MilestonesTestCaseMixin from mock import patch from six.moves import range -from six.moves.urllib.parse import parse_qs # pylint: disable=import-error +from six.moves.urllib.parse import parse_qs from course_modes.models import CourseMode from lms.djangoapps.courseware.access_response import MilestoneAccessError, StartDateError, VisibilityError @@ -280,8 +280,10 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest user=self.user, course_id=course.id ) + enrollment.created = self.THREE_YEARS_AGO + datetime.timedelta(days=1) + enrollment.save() + ScheduleFactory( - start_date=self.THREE_YEARS_AGO + datetime.timedelta(days=1), enrollment=enrollment ) else: @@ -318,7 +320,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest Test that expired courses are only returned in v1 of API when waffle flag enabled, and un-expired courses always returned ''' - CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime.datetime(2018, 1, 1)) + CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime.datetime(2015, 1, 1)) courses = self._get_enrollment_data(api_version, expired) self._assert_enrollment_results(api_version, courses, num_courses_returned, True) diff --git a/lms/djangoapps/mobile_api/users/views.py b/lms/djangoapps/mobile_api/users/views.py index 135ba536006dcbe9ab00d23a9fe4f2df0e8ffdfd..68ace1c3fc1941714ec41d18b27d4d0f89951be9 100644 --- a/lms/djangoapps/mobile_api/users/views.py +++ b/lms/djangoapps/mobile_api/users/views.py @@ -179,7 +179,7 @@ class UserCourseStatus(views.APIView): return self._get_course_info(request, course) @mobile_course_access(depth=2) - def get(self, request, course, *args, **kwargs): # pylint: disable=unused-argument + def get(self, request, course, *args, **kwargs): """ Get the ID of the module that the specified user last visited in the specified course. """ @@ -187,7 +187,7 @@ class UserCourseStatus(views.APIView): return self._get_course_info(request, course) @mobile_course_access(depth=2) - def patch(self, request, course, *args, **kwargs): # pylint: disable=unused-argument + def patch(self, request, course, *args, **kwargs): """ Update the ID of the module that the specified user last visited in the specified course. """ diff --git a/lms/djangoapps/monitoring/__init__.py b/lms/djangoapps/monitoring/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..89f1b2b54799a6eacb194e6c96782ad2e8dfa5f9 --- /dev/null +++ b/lms/djangoapps/monitoring/__init__.py @@ -0,0 +1,3 @@ +""" +LMS specific monitoring helpers. +""" diff --git a/lms/djangoapps/monitoring/apps.py b/lms/djangoapps/monitoring/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..1ae13624c4f0894f61405df0f8df24b40b7ce39c --- /dev/null +++ b/lms/djangoapps/monitoring/apps.py @@ -0,0 +1,11 @@ +""" +Configuration for the monitoring Django application. +""" +from django.apps import AppConfig + + +class MonitoringConfig(AppConfig): + """ + Configuration class for the monitoring Django application. + """ + name = 'monitoring' diff --git a/lms/djangoapps/monitoring/docs/decisions/0001-monitoring-by-code-owner.rst b/lms/djangoapps/monitoring/docs/decisions/0001-monitoring-by-code-owner.rst new file mode 100644 index 0000000000000000000000000000000000000000..fefb4664033550adfd9393e2b1dfc4d8938a43d3 --- /dev/null +++ b/lms/djangoapps/monitoring/docs/decisions/0001-monitoring-by-code-owner.rst @@ -0,0 +1,50 @@ +Monitoring by Code Owner +************************ + +Status +====== + +Accepted + +Context +======= + +It is currently difficult for different teams to have team-based on-calls rotations, alerting and monitoring for various parts of the edx-platform (specifically LMS). + +Decision +======== + +We will implement a custom metric "code_owner" that can be used in NewRelic (or other monitoring solutions that are made pluggable). + +The new custom metric makes it simple to query NewRelic for all Transactions or TransactionErrors that are associated with requests with a specific owner. This enables a team to quickly identify data that they own, for use in NewRelic alerts or NewRelic dashboards. + +To minimize maintenance, the value of the "code_owner" metric will be populated using the source-of-truth of ownership of various parts of edx-platform. + +See `Rejected Alternatives`_ for details of the decision **not** to split the NewRelic application into multiple NewRelic applications. + +Note: "owner" is a MySql reserved word, which NewRelic cautions against using, so we are using "code_owner". + +Consequences +============ + +This metric should be quickly available for use with custom alerts and custom dashboards. + +In the future, this metric could potentially be added to logging as well. + +Rejected Alternatives +===================== + +Splitting the NewRelic application +---------------------------------- + +The edx-platform (LMS) NewRelic application could have been split into multiple applications. This would have had the benefit of getting the out-of-the-box APM Dashboards for free. + +We decided against this alternative because: + +* To enable this solution, we would need to disable gunicorn instrumentation, and this instrumentation has proved to be valuable for understanding certain types of production issues. +* Splitting the app may make it more difficult to pinpoint the source of any problem that affects multiple applications. +* The application splitting depends on a slight "hack" from NewRelic, by resetting the application name for each path. + + * This "hack" goes against the grain of NewRelic's typical recommendations, so there could be unknown pitfalls. + * The mapping of request path to owner would require additional maintenance. + * Processing time is **not** accounted for in the NewRelic transaction time, because any processing required takes place before the NewRelic transaction gets started. diff --git a/lms/djangoapps/monitoring/middleware.py b/lms/djangoapps/monitoring/middleware.py new file mode 100644 index 0000000000000000000000000000000000000000..05bca4c9565b32cde05f8446c24c6918b669c577 --- /dev/null +++ b/lms/djangoapps/monitoring/middleware.py @@ -0,0 +1,49 @@ +""" +Middleware for monitoring the LMS +""" +import logging +from django.urls import Resolver404, resolve +from edx_django_utils.monitoring import set_custom_metric + +from .utils import get_code_owner_from_module, is_code_owner_mappings_configured + +log = logging.getLogger(__name__) + + +class CodeOwnerMetricMiddleware: + """ + Django middleware object to set custom metrics for the owner of each view. + + Custom metrics set: + - code_owner: The owning team mapped to the current view. + - code_owner_mapping_error: If there are any errors when trying to perform the mapping. + - view_func_module: The __module__ of the view_func, which can be used to + find missing mappings. + + """ + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + self._set_owner_metrics_for_request(request) + response = self.get_response(request) + return response + + def _set_owner_metrics_for_request(self, request): + """ + Uses the request path to find the view_func and then sets code owner metrics based on the view. + """ + if not is_code_owner_mappings_configured(): + return + + try: + view_func, _, _ = resolve(request.path) + view_func_module = view_func.__module__ + set_custom_metric('view_func_module', view_func_module) + code_owner = get_code_owner_from_module(view_func_module) + if code_owner: + set_custom_metric('code_owner', code_owner) + except Resolver404: + set_custom_metric('code_owner_mapping_error', "Couldn't resolve view for request path {}".format(request.path)) + except Exception as e: + set_custom_metric('code_owner_mapping_error', e) diff --git a/lms/djangoapps/monitoring/scripts/clean_unmapped_view_modules.py b/lms/djangoapps/monitoring/scripts/clean_unmapped_view_modules.py new file mode 100644 index 0000000000000000000000000000000000000000..2d6233ff5b232298452d218677cf8aef758df1f3 --- /dev/null +++ b/lms/djangoapps/monitoring/scripts/clean_unmapped_view_modules.py @@ -0,0 +1,73 @@ +""" +Provided a CSV of data from our monitoring system, this script outputs a unique and clean +set of apps of unmapped view_func_modules. + +Context: This script was useful when first introducing ownership mapping and we had many +apps from 3rd-party dependencies that were missed. At this point, we'd probably only +expect 0-2 new unmapped apps, which could be cleaned manually very quickly without this +script. + +Sample usage:: + + python lms/djangoapps/monitoring/scripts/clean_unmapped_view_modules.py --unmapped-csv "unmapped-apps.csv" + +Or for more details:: + + python lms/djangoapps/monitoring/scripts/clean_unmapped_view_modules.py --help + + +""" +import csv +import click + + +@click.command() +@click.option( + '--unmapped-csv', + help="File name of .csv file with unmapped edx-platform view modules.", + required=True +) +def main(unmapped_csv): + """ + Reads CSV of unmapped view_func_modules and outputs a clean list of apps to map. + + NewRelic Insights Query to create CSV of unmapped modules: + + \b + SELECT count(view_func_module) FROM Transaction + WHERE code_owner is null FACET view_func_module + SINCE 1 week ago + LIMIT 50 + + \b + * Increase or decrease SINCE clause as necessary based on when the mappings were last updated. + * Save results as CSV for use in script + + Sample CSV input:: + + \b + View Func Module,View Func Modules + enterprise.api.v1.views,1542 + edx_proctoring.views,116 + social_django.views,53 + + Script removes duplicates in addition to providing sorted list of plain app names. + + """ + with open(unmapped_csv, 'r') as file: + csv_data = file.read() + reader = csv.DictReader(csv_data.splitlines()) + + clean_apps_set = set() + for row in reader: + path = row.get('View Func Module') + path_parts = path.split('.') + clean_apps_set.add(path_parts[0]) + + print('# Move into generate_code_owner_mappings.py and complete mappings.') + for clean_app in sorted(clean_apps_set): + print(clean_app) + + +if __name__ == "__main__": + main() # pylint: disable=no-value-for-parameter diff --git a/lms/djangoapps/monitoring/scripts/generate_code_owner_mappings.py b/lms/djangoapps/monitoring/scripts/generate_code_owner_mappings.py new file mode 100644 index 0000000000000000000000000000000000000000..0913e553dfd8f066e11e4970aa40fa81a6217bdd --- /dev/null +++ b/lms/djangoapps/monitoring/scripts/generate_code_owner_mappings.py @@ -0,0 +1,170 @@ +""" +This script generates code owner mappings for monitoring LMS. + +Sample usage:: + + python lms/djangoapps/monitoring/scripts/generate_code_owner_mappings.py --repo-csv "Individual Repo Ownership.csv" --app-csv "edx-platform Apps Ownership.csv" --dep-csv "edx-platform 3rd-party Ownership.csv" + +Or for more details:: + + python lms/djangoapps/monitoring/scripts/generate_code_owner_mappings.py --help + + +""" +import csv +import click +import os +import re + +# Maps edx-platform installed Django apps to the edx repo that contains +# the app code. +EDX_REPO_APPS = { + 'bulk_grades': 'https://github.com/edx/edx-bulk-grades', + 'coaching': 'https://github.com/edx/platform-plugin-coaching', + 'completion': 'https://github.com/edx/completion', + 'config_models': 'https://github.com/edx/django-config-models', + 'consent': 'https://github.com/edx/edx-enterprise', + 'csrf': 'https://github.com/edx/edx-drf-extensions', + 'edx_proctoring': 'https://github.com/edx/edx-proctoring', + 'edxval': 'https://github.com/edx/edx-val', + 'enterprise': 'https://github.com/edx/edx-enterprise', + 'enterprise_learner_portal': 'https://github.com/edx/edx-enterprise', + 'help_tokens': 'https://github.com/edx/help-tokens', + 'integrated_channels': 'https://github.com/edx/edx-enterprise', + 'organizations': 'https://github.com/edx/edx-organizations', + 'search': 'https://github.com/edx/edx-search', + 'wiki': 'https://github.com/edx/django-wiki', +} + +# Maps edx-platform installed Django apps to the third-party repo that contains +# the app code. +THIRD_PARTY_APPS = { + 'django': 'https://github.com/django/django', + 'django_object_actions': 'https://github.com/crccheck/django-object-actions', + 'drf_yasg': 'https://github.com/axnsan12/drf-yasg', + 'lx_pathway_plugin': 'https://github.com/open-craft/lx-pathway-plugin', + 'simple_history': 'https://github.com/treyhunner/django-simple-history', + 'social_django': 'https://github.com/python-social-auth/social-app-django', +} + + +@click.command() +@click.option( + '--repo-csv', + help="File name of .csv file with repo ownership details.", + required=True +) +@click.option( + '--app-csv', + help="File name of .csv file with edx-platform app ownership details.", + required=True +) +@click.option( + '--dep-csv', + help="File name of .csv file with edx-platform 3rd-party dependency ownership details.", + required=True +) +def main(repo_csv, app_csv, dep_csv): + """ + Reads CSV of ownership data and outputs config.yml setting to system.out. + + Expected Repo CSV format: + + \b + repo url,owner.squad + https://github.com/edx/edx-bulk-grades,team-red + ... + + Expected App CSV format: + + \b + Path,owner.squad + ./openedx/core/djangoapps/user_authn,team-blue + ... + + Expected 3rd-party Dependency CSV format: + + \b + repo url,owner.squad + https://github.com/django/django,team-red + ... + + Final output only includes paths which might contain views. + + """ + # Maps owner names to a list of dotted module paths. + # For example: { 'team-red': [ 'openedx.core.djangoapps.api_admin', 'openedx.core.djangoapps.auth_exchange' ] } + owner_to_paths_map = {} + _map_repo_apps('edx-repo', repo_csv, EDX_REPO_APPS, owner_to_paths_map) + _map_repo_apps('3rd-party', dep_csv, THIRD_PARTY_APPS, owner_to_paths_map) + _map_edx_platform_apps(app_csv, owner_to_paths_map) + + print('# Do not hand edit CODE_OWNER_MAPPINGS. Generated by {}'.format(os.path.basename(__file__))) + print('CODE_OWNER_MAPPINGS:') + for owner, path_list in sorted(owner_to_paths_map.items()): + print(" {}:".format(owner)) + path_list.sort() + for path in path_list: + print(" - {}".format(path)) + + +def _map_repo_apps(csv_type, repo_csv, app_to_repo_map, owner_to_paths_map): + """ + Reads CSV of repo ownership and uses app_to_repo_map to updates owner_to_paths_map + + Arguments: + csv_type (string): Either 'edx-repo' or '3rd-party' for warning message + repo_csv (string): File name for the edx-repo or 3rd-party repo csv + app_to_repo_map (dict): Dict mapping Django apps to repo urls + owner_to_paths_map (dict): Holds results mapping owner to paths. + + """ + with open(repo_csv, 'r') as file: + csv_data = file.read() + reader = csv.DictReader(csv_data.splitlines()) + + csv_repo_to_owner_map = {} + for row in reader: + csv_repo_to_owner_map[row.get('repo url')] = row.get('owner.squad') + + for app, repo_url in app_to_repo_map.items(): + owner = csv_repo_to_owner_map.get(repo_url, None) + if owner: + if owner not in owner_to_paths_map: + owner_to_paths_map[owner] = [] + owner_to_paths_map[owner].append(app) + else: + print('WARNING: Repo {} was not found in {} csv. Needed for app {}.'.format(repo_url, csv_type, app)) + + +def _map_edx_platform_apps(app_csv, owner_to_paths_map): + """ + Reads CSV of edx-platform app ownership and updates mappings + """ + with open(app_csv, 'r') as file: + csv_data = file.read() + reader = csv.DictReader(csv_data.splitlines()) + for row in reader: + path = row.get('Path') + owner = row.get('owner.squad') + + # add paths that may have views + may_have_views = re.match(r'.*djangoapps', path) or re.match(r'[./]*openedx\/features', path) + # remove cms (studio) paths and tests + may_have_views = may_have_views and not re.match(r'.*(\/tests\b|cms\/).*', path) + + if may_have_views: + path = path.replace('./', '') # remove ./ from beginning of path + path = path.replace('/', '.') # convert path to dotted module name + + # skip catch-alls to ensure everything is properly mapped + if path in ('common.djangoapps', 'lms.djangoapps', 'openedx.core.djangoapps', 'openedx.features'): + continue + + if owner not in owner_to_paths_map: + owner_to_paths_map[owner] = [] + owner_to_paths_map[owner].append(path) + + +if __name__ == "__main__": + main() # pylint: disable=no-value-for-parameter diff --git a/lms/djangoapps/monitoring/tests/mock_views.py b/lms/djangoapps/monitoring/tests/mock_views.py new file mode 100644 index 0000000000000000000000000000000000000000..dee7872a28357cd649af17503525c8fefc50530b --- /dev/null +++ b/lms/djangoapps/monitoring/tests/mock_views.py @@ -0,0 +1,13 @@ +""" +Mock views with a different module to enable testing of mapping +code_owner to modules. Trying to mock __module__ on a view was +getting too complex. +""" +from rest_framework.views import APIView + + +class MockViewTest(APIView): + """ + Mock view for use in testing. + """ + pass diff --git a/lms/djangoapps/monitoring/tests/test_middleware.py b/lms/djangoapps/monitoring/tests/test_middleware.py new file mode 100644 index 0000000000000000000000000000000000000000..62cd907de981d6c17393ef57515f15709672b382 --- /dev/null +++ b/lms/djangoapps/monitoring/tests/test_middleware.py @@ -0,0 +1,122 @@ +""" +Tests for the LMS monitoring middleware +""" +import ddt +from django.conf.urls import url +from django.test import override_settings, RequestFactory +from django.urls import resolve +from mock import call, patch, Mock +from rest_framework.views import APIView +from unittest import TestCase +from unittest.mock import ANY + +from lms.djangoapps.monitoring.middleware import CodeOwnerMetricMiddleware +from lms.djangoapps.monitoring.tests.mock_views import MockViewTest +from lms.djangoapps.monitoring.utils import _process_code_owner_mappings + + +class MockMiddlewareViewTest(APIView): + pass + + +urlpatterns = [ + url(r'^middleware-test/$', MockMiddlewareViewTest.as_view()), + url(r'^test/$', MockViewTest.as_view()), +] + + +@ddt.ddt +class CodeOwnerMetricMiddlewareTests(TestCase): + """ + Tests for the LMS monitoring utility functions + """ + urls = 'lms.djangoapps.monitoring.tests.test_middleware.test_urls' + + def setUp(self): + super().setUp() + self.mock_get_response = Mock() + self.middleware = CodeOwnerMetricMiddleware(self.mock_get_response) + + def test_init(self): + self.assertEqual(self.middleware.get_response, self.mock_get_response) + + def test_request_call(self): + self.mock_get_response.return_value = 'test-response' + request = Mock() + self.assertEqual(self.middleware(request), 'test-response') + + _REQUEST_PATH_TO_MODULE_PATH = { + '/middleware-test/': 'test_middleware', + '/test/': 'lms.djangoapps.monitoring.tests.mock_views', + } + + @override_settings( + CODE_OWNER_MAPPINGS={'team-red': ['lms.djangoapps.monitoring.tests.mock_views']}, + ROOT_URLCONF=__name__, + ) + @patch('lms.djangoapps.monitoring.middleware.set_custom_metric') + @ddt.data( + ('/middleware-test/', None), + ('/test/', 'team-red'), + ) + @ddt.unpack + def test_code_owner_mapping_hits_and_misses( + self, request_path, expected_owner, mock_set_custom_metric + ): + with patch('lms.djangoapps.monitoring.utils._PATH_TO_CODE_OWNER_MAPPINGS', _process_code_owner_mappings()): + request = RequestFactory().get(request_path) + self.middleware(request) + view_func, _, _ = resolve(request_path) + expected_view_func_module = self._REQUEST_PATH_TO_MODULE_PATH[request_path] + self._assert_code_owner_custom_metrics( + expected_view_func_module, mock_set_custom_metric, expected_code_owner=expected_owner + ) + + @patch('lms.djangoapps.monitoring.middleware.set_custom_metric') + def test_code_owner_no_mappings(self, mock_set_custom_metric): + request = RequestFactory().get('/test/') + self.middleware(request) + mock_set_custom_metric.assert_not_called() + + @override_settings( + CODE_OWNER_MAPPINGS={'team-red': ['lms.djangoapps.monitoring.tests.mock_views']}, + ) + @patch('lms.djangoapps.monitoring.middleware.set_custom_metric') + def test_no_resolver_for_request_path(self, mock_set_custom_metric): + with patch('lms.djangoapps.monitoring.utils._PATH_TO_CODE_OWNER_MAPPINGS', _process_code_owner_mappings()): + request = RequestFactory().get('/bad/path/') + self.middleware(request) + self._assert_code_owner_custom_metrics( + None, mock_set_custom_metric, has_error=True + ) + + @override_settings( + CODE_OWNER_MAPPINGS=['invalid_setting_as_list'], + ROOT_URLCONF=__name__, + ) + @patch('lms.djangoapps.monitoring.middleware.set_custom_metric') + def test_load_config_with_invalid_dict(self, mock_set_custom_metric): + with patch('lms.djangoapps.monitoring.utils._PATH_TO_CODE_OWNER_MAPPINGS', _process_code_owner_mappings()): + request = RequestFactory().get('/test/') + self.middleware(request) + expected_view_func_module = self._REQUEST_PATH_TO_MODULE_PATH['/test/'] + self._assert_code_owner_custom_metrics( + expected_view_func_module, mock_set_custom_metric, has_error=True + ) + + def _assert_code_owner_custom_metrics( + self, view_func_module, mock_set_custom_metric, expected_code_owner=None, has_error=False, + process_view_func=None, + ): + call_list = [] + if view_func_module: + call_list.append(call('view_func_module', view_func_module)) + if expected_code_owner: + call_list.append(call('code_owner', expected_code_owner)) + if has_error: + call_list.append(call('code_owner_mapping_error', ANY)) + mock_set_custom_metric.assert_has_calls(call_list) + self.assertEqual( + len(mock_set_custom_metric.call_args_list), len(call_list), + 'Expected calls {} vs actual calls {}'.format(call_list, mock_set_custom_metric.call_args_list) + ) diff --git a/lms/djangoapps/monitoring/tests/test_monitoring_utils.py b/lms/djangoapps/monitoring/tests/test_monitoring_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..fa4cb9caf95a801f792180edc7d780cb6ca9ce86 --- /dev/null +++ b/lms/djangoapps/monitoring/tests/test_monitoring_utils.py @@ -0,0 +1,93 @@ +""" +Tests for the LMS monitoring middleware + +Note: File named test_monitoring_utils.py instead of test_utils.py because of an error +in Jenkins with test collection and a conflict with another test_utils.py file. + +""" +import ddt +import timeit +from django.test import override_settings +from mock import call, patch, Mock +from unittest import TestCase + +from lms.djangoapps.monitoring.utils import ( + _process_code_owner_mappings, + get_code_owner_from_module, + is_code_owner_mappings_configured, +) + + +@ddt.ddt +class MonitoringUtilsTests(TestCase): + """ + Tests for the LMS monitoring utility functions + """ + @override_settings(CODE_OWNER_MAPPINGS=None) + def test_is_config_loaded_with_no_config(self): + with patch('lms.djangoapps.monitoring.utils._PATH_TO_CODE_OWNER_MAPPINGS', _process_code_owner_mappings()): + self.assertFalse(is_code_owner_mappings_configured(), "Mappings should not be configured.") + + @override_settings(CODE_OWNER_MAPPINGS={'team-red': ['openedx.core.djangoapps.xblock']}) + def test_is_config_loaded_with_valid_dict(self): + with patch('lms.djangoapps.monitoring.utils._PATH_TO_CODE_OWNER_MAPPINGS', _process_code_owner_mappings()): + self.assertTrue(is_code_owner_mappings_configured(), "Mappings should be configured.") + + @override_settings(CODE_OWNER_MAPPINGS=['invalid_setting_as_list']) + def test_is_config_loaded_with_invalid_dict(self): + with patch('lms.djangoapps.monitoring.utils._PATH_TO_CODE_OWNER_MAPPINGS', _process_code_owner_mappings()): + self.assertTrue(is_code_owner_mappings_configured(), "Although invalid, mappings should be configured.") + + @override_settings(CODE_OWNER_MAPPINGS={ + 'team-red': [ + 'openedx.core.djangoapps.xblock', + 'lms.djangoapps.grades', + ], + 'team-blue': [ + 'common.djangoapps.xblock_django', + ], + }) + @ddt.data( + ('xbl', None), + ('xblock_2', None), + ('xblock', 'team-red'), + ('openedx.core.djangoapps', None), + ('openedx.core.djangoapps.xblock', 'team-red'), + ('openedx.core.djangoapps.xblock.views', 'team-red'), + ('grades', 'team-red'), + ('lms.djangoapps.grades', 'team-red'), + ('xblock_django', 'team-blue'), + ('common.djangoapps.xblock_django', 'team-blue'), + ) + @ddt.unpack + def test_code_owner_mapping_hits_and_misses(self, module, expected_owner): + with patch('lms.djangoapps.monitoring.utils._PATH_TO_CODE_OWNER_MAPPINGS', _process_code_owner_mappings()): + actual_owner = get_code_owner_from_module(module) + self.assertEqual(expected_owner, actual_owner) + + @override_settings(CODE_OWNER_MAPPINGS=['invalid_setting_as_list']) + def test_load_config_with_invalid_dict(self): + with patch('lms.djangoapps.monitoring.utils._PATH_TO_CODE_OWNER_MAPPINGS', _process_code_owner_mappings()): + self.assertTrue(is_code_owner_mappings_configured(), "Although invalid, mappings should be configured.") + with self.assertRaises(AssertionError): + get_code_owner_from_module('xblock') + + def test_mapping_performance(self): + code_owner_mappings = { + 'team-red': [] + } + # create a long list of mappings that are nearly identical + for n in range(1, 200): + path = 'openedx.core.djangoapps.{}'.format(n) + code_owner_mappings['team-red'].append(path) + with override_settings(CODE_OWNER_MAPPINGS=code_owner_mappings): + with patch( + 'lms.djangoapps.monitoring.utils._PATH_TO_CODE_OWNER_MAPPINGS', _process_code_owner_mappings() + ): + call_iterations = 100 + time = timeit.timeit( + # test a module name that matches nearly to the end, but doesn't actually match + lambda: get_code_owner_from_module('openedx.core.djangoapps.XXX.views'), number=call_iterations + ) + average_time = time / call_iterations + self.assertTrue(average_time < 0.0005, 'Mapping takes {}s which is too slow.'.format(average_time)) diff --git a/lms/djangoapps/monitoring/utils.py b/lms/djangoapps/monitoring/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..536b92c205879e21e61857c466ca60027d06552a --- /dev/null +++ b/lms/djangoapps/monitoring/utils.py @@ -0,0 +1,114 @@ +""" +Utilities for monitoring the LMS +""" +import logging +import re +from django.conf import settings + +log = logging.getLogger(__name__) + + +def get_code_owner_from_module(module): + """ + Attempts lookup of code_owner based on a code module, + finding the most specific match. If no match, returns None. + + For example, if the module were 'openedx.features.discounts.views', + this lookup would match on 'openedx.features.discounts' before + 'openedx.features', because the former is more specific. + + """ + assert _PATH_TO_CODE_OWNER_MAPPINGS != _INVALID_CODE_OWNER_MAPPING,\ + 'CODE_OWNER_MAPPINGS django setting set with invalid configuration. See logs for details.' + + module_parts = module.split('.') + # To make the most specific match, start with the max number of parts + for number_of_parts in range(len(module_parts), 0, -1): + partial_path = '.'.join(module_parts[0:number_of_parts]) + if partial_path in _PATH_TO_CODE_OWNER_MAPPINGS: + code_owner = _PATH_TO_CODE_OWNER_MAPPINGS[partial_path] + return code_owner + return None + + +def is_code_owner_mappings_configured(): + """ + Returs True if code owner mappings were configured, and False otherwise. + """ + return bool(_PATH_TO_CODE_OWNER_MAPPINGS) + + +def _process_code_owner_mappings(): + """ + Processes the CODE_OWNER_MAPPINGS Django Setting and returns a dict optimized + for efficient lookup by path. + + Returns: + (dict): optimized dict for success processing, None if there are no + configured mappings, or _INVALID_CODE_OWNER_MAPPING if there is an + error processing the setting. + + Example CODE_OWNER_MAPPINGS Django Setting:: + + CODE_OWNER_MAPPINGS = { + 'team-red': [ + 'xblock_django', + 'openedx.core.djangoapps.xblock', + ], + 'team-blue': [ + 'badges', + ], + } + + Example return value:: + + { + 'xblock_django': 'team-red', + 'openedx.core.djangoapps.xblock': 'team-red', + 'badges': 'team-blue', + } + + """ + _CODE_OWNER_MAPPINGS = getattr(settings, 'CODE_OWNER_MAPPINGS', None) + if not _CODE_OWNER_MAPPINGS: + return None + + try: + path_to_code_owner_mappings = {} + for code_owner in _CODE_OWNER_MAPPINGS: + path_list = _CODE_OWNER_MAPPINGS[code_owner] + for path in path_list: + path_to_code_owner_mappings[path] = code_owner + optional_module_prefix_match = _OPTIONAL_MODULE_PREFIX_PATTERN.match(path) + # if path has an optional prefix, also add the module name without the prefix + if optional_module_prefix_match: + path_without_prefix = path[optional_module_prefix_match.end():] + path_to_code_owner_mappings[path_without_prefix] = code_owner + + return path_to_code_owner_mappings + except Exception as e: + log.exception('Error processing code_owner_mappings. {}'.format(e)) + # errors should be unlikely due do scripting the setting values. + # this will trigger an error custom metric that can be alerted on. + return _INVALID_CODE_OWNER_MAPPING + +# .. toggle_name: CODE_OWNER_MAPPINGS +# .. toggle_implementation: DjangoSetting +# .. toggle_default: None +# .. toggle_description: Used to set monitoring custom metrics for owner. Dict with keys of code owner and value as list of dotted path module names owned by code owner. +# .. toggle_category: monitoring +# .. toggle_use_cases: open_edx +# .. toggle_creation_date: 2020-05-29 +# .. toggle_expiration_date: None +# .. toggle_tickets: None +# .. toggle_status: supported +# .. toggle_warnings: None +# Set to settings.CODE_OWNER_MAPPINGS during processing for simpler testing +_CODE_OWNER_MAPPINGS = None + +# The following module prefixes are optional in a view's reported module: +# 'common.djangoapps.', 'lms.djangoapps.', 'openedx.core.djangoapps.' +_OPTIONAL_MODULE_PREFIX_PATTERN = re.compile(r'^(lms|common|openedx\.core)\.djangoapps\.') +_INVALID_CODE_OWNER_MAPPING = 'invalid-code-owner-mapping' +# lookup table for code owner given a module path +_PATH_TO_CODE_OWNER_MAPPINGS = _process_code_owner_mappings() diff --git a/lms/djangoapps/program_enrollments/api/__init__.py b/lms/djangoapps/program_enrollments/api/__init__.py index 9c048a14848665e877de18800b6871c8bdf867cb..1b35870eeddefaff144277ff61bad366497273c7 100644 --- a/lms/djangoapps/program_enrollments/api/__init__.py +++ b/lms/djangoapps/program_enrollments/api/__init__.py @@ -22,11 +22,11 @@ from .reading import ( fetch_program_enrollments, fetch_program_enrollments_by_student, get_external_key_by_user_and_course, + get_org_key_for_program, get_program_course_enrollment, get_program_enrollment, get_provider_slug, get_saml_provider_for_organization, - get_org_key_for_program, get_users_by_external_keys, get_users_by_external_keys_and_org_key, is_course_staff_enrollment diff --git a/lms/djangoapps/program_enrollments/api/linking.py b/lms/djangoapps/program_enrollments/api/linking.py index eb7a869475c07bac8ba453a4667f86267d9b7e0e..cc17988c633908b9615c3fc4d992e9a8cfc6716e 100644 --- a/lms/djangoapps/program_enrollments/api/linking.py +++ b/lms/djangoapps/program_enrollments/api/linking.py @@ -1,5 +1,5 @@ """ -Python API function to link program enrollments and external_student_keys to an +Python API function to link program enrollments and external_user_keys to an LMS user. Outside of this subpackage, import these functions @@ -12,6 +12,7 @@ import logging from django.contrib.auth import get_user_model from django.db import IntegrityError, transaction +from course_modes.models import CourseMode from student.api import get_access_role_by_role_name from student.models import CourseEnrollmentException @@ -24,16 +25,15 @@ User = get_user_model() NO_PROGRAM_ENROLLMENT_TEMPLATE = ( 'No program enrollment found for program uuid={program_uuid} and external student ' - 'key={external_student_key}' + 'key={external_user_key}' ) NO_LMS_USER_TEMPLATE = 'No user found with username {}' EXISTING_USER_TEMPLATE = ( - 'Program enrollment with external_student_key={external_student_key} is already linked to ' + 'Program enrollment with external_student_key={external_user_key} is already linked to ' '{account_relation} account username={username}' ) -@transaction.atomic def link_program_enrollments(program_uuid, external_keys_to_usernames): """ Utility function to link ProgramEnrollments to LMS Users @@ -55,11 +55,20 @@ def link_program_enrollments(program_uuid, external_keys_to_usernames): For each external_user_key:lms_username, if: - The user is not found - No enrollment is found for the given program and external_user_key - - The enrollment already has a user + - The enrollment already has a user and that user is the same as the given user An error message will be logged, and added to a dictionary of error messages keyed by external_key. The input will be skipped. All other inputs will be processed and enrollments updated, and then the function will return the dictionary of error messages. + For each external_user_key:lms_username, if the enrollment already has a user, but that user + is different than the requested user, we do the following. We unlink the existing user from + the program enrollment and link the requested user to the program enrollment. This is accomplished by + removing the existing user's link to the program enrollment. If the program enrollment + has course enrollments, then we unenroll the user. If there is an audit track in the course, + we also move the enrollment into the audit track. We also remove the association between those + course enrollments and the program course enrollments. The + requested user is then linked to the program following the above logic. + If there is an error while enrolling a user in a waiting program course enrollment, the error will be logged, and added to the returned error dictionary, and we will roll back all transactions for that user so that their db state will be the same as it was before this @@ -72,37 +81,56 @@ def link_program_enrollments(program_uuid, external_keys_to_usernames): program_uuid, external_keys_to_usernames.keys() ) users_by_username = _get_lms_users(external_keys_to_usernames.values()) - for external_student_key, username in external_keys_to_usernames.items(): - program_enrollment = program_enrollments.get(external_student_key) + for external_user_key, username in external_keys_to_usernames.items(): + program_enrollment = program_enrollments.get(external_user_key) user = users_by_username.get(username) if not user: error_message = NO_LMS_USER_TEMPLATE.format(username) elif not program_enrollment: error_message = NO_PROGRAM_ENROLLMENT_TEMPLATE.format( program_uuid=program_uuid, - external_student_key=external_student_key + external_user_key=external_user_key ) - elif program_enrollment.user: + # if we're trying to establish a link that already exists + elif program_enrollment.user and program_enrollment.user == user: error_message = _user_already_linked_message(program_enrollment, user) else: error_message = None if error_message: logger.warning(error_message) - errors[external_student_key] = error_message + errors[external_user_key] = error_message continue try: with transaction.atomic(): + # If the ProgramEnrollment already has a linked edX user that is different than + # the requested user, then we should sever the link to the existing edX user before + # linking the ProgramEnrollment to the new user. + if program_enrollment.user and program_enrollment.user != user: + message = ('Unlinking user with username={old_username} from program enrollment with ' + 'program uuid={program_uuid} with external_student_key={external_user_key} ' + 'and linking user with username={new_username} ' + 'to program enrollment.').format( + old_username=program_enrollment.user.username, + program_uuid=program_uuid, + external_user_key=external_user_key, + new_username=user, + ) + logger.info(_user_already_linked_message(program_enrollment, user)) + logger.info(message) + + unlink_program_enrollment(program_enrollment) + link_program_enrollment_to_lms_user(program_enrollment, user) except (CourseEnrollmentException, IntegrityError) as e: logger.exception("Rolling back all operations for {}:{}".format( - external_student_key, + external_user_key, username, )) error_message = type(e).__name__ if str(e): error_message += ': ' error_message += str(e) - errors[external_student_key] = error_message + errors[external_user_key] = error_message return errors @@ -111,22 +139,22 @@ def _user_already_linked_message(program_enrollment, user): Creates an error message that the specified program enrollment is already linked to an lms user """ existing_username = program_enrollment.user.username - external_student_key = program_enrollment.external_user_key + external_user_key = program_enrollment.external_user_key return EXISTING_USER_TEMPLATE.format( - external_student_key=external_student_key, + external_user_key=external_user_key, account_relation='target' if program_enrollment.user.id == user.id else 'a different', username=existing_username, ) -def _get_program_enrollments_by_ext_key(program_uuid, external_student_keys): +def _get_program_enrollments_by_ext_key(program_uuid, external_user_keys): """ Does a bulk read of ProgramEnrollments for a given program and list of external student keys and returns a dict keyed by external student key """ program_enrollments = fetch_program_enrollments( program_uuid=program_uuid, - external_user_keys=external_student_keys, + external_user_keys=external_user_keys, ).prefetch_related( 'program_course_enrollments' ).select_related('user') @@ -146,6 +174,45 @@ def _get_lms_users(lms_usernames): } +def unlink_program_enrollment(program_enrollment): + """ + Unlinks CourseEnrollments from the ProgramEnrollment by doing the following for + each ProgramCourseEnrollment associated with the Program Enrollment. + 1. unenrolling the corresponding user from the course + 2. moving the user into the audit track, if the track exists + 3. removing the link between the ProgramCourseEnrollment and the CourseEnrollment + + Arguments: + program_enrollment: the ProgramEnrollment object + """ + program_course_enrollments = program_enrollment.program_course_enrollments.all() + + for pce in program_course_enrollments: + course_key = pce.course_enrollment.course.id + modes = CourseMode.modes_for_course_dict(course_key) + + update_enrollment_kwargs = { + 'is_active': False, + 'skip_refund': True, + } + + if CourseMode.contains_audit_mode(modes): + # if the course contains an audit mode, move the + # learner's enrollment into the audit mode + update_enrollment_kwargs['mode'] = 'audit' + + # deactive the learner's course enrollment and move them into the + # audit track, if it exists + pce.course_enrollment.update_enrollment(**update_enrollment_kwargs) + + # sever ties to the user from the ProgramCourseEnrollment + pce.course_enrollment = None + pce.save() + + program_enrollment.user = None + program_enrollment.save() + + def link_program_enrollment_to_lms_user(program_enrollment, user): """ Attempts to link the given program enrollment to the given user diff --git a/lms/djangoapps/program_enrollments/api/tests/test_linking.py b/lms/djangoapps/program_enrollments/api/tests/test_linking.py index 45664833c23d42ba592f9f35e15e86c397037f0d..c71d692e02ac78a3f5411a583c194ff0ebeb371e 100644 --- a/lms/djangoapps/program_enrollments/api/tests/test_linking.py +++ b/lms/djangoapps/program_enrollments/api/tests/test_linking.py @@ -5,6 +5,7 @@ Tests for account linking Python API. from uuid import uuid4 +from unittest.mock import patch from django.test import TestCase from edx_django_utils.cache import RequestCache from opaque_keys.edx.keys import CourseKey @@ -13,12 +14,12 @@ from testfixtures import LogCapture from lms.djangoapps.program_enrollments.tests.factories import ( CourseAccessRoleAssignmentFactory, ProgramCourseEnrollmentFactory, - ProgramEnrollmentFactory, + ProgramEnrollmentFactory ) from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory from student.api import get_course_access_role from student.roles import CourseStaffRole -from student.tests.factories import UserFactory, CourseAccessRoleFactory +from student.tests.factories import CourseAccessRoleFactory, UserFactory from ..linking import ( NO_LMS_USER_TEMPLATE, @@ -34,7 +35,7 @@ class TestLinkProgramEnrollmentsMixin(object): """ Utility methods and test data for testing linking """ @classmethod - def setUpTestData(cls): # pylint: disable=missing-docstring + def setUpTestData(cls): # pylint: disable=missing-function-docstring cls.program = uuid4() cls.curriculum = uuid4() cls.other_program = uuid4() @@ -103,7 +104,7 @@ class TestLinkProgramEnrollmentsMixin(object): def _assert_user_enrolled_in_program_courses(self, user, program_uuid, *course_keys): """ - Assert that the given user is has active enrollments in the given courses + Assert that the given user has active enrollments in the given courses through the given program. """ user.refresh_from_db() @@ -256,6 +257,86 @@ class TestLinkProgramEnrollments(TestLinkProgramEnrollmentsMixin, TestCase): # assert that all CourseAccessRoleAssignment objects are deleted assert not active_enrollment_1.courseaccessroleassignment_set.all().exists() + @staticmethod + def _assert_course_enrollments_in_mode(course_enrollments, course_keys_to_mode): + """ + Assert that all program course enrollments are in the correct modes as + described by course_keys_to_mode. + + Arguments: + user: the user whose course enrollments we are checking + program_uuid: the UUID of the program in which the user is enrolled + course_keys_to_mode: a mapping from course keys to the the mode + slug the user's enrollment should be in + """ + assert len(course_enrollments) == len(course_keys_to_mode) + + for course_enrollment in course_enrollments: + assert course_enrollment.mode == course_keys_to_mode[course_enrollment.course.id] + + @patch('lms.djangoapps.program_enrollments.api.linking.CourseMode.modes_for_course_dict') + def test_update_linking_enrollment_to_another_user(self, mock_modes_for_course_dict): + """ + Test that when link_program_enrollments is called with a program and an external_user_key, + user pair and that program is already linked to a different user with the same external_user_key + that the original user's link is removed and replaced by a link with the new user. + """ + program_enrollment = self._create_waiting_enrollment(self.program, '0001') + + self._create_waiting_course_enrollment(program_enrollment, self.fruit_course) + self._create_waiting_course_enrollment(program_enrollment, self.animal_course) + + # in order to test what happens to a learner's enrollment in a course without an audit mode + # (e.g. Master's only course), we need to mock out the course modes that exist for our courses; + # doing it this way helps to avoid needing to use the modulestore when using the CourseModeFactory + def mocked_modes_for_course_dict(course_key): + if course_key == self.animal_course: + return {'masters': 'masters'} + else: + return {'audit': 'audit'} + + mock_modes_for_course_dict.side_effect = mocked_modes_for_course_dict + + # do the initial link of user_1 to the program enrollment + link_program_enrollments(self.program, {'0001': self.user_1.username}) + + self._assert_program_enrollment(self.user_1, self.program, '0001', refresh=False) + self._assert_no_program_enrollment(self.user_2, self.program, refresh=False) + + # grab the user's original course enrollment before the link between the program + # and the course enrollments is severed + course_enrollments_for_user_1 = [pce.course_enrollment + for pce + in program_enrollment.program_course_enrollments.all()] + + errors = link_program_enrollments( + self.program, + { + '0001': self.user_2.username, + } + ) + + assert errors == {} + self._assert_program_enrollment(self.user_2, self.program, '0001') + self._assert_no_program_enrollment(self.user_1, self.program) + # assert that all of user_1's course enrollments as part of the program + # are inactive + for course_enrollment in course_enrollments_for_user_1: + course_enrollment.refresh_from_db() + assert not course_enrollment.is_active + + # assert that user_1's course enrollments are in the expected mode + # after unlinking + course_keys_to_mode = { + self.fruit_course: 'audit', + self.animal_course: 'masters', + } + self._assert_course_enrollments_in_mode(course_enrollments_for_user_1, course_keys_to_mode) + + # assert that user_2 has been successfully linked to the program + self._assert_program_enrollment(self.user_2, self.program, '0001') + self._assert_user_enrolled_in_program_courses(self.user_2, self.program, self.fruit_course, self.animal_course) + class TestLinkProgramEnrollmentsErrors(TestLinkProgramEnrollmentsMixin, TestCase): """ Tests for linking error behavior """ @@ -285,7 +366,7 @@ class TestLinkProgramEnrollmentsErrors(TestLinkProgramEnrollmentsMixin, TestCase ) expected_error_msg = NO_PROGRAM_ENROLLMENT_TEMPLATE.format( program_uuid=self.program, - external_student_key='0002' + external_user_key='0002' ) logger.check_present((LOG_PATH, 'WARNING', expected_error_msg)) @@ -337,34 +418,6 @@ class TestLinkProgramEnrollmentsErrors(TestLinkProgramEnrollmentsMixin, TestCase self._assert_program_enrollment(self.user_1, self.program, '0001') self._assert_program_enrollment(self.user_2, self.program, '0002') - def test_enrollment_already_linked_to_different_user(self): - self._create_waiting_enrollment(self.program, '0001') - enrollment = ProgramEnrollmentFactory.create( - program_uuid=self.program, - external_user_key='0003', - ) - user_3 = enrollment.user - - self._assert_no_program_enrollment(self.user_1, self.program, refresh=False) - self._assert_no_program_enrollment(self.user_2, self.program, refresh=False) - self._assert_program_enrollment(user_3, self.program, '0003', refresh=False) - - with LogCapture() as logger: - errors = link_program_enrollments( - self.program, - { - '0001': self.user_1.username, - '0003': self.user_2.username, - } - ) - expected_error_msg = _user_already_linked_message(enrollment, self.user_2) - logger.check_present((LOG_PATH, 'WARNING', expected_error_msg)) - - self.assertDictEqual(errors, {'0003': expected_error_msg}) - self._assert_program_enrollment(self.user_1, self.program, '0001') - self._assert_no_program_enrollment(self.user_2, self.program) - self._assert_program_enrollment(user_3, self.program, '0003') - def test_error_enrolling_in_course(self): nonexistant_course = CourseKey.from_string('course-v1:edX+Zilch+Bupkis') diff --git a/lms/djangoapps/program_enrollments/api/tests/test_reading.py b/lms/djangoapps/program_enrollments/api/tests/test_reading.py index 794852f6364a437e88d1f8098b842d017da6220d..a5dcf74fc45ebc6eb1de478251dbcf95db8ddf27 100644 --- a/lms/djangoapps/program_enrollments/api/tests/test_reading.py +++ b/lms/djangoapps/program_enrollments/api/tests/test_reading.py @@ -22,7 +22,7 @@ from lms.djangoapps.program_enrollments.exceptions import ( ProviderConfigurationException, ProviderDoesNotExistException ) -from lms.djangoapps.program_enrollments.models import ProgramEnrollment, ProgramCourseEnrollment +from lms.djangoapps.program_enrollments.models import ProgramCourseEnrollment, ProgramEnrollment from lms.djangoapps.program_enrollments.tests.factories import ( CourseAccessRoleAssignmentFactory, ProgramCourseEnrollmentFactory, @@ -46,7 +46,7 @@ from ..reading import ( get_program_course_enrollment, get_program_enrollment, get_users_by_external_keys, - is_course_staff_enrollment, + is_course_staff_enrollment ) User = get_user_model() diff --git a/lms/djangoapps/program_enrollments/api/tests/test_writing.py b/lms/djangoapps/program_enrollments/api/tests/test_writing.py index 79968bb842f82ab9c260024a009ee82a9e3a8ce2..c71bd259cfcbcd0e7dcebd6447f13d8bee61ccc2 100644 --- a/lms/djangoapps/program_enrollments/api/tests/test_writing.py +++ b/lms/djangoapps/program_enrollments/api/tests/test_writing.py @@ -426,9 +426,14 @@ class WriteProgramCourseEnrollmentTest(EnrollmentTestMixin): self.create_program_and_course_enrollments('learner-1', user=self.student_1) self.create_program_and_course_enrollments('learner-2', user=self.student_2) self.create_program_and_course_enrollments('learner-3', user=None) - enrollment = self.create_program_and_course_enrollments('learner-4', user=None) + learner_4_enrollment = self.create_program_and_course_enrollments('learner-4', user=None) + learner_5_enrollment = self.create_program_and_course_enrollments('learner-5', user=None) CourseAccessRoleAssignment.objects.create( - enrollment=enrollment, + enrollment=learner_4_enrollment, + role=ProgramCourseEnrollmentRoles.COURSE_STAFF, + ) + CourseAccessRoleAssignment.objects.create( + enrollment=learner_5_enrollment, role=ProgramCourseEnrollmentRoles.COURSE_STAFF, ) course_enrollment_requests = [ @@ -436,6 +441,7 @@ class WriteProgramCourseEnrollmentTest(EnrollmentTestMixin): self.course_enrollment_request('learner-2', CourseStatuses.ACTIVE, False), self.course_enrollment_request('learner-3', CourseStatuses.ACTIVE, True), self.course_enrollment_request('learner-4', CourseStatuses.ACTIVE, False), + self.course_enrollment_request('learner-5', CourseStatuses.ACTIVE, True), ] write_program_course_enrollments( self.program_uuid, @@ -452,11 +458,15 @@ class WriteProgramCourseEnrollmentTest(EnrollmentTestMixin): # CourseAccessRoleAssignment objects are created/revoked for enrollments with no linked user pending_role_assingments = CourseAccessRoleAssignment.objects.all() - assert pending_role_assingments.count() == 1 + assert pending_role_assingments.count() == 2 pending_role_assingments.get( enrollment__program_enrollment__external_user_key='learner-3', enrollment__course_key=self.course_id ) + pending_role_assingments.get( + enrollment__program_enrollment__external_user_key='learner-5', + enrollment__course_key=self.course_id + ) def test_user_currently_enrolled_in_course(self): """ diff --git a/lms/djangoapps/program_enrollments/api/writing.py b/lms/djangoapps/program_enrollments/api/writing.py index 65ce383dff823f04c0d17f1a0c50e34474b702cb..e138a69e24ea3e8f838ee0be56790fba36579480 100644 --- a/lms/djangoapps/program_enrollments/api/writing.py +++ b/lms/djangoapps/program_enrollments/api/writing.py @@ -382,7 +382,7 @@ def enroll_in_masters_track(user, course_key, status): Arguments: user (User) course_key (CourseKey|str) - status (str): from ProgramCourseEnrollmenStatuses + status (str): from ProgramCourseEnrollmentStatuses Returns: CourseEnrollment @@ -390,7 +390,7 @@ def enroll_in_masters_track(user, course_key, status): """ _ensure_course_exists(course_key, user.id) if status not in ProgramCourseEnrollmentStatuses.__ALL__: - raise ValueError("invalid ProgramCourseEnrollmenStatus: {}".format(status)) + raise ValueError("invalid ProgramCourseEnrollmentStatus: {}".format(status)) if CourseEnrollment.is_enrolled(user, course_key): course_enrollment = CourseEnrollment.objects.get( user=user, @@ -437,7 +437,6 @@ def _assign_course_staff_role(course_key, enrollments, staff_assignments): enrollments (list): ProgramCourseEnrollments to update staff_assignments (dict): Maps an enrollment's external key to a course staff value """ - role_assignments_to_save = [] enrollment_role_assignments_to_delete = [] for enrollment in enrollments: if enrollment.course_key != course_key: @@ -454,16 +453,13 @@ def _assign_course_staff_role(course_key, enrollments, staff_assignments): CourseStaffRole(course_key).remove_users(user) else: if course_staff is True: - role_assignments_to_save.append(CourseAccessRoleAssignment( + CourseAccessRoleAssignment.objects.update_or_create( enrollment=enrollment, role=ProgramCourseEnrollmentRoles.COURSE_STAFF - )) + ) elif course_staff is False: enrollment_role_assignments_to_delete.append(enrollment) - if role_assignments_to_save: - CourseAccessRoleAssignment.objects.bulk_create(role_assignments_to_save) - if enrollment_role_assignments_to_delete: CourseAccessRoleAssignment.objects.filter( enrollment__in=enrollment_role_assignments_to_delete diff --git a/lms/djangoapps/program_enrollments/apps.py b/lms/djangoapps/program_enrollments/apps.py index c2e56b06976e5cba28f1396115ee4199927090ed..d4017b6e0da5f88bd4d14f3a028a2ac62acaaa1e 100644 --- a/lms/djangoapps/program_enrollments/apps.py +++ b/lms/djangoapps/program_enrollments/apps.py @@ -29,5 +29,5 @@ class ProgramEnrollmentsConfig(AppConfig): """ Connect handlers to signals. """ - from . import signals # pylint: disable=unused-variable - from . import tasks # pylint: disable=unused-variable + from . import signals # pylint: disable=unused-import + from . import tasks # pylint: disable=unused-import diff --git a/lms/djangoapps/program_enrollments/docs/decisions/0003-enrollments-into-course-shared-by-programs.rst b/lms/djangoapps/program_enrollments/docs/decisions/0003-enrollments-into-course-shared-by-programs.rst new file mode 100644 index 0000000000000000000000000000000000000000..3f667efd6c40121d4c682e54a231b69e0090aea5 --- /dev/null +++ b/lms/djangoapps/program_enrollments/docs/decisions/0003-enrollments-into-course-shared-by-programs.rst @@ -0,0 +1,69 @@ +Enrollments Into A Course Shared By Multiple Programs +----------------------------------------------------- + +Status +====== + +Accepted (circa March 2020) + + +Context +======= + +For the spring term 2020 (Starting Jan 6th), Georgia Tech has created 3 +different Masters programs on edX. One such Masters program is named +"Other Master Program". This program is linked to all the courses +offered by both the Cybersecurity and Data Analytics programs. +This created a situation where every Georgia Tech's course run is +referenced by two different Masters program at least. We need a +mechanism to properly control the integrity of student enrollment data +in light of the cross reference. + +The scope of this decision is related to how API would react to enrollment +requests to a course for a single user, but from more than one programs. +The decision also covers the scenario where a learner needs to move +program enrollment from one program to another program. + +Decisions +========= + +We update the field "Course Enrollment" of the "ProgramCourseEnrollment" +model from OneToOne field to a Foreign Key field. +We also implemented logic to prevent two "active" "programCourseEnrollment" +records to be written into data store for the same user for the same course +across any number of affliated programs. This means, only 0 or 1 "active" +enrollment for a learner and the enrolled course can exist in our data store +at any given time. + +Consequences +============ + +API caller who wants to enroll learner into the course of Program 1 would +succeed, and then the call to enroll the same learner into the same course +of program 2 would result in "conflicted" status and fail. The only way +to enroll learner into course of program 2 is to cancel the enrollment of +the learner into course of program 1. +With this change, we will have multiple ProgramCourseEnrollment model +referencing the same student_courseenrollment record. But only one +of those ProgramCourseEnrollment record should be in "active" status + +Alternatives +============ + +We also considered, but rejected the following possibilities: + +1) Instead of preventing the ProgramCourseEnrollment to have another + "active" record for the same learner and course, update the only such + ProgramCourseEnrollment record to point to the ProgramEnrollment + where the latest request is made for. + This is rejected because the update would make the transition of program + course enrollment records opague. The data model is setup with assumption + where program course enrollment records are children of program enrollment + records. This solution would break such assumption. + +2) Allow multiple "active" ProgramCourseEnrollment for the same learner + and course for multiple ProgramEnrollments + This makes database integraty difficult to enforce. It might generate multiple + duplicate records that confuses our system. This option would also result in + inactive ProgramCourseEnrollment pointing at an active student_courseenrollment + record, thus making it confusing. diff --git a/lms/djangoapps/program_enrollments/exceptions.py b/lms/djangoapps/program_enrollments/exceptions.py index 1cf14c9c84d37b315a8d642bc6eceeccf8f4cc9b..809f77cf73fb8514b3457ab4245970409db757c9 100644 --- a/lms/djangoapps/program_enrollments/exceptions.py +++ b/lms/djangoapps/program_enrollments/exceptions.py @@ -6,6 +6,8 @@ Exceptions raised by functions exposed by program_enrollments Django app. # Every `__init__` here calls empty Exception() constructor. # pylint: disable=super-init-not-called +# pylint: disable=missing-class-docstring + class ProgramDoesNotExistException(Exception): diff --git a/lms/djangoapps/program_enrollments/management/commands/tests/test_migrate_saml_uids.py b/lms/djangoapps/program_enrollments/management/commands/tests/test_migrate_saml_uids.py index 2e83acf9670367a83924664cf53a8b730e073be1..b426d9d79eb7fae1ed658745c4fc6486da889f6f 100644 --- a/lms/djangoapps/program_enrollments/management/commands/tests/test_migrate_saml_uids.py +++ b/lms/djangoapps/program_enrollments/management/commands/tests/test_migrate_saml_uids.py @@ -3,13 +3,10 @@ Tests for the migrate_saml_uids management command. """ -from mock import mock_open, patch import six - from django.core.management import call_command from django.test import TestCase -from factory import LazyAttributeSequence, SubFactory -from factory.django import DjangoModelFactory +from mock import mock_open, patch from social_django.models import UserSocialAuth from lms.djangoapps.program_enrollments.management.commands import migrate_saml_uids @@ -39,6 +36,9 @@ class TestMigrateSamlUids(TestCase): ) def _call_command(self, data): + """ + Call management command with `data` as contents of input file. + """ with patch( _COMMAND_PATH + '.py3_open', mock_open(read_data=data) @@ -121,7 +121,7 @@ class TestMigrateSamlUids(TestCase): def test_learner_missed_by_mapping_file(self, mock_log): auth = UserSocialAuthFactory() # pylint disable required b/c this lint rule is confused about subfactories - email = auth.user.email # pylint: disable=no-member + email = auth.user.email new_urn = '9001' mock_info = mock_log.info @@ -145,7 +145,7 @@ class TestMigrateSamlUids(TestCase): ','.join( [ self._format_email_uid_pair( - auth.user.email, # pylint disable=no-member + auth.user.email, new_urn + six.text_type(ind) ) for ind, auth @@ -162,7 +162,7 @@ class TestMigrateSamlUids(TestCase): @patch(_COMMAND_PATH + '.log') def test_learner_duplicated_in_mapping(self, mock_log): auth = UserSocialAuthFactory() - email = auth.user.email # pylint: disable=no-member + email = auth.user.email new_urn = '9001' mock_info = mock_log.info diff --git a/lms/djangoapps/program_enrollments/management/commands/tests/test_reset_enrollment_data.py b/lms/djangoapps/program_enrollments/management/commands/tests/test_reset_enrollment_data.py index e8322807f16ddb974f635f3ec710f98725795830..00d7e30a7e160d37b0791901c32f9333e004bffe 100644 --- a/lms/djangoapps/program_enrollments/management/commands/tests/test_reset_enrollment_data.py +++ b/lms/djangoapps/program_enrollments/management/commands/tests/test_reset_enrollment_data.py @@ -34,6 +34,9 @@ class TestResetEnrollmentData(TestCase): @contextmanager def _replace_stdin(self, text): + """ + Mock out standard input to return `text` when read from. + """ orig = sys.stdin sys.stdin = StringIO(text) yield diff --git a/lms/djangoapps/program_enrollments/management/commands/tests/utils.py b/lms/djangoapps/program_enrollments/management/commands/tests/utils.py index 911098bd0df92271acbd2f411d11ae7a349e8fe4..8ea752f1846946e6ce4e5b8f8847c2a7473d6323 100644 --- a/lms/djangoapps/program_enrollments/management/commands/tests/utils.py +++ b/lms/djangoapps/program_enrollments/management/commands/tests/utils.py @@ -5,6 +5,7 @@ Sharable utilities for testing program enrollments from factory import LazyAttributeSequence, SubFactory from factory.django import DjangoModelFactory from social_django.models import UserSocialAuth + from student.tests.factories import UserFactory diff --git a/lms/djangoapps/program_enrollments/models.py b/lms/djangoapps/program_enrollments/models.py index 7aca2575913e1e1a4ff0482b3778805f1a10dcb3..134a3df6a884cf8ea5e2afb9b13254940d3bb20e 100644 --- a/lms/djangoapps/program_enrollments/models.py +++ b/lms/djangoapps/program_enrollments/models.py @@ -105,11 +105,6 @@ class ProgramCourseEnrollment(TimeStampedModel): # For each program enrollment, there may be only one # waiting program-course enrollment per course key. - # This same constraint is implicitly enforced for - # completed program-course enrollments by the - # OneToOneField on `course_enrollment`, which mandates that - # there may be at most one program-course enrollment per - # (user, course) pair. unique_together = ( ('program_enrollment', 'course_key'), ) diff --git a/lms/djangoapps/program_enrollments/rest_api/v1/serializers.py b/lms/djangoapps/program_enrollments/rest_api/v1/serializers.py index 202dffb5f9917523f848525143bef82ce7124f71..009585e62800ff558540fa9ada7b543f032bcd3b 100644 --- a/lms/djangoapps/program_enrollments/rest_api/v1/serializers.py +++ b/lms/djangoapps/program_enrollments/rest_api/v1/serializers.py @@ -37,6 +37,8 @@ class ProgramEnrollmentSerializer(serializers.Serializer): status = serializers.CharField() account_exists = serializers.SerializerMethodField() curriculum_uuid = serializers.UUIDField() + username = serializers.SerializerMethodField() + email = serializers.SerializerMethodField() class Meta(object): model = ProgramEnrollment @@ -44,6 +46,16 @@ class ProgramEnrollmentSerializer(serializers.Serializer): def get_account_exists(self, obj): return bool(obj.user) + def get_username(self, obj): + if obj.user: + return obj.user.username + return "" + + def get_email(self, obj): + if obj.user: + return obj.user.email + return "" + class ProgramEnrollmentRequestMixin(InvalidStatusMixin, serializers.Serializer): """ @@ -68,7 +80,6 @@ class ProgramEnrollmentUpdateRequestSerializer(ProgramEnrollmentRequestMixin): """ Serializer for program enrollment update requests. """ - pass class ProgramCourseEnrollmentSerializer(serializers.Serializer): @@ -150,17 +161,64 @@ class CourseRunOverviewSerializer(serializers.Serializer): CourseRunProgressStatuses.COMPLETED ] - course_run_id = serializers.CharField() - display_name = serializers.CharField() - resume_course_run_url = serializers.CharField(required=False) - course_run_url = serializers.CharField() - start_date = serializers.DateTimeField() - end_date = serializers.DateTimeField() - course_run_status = serializers.ChoiceField(allow_blank=False, choices=STATUS_CHOICES) - emails_enabled = serializers.BooleanField(required=False) - due_dates = serializers.ListField(child=DueDateSerializer()) - micromasters_title = serializers.CharField(required=False) - certificate_download_url = serializers.CharField(required=False) + course_run_id = serializers.CharField( + help_text="ID for the course run.", + ) + display_name = serializers.CharField( + help_text="Display name of the course run.", + ) + resume_course_run_url = serializers.CharField( + required=False, + help_text=( + "The absolute url that takes the user back to their position in the " + "course run; if absent, user has not made progress in the course." + ), + ) + course_run_url = serializers.CharField( + help_text="The absolute url for the course run.", + ) + start_date = serializers.DateTimeField( + help_text="Start date for the course run; null if no start date.", + ) + end_date = serializers.DateTimeField( + help_text="End date for the course run; null if no end date.", + ) + course_run_status = serializers.ChoiceField( + allow_blank=False, + choices=STATUS_CHOICES, + help_text="The user's status of the course run.", + ) + emails_enabled = serializers.BooleanField( + required=False, + help_text=( + "Boolean representing whether emails are enabled for the course;" + "if absent, the bulk email feature is either not enable at the platform" + "level or is not enabled for the course; if True or False, bulk email" + "feature is enabled, and value represents whether or not user wants" + "to receive emails." + ), + ) + due_dates = serializers.ListField( + child=DueDateSerializer(), + help_text=( + "List of subsection due dates for the course run. " + "Due dates are only returned if the course run is in progress." + ), + ) + micromasters_title = serializers.CharField( + required=False, + help_text=( + "Title of the MicroMasters program that the course run is a part of; " + "if absent, the course run is not a part of a MicroMasters program." + ), + ) + certificate_download_url = serializers.CharField( + required=False, + help_text=( + "URL to download a certificate, if available; " + "if absent, certificate is not downloadable." + ), + ) class CourseRunOverviewListSerializer(serializers.Serializer): diff --git a/lms/djangoapps/program_enrollments/rest_api/v1/tests/test_views.py b/lms/djangoapps/program_enrollments/rest_api/v1/tests/test_views.py index 650d953b08a97777d772b510cffd71ba9b2d4a7b..ea88bc4fb9df5c76f3b6a419783f6fc9ae79a70a 100644 --- a/lms/djangoapps/program_enrollments/rest_api/v1/tests/test_views.py +++ b/lms/djangoapps/program_enrollments/rest_api/v1/tests/test_views.py @@ -2,9 +2,8 @@ Unit tests for ProgramEnrollment views. """ - import json -from collections import defaultdict, OrderedDict +from collections import OrderedDict, defaultdict from datetime import datetime, timedelta from uuid import UUID, uuid4 @@ -38,7 +37,7 @@ from lms.djangoapps.program_enrollments.models import ProgramCourseEnrollment, P from lms.djangoapps.program_enrollments.tests.factories import ( CourseAccessRoleAssignmentFactory, ProgramCourseEnrollmentFactory, - ProgramEnrollmentFactory, + ProgramEnrollmentFactory ) from openedx.core.djangoapps.catalog.cache import PROGRAM_CACHE_KEY_TPL, PROGRAMS_BY_ORGANIZATION_CACHE_KEY_TPL from openedx.core.djangoapps.catalog.tests.factories import ( @@ -51,6 +50,7 @@ from openedx.core.djangoapps.catalog.tests.factories import ( from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory from openedx.core.djangolib.testing.utils import CacheIsolationMixin +from student.models import CourseEnrollment from student.roles import CourseStaffRole from student.tests.factories import CourseEnrollmentFactory, UserFactory from third_party_auth.tests.factories import SAMLProviderConfigFactory @@ -58,6 +58,7 @@ from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory as ModulestoreCourseFactory from xmodule.modulestore.tests.factories import ItemFactory +from .. import views from ..constants import ( ENABLE_ENROLLMENT_RESET_FLAG, MAX_ENROLLMENT_RECORDS, @@ -68,6 +69,7 @@ from ..constants import ( _DJANGOAPP_PATCH_FORMAT = 'lms.djangoapps.program_enrollments.{}' _REST_API_PATCH_FORMAT = _DJANGOAPP_PATCH_FORMAT.format('rest_api.v1.{}') _VIEW_PATCH_FORMAT = _REST_API_PATCH_FORMAT.format('views.{}') +_UTILS_PATCH_FORMAT = _REST_API_PATCH_FORMAT.format('utils.{}') _get_users_patch_path = _DJANGOAPP_PATCH_FORMAT.format('api.writing.get_users_by_external_keys') @@ -229,7 +231,10 @@ class ProgramEnrollmentsGetTests(EnrollmentsDataMixin, APITestCase): for i in range(2, 4): user_key = 'user-{}'.format(i) ProgramEnrollmentFactory.create( - program_uuid=self.program_uuid, curriculum_uuid=self.curriculum_uuid, external_user_key=user_key, + program_uuid=self.program_uuid, + curriculum_uuid=self.curriculum_uuid, + user=UserFactory.create(username='student-{}'.format(i), email='email-{}'.format(i)), + external_user_key=user_key, ) self.addCleanup(self.destroy_program_enrollments) @@ -281,19 +286,19 @@ class ProgramEnrollmentsGetTests(EnrollmentsDataMixin, APITestCase): 'results': [ { 'student_key': 'user-0', 'status': 'pending', 'account_exists': False, - 'curriculum_uuid': text_type(self.curriculum_uuid), + 'curriculum_uuid': text_type(self.curriculum_uuid), 'username': "", 'email': "" }, { 'student_key': 'user-1', 'status': 'pending', 'account_exists': False, - 'curriculum_uuid': text_type(self.curriculum_uuid), + 'curriculum_uuid': text_type(self.curriculum_uuid), 'username': "", 'email': "" }, { 'student_key': 'user-2', 'status': 'enrolled', 'account_exists': True, - 'curriculum_uuid': text_type(self.curriculum_uuid), + 'curriculum_uuid': text_type(self.curriculum_uuid), 'username': "student-2", 'email': "email-2" }, { 'student_key': 'user-3', 'status': 'enrolled', 'account_exists': True, - 'curriculum_uuid': text_type(self.curriculum_uuid), + 'curriculum_uuid': text_type(self.curriculum_uuid), 'username': "student-3", 'email': "email-3" }, ], } @@ -310,11 +315,11 @@ class ProgramEnrollmentsGetTests(EnrollmentsDataMixin, APITestCase): expected_results = [ { 'student_key': 'user-0', 'status': 'pending', 'account_exists': False, - 'curriculum_uuid': text_type(self.curriculum_uuid), + 'curriculum_uuid': text_type(self.curriculum_uuid), 'username': "", 'email': "" }, { 'student_key': 'user-1', 'status': 'pending', 'account_exists': False, - 'curriculum_uuid': text_type(self.curriculum_uuid), + 'curriculum_uuid': text_type(self.curriculum_uuid), 'username': "", 'email': "" }, ] assert expected_results == response.data['results'] @@ -329,11 +334,11 @@ class ProgramEnrollmentsGetTests(EnrollmentsDataMixin, APITestCase): next_expected_results = [ { 'student_key': 'user-2', 'status': 'enrolled', 'account_exists': True, - 'curriculum_uuid': text_type(self.curriculum_uuid), + 'curriculum_uuid': text_type(self.curriculum_uuid), 'username': "student-2", 'email': "email-2" }, { 'student_key': 'user-3', 'status': 'enrolled', 'account_exists': True, - 'curriculum_uuid': text_type(self.curriculum_uuid), + 'curriculum_uuid': text_type(self.curriculum_uuid), 'username': "student-3", 'email': "email-3" }, ] assert next_expected_results == next_response.data['results'] @@ -1488,13 +1493,28 @@ class UserProgramReadOnlyAccessGetTests(EnrollmentsDataMixin, APITestCase): with mock.patch( _VIEW_PATCH_FORMAT.format('get_programs'), autospec=True, - return_value=[self.mock_program_data[0]] + side_effect=[[self.mock_program_data[0]], []] ) as mock_get_programs: response = self.client.get(reverse(self.view_name) + '?type=masters') assert status.HTTP_200_OK == response.status_code assert len(response.data) == 1 - mock_get_programs.assert_called_once_with(course=self.course_id) + mock_get_programs.assert_has_calls([ + mock.call(course=self.course_id), + mock.call(uuids=[]), + ], any_order=True) + + def _enroll_user_into_course_as_course_staff(self, user, course_key_string): + """ + This is a helper function to create a course run based on the course key string, + then enroll the user to the course run as a course staff. + """ + course_key_to_create = CourseKey.from_string(course_key_string) + CourseOverviewFactory(id=course_key_to_create) + CourseRunFactory.create(key=text_type(course_key_to_create)) + CourseEnrollmentFactory.create(course_id=course_key_to_create, user=user) + CourseStaffRole(course_key_to_create).add_users(user) + return course_key_to_create @ddt.data( ( @@ -1518,11 +1538,11 @@ class UserProgramReadOnlyAccessGetTests(EnrollmentsDataMixin, APITestCase): return program return None - other_course_key = CourseKey.from_string('course-v1:edX+ToyX+Other_Course') - CourseOverviewFactory(id=other_course_key) - CourseRunFactory.create(key=text_type(other_course_key)) - CourseEnrollmentFactory.create(course_id=other_course_key, user=self.course_staff) - CourseStaffRole(other_course_key).add_users(self.course_staff) + other_course_key = self._enroll_user_into_course_as_course_staff( + self.course_staff, + 'course-v1:edX+ToyX+Other_Course' + ) + self.client.login(username=self.course_staff.username, password=self.password) programs_to_return_first = [ @@ -1541,7 +1561,7 @@ class UserProgramReadOnlyAccessGetTests(EnrollmentsDataMixin, APITestCase): with mock.patch( _VIEW_PATCH_FORMAT.format('get_programs'), autospec=True, - side_effect=[programs_to_return_first, programs_to_return_second] + side_effect=[[], programs_to_return_first, programs_to_return_second] ) as mock_get_programs: response = self.client.get(reverse(self.view_name) + '?type=masters') @@ -1552,6 +1572,37 @@ class UserProgramReadOnlyAccessGetTests(EnrollmentsDataMixin, APITestCase): mock.call(course=other_course_key), ], any_order=True) + def test_course_staff_of_non_program_course(self): + created_course_key = self._enroll_user_into_course_as_course_staff( + self.student, + 'course-v1:edX+ToyX+Other_Course' + ) + + program_to_enroll = self.mock_program_data[0] + ProgramEnrollmentFactory.create( + program_uuid=program_to_enroll['uuid'], + curriculum_uuid=self.curriculum_uuid, + user=self.student, + status='enrolled', + external_user_key='user-{}'.format(self.student.id), + ) + + self.client.login(username=self.student.username, password=self.password) + + with mock.patch( + _VIEW_PATCH_FORMAT.format('get_programs'), + autospec=True, + side_effect=[[], [program_to_enroll]] + ) as mock_get_programs: + response = self.client.get(reverse(self.view_name)) + + assert status.HTTP_200_OK == response.status_code + assert len(response.data) == 1 + mock_get_programs.assert_has_calls([ + mock.call(course=created_course_key), + mock.call(uuids=[UUID(program_to_enroll['uuid'])]), + ]) + @mock.patch(_VIEW_PATCH_FORMAT.format('get_programs'), autospec=True, return_value=None) def test_learner_200_if_no_programs_enrolled(self, mock_get_programs): self.client.login(username=self.student.username, password=self.password) @@ -1594,7 +1645,7 @@ class ProgramCourseEnrollmentOverviewGetTests( Tests for the ProgramCourseEnrollmentOverview view GET method. """ patch_resume_url = mock.patch( - _VIEW_PATCH_FORMAT.format('get_resume_urls_for_enrollments'), + _UTILS_PATCH_FORMAT.format('get_resume_urls_for_enrollments'), autospec=True, ) @@ -1610,8 +1661,9 @@ class ProgramCourseEnrollmentOverviewGetTests( cls.course_run = CourseRunFactory.create(key=text_type(cls.course_id)) cls.course = CourseFactory.create(course_runs=[cls.course_run]) + cls.username = 'student' cls.password = 'password' - cls.student = UserFactory.create(username='student', password=cls.password) + cls.student = UserFactory.create(username=cls.username, password=cls.password) # only freeze time when defining these values and not on the whole test case # as test_multiple_enrollments_all_enrolled relies on actual differences in modified datetimes @@ -1619,48 +1671,55 @@ class ProgramCourseEnrollmentOverviewGetTests( cls.yesterday = timezone.now() - timedelta(1) cls.tomorrow = timezone.now() + timedelta(1) + cls.modulestore_course = ModulestoreCourseFactory.create( + org="edX", + course="ToyX", + run="Toy_Course", + start=cls.yesterday, + end=cls.tomorrow, + ) cls.relative_certificate_download_url = '/download-the-certificates' cls.absolute_certificate_download_url = 'http://www.certificates.com/' - def setUp(self): - super(ProgramCourseEnrollmentOverviewGetTests, self).setUp() - # create program enrollment - self.program_enrollment = ProgramEnrollmentFactory.create( - program_uuid=self.program_uuid, - curriculum_uuid=self.curriculum_uuid, - user=self.student, + cls.program_enrollment = ProgramEnrollmentFactory.create( + program_uuid=cls.program_uuid, + curriculum_uuid=cls.curriculum_uuid, + user=cls.student, ) # create course overview - self.course_overview = CourseOverviewFactory.create( - id=self.course_id, - start=self.yesterday, - end=self.tomorrow, + cls.course_overview = CourseOverviewFactory.create( + id=cls.course_id, + start=cls.yesterday, + end=cls.tomorrow, ) # create course enrollment - self.course_enrollment = CourseEnrollmentFactory.create( - course=self.course_overview, - user=self.student, + cls.course_enrollment = CourseEnrollmentFactory.create( + course=cls.course_overview, + user=cls.student, mode=CourseMode.MASTERS, ) # create program course enrollment - self.program_course_enrollment = ProgramCourseEnrollmentFactory.create( - program_enrollment=self.program_enrollment, - course_enrollment=self.course_enrollment, - course_key=self.course_id, + cls.program_course_enrollment = ProgramCourseEnrollmentFactory.create( + program_enrollment=cls.program_enrollment, + course_enrollment=cls.course_enrollment, + course_key=cls.course_id, status='active', ) # create program catalog_org = OrganizationFactory(key='organization_key') - self.program = ProgramFactory( - uuid=self.program_uuid, + cls.program = ProgramFactory( + uuid=cls.program_uuid, authoring_organizations=[catalog_org], ) - self.program['curricula'][0]['courses'].append(self.course) + cls.program['curricula'][0]['courses'].append(cls.course) + + def setUp(self): + super().setUp() self.set_program_in_catalog_cache(self.program_uuid, self.program) def create_generated_certificate(self, download_url=None): @@ -1674,29 +1733,59 @@ class ProgramCourseEnrollmentOverviewGetTests( verify_uuid=uuid4(), ) + def log_in(self, user=None): + """ + Log in `self.client` as `user` if provided or `self.student` otherwise. + """ + return self.client.login( + username=(user or self.student).username, + password=self.password, + ) + def get_url(self, program_uuid=None): - """ Returns the primary URL requested by the test case. """ + """ + Returns the primary URL requested by the test case. + + May be overriden by subclasses of this test case. + """ kwargs = {'program_uuid': program_uuid or self.program_uuid} return reverse('programs_api:v1:program_course_enrollments_overview', kwargs=kwargs) + def get_status_and_course_runs(self): + """ + GETs the endpoint at `self.get_url`. + + May be overriden by subclasses of this test case. + + Returns: (status, course_runs) + * status (int): HTTP status code. + * course_runs (list[dict]|None): List of dicts if 200 OK; else, None. + """ + url = self.get_url() + response = self.client.get(url) + return ( + response.status_code, + response.data['course_runs'] if response.status_code == 200 else None + ) + def test_401_if_anonymous(self): - response = self.client.get(self.get_url(self.program_uuid)) - assert status.HTTP_401_UNAUTHORIZED == response.status_code + response_status_code, _ = self.get_status_and_course_runs() + assert status.HTTP_401_UNAUTHORIZED == response_status_code def test_404_if_no_program_with_key(self): - self.client.login(username=self.student.username, password=self.password) + self.log_in() self.set_program_in_catalog_cache(self.program_uuid, None) - response = self.client.get(self.get_url(self.program_uuid)) - assert status.HTTP_404_NOT_FOUND == response.status_code + response_status_code, _ = self.get_status_and_course_runs() + assert status.HTTP_404_NOT_FOUND == response_status_code def test_403_if_not_enrolled_in_program(self): # delete program enrollment ProgramEnrollment.objects.all().delete() - self.client.login(username=self.student.username, password=self.password) - response = self.client.get(self.get_url(self.program_uuid)) - assert status.HTTP_403_FORBIDDEN == response.status_code + self.log_in() + response_status_code, _ = self.get_status_and_course_runs() + assert status.HTTP_403_FORBIDDEN == response_status_code def _add_new_course_to_program(self, course_run_key, program): """ @@ -1727,11 +1816,11 @@ class ProgramCourseEnrollmentOverviewGetTests( if not other_enrollment_active: other_enrollment.deactivate() - self.client.login(username=self.student.username, password=self.password) - response = self.client.get(self.get_url(self.program_uuid)) + self.log_in() + response_status_code, response_course_runs = self.get_status_and_course_runs() - self.assertEqual(status.HTTP_200_OK, response.status_code) - actual_course_run_ids = {run['course_run_id'] for run in response.data['course_runs']} + self.assertEqual(status.HTTP_200_OK, response_status_code) + actual_course_run_ids = {run['course_run_id'] for run in response_course_runs} expected_course_run_ids = {text_type(self.course_id)} if other_enrollment_active: expected_course_run_ids.add(text_type(other_course_key)) @@ -1739,75 +1828,79 @@ class ProgramCourseEnrollmentOverviewGetTests( @patch_resume_url def test_blank_resume_url_omitted(self, mock_get_resume_urls): - self.client.login(username=self.student.username, password=self.password) + self.log_in() mock_get_resume_urls.return_value = {self.course_id: ''} - response = self.client.get(self.get_url(self.program_uuid)) - self.assertNotIn('resume_course_run_url', response.data['course_runs'][0]) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertNotIn('resume_course_run_url', response_course_runs[0]) @patch_resume_url def test_relative_resume_url_becomes_absolute(self, mock_get_resume_urls): - self.client.login(username=self.student.username, password=self.password) + self.log_in() resume_url = '/resume-here' mock_get_resume_urls.return_value = {self.course_id: resume_url} - response = self.client.get(self.get_url(self.program_uuid)) - response_resume_url = response.data['course_runs'][0]['resume_course_run_url'] + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + response_resume_url = response_course_runs[0]['resume_course_run_url'] self.assertTrue(response_resume_url.startswith("http://testserver")) self.assertTrue(response_resume_url.endswith(resume_url)) @patch_resume_url def test_absolute_resume_url_stays_absolute(self, mock_get_resume_urls): - self.client.login(username=self.student.username, password=self.password) + self.log_in() resume_url = 'http://www.resume.com/' mock_get_resume_urls.return_value = {self.course_id: resume_url} - response = self.client.get(self.get_url(self.program_uuid)) - response_resume_url = response.data['course_runs'][0]['resume_course_run_url'] + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + response_resume_url = response_course_runs[0]['resume_course_run_url'] self.assertEqual(response_resume_url, resume_url) def test_no_url_without_certificate(self): - self.client.login(username=self.student.username, password=self.password) - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertNotIn('certificate_download_url', response.data['course_runs'][0]) + self.log_in() + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertNotIn('certificate_download_url', response_course_runs[0]) def test_relative_certificate_url_becomes_absolute(self): - self.client.login(username=self.student.username, password=self.password) + self.log_in() self.create_generated_certificate( download_url=self.relative_certificate_download_url ) - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - response_url = response.data['course_runs'][0]['certificate_download_url'] + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + response_url = response_course_runs[0]['certificate_download_url'] self.assertTrue(response_url.startswith("http://testserver")) self.assertTrue(response_url.endswith(self.relative_certificate_download_url)) def test_absolute_certificate_url_stays_absolute(self): - self.client.login(username=self.student.username, password=self.password) + self.log_in() self.create_generated_certificate( download_url=self.absolute_certificate_download_url ) - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - response_url = response.data['course_runs'][0]['certificate_download_url'] + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + response_url = response_course_runs[0]['certificate_download_url'] self.assertEqual(response_url, self.absolute_certificate_download_url) def test_no_due_dates(self): - self.client.login(username=self.student.username, password=self.password) + self.log_in() - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - assert [] == response.data['course_runs'][0]['due_dates'] + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + assert [] == response_course_runs[0]['due_dates'] - def test_due_dates(self): - course = ModulestoreCourseFactory.create( - org="edX", - course="ToyX", - run="Toy_Course", - ) + @ddt.data( + ('2018-12-01', False), + ('2019-01-01', True), + ('2019-01-09', False), + ) + @ddt.unpack + def test_due_dates(self, now_time, course_in_progress): section_1 = ItemFactory.create( category='chapter', start=self.yesterday, due=self.tomorrow, - parent=course, + parent=self.modulestore_course, display_name='section 1' ) @@ -1839,7 +1932,7 @@ class ProgramCourseEnrollmentOverviewGetTests( ) mock_path = 'lms.djangoapps.course_api.api.get_dates_for_course' - with mock.patch(mock_path) as mock_get_dates: + with mock.patch(mock_path) as mock_get_dates, freeze_time(now_time): mock_get_dates.return_value = { (section_1.location, 'due'): section_1.due, (section_1.location, 'start'): section_1.start, @@ -1848,9 +1941,9 @@ class ProgramCourseEnrollmentOverviewGetTests( (unit_1.location, 'due'): unit_1.due, } - self.client.login(username=self.student.username, password=self.password) - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) + self.log_in() + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) block_data = [ { @@ -1878,14 +1971,17 @@ class ProgramCourseEnrollmentOverviewGetTests( 'date': '2019-01-04T00:00:00Z', }, ] - due_dates = response.data['course_runs'][0]['due_dates'] + due_dates = response_course_runs[0]['due_dates'] - for block in block_data: - self.assertIn(block, due_dates) + if course_in_progress: + for block in block_data: + self.assertIn(block, due_dates) + else: + assert due_dates == [] @mock.patch.object(CourseOverview, 'has_ended') def test_course_run_status_instructor_paced_completed(self, mock_has_ended): - self.client.login(username=self.student.username, password=self.password) + self.log_in() # set as instructor paced self.course_overview.self_paced = False @@ -1893,14 +1989,14 @@ class ProgramCourseEnrollmentOverviewGetTests( mock_has_ended.return_value = True - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(CourseRunProgressStatuses.COMPLETED, response.data['course_runs'][0]['course_run_status']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(CourseRunProgressStatuses.COMPLETED, response_course_runs[0]['course_run_status']) @mock.patch.object(CourseOverview, 'has_ended') @mock.patch.object(CourseOverview, 'has_started') def test_course_run_status_instructor_paced_in_progress(self, mock_has_started, mock_has_ended): - self.client.login(username=self.student.username, password=self.password) + self.log_in() # set as instructor paced self.course_overview.self_paced = False @@ -1909,14 +2005,14 @@ class ProgramCourseEnrollmentOverviewGetTests( mock_has_started.return_value = True mock_has_ended.return_value = False - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(CourseRunProgressStatuses.IN_PROGRESS, response.data['course_runs'][0]['course_run_status']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(CourseRunProgressStatuses.IN_PROGRESS, response_course_runs[0]['course_run_status']) @mock.patch.object(CourseOverview, 'has_ended') @mock.patch.object(CourseOverview, 'has_started') def test_course_run_status_instructor_paced_upcoming(self, mock_has_started, mock_has_ended): - self.client.login(username=self.student.username, password=self.password) + self.log_in() # set as instructor paced self.course_overview.self_paced = False @@ -1925,13 +2021,13 @@ class ProgramCourseEnrollmentOverviewGetTests( mock_has_started.return_value = False mock_has_ended.return_value = False - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(CourseRunProgressStatuses.UPCOMING, response.data['course_runs'][0]['course_run_status']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(CourseRunProgressStatuses.UPCOMING, response_course_runs[0]['course_run_status']) @mock.patch.object(CourseOverview, 'has_ended') def test_course_run_status_self_paced_completed(self, mock_has_ended): - self.client.login(username=self.student.username, password=self.password) + self.log_in() # set as self paced self.course_overview.self_paced = True @@ -1940,9 +2036,9 @@ class ProgramCourseEnrollmentOverviewGetTests( # course run has ended mock_has_ended.return_value = True - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(CourseRunProgressStatuses.COMPLETED, response.data['course_runs'][0]['course_run_status']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(CourseRunProgressStatuses.COMPLETED, response_course_runs[0]['course_run_status']) # course run has not ended and user has earned a passing certificate more than 30 days ago certificate = self.create_generated_certificate() @@ -1950,21 +2046,21 @@ class ProgramCourseEnrollmentOverviewGetTests( certificate.save() mock_has_ended.return_value = False - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(CourseRunProgressStatuses.COMPLETED, response.data['course_runs'][0]['course_run_status']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(CourseRunProgressStatuses.COMPLETED, response_course_runs[0]['course_run_status']) # course run has ended and user has earned a passing certificate mock_has_ended.return_value = True - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(CourseRunProgressStatuses.COMPLETED, response.data['course_runs'][0]['course_run_status']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(CourseRunProgressStatuses.COMPLETED, response_course_runs[0]['course_run_status']) @mock.patch.object(CourseOverview, 'has_ended') @mock.patch.object(CourseOverview, 'has_started') def test_course_run_status_self_paced_in_progress(self, mock_has_started, mock_has_ended): - self.client.login(username=self.student.username, password=self.password) + self.log_in() # set as self paced self.course_overview.self_paced = True @@ -1974,23 +2070,23 @@ class ProgramCourseEnrollmentOverviewGetTests( mock_has_started.return_value = True mock_has_ended.return_value = False - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(CourseRunProgressStatuses.IN_PROGRESS, response.data['course_runs'][0]['course_run_status']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(CourseRunProgressStatuses.IN_PROGRESS, response_course_runs[0]['course_run_status']) # course run has not ended and user has earned a passing certificate fewer than 30 days ago certificate = self.create_generated_certificate() certificate.created_date = timezone.now() - timedelta(5) certificate.save() - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(CourseRunProgressStatuses.IN_PROGRESS, response.data['course_runs'][0]['course_run_status']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(CourseRunProgressStatuses.IN_PROGRESS, response_course_runs[0]['course_run_status']) @mock.patch.object(CourseOverview, 'has_ended') @mock.patch.object(CourseOverview, 'has_started') def test_course_run_status_self_paced_upcoming(self, mock_has_started, mock_has_ended): - self.client.login(username=self.student.username, password=self.password) + self.log_in() # set as self paced self.course_overview.self_paced = True @@ -2000,26 +2096,26 @@ class ProgramCourseEnrollmentOverviewGetTests( mock_has_started.return_value = False mock_has_ended.return_value = False - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(CourseRunProgressStatuses.UPCOMING, response.data['course_runs'][0]['course_run_status']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(CourseRunProgressStatuses.UPCOMING, response_course_runs[0]['course_run_status']) def test_course_run_url(self): - self.client.login(username=self.student.username, password=self.password) + self.log_in() course_run_url = 'http://testserver/courses/{}/course/'.format(text_type(self.course_id)) - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(course_run_url, response.data['course_runs'][0]['course_run_url']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(course_run_url, response_course_runs[0]['course_run_url']) def test_course_run_dates(self): - self.client.login(username=self.student.username, password=self.password) + self.log_in() - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) - course_run_overview = response.data['course_runs'][0] + course_run_overview = response_course_runs[0] self.assertEqual(course_run_overview['start_date'], '2018-12-31T00:00:00Z') self.assertEqual(course_run_overview['end_date'], '2019-01-02T00:00:00Z') @@ -2028,56 +2124,237 @@ class ProgramCourseEnrollmentOverviewGetTests( self.course_overview.end = None self.course_overview.save() - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertEqual(response.data['course_runs'][0]['end_date'], None) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertEqual(response_course_runs[0]['end_date'], None) def test_course_run_id_and_display_name(self): - self.client.login(username=self.student.username, password=self.password) + self.log_in() - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) - course_run_overview = response.data['course_runs'][0] + course_run_overview = response_course_runs[0] self.assertEqual(course_run_overview['course_run_id'], text_type(self.course_id)) self.assertEqual(course_run_overview['display_name'], "{} Course".format(text_type(self.course_id))) def test_emails_enabled(self): - self.client.login(username=self.student.username, password=self.password) + self.log_in() # by default, BulkEmailFlag is not enabled, so 'emails_enabled' won't be in the response - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertNotIn('emails_enabled', response.data['course_runs'][0]) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertNotIn('emails_enabled', response_course_runs[0]) with mock.patch.object(BulkEmailFlag, 'feature_enabled', return_value=True): - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertTrue(response.data['course_runs'][0]['emails_enabled']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertTrue(response_course_runs[0]['emails_enabled']) Optout.objects.create( user=self.student, course_id=self.course_id ) - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertFalse(response.data['course_runs'][0]['emails_enabled']) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertFalse(response_course_runs[0]['emails_enabled']) def test_micromasters_title(self): - self.client.login(username=self.student.username, password=self.password) + self.log_in() - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertNotIn('micromasters_title', response.data['course_runs'][0]) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertNotIn('micromasters_title', response_course_runs[0]) self.program['type'] = 'MicroMasters' # update the program in the catalog cache self.set_program_in_catalog_cache(self.program_uuid, self.program) - response = self.client.get(self.get_url(self.program_uuid)) - self.assertEqual(status.HTTP_200_OK, response.status_code) - self.assertIn('micromasters_title', response.data['course_runs'][0]) + response_status_code, response_course_runs = self.get_status_and_course_runs() + self.assertEqual(status.HTTP_200_OK, response_status_code) + self.assertIn('micromasters_title', response_course_runs[0]) + + +@ddt.ddt +class UserProgramCourseEnrollmentViewGetTests(ProgramCourseEnrollmentOverviewGetTests): + """ + Tests for UserProgramCourseEnrollmentViewGetTests. + + For now, we just subclass ProgramCourseEnrollmentOverviewGetTests + because there are so many shared test cases. + + TODO: When the old, non-paginated ProgramCourseEnrollmentOverview endpoint + is removed, these two test cases should be collapsed into one test case. + """ + + # pylint: disable=test-inherits-tests + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.student_many_enrollments = UserFactory( + username='student_many_enrollments', + password=cls.password, + ) + cls.program_enrollment = ProgramEnrollmentFactory( + program_uuid=cls.program_uuid, + curriculum_uuid=cls.curriculum_uuid, + user=cls.student_many_enrollments, + ) + for _ in range(40): + CourseEnrollmentFactory(user=cls.student_many_enrollments) + + def get_url(self, program_uuid=None, username=None, page_size_string=None): + """ + Returns the primary URL requested by the test case. + + May be overriden by subclasses of this test case. + """ + # pylint: disable=arguments-differ + url = reverse( + 'programs_api:v1:user_program_course_enrollments', + kwargs={ + 'username': username or self.username, + 'program_uuid': program_uuid or self.program_uuid, + }, + ) + return ( + url + '?page_size=' + page_size_string + if page_size_string + else url + ) + + def get_status_and_course_runs(self): + """ + GETs the endpoint at `self.get_url`. + + Unlike the superclass's implementation of this, + this method takes into account the endpoint being paginated. + returning the concatentsaed results of repeated calls to the `next` URL. + + If any GET call returns non-200, immediately return that HTTP status code + along with the results collected so far. + + Returns: (status, course_runs) + * status (int): HTTP status code. + * course_runs (list[dict]|None): List of dicts if 200 OK; else, None. + """ + results = [] + next_url = self.get_url(self.program_uuid) + while next_url: + response = self.client.get(next_url) + if response.status_code != 200: + break + results += response.data['results'] + next_url = response.data.get('next') + return response.status_code, results + + def test_requester_must_match_username(self): + """ + Test that the username in the URL must match the username of the requester. + + (The plan is that we will eventually allow masquerading, which will change + require changing this test to be more permissive). + """ + self.log_in() + url = self.get_url(username='other_student') + response = self.client.get(url) + assert response.status_code == 403 + + def test_no_enrollments(self): + """ + Test that a user with no enrollments will get a 200 from this endpoint + with an empty list of results. + """ + self.log_in() + no_enrollments = CourseEnrollment.objects.none() + with mock.patch.object( + views, + 'get_enrollments_for_courses_in_program', + lambda _user, _program: no_enrollments, + ): + response_status, response_course_runs = self.get_status_and_course_runs() + assert response_status == 200 + assert response_course_runs == [] + + @ddt.data( + # If not provided, the page size is defaults to 10. + (None, [10, 10, 10, 10]), + # We can set the page size below the default. + ('5', [5, 5, 5, 5, 5, 5, 5, 5]), + # We can set the page size above the default. + ('19', [19, 19, 2]), + # Invalid parameter values fall back to page size of 10. + ('covid-19', [10, 10, 10, 10]), + # The max page size is 25. Numbers above this will be interpreted as 25. + ('30', [25, 15]), + ) + @ddt.unpack + def test_pagination(self, page_size_string, expected_page_sizes): + """ + Test the interactions between the `page_size` parameter + and the sizes of the each request. + """ + + def mock_get_enrollment_overviews(user, program, enrollments, request): + """ + Mock implementation of `utils.get_enrollments_overviews` + that returns a dict with the correct `course_run_id` + but fake values for all the rest. + + This function should never get an enrollment queryset greater than the + max page size. + """ + assert len(enrollments) <= 25 + return [ + { + 'course_run_id': enrollment.course.id, + 'display_name': 'Fake Display Name for {enrollment.course.id}'.format( + enrollment=enrollment, + ), + 'course_run_url': 'http://fake.url.example.com/course-run', + 'start_date': '2112-02-20', + 'end_date': '2112-12-21', + 'course_run_status': '', + 'due_dates': [], + } + for enrollment in enrollments + ] + + self.log_in(user=self.student_many_enrollments) + many_enrollments = CourseEnrollment.objects.filter(user=self.student_many_enrollments) + + with mock.patch.object( + views, + 'get_enrollments_for_courses_in_program', + lambda _user, _program: many_enrollments, + ): + with mock.patch.object( + views, + 'get_enrollment_overviews', + mock_get_enrollment_overviews, + ): + actual_page_sizes = [] + all_results = [] + next_url = self.get_url( + program_uuid=self.program_uuid, + username=self.student_many_enrollments.username, + page_size_string=page_size_string, + ) + while next_url: + response = self.client.get(next_url) + assert response.status_code == 200 + actual_page_sizes.append(len(response.data['results'])) + all_results += response.data['results'] + next_url = response.data.get('next') + + assert actual_page_sizes == expected_page_sizes + all_course_run_ids = {result['course_run_id'] for result in all_results} + assert len(all_course_run_ids) == 40, ( + "Expected 40 unique course run IDs to be processed " + "across all pages." + ) class EnrollmentDataResetViewTests(ProgramCacheMixin, APITestCase): diff --git a/lms/djangoapps/program_enrollments/rest_api/v1/urls.py b/lms/djangoapps/program_enrollments/rest_api/v1/urls.py index 9899ecbaa9de6f58ad5d848f76266d0ceef365b0..145a614bbce5a565f539fdaa0416cb36c9d77414 100644 --- a/lms/djangoapps/program_enrollments/rest_api/v1/urls.py +++ b/lms/djangoapps/program_enrollments/rest_api/v1/urls.py @@ -1,6 +1,7 @@ """ Program Enrollments API v1 URLs. """ +from django.conf import settings from django.conf.urls import url from openedx.core.constants import COURSE_ID_PATTERN @@ -12,6 +13,7 @@ from .views import ( ProgramCourseEnrollmentsView, ProgramCourseGradesView, ProgramEnrollmentsView, + UserProgramCourseEnrollmentView, UserProgramReadOnlyAccessView ) @@ -56,6 +58,14 @@ urlpatterns = [ ProgramCourseEnrollmentOverviewView.as_view(), name="program_course_enrollments_overview" ), + url( + r'^users/{username}/programs/{program_uuid}/courses'.format( + username=settings.USERNAME_PATTERN, + program_uuid=PROGRAM_UUID_PATTERN, + ), + UserProgramCourseEnrollmentView.as_view(), + name="user_program_course_enrollments" + ), url( r'^integration-reset', EnrollmentDataResetView.as_view(), diff --git a/lms/djangoapps/program_enrollments/rest_api/v1/utils.py b/lms/djangoapps/program_enrollments/rest_api/v1/utils.py index a7331a50b3328b25bae98f17a2c0635adf9bd107..5aacc94a28d64732d00ac29e07c292faadc1860c 100644 --- a/lms/djangoapps/program_enrollments/rest_api/v1/utils.py +++ b/lms/djangoapps/program_enrollments/rest_api/v1/utils.py @@ -2,28 +2,58 @@ """ ProgramEnrollment V1 API internal utilities. """ - - from datetime import datetime, timedelta from functools import wraps +from django.core.exceptions import PermissionDenied from django.utils.functional import cached_property from opaque_keys.edx.keys import CourseKey from pytz import UTC from rest_framework import status - -from lms.djangoapps.grades.rest_api.v1.utils import CourseEnrollmentPagination -from openedx.core.djangoapps.catalog.utils import get_programs, is_course_run_in_program +from rest_framework.pagination import CursorPagination + +from course_modes.models import CourseMode +from lms.djangoapps.bulk_email.api import get_emails_enabled +from lms.djangoapps.certificates.api import get_certificates_for_user_by_course_keys +from lms.djangoapps.course_api.api import get_course_run_url, get_due_dates +from lms.djangoapps.program_enrollments.api import fetch_program_enrollments +from lms.djangoapps.program_enrollments.constants import ProgramEnrollmentStatuses +from openedx.core.djangoapps.catalog.utils import course_run_keys_for_program, get_programs, is_course_run_in_program from openedx.core.lib.api.view_utils import verify_course_exists +from student.helpers import get_resume_urls_for_enrollments +from student.models import CourseEnrollment from .constants import CourseRunProgressStatuses -class ProgramEnrollmentPagination(CourseEnrollmentPagination): +class ProgramEnrollmentPagination(CursorPagination): """ Pagination class for views in the Program Enrollments app. """ + ordering = 'id' page_size = 100 + page_size_query_param = 'page_size' + + def get_paginated_response(self, data, status_code=200, **kwargs): # pylint: disable=arguments-differ + """ + Return a response given serialized page data, optional status_code (defaults to 200), + and kwargs. Each key-value pair of kwargs is added to the response data. + """ + resp = super().get_paginated_response(data) + for (key, value) in kwargs.items(): + resp.data[key] = value + resp.status_code = status_code + return resp + + +class UserProgramCourseEnrollmentPagination(CursorPagination): + """ + Pagination parameters for UserProgramCourseEnrollmentView. + """ + page_size = 10 + max_page_size = 25 + page_size_query_param = 'page_size' + ordering = 'id' class ProgramSpecificViewMixin(object): @@ -37,6 +67,8 @@ class ProgramSpecificViewMixin(object): def program(self): """ The program specified by the `program_uuid` URL parameter. + + Returns: dict """ return get_programs(uuid=self.program_uuid) @@ -44,10 +76,35 @@ class ProgramSpecificViewMixin(object): def program_uuid(self): """ The program specified by the `program_uuid` URL parameter. + + Returns: str """ return self.kwargs['program_uuid'] +class UserProgramSpecificViewMixin(ProgramSpecificViewMixin): + """ + A mixin for views that operate on a specific program in the context of a user. + + Requires `program_uuid` to be one of the kwargs to the view. + + The property `target_user` returns the user that that we should operate with. + """ + @property + def target_user(self): + """ + The user that this view's operations should operate in the context of. + + By default, this is the requesting user. + + This can be overriden in order to implement "user-parameterized" views, + which, for example, a global staff member could use to see API responses + in the context of a specific learner. This could be used to help implement + masquerading. + """ + return self.request.user + + class ProgramCourseSpecificViewMixin(ProgramSpecificViewMixin): """ A mixin for views that operate on or within a specific course run in a program @@ -72,7 +129,7 @@ def verify_program_exists(view_func): Expects to be used within a ProgramSpecificViewMixin subclass. """ @wraps(view_func) - def wrapped_function(self, request, **kwargs): + def wrapped_function(self, *args, **kwargs): """ Wraps the given view_function. """ @@ -82,7 +139,7 @@ def verify_program_exists(view_func): developer_message='no program exists with given key', error_code='program_does_not_exist' ) - return view_func(self, request, **kwargs) + return view_func(self, *args, **kwargs) return wrapped_function @@ -101,7 +158,7 @@ def verify_course_exists_and_in_program(view_func): @wraps(view_func) @verify_program_exists @verify_course_exists - def wrapped_function(self, request, **kwargs): + def wrapped_function(self, *args, **kwargs): """ Wraps view function """ @@ -111,10 +168,143 @@ def verify_course_exists_and_in_program(view_func): developer_message="the program's curriculum does not contain the given course", error_code='course_not_in_program' ) - return view_func(self, request, **kwargs) + return view_func(self, *args, **kwargs) return wrapped_function +def verify_user_enrolled_in_program(view_func): + """ + Raised PermissionDenied if the `target_user` is not enrolled in the program. + + Expects to be used within a UserProgramViewMixin subclass. + """ + @wraps(view_func) + def wrapped_function(self, *args, **kwargs): + """ + Wraps the given view_function. + """ + user_enrollment_qs = fetch_program_enrollments( + program_uuid=self.program_uuid, + users={self.target_user}, + program_enrollment_statuses={ProgramEnrollmentStatuses.ENROLLED}, + ) + if not user_enrollment_qs.exists(): + raise PermissionDenied + return view_func(self, *args, **kwargs) + return wrapped_function + + +def get_enrollments_for_courses_in_program(user, program): + """ + Get a user's active enrollments for course runs with the given program. + + Note that this is distinct from the user's *program course enrollments*, + which refers to courses that were enrollmed in *through* a program. + + In the case of this function, the course runs themselves must be part of the + program, but the enrollments do not need to be associated with a program enrollment. + + Arguments: + user (User) + program (dict) + + Returns QuerySet[CourseEnrollment] + """ + course_keys = [ + CourseKey.from_string(key) + for key in course_run_keys_for_program(program) + ] + return CourseEnrollment.objects.filter( + user=user, + course_id__in=course_keys, + mode__in=[CourseMode.VERIFIED, CourseMode.MASTERS], + is_active=True, + ) + + +def get_enrollment_overviews(user, program, enrollments, request): + """ + Get a list of overviews for a user's course run enrollments within a program. + + Arguments: + user (User) + program (dict) + enrollments (iterable[CourseEnrollment]) + request (HttpRequest): Source HTTP request. Needed for URL generation. + + Returns list[dict] + """ + overviews_by_course_key = { + enrollment.course.id: enrollment.course for enrollment in enrollments + } + course_keys = list(overviews_by_course_key.keys()) + certficates_by_course_key = get_certificates_for_user_by_course_keys(user, course_keys) + resume_urls_by_course_key = get_resume_urls_for_enrollments(user, enrollments) + return [ + get_single_enrollment_overview( + user=user, + program=program, + course_overview=overviews_by_course_key[enrollment.course_id], + certificate_info=certficates_by_course_key.get(enrollment.course_id, {}), + relative_resume_url=resume_urls_by_course_key.get(enrollment.course_id), + request=request, + ) + for enrollment in enrollments + ] + + +def get_single_enrollment_overview( + user, + program, + course_overview, + certificate_info, + relative_resume_url, + request, +): + """ + Get an overview of a user's enrollment in a course run within a program. + + Arguments: + user (User) + program (Program) + course_overview (CourseOverview) + certificate_info (dict): Info about a user's certificate in this course run. + relative_resume_url (str): URL to resume course. Relative to LMS root. + request (HttpRequest): Source HTTP request. Needed for URL generation. + + Returns: dict + """ + course_key = course_overview.id + course_run_status = get_course_run_status(course_overview, certificate_info) + due_dates = ( + get_due_dates(request, course_key, user) + if course_run_status == CourseRunProgressStatuses.IN_PROGRESS + else [] + ) + result = { + 'course_run_id': str(course_key), + 'display_name': course_overview.display_name_with_default, + 'course_run_status': course_run_status, + 'course_run_url': get_course_run_url(request, course_key), + 'start_date': course_overview.start, + 'end_date': course_overview.end, + 'due_dates': due_dates, + } + emails_enabled = get_emails_enabled(user, course_key) + if emails_enabled is not None: + result['emails_enabled'] = emails_enabled + download_url = certificate_info.get('download_url') + if download_url: + result['certificate_download_url'] = request.build_absolute_uri( + certificate_info['download_url'] + ) + if program['type'] == 'MicroMasters': + result['micromasters_title'] = program['title'] + if relative_resume_url: + result['resume_course_run_url'] = request.build_absolute_uri(relative_resume_url) + return result + + def get_enrollment_http_code(result_statuses, ok_statuses): """ Given a set of enrollment create/update statuses, diff --git a/lms/djangoapps/program_enrollments/rest_api/v1/views.py b/lms/djangoapps/program_enrollments/rest_api/v1/views.py index 58ec982f183de74c2879d59062f7d8901fd5c054..05a25affec28a702d07d68a72332a032624ac4c0 100644 --- a/lms/djangoapps/program_enrollments/rest_api/v1/views.py +++ b/lms/djangoapps/program_enrollments/rest_api/v1/views.py @@ -2,27 +2,22 @@ """ ProgramEnrollment Views """ - - from ccx_keys.locator import CCXLocator from django.conf import settings -from django.core.exceptions import PermissionDenied from django.core.management import call_command from django.db import transaction +from edx_api_doc_tools import path_parameter, query_parameter, schema from edx_rest_framework_extensions import permissions from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser -from opaque_keys.edx.keys import CourseKey from organizations.models import Organization from rest_framework import status +from rest_framework.exceptions import PermissionDenied +from rest_framework.generics import RetrieveAPIView from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView -from course_modes.models import CourseMode -from lms.djangoapps.bulk_email.api import get_emails_enabled -from lms.djangoapps.certificates.api import get_certificate_for_user -from lms.djangoapps.course_api.api import get_course_run_url, get_due_dates from lms.djangoapps.program_enrollments.api import ( fetch_program_course_enrollments, fetch_program_enrollments, @@ -39,24 +34,22 @@ from lms.djangoapps.program_enrollments.constants import ( ProgramOperationStatuses ) from lms.djangoapps.program_enrollments.exceptions import ProviderDoesNotExistException +from openedx.core.apidocs import cursor_paginate_serializer from openedx.core.djangoapps.catalog.utils import ( - course_run_keys_for_program, get_programs, get_programs_by_type, get_programs_for_organization, normalize_program_type ) -from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, PaginatedAPIView -from student.helpers import get_resume_urls_for_enrollments -from student.models import CourseEnrollment from student.roles import CourseInstructorRole, CourseStaffRole, UserBasedRole from util.query import read_replica_or_default from .constants import ENABLE_ENROLLMENT_RESET_FLAG, MAX_ENROLLMENT_RECORDS from .serializers import ( CourseRunOverviewListSerializer, + CourseRunOverviewSerializer, ProgramCourseEnrollmentRequestSerializer, ProgramCourseEnrollmentSerializer, ProgramCourseGradeSerializer, @@ -68,10 +61,14 @@ from .utils import ( ProgramCourseSpecificViewMixin, ProgramEnrollmentPagination, ProgramSpecificViewMixin, - get_course_run_status, + UserProgramCourseEnrollmentPagination, + UserProgramSpecificViewMixin, get_enrollment_http_code, + get_enrollment_overviews, + get_enrollments_for_courses_in_program, verify_course_exists_and_in_program, - verify_program_exists + verify_program_exists, + verify_user_enrolled_in_program ) @@ -360,14 +357,14 @@ class ProgramEnrollmentsView( return self.handle_write_request() @verify_program_exists - def patch(self, request, program_uuid=None): # pylint: disable=unused-argument + def patch(self, request, program_uuid=None): """ Update program enrollments for a list of learners """ return self.handle_write_request() @verify_program_exists - def put(self, request, program_uuid=None): # pylint: disable=unused-argument + def put(self, request, program_uuid=None): """ Create/update program enrollments for a list of learners """ @@ -508,7 +505,6 @@ class ProgramCourseEnrollmentsView( return self.handle_write_request() @verify_course_exists_and_in_program - # pylint: disable=unused-argument def patch(self, request, program_uuid=None, course_id=None): """ Modify the program course enrollments of a list of learners @@ -516,7 +512,6 @@ class ProgramCourseEnrollmentsView( return self.handle_write_request() @verify_course_exists_and_in_program - # pylint: disable=unused-argument def put(self, request, program_uuid=None, course_id=None): """ Create or Update the program course enrollments of a list of learners @@ -714,15 +709,17 @@ class UserProgramReadOnlyAccessView(DeveloperErrorViewMixin, PaginatedAPIView): if request_user.is_staff: programs = get_programs_by_type(request.site, requested_program_type) - elif self.is_course_staff(request_user): - programs = self.get_programs_user_is_course_staff_for(request_user, requested_program_type) else: - program_enrollments = fetch_program_enrollments_by_student( - user=request.user, - program_enrollment_statuses=ProgramEnrollmentStatuses.__ACTIVE__, - ) - uuids = [enrollment.program_uuid for enrollment in program_enrollments] - programs = get_programs(uuids=uuids) or [] + program_dict = {} + # Check if the user is a course staff of any course which is a part of a program. + for staff_program in self.get_programs_user_is_course_staff_for(request_user, requested_program_type): + program_dict.setdefault(staff_program['uuid'], staff_program) + + # Now get the program enrollments for user purely as a learner add to the list + for learner_program in self._get_enrolled_programs_from_model(request_user): + program_dict.setdefault(learner_program['uuid'], learner_program) + + programs = list(program_dict.values()) programs_in_which_user_has_access = [ {'uuid': program['uuid'], 'slug': program['marketing_slug']} @@ -731,12 +728,16 @@ class UserProgramReadOnlyAccessView(DeveloperErrorViewMixin, PaginatedAPIView): return Response(programs_in_which_user_has_access, status.HTTP_200_OK) - def is_course_staff(self, user): + def _get_enrolled_programs_from_model(self, user): """ - Returns true if the user is a course_staff member of any course within a program + Return the Program Enrollments linked to the learner within the data model. """ - staff_course_keys = self.get_course_keys_user_is_staff_for(user) - return len(staff_course_keys) + program_enrollments = fetch_program_enrollments_by_student( + user=user, + program_enrollment_statuses=ProgramEnrollmentStatuses.__ACTIVE__, + ) + uuids = [enrollment.program_uuid for enrollment in program_enrollments] + return get_programs(uuids=uuids) or [] def get_course_keys_user_is_staff_for(self, user): """ @@ -773,63 +774,76 @@ class UserProgramReadOnlyAccessView(DeveloperErrorViewMixin, PaginatedAPIView): return program_dict.values() -class ProgramCourseEnrollmentOverviewView( +class UserProgramCourseEnrollmentView( DeveloperErrorViewMixin, - ProgramSpecificViewMixin, - APIView, + UserProgramSpecificViewMixin, + PaginatedAPIView, ): """ A view for getting data associated with a user's course enrollments as part of a program enrollment. - Path: ``/api/program_enrollments/v1/programs/{program_uuid}/overview/`` - - Accepts: [GET] - - ------------------------------------------------------------------------------------ - GET - ------------------------------------------------------------------------------------ - - **Returns** - - * 200: OK - Contains an object of user program course enrollment data. - * 401: Unauthorized - The requesting user is not authenticated. - * 403: Forbidden -The requesting user lacks access for the given program. - * 404: Not Found - The requested program does not exist. - - **Response** + For full documentation, see the `program_enrollments` section of + http://$LMS_BASE_URL/api-docs/. + """ + authentication_classes = ( + JwtAuthentication, + BearerAuthenticationAllowInactiveUser, + SessionAuthenticationAllowInactiveUser, + ) + permission_classes = (IsAuthenticated,) + serializer_class = CourseRunOverviewSerializer + pagination_class = UserProgramCourseEnrollmentPagination + + @schema( + parameters=[ + path_parameter('username', str, description=( + 'The username of the user for which enrollment overviews will be fetched. ' + 'For now, this must be the requesting user; otherwise, 403 will be returned. ' + 'In the future, global staff users may be able to supply other usernames.' + )), + path_parameter('program_uuid', str, description=( + 'UUID of a program. ' + 'Enrollments will be returned for course runs in this program.' + )), + query_parameter('page_size', int, description=( + 'Number of results to return per page. ' + 'Defaults to 10. Maximum is 25.' + )), + ], + responses={ + 200: cursor_paginate_serializer(CourseRunOverviewSerializer), + 401: 'The requester is not authenticated.', + 403: ( + 'The requester cannot access the specified program and/or ' + 'the requester may not retrieve this data for the specified user.' + ), + 404: 'The requested program does not exist.' + }, + ) + @verify_program_exists + @verify_user_enrolled_in_program + def get(self, request, username, program_uuid): + """ + Get an overview of each of a user's course enrollments associated with a program. - In the case of a 200 response code, the response will include a - data set. The `course_runs` section of the response consists of a list of - program course enrollment overview, where each overview contains the following keys: - * course_run_id: the id for the course run - * display_name: display name of the course run - * resume_course_run_url: the absolute url that takes the user back to - their position in the course run; - if absent, user has not made progress in the course - * course_run_url: the absolute url for the course run - * start_date: the start date for the course run; null if no start date - * end_date: the end date for the course run' null if no end date - * course_run_status: the status of the course; one of "in_progress", - "upcoming", and "completed" - * emails_enabled: boolean representing whether emails are enabled for the course; - if absent, the bulk email feature is either not enable at the platform - level or is not enabled for the course; if True or False, bulk email - feature is enabled, and value represents whether or not user wants - to receive emails due_dates: a list of subsection due dates for the - course run: - ** name: name of the subsection - ** url: deep link to the subsection - ** date: due date for the subsection - * micromasters_title: title of the MicroMasters program that the course run is a part of; - if absent, the course run is not a part of a MicroMasters program - * certificate_download_url: url to download a certificate, if available; - if absent, certificate is not downloadable + This endpoint exists to get an overview of each course-run enrollment + that a user has for course-runs within a given program. + Fields included are the title, upcoming due dates, etc. + This API endpoint is intended for use with the + [Program Learner Portal MFE](https://github.com/edx/frontend-app-learner-portal-programs). - **Example** + It is important to note that the set of enrollments that this endpoint returns + is different than a user's set of *program-course-run enrollments*. + Specifically, this endpoint may include course runs that are *within* + the specified program but were not *enrolled in* via the specified program. + **Example Response:** + ```json { - "course_runs": [ + "next": null, + "previous": null, + "results": [ { "course_run_id": "edX+AnimalsX+Aardvarks", "display_name": "Astonishing Aardvarks", @@ -871,6 +885,41 @@ class ProgramCourseEnrollmentOverviewView( } ] } + ``` + """ + if request.user.username != username: + # TODO: Should this be case-insensitive? + raise PermissionDenied() + enrollments = get_enrollments_for_courses_in_program( + self.request.user, self.program + ) + paginated_enrollments = self.paginate_queryset(enrollments) + paginated_enrollment_overviews = get_enrollment_overviews( + user=self.request.user, + program=self.program, + enrollments=paginated_enrollments, + request=self.request, + ) + serializer = CourseRunOverviewSerializer(paginated_enrollment_overviews, many=True) + return self.get_paginated_response(serializer.data) + + +class ProgramCourseEnrollmentOverviewView( + DeveloperErrorViewMixin, + UserProgramSpecificViewMixin, + RetrieveAPIView, +): + """ + A view for getting data associated with a user's course enrollments + as part of a program enrollment. + + Path: ``/api/program_enrollments/v1/programs/{program_uuid}/overview/`` + + DEPRECATED: + This is deprecated in favor of the new UserProgramCourseEnrollmentView, + which is paginated. + It will be removed in a follow-up to MST-126 after the Programs Learner Portal + has been updated to use UserProgramCourseEnrollmentView. """ authentication_classes = ( JwtAuthentication, @@ -878,86 +927,25 @@ class ProgramCourseEnrollmentOverviewView( SessionAuthenticationAllowInactiveUser, ) permission_classes = (IsAuthenticated,) + serializer_class = CourseRunOverviewListSerializer @verify_program_exists - def get(self, request, program_uuid=None): + @verify_user_enrolled_in_program + def get_object(self): """ Defines the GET endpoint for overviews of course enrollments for a user as part of a program. """ - user = request.user - self._check_program_enrollment_exists(user, program_uuid) - - course_run_keys = [ - CourseKey.from_string(key) - for key in course_run_keys_for_program(self.program) - ] - - course_enrollments = CourseEnrollment.objects.filter( - user=user, - course_id__in=course_run_keys, - mode__in=[CourseMode.VERIFIED, CourseMode.MASTERS], - is_active=True, + enrollments = get_enrollments_for_courses_in_program( + self.request.user, self.program ) - - overviews = CourseOverview.get_from_ids(course_run_keys) - - course_run_resume_urls = get_resume_urls_for_enrollments(user, course_enrollments) - - course_runs = [] - - for enrollment in course_enrollments: - overview = overviews[enrollment.course_id] - - certificate_info = get_certificate_for_user(user.username, enrollment.course_id) or {} - - course_run_dict = { - 'course_run_id': enrollment.course_id, - 'display_name': overview.display_name_with_default, - 'course_run_status': get_course_run_status(overview, certificate_info), - 'course_run_url': get_course_run_url(request, enrollment.course_id), - 'start_date': overview.start, - 'end_date': overview.end, - 'due_dates': get_due_dates(request, enrollment.course_id, user), - } - - emails_enabled = get_emails_enabled(user, enrollment.course_id) - if emails_enabled is not None: - course_run_dict['emails_enabled'] = emails_enabled - - if certificate_info.get('download_url'): - course_run_dict['certificate_download_url'] = request.build_absolute_uri( - certificate_info['download_url'] - ) - - if self.program['type'] == 'MicroMasters': - course_run_dict['micromasters_title'] = self.program['title'] - - if course_run_resume_urls.get(enrollment.course_id): - relative_resume_course_run_url = course_run_resume_urls.get( - enrollment.course_id - ) - course_run_dict['resume_course_run_url'] = request.build_absolute_uri( - relative_resume_course_run_url - ) - - course_runs.append(course_run_dict) - - serializer = CourseRunOverviewListSerializer({'course_runs': course_runs}) - return Response(serializer.data) - - @staticmethod - def _check_program_enrollment_exists(user, program_uuid): - """ - Raises ``PermissionDenied`` if the user is not enrolled in the program with the given UUID. - """ - user_enrollment_qs = fetch_program_enrollments( - program_uuid=program_uuid, - users={user}, - program_enrollment_statuses={ProgramEnrollmentStatuses.ENROLLED}, + enrollment_overviews = get_enrollment_overviews( + user=self.request.user, + program=self.program, + enrollments=enrollments, + request=self.request, ) - if not user_enrollment_qs.exists(): - raise PermissionDenied + return {'course_runs': enrollment_overviews} class EnrollmentDataResetView(APIView): diff --git a/lms/djangoapps/program_enrollments/signals.py b/lms/djangoapps/program_enrollments/signals.py index 16949a857529113c1e66d0df180eeed7c645a8e3..cd64c8278c5d99a845db34ac6290de42185b9de5 100644 --- a/lms/djangoapps/program_enrollments/signals.py +++ b/lms/djangoapps/program_enrollments/signals.py @@ -29,7 +29,7 @@ def _listen_for_lms_retire(sender, **kwargs): # pylint: disable=unused-argument @receiver(post_save, sender=UserSocialAuth) -def listen_for_social_auth_creation(sender, instance, created, **kwargs): # pylint: disable=unused-argument +def listen_for_social_auth_creation(sender, instance, created, **kwargs): """ Post-save signal that will attempt to link a social auth entry with waiting enrollments """ diff --git a/lms/djangoapps/program_enrollments/tests/test_models.py b/lms/djangoapps/program_enrollments/tests/test_models.py index 01f363623b2d4bba6b9ee8f53107d4d138982386..919dba641a640f6752109ea21e98e321621f83b3 100644 --- a/lms/djangoapps/program_enrollments/tests/test_models.py +++ b/lms/djangoapps/program_enrollments/tests/test_models.py @@ -17,11 +17,7 @@ from student.tests.factories import CourseEnrollmentFactory, UserFactory from ..constants import ProgramCourseEnrollmentRoles from ..models import ProgramEnrollment -from .factories import ( - CourseAccessRoleAssignmentFactory, - ProgramCourseEnrollmentFactory, - ProgramEnrollmentFactory -) +from .factories import CourseAccessRoleAssignmentFactory, ProgramCourseEnrollmentFactory, ProgramEnrollmentFactory class ProgramEnrollmentModelTests(TestCase): diff --git a/lms/djangoapps/shoppingcart/models.py b/lms/djangoapps/shoppingcart/models.py index 26c8d1f8f84c18b672f7a87df1af7ecc7169ac17..026f659c937d08cbd2619366f3dbe5f5af44d7b7 100644 --- a/lms/djangoapps/shoppingcart/models.py +++ b/lms/djangoapps/shoppingcart/models.py @@ -1747,7 +1747,7 @@ class CourseRegCodeItem(OrderItem): # file, but there's also a shared dependency on a random string generator which # is in another PR (for another feature) from lms.djangoapps.instructor.views.api import save_registration_code - for i in range(total_registration_codes): # pylint: disable=unused-variable + for i in range(total_registration_codes): save_registration_code(self.user, self.course_id, self.mode, order=self.order) log.info(u"Enrolled {0} in paid course {1}, paid ${2}" diff --git a/lms/djangoapps/shoppingcart/tests/test_models.py b/lms/djangoapps/shoppingcart/tests/test_models.py index 48ed275ddef24fda7d113f0d8bc9e085caa6a816..09c00c1a3f87c7d4dbc4b45a615ea34eeba26d19 100644 --- a/lms/djangoapps/shoppingcart/tests/test_models.py +++ b/lms/djangoapps/shoppingcart/tests/test_models.py @@ -491,353 +491,6 @@ class OrderItemTest(TestCase): self.assertEqual(item.get_list_price(), item.list_price) -@patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True}) -class PaidCourseRegistrationTest(ModuleStoreTestCase): - """ - Paid Course Registration Tests. - """ - - def setUp(self): - super(PaidCourseRegistrationTest, self).setUp() - - self.user = UserFactory.create() - self.user.set_password('password') - self.user.save() - self.cost = 40 - self.course = CourseFactory.create() - self.course_key = self.course.id - self.course_mode = CourseMode( - course_id=self.course_key, - mode_slug=CourseMode.HONOR, - mode_display_name="honor cert", - min_price=self.cost - ) - self.course_mode.save() - self.percentage_discount = 20.0 - self.cart = Order.get_cart_for_user(self.user) - - def test_get_total_amount_of_purchased_items(self): - """ - Test to check the total amount of the - purchased items. - """ - PaidCourseRegistration.add_to_order(self.cart, self.course_key, mode_slug=CourseMode.HONOR) - self.cart.purchase() - - total_amount = PaidCourseRegistration.get_total_amount_of_purchased_item(course_key=self.course_key) - self.assertEqual(total_amount, 40.00) - - def test_get_total_amount_empty(self): - """ - Test to check the total amount of the - purchased items. - """ - total_amount = PaidCourseRegistration.get_total_amount_of_purchased_item(course_key=self.course_key) - self.assertEqual(total_amount, 0.00) - - def test_add_to_order(self): - reg1 = PaidCourseRegistration.add_to_order(self.cart, self.course_key, mode_slug=CourseMode.HONOR) - - self.assertEqual(reg1.unit_cost, self.cost) - self.assertEqual(reg1.line_cost, self.cost) - self.assertEqual(reg1.unit_cost, self.course_mode.min_price) - self.assertEqual(reg1.mode, "honor") - self.assertEqual(reg1.user, self.user) - self.assertEqual(reg1.status, "cart") - self.assertTrue(PaidCourseRegistration.contained_in_order(self.cart, self.course_key)) - self.assertFalse(PaidCourseRegistration.contained_in_order( - self.cart, CourseLocator(org="MITx", course="999", run="Robot_Super_Course_abcd")) - ) - - self.assertEqual(self.cart.total_cost, self.cost) - - def test_order_generated_registration_codes(self): - """ - Test to check for the order generated registration - codes. - """ - self.cart.order_type = 'business' - self.cart.save() - item = CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) - self.cart.purchase() - registration_codes = CourseRegistrationCode.order_generated_registration_codes(self.course_key) - self.assertEqual(registration_codes.count(), item.qty) - - def test_order_generated_totals(self): - """ - Test to check for the order generated registration - codes. - """ - - total_amount = CourseRegCodeItem.get_total_amount_of_purchased_item(self.course_key) - self.assertEqual(total_amount, 0) - - self.cart.order_type = 'business' - self.cart.save() - item = CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2, mode_slug=CourseMode.HONOR) - self.cart.purchase() - registration_codes = CourseRegistrationCode.order_generated_registration_codes(self.course_key) - self.assertEqual(registration_codes.count(), item.qty) - - total_amount = CourseRegCodeItem.get_total_amount_of_purchased_item(self.course_key) - self.assertEqual(total_amount, 80.00) - - def add_coupon(self, course_key, is_active, code): - """ - add dummy coupon into models - """ - Coupon.objects.create( - code=code, - description='testing code', - course_id=course_key, - percentage_discount=self.percentage_discount, - created_by=self.user, - is_active=is_active - ) - - def login_user(self, username): - """ - login the user to the platform. - """ - self.client.login(username=username, password="password") - - def test_get_top_discount_codes_used(self): - """ - Test to check for the top coupon codes used. - """ - self.login_user(self.user.username) - self.add_coupon(self.course_key, True, 'Ad123asd') - self.add_coupon(self.course_key, True, '32213asd') - self.purchases_using_coupon_codes() - top_discounted_codes = CouponRedemption.get_top_discount_codes_used(self.course_key) - self.assertTrue(top_discounted_codes[0]['coupon__code'], 'Ad123asd') - self.assertTrue(top_discounted_codes[0]['coupon__used_count'], 1) - self.assertTrue(top_discounted_codes[1]['coupon__code'], '32213asd') - self.assertTrue(top_discounted_codes[1]['coupon__used_count'], 2) - - def test_get_total_coupon_code_purchases(self): - """ - Test to assert the number of coupon code purchases. - """ - self.login_user(self.user.username) - self.add_coupon(self.course_key, True, 'Ad123asd') - self.add_coupon(self.course_key, True, '32213asd') - self.purchases_using_coupon_codes() - - total_coupon_code_purchases = CouponRedemption.get_total_coupon_code_purchases(self.course_key) - self.assertTrue(total_coupon_code_purchases['coupon__count'], 3) - - def test_get_self_purchased_seat_count(self): - """ - Test to assert the number of seats - purchased using individual purchases. - """ - PaidCourseRegistration.add_to_order(self.cart, self.course_key) - self.cart.purchase() - - test_student = UserFactory.create() - test_student.set_password('password') - test_student.save() - - self.cart = Order.get_cart_for_user(test_student) - PaidCourseRegistration.add_to_order(self.cart, self.course_key) - self.cart.purchase() - - total_seats_count = PaidCourseRegistration.get_self_purchased_seat_count(course_key=self.course_key) - self.assertTrue(total_seats_count, 2) - - def purchases_using_coupon_codes(self): - """ - helper method that uses coupon codes when purchasing courses. - """ - self.cart.order_type = 'business' - self.cart.save() - CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) - resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': 'Ad123asd'}) - self.assertEqual(resp.status_code, 200) - self.cart.purchase() - - self.cart.clear() - self.cart = Order.get_cart_for_user(self.user) - self.cart.order_type = 'business' - self.cart.save() - CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) - resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': 'Ad123asd'}) - self.assertEqual(resp.status_code, 200) - self.cart.purchase() - - self.cart.clear() - self.cart = Order.get_cart_for_user(self.user) - PaidCourseRegistration.add_to_order(self.cart, self.course_key) - resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': '32213asd'}) - self.assertEqual(resp.status_code, 200) - self.cart.purchase() - - def test_cart_type_business(self): - self.cart.order_type = 'business' - self.cart.save() - item = CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) - self.cart.purchase() - self.assertFalse(CourseEnrollment.is_enrolled(self.user, self.course_key)) - # check that the registration codes are generated against the order - registration_codes = CourseRegistrationCode.order_generated_registration_codes(self.course_key) - self.assertEqual(registration_codes.count(), item.qty) - - def test_regcode_redemptions(self): - """ - Asserts the data model around RegistrationCodeRedemption - """ - self.cart.order_type = 'business' - self.cart.save() - CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) - self.cart.purchase() - - reg_code = CourseRegistrationCode.order_generated_registration_codes(self.course_key)[0] - - enrollment = CourseEnrollment.enroll(self.user, self.course_key) - - redemption = RegistrationCodeRedemption( - registration_code=reg_code, - redeemed_by=self.user, - course_enrollment=enrollment - ) - redemption.save() - - test_redemption = RegistrationCodeRedemption.registration_code_used_for_enrollment(enrollment) - - self.assertEqual(test_redemption.id, redemption.id) - - def test_regcode_multi_redemptions(self): - """ - Asserts the data model around RegistrationCodeRedemption and - what happens when we do multiple redemptions by same user - """ - self.cart.order_type = 'business' - self.cart.save() - CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) - self.cart.purchase() - - reg_codes = CourseRegistrationCode.order_generated_registration_codes(self.course_key) - - self.assertEqual(len(reg_codes), 2) - - enrollment = CourseEnrollment.enroll(self.user, self.course_key) - - ids = [] - for reg_code in reg_codes: - redemption = RegistrationCodeRedemption( - registration_code=reg_code, - redeemed_by=self.user, - course_enrollment=enrollment - ) - redemption.save() - ids.append(redemption.id) - - test_redemption = RegistrationCodeRedemption.registration_code_used_for_enrollment(enrollment) - - self.assertIn(test_redemption.id, ids) - - def test_add_with_default_mode(self): - """ - Tests add_to_cart where the mode specified in the argument is NOT - in the database and NOT the default "audit". In this case it - just adds the user in the CourseMode.DEFAULT_MODE for free. - """ - reg1 = PaidCourseRegistration.add_to_order(self.cart, self.course_key, mode_slug="DNE") - - self.assertEqual(reg1.unit_cost, 0) - self.assertEqual(reg1.line_cost, 0) - self.assertEqual(reg1.mode, CourseMode.DEFAULT_SHOPPINGCART_MODE_SLUG) - self.assertEqual(reg1.user, self.user) - self.assertEqual(reg1.status, "cart") - self.assertEqual(self.cart.total_cost, 0) - self.assertTrue(PaidCourseRegistration.contained_in_order(self.cart, self.course_key)) - - course_reg_code_item = CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2, mode_slug="DNE") - - self.assertEqual(course_reg_code_item.unit_cost, 0) - self.assertEqual(course_reg_code_item.line_cost, 0) - self.assertEqual(course_reg_code_item.mode, CourseMode.DEFAULT_SHOPPINGCART_MODE_SLUG) - self.assertEqual(course_reg_code_item.user, self.user) - self.assertEqual(course_reg_code_item.status, "cart") - self.assertEqual(self.cart.total_cost, 0) - self.assertTrue(CourseRegCodeItem.contained_in_order(self.cart, self.course_key)) - - def test_add_course_reg_item_with_no_course_item(self): - fake_course_id = CourseLocator(org="edx", course="fake", run="course") - with self.assertRaises(CourseDoesNotExistException): - CourseRegCodeItem.add_to_order(self.cart, fake_course_id, 2) - - def test_course_reg_item_already_in_cart(self): - CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) - with self.assertRaises(ItemAlreadyInCartException): - CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) - - def test_course_reg_item_already_enrolled_in_course(self): - CourseEnrollment.enroll(self.user, self.course_key) - with self.assertRaises(AlreadyEnrolledInCourseException): - CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) - - def test_purchased_callback(self): - reg1 = PaidCourseRegistration.add_to_order(self.cart, self.course_key) - self.cart.purchase() - self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course_key)) - reg1 = PaidCourseRegistration.objects.get(id=reg1.id) # reload from DB to get side-effect - self.assertEqual(reg1.status, "purchased") - self.assertIsNotNone(reg1.course_enrollment) - self.assertEqual(reg1.course_enrollment.id, CourseEnrollment.objects.get(user=self.user, course_id=self.course_key).id) - - def test_generate_receipt_instructions(self): - """ - Add 2 courses to the order and make sure the instruction_set only contains 1 element (no dups) - """ - course2 = CourseFactory.create() - course_mode2 = CourseMode(course_id=course2.id, - mode_slug="honor", - mode_display_name="honor cert", - min_price=self.cost) - course_mode2.save() - pr1 = PaidCourseRegistration.add_to_order(self.cart, self.course_key) - pr2 = PaidCourseRegistration.add_to_order(self.cart, course2.id) - self.cart.purchase() - inst_dict, inst_set = self.cart.generate_receipt_instructions() - self.assertEqual(2, len(inst_dict)) - self.assertEqual(1, len(inst_set)) - self.assertIn("dashboard", inst_set.pop()) - self.assertIn(pr1.pk_with_subclass, inst_dict) - self.assertIn(pr2.pk_with_subclass, inst_dict) - - def test_purchased_callback_exception(self): - reg1 = PaidCourseRegistration.add_to_order(self.cart, self.course_key) - reg1.course_id = CourseLocator(org="changed", course="forsome", run="reason") - reg1.save() - with self.assertRaises(PurchasedCallbackException): - reg1.purchased_callback() - self.assertFalse(CourseEnrollment.is_enrolled(self.user, self.course_key)) - - reg1.course_id = CourseLocator(org="abc", course="efg", run="hij") - reg1.save() - with self.assertRaises(PurchasedCallbackException): - reg1.purchased_callback() - self.assertFalse(CourseEnrollment.is_enrolled(self.user, self.course_key)) - - course_reg_code_item = CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) - course_reg_code_item.course_id = CourseLocator(org="changed1", course="forsome1", run="reason1") - course_reg_code_item.save() - with self.assertRaises(PurchasedCallbackException): - course_reg_code_item.purchased_callback() - - def test_user_cart_has_both_items(self): - """ - This test exists b/c having both CertificateItem and PaidCourseRegistration in an order used to break - PaidCourseRegistration.contained_in_order - """ - cart = Order.get_cart_for_user(self.user) - CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor') - PaidCourseRegistration.add_to_order(self.cart, self.course_key) - self.assertTrue(PaidCourseRegistration.contained_in_order(cart, self.course_key)) - - class CertificateItemTest(ModuleStoreTestCase): """ Tests for verifying specific CertificateItem functionality diff --git a/lms/djangoapps/shoppingcart/tests/test_reports.py b/lms/djangoapps/shoppingcart/tests/test_reports.py index b4ae695b3dc402430c5c62be4063681e03dd160d..28d9e26d6f465c1bc6c21346cf46b45b37a115a0 100644 --- a/lms/djangoapps/shoppingcart/tests/test_reports.py +++ b/lms/djangoapps/shoppingcart/tests/test_reports.py @@ -55,7 +55,6 @@ class ReportTypeTests(ModuleStoreTestCase): self.cost = 40 self.course = CourseFactory.create(org='MITx', number='999', display_name=u'Robot Super Course') self.course_key = self.course.id - settings.COURSE_LISTINGS['default'] = [text_type(self.course_key)] course_mode = CourseMode(course_id=self.course_key, mode_slug="honor", mode_display_name="honor cert", diff --git a/lms/djangoapps/shoppingcart/tests/test_views.py b/lms/djangoapps/shoppingcart/tests/test_views.py index 2dd37169d686873a0a83d18d248232e0d4c6c999..79405d50a865201de8918bc1550d92e8431a11af 100644 --- a/lms/djangoapps/shoppingcart/tests/test_views.py +++ b/lms/djangoapps/shoppingcart/tests/test_views.py @@ -26,7 +26,7 @@ from mock import Mock, patch from pytz import UTC from six import text_type from six.moves import range -from six.moves.urllib.parse import urlparse # pylint: disable=import-error +from six.moves.urllib.parse import urlparse from common.test.utils import XssTestMixin from course_modes.models import CourseMode @@ -750,7 +750,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): self.assertEqual(resp.status_code, 200) self.assertEqual(self.cart.orderitem_set.count(), 1) info_log.assert_called_with( - 'Coupon "%s" redemption entry removed for user "%s" for order item "%s"', # pylint: disable=unicode-format-string + 'Coupon "%s" redemption entry removed for user "%s" for order item "%s"', self.coupon_code, self.user, str(reg_item.id) @@ -1239,94 +1239,6 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): self.assertEqual(context['currency_symbol'], 'Rs') self.assertEqual(context['currency'], 'PKR') - @patch('shoppingcart.views.render_to_response', render_mock) - def test_courseregcode_item_total_price(self): - self.cart.order_type = 'business' - self.cart.save() - CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2, mode_slug=self.course_mode.mode_slug) - self.cart.purchase(first='FirstNameTesting123', street1='StreetTesting123') - self.assertEqual(CourseRegCodeItem.get_total_amount_of_purchased_item(self.course_key), 80) - - @patch('shoppingcart.views.render_to_response', render_mock) - def test_show_receipt_success_with_order_type_business(self): - self.cart.order_type = 'business' - self.cart.save() - reg_item = CourseRegCodeItem.add_to_order( - self.cart, - self.course_key, - 2, - mode_slug=self.course_mode.mode_slug - ) - self.cart.add_billing_details(company_name='T1Omega', company_contact_name='C1', - company_contact_email='test@t1.com', recipient_email='test@t2.com') - self.cart.purchase(first='FirstNameTesting123', street1='StreetTesting123') - - # mail is sent to these emails recipient_email, company_contact_email, order.user.email - self.assertEqual(len(mail.outbox), 3) - - self.login_user() - resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id])) - self.assertEqual(resp.status_code, 200) - - # when order_type = 'business' the user is not enrolled in the - # course but presented with the enrollment links - self.assertFalse(CourseEnrollment.is_enrolled(self.cart.user, self.course_key)) - self.assertContains(resp, 'FirstNameTesting123') - self.assertContains(resp, '80.00') - # check for the enrollment codes content - self.assertContains( - resp, - 'Please send each professional one of these unique registration codes to enroll into the course.', - ) - - # fetch the newly generated registration codes - course_registration_codes = CourseRegistrationCode.objects.filter(order=self.cart) - - ((template, context), _) = render_mock.call_args # pylint: disable=unpacking-non-sequence - self.assertEqual(template, 'shoppingcart/receipt.html') - self.assertEqual(context['order'], self.cart) - self.assertIn(reg_item, context['shoppingcart_items'][0]) - # now check for all the registration codes in the receipt - # and all the codes should be unused at this point - self.assertIn(course_registration_codes[0].code, context['reg_code_info_list'][0]['code']) - self.assertIn(course_registration_codes[1].code, context['reg_code_info_list'][1]['code']) - self.assertFalse(context['reg_code_info_list'][0]['is_redeemed']) - self.assertFalse(context['reg_code_info_list'][1]['is_redeemed']) - - self.assertContains( - resp, - self.cart.purchase_time.strftime(u"%B %d, %Y"), - ) - self.assertContains(resp, self.cart.company_name) - self.assertContains(resp, self.cart.company_contact_name) - self.assertContains(resp, self.cart.company_contact_email) - self.assertContains(resp, self.cart.recipient_email) - self.assertIn(u"Invoice #{order_id}".format(order_id=self.cart.id), resp.content.decode(resp.charset)) - codes_string = u'You have successfully purchased <b>{total_registration_codes} course registration codes' - self.assertIn(codes_string.format( - total_registration_codes=context['total_registration_codes']), - resp.content.decode(resp.charset) - ) - - # now redeem one of registration code from the previous order - redeem_url = reverse('register_code_redemption', args=[context['reg_code_info_list'][0]['code']]) - - #now activate the user by enrolling him/her to the course - response = self.client.post(redeem_url) - self.assertEqual(response.status_code, 200) - self.assertContains(response, 'View Dashboard') - - # now view the receipt page again to see if any registration codes - # has been expired or not - resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id])) - self.assertEqual(resp.status_code, 200) - ((template, context), _) = render_mock.call_args # pylint: disable=unpacking-non-sequence - self.assertEqual(template, 'shoppingcart/receipt.html') - # now check for all the registration codes in the receipt - # and one of code should be used at this point - self.assertTrue(context['reg_code_info_list'][0]['is_redeemed']) - self.assertFalse(context['reg_code_info_list'][1]['is_redeemed']) - @patch('shoppingcart.views.render_to_response', render_mock) def test_show_receipt_success_with_upgrade(self): @@ -1471,25 +1383,6 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin): } ) - def test_shopping_cart_navigation_link(self): - """ - Tests shopping cart link is available in navigation header. - """ - CourseEnrollment.enroll(self.user, self.course_key) - self.add_course_to_user_cart(self.testing_course.id) - resp = self.client.get(reverse('courseware', kwargs={'course_id': text_type(self.course.id)})) - self.assertContains(resp, '<a class="shopping-cart"') - - def test_shopping_cart_navigation_link_and_not_on_courseware(self): - """ - Tests shopping cart link is available in navigation header - and requested page is not courseware too. - """ - CourseEnrollment.enroll(self.user, self.course_key) - self.add_course_to_user_cart(self.testing_course.id) - resp = self.client.get(reverse('dashboard')) - self.assertContains(resp, '<a class="shopping-cart"') - class ReceiptRedirectTest(SharedModuleStoreTestCase): """Test special-case redirect from the receipt page. """ @@ -1799,108 +1692,6 @@ class RegistrationCodeRedemptionCourseEnrollment(SharedModuleStoreTestCase): cache.clear() - def test_course_enrollment_active_registration_code_redemption(self): - """ - Test for active registration code course enrollment - """ - cache.clear() - instructor = InstructorFactory(course_key=self.course_key) - self.client.login(username=instructor.username, password='test') - - # Registration Code Generation only available to Sales Admins. - CourseSalesAdminRole(self.course.id).add_users(instructor) - - url = reverse('generate_registration_codes', - kwargs={'course_id': text_type(self.course.id)}) - - data = { - 'total_registration_codes': 12, 'company_name': 'Test Group', 'company_contact_name': 'Test@company.com', - 'company_contact_email': 'Test@company.com', 'unit_price': 122.45, 'recipient_name': 'Test123', - 'recipient_email': 'test@123.com', 'address_line_1': 'Portland Street', - 'address_line_2': '', 'address_line_3': '', 'city': '', 'state': '', 'zip': '', 'country': '', - 'customer_reference_number': '123A23F', 'internal_reference': '', 'invoice': '' - } - - response = self.client.post(url, data) - self.assertEqual(response.status_code, 200) - # get the first registration from the newly created registration codes - registration_code = CourseRegistrationCode.objects.all()[0].code - redeem_url = reverse('register_code_redemption', args=[registration_code]) - self.login_user() - - response = self.client.get(redeem_url) - self.assertEqual(response.status_code, 200) - # check button text - self.assertContains(response, 'Activate Course Enrollment') - - #now activate the user by enrolling him/her to the course - response = self.client.post(redeem_url) - self.assertEqual(response.status_code, 200) - self.assertContains(response, 'View Dashboard') - - #now check that the registration code has already been redeemed and user is already registered in the course - RegistrationCodeRedemption.objects.filter(registration_code__code=registration_code) - response = self.client.get(redeem_url) - self.assertEqual(len(RegistrationCodeRedemption.objects.filter(registration_code__code=registration_code)), 1) - self.assertContains(response, "You've clicked a link for an enrollment code that has already been used.") - - #now check that the registration code has already been redeemed - response = self.client.post(redeem_url) - self.assertContains(response, "You've clicked a link for an enrollment code that has already been used.") - - #now check the response of the dashboard page - dashboard_url = reverse('dashboard') - response = self.client.get(dashboard_url) - self.assertEqual(response.status_code, 200) - self.assertContains(response, self.course.display_name.encode('utf-8')) - - -@ddt.ddt -class RedeemCodeEmbargoTests(UrlResetMixin, ModuleStoreTestCase): - """Test blocking redeem code redemption based on country access rules. """ - - USERNAME = 'bob' - PASSWORD = 'test' - - URLCONF_MODULES = ['openedx.core.djangoapps.embargo'] - - @patch.dict(settings.FEATURES, {'EMBARGO': True}) - def setUp(self): - super(RedeemCodeEmbargoTests, self).setUp() - self.course = CourseFactory.create() - self.user = UserFactory.create(username=self.USERNAME, password=self.PASSWORD) - result = self.client.login(username=self.user.username, password=self.PASSWORD) - self.assertTrue(result, msg="Could not log in") - - @ddt.data('get', 'post') - @patch.dict(settings.FEATURES, {'EMBARGO': True}) - def test_registration_code_redemption_embargo(self, method): - # Create a valid registration code - reg_code = CourseRegistrationCode.objects.create( - code="abcd1234", - course_id=self.course.id, - created_by=self.user - ) - - # Try to redeem the code from a restricted country - with restrict_course(self.course.id) as redirect_url: - url = reverse( - 'register_code_redemption', - kwargs={'registration_code': 'abcd1234'} - ) - response = getattr(self.client, method)(url) - self.assertRedirects(response, redirect_url) - - # The registration code should NOT be redeemed - is_redeemed = RegistrationCodeRedemption.objects.filter( - registration_code=reg_code - ).exists() - self.assertFalse(is_redeemed) - - # The user should NOT be enrolled - is_enrolled = CourseEnrollment.is_enrolled(self.user, self.course.id) - self.assertFalse(is_enrolled) - @ddt.ddt class DonationViewTest(SharedModuleStoreTestCase): diff --git a/lms/djangoapps/shoppingcart/views.py b/lms/djangoapps/shoppingcart/views.py index bc7b3a1573697f294ccc065b233502d490f44161..3a4a785e29096a832d06ee91b38d649fd9179713 100644 --- a/lms/djangoapps/shoppingcart/views.py +++ b/lms/djangoapps/shoppingcart/views.py @@ -494,9 +494,7 @@ def use_registration_code(course_reg, user): else: applicable_cart_items = [ cart_item for cart_item in cart_items - if ( - (isinstance(cart_item, PaidCourseRegistration) or isinstance(cart_item, CourseRegCodeItem))and cart_item.qty == 1 - ) + if isinstance(cart_item, (CourseRegCodeItem, PaidCourseRegistration)) and cart_item.qty == 1 ] if not applicable_cart_items: return HttpResponseNotFound( diff --git a/lms/djangoapps/static_template_view/views.py b/lms/djangoapps/static_template_view/views.py index 8d314e535a56071aed1a2d3aa80f179ef68e40a0..d9ff099b5c39898935d6eb8ffee16341096e4cc0 100644 --- a/lms/djangoapps/static_template_view/views.py +++ b/lms/djangoapps/static_template_view/views.py @@ -1,4 +1,4 @@ -# pylint: disable=missing-docstring,unused-argument +# pylint: disable=missing-module-docstring # View for semi-static templatized content. # diff --git a/lms/djangoapps/support/static/support/jsx/errors_list.jsx b/lms/djangoapps/support/static/support/jsx/errors_list.jsx index cf54911a218425fc64ae5074b44437330265d76c..86da7c13a03d2b6737e53b04dc772b0adfde1c8e 100644 --- a/lms/djangoapps/support/static/support/jsx/errors_list.jsx +++ b/lms/djangoapps/support/static/support/jsx/errors_list.jsx @@ -6,25 +6,23 @@ import PropTypes from 'prop-types'; class ShowErrors extends React.Component { render() { - if (this.props.errorList.length > 0) { - window.scrollTo(0, 0); - } - return this.props.errorList.length > 0 && - <div className="col-sm-12"> + return ( + this.props.hasErrors && <div className="col-sm-12"> <div className="alert alert-danger" role="alert"> <strong>{gettext('Please fix the following errors:')}</strong> <ul> - {this.props.errorList.map(error => - <li>{error}</li>, + { Object.keys(this.props.errorList).map(key => + this.props.errorList[key] && <li key={key}>{this.props.errorList[key]}</li>, )} </ul> </div> - </div>; + </div>); } } ShowErrors.propTypes = { - errorList: PropTypes.arrayOf(PropTypes.object).isRequired, + errorList: PropTypes.objectOf(PropTypes.string).isRequired, + hasErrors: PropTypes.bool.isRequired, }; export default ShowErrors; diff --git a/lms/djangoapps/support/static/support/jsx/logged_in_user.jsx b/lms/djangoapps/support/static/support/jsx/logged_in_user.jsx index f71f0019bca4973a6cbfa72508291e89cb9f7d9b..477520bec004c149a9496623f4fd66f654bfe071 100644 --- a/lms/djangoapps/support/static/support/jsx/logged_in_user.jsx +++ b/lms/djangoapps/support/static/support/jsx/logged_in_user.jsx @@ -2,29 +2,33 @@ import React from 'react'; import PropTypes from 'prop-types'; - +import { Button, StatusAlert } from '@edx/paragon'; import StringUtils from 'edx-ui-toolkit/js/utils/string-utils'; -import FileUpload from './file_upload'; - -function LoggedInUser({ userInformation, setErrorState, zendeskApiHost, submitForm }) { +function LoggedInUser({ userInformation, onChangeCallback, handleClick, showWarning, showDiscussionButton, reDirectUser, errorList }) { let courseElement; + let detailElement; + let discussionElement = ''; if (userInformation.enrollments) { courseElement = (<div> <label className="label-course" htmlFor="course">{gettext('Course Name')}</label> <p className="message-desc"><i> - {gettext('For inquiries regarding assignments, grades, or structure of a specific course, please post in the discussion forums for that course directly.')} + {gettext('For inquiries regarding assignments, grades, or structure of a specific course, please post in the discussion forums for that course directly.')} </i></p> - <select className="form-control select-course" id="course" defaultValue={userInformation.course_id}> + <select + className="form-control select-course" + id="course" + defaultValue={userInformation.course_id} + > <option key="select-course" value="">--------</option> <option key="not-course-specific" value="Not specific to a course"> {gettext('Not specific to a course')} </option> {userInformation.enrollments.map(enrollment => - (<option key={enrollment.course_id} value={enrollment.course_id}> - {enrollment.course_name} - </option>), - )} + (<option key={enrollment.course_id} value={enrollment.course_id}> + {enrollment.course_name} + </option>), + )} </select> </div>); } else { @@ -33,9 +37,7 @@ function LoggedInUser({ userInformation, setErrorState, zendeskApiHost, submitFo <input type="text" className="form-control" id="course" /> </div>); } - - let subjectElement; - subjectElement = (<div> + const subjectElement = (<div> <label htmlFor="subject">{gettext('Subject')}</label> <select className="form-control select-subject" id="subject"> <option value="">--------</option> @@ -55,10 +57,69 @@ function LoggedInUser({ userInformation, setErrorState, zendeskApiHost, submitFo <option value="Other">{gettext('Other')}</option> </select> </div>); + if (showDiscussionButton) { + discussionElement = ( + <div className="row"> + <div className="col-sm-12"> + <Button + className={['btn', 'btn-primary', 'btn-submit']} + onClick={reDirectUser} + label={gettext('Course Discussion Forum')} + /> + </div> + </div> + ); + } + if (showWarning) { + detailElement = ( + <div id="warning-msg"> + <div className="row"> + <div className="col-sm-12"> + <div className="form-group"> + <StatusAlert + alertType="info" + className={['in', 'pattern-library-shim']} + dismissible={false} + dialog={ + gettext('While our support team is happy to assist with the edX platform, the course staff has the expertise for specific assignment questions, grading or the proper procedures in each course. Please post all course related questions within the Discussion Forum where the Course Staff can directly respond.') + } + open + /> + </div> + </div> + </div> + { discussionElement } + </div> + ); + } else { + detailElement = ( + <div> + <div className="row"> + <div className="col-sm-12"> + <div className={`form-group ${errorList.message ? 'has-error' : ''}`}> + <label htmlFor="message">{gettext('Details')}</label> + <p className="message-desc">{gettext('the more quickly and helpfully we can respond!')}</p> + <textarea aria-describedby="message" className="form-control" rows="7" id="message" /> + </div> + </div> + </div> + <div className="row"> + <div className="col-sm-12"> + <Button + className={['btn', 'btn-primary', 'btn-submit']} + type="button" + onClick={handleClick} + label={gettext('Create Support Ticket')} + /> + </div> + </div> + </div> + ); + } - return (<div> + return (<form id="contact-us-form" onChange={onChangeCallback}> <div className="row"> - <hr className="col-sm-12"></hr> + <hr className="col-sm-12" /> </div> <div className="row"> <div @@ -77,15 +138,7 @@ function LoggedInUser({ userInformation, setErrorState, zendeskApiHost, submitFo <div className="row"> <div className="col-sm-12"> - <div className="form-group"> - {courseElement} - </div> - </div> - </div> - - <div className="row"> - <div className="col-sm-12"> - <div className="form-group"> + <div className={`form-group ${errorList.subject ? 'has-error' : ''}`}> {subjectElement} </div> </div> @@ -93,44 +146,35 @@ function LoggedInUser({ userInformation, setErrorState, zendeskApiHost, submitFo <div className="row"> <div className="col-sm-12"> - <div className="form-group"> - <label htmlFor="message">{gettext('Details')}</label> - <p - className="message-desc" - >{gettext('The more you tell us, the more quickly and helpfully we can respond!')}</p> - <textarea - aria-describedby="message" - className="form-control" - rows="7" - id="message" - /> + <div className={`form-group ${errorList.course ? 'has-error' : ''}`}> + {courseElement} </div> </div> </div> - - {/* TODO file uploading will be done after initial release */} - {/* <FileUpload */} - {/* setErrorState={setErrorState} */} - {/* zendeskApiHost={zendeskApiHost} */} - {/* accessToken={accessToken} */} - {/* /> */} - - <div className="row"> - <div className="col-sm-12"> - <button - className="btn btn-primary btn-submit" - onClick={submitForm} - >{gettext('Submit')}</button> - </div> - </div> - </div>); + {detailElement} + </form>); } + /* TODO file uploading will be done after initial release */ + /* <FileUpload */ + /* setErrorState={setErrorState} */ + /* zendeskApiHost={zendeskApiHost} */ + /* accessToken={accessToken} */ + /* /> */ + LoggedInUser.propTypes = { - setErrorState: PropTypes.func.isRequired, - submitForm: PropTypes.func.isRequired, - userInformation: PropTypes.arrayOf(PropTypes.object).isRequired, - submitFormUrl: PropTypes.string.isRequired, + handleClick: PropTypes.func.isRequired, + onChangeCallback: PropTypes.func.isRequired, + reDirectUser: PropTypes.func.isRequired, + userInformation: PropTypes.shape({ + course_id: PropTypes.string, + username: PropTypes.string, + email: PropTypes.string, + enrollments: PropTypes.arrayOf(PropTypes.object), + }).isRequired, + showWarning: PropTypes.bool.isRequired, + showDiscussionButton: PropTypes.bool.isRequired, + errorList: PropTypes.objectOf(PropTypes.string).isRequired, }; export default LoggedInUser; diff --git a/lms/djangoapps/support/static/support/jsx/logged_out_user.jsx b/lms/djangoapps/support/static/support/jsx/logged_out_user.jsx index d9b59fbdbe138a458a79e1149833d28abb3e9e27..6cf229488061a779199ec2e55592b4274aba40b0 100644 --- a/lms/djangoapps/support/static/support/jsx/logged_out_user.jsx +++ b/lms/djangoapps/support/static/support/jsx/logged_out_user.jsx @@ -18,26 +18,19 @@ function LoggedOutUser({ platformName, loginQuery, supportEmail }) { </div> <div className="row"> - <div className="col-sm-12"> + <div className="col-sm-6"> <a href={`/login${loginQuery}`} className="btn btn-primary btn-signin">{gettext('Sign in')}</a> </div> + <div className="col-sm-6"> + <a className="btn btn-secondary" href={`/register${loginQuery}`}> + {gettext('Create an Account')} + </a> + </div> </div> <div className="row"> <div className="col-sm-12"> - <a className="create-account" href={`/register${loginQuery}`}> - {StringUtils.interpolate( - // FIXME: not all platforms start with a vowel - gettext('Create an {platform} account'), - { platform: platformName }, - )} - </a> - <p className="create-account-note"> - {StringUtils.interpolate( - gettext('If you are unable to access your account contact us via email using {email}.'), - { email: supportEmail }, - )} - </p> + <a href="/password_assistance" type="button" class="forgot-password field-link">{gettext('Need help logging in?')}</a> </div> </div> </div> diff --git a/lms/djangoapps/support/static/support/jsx/single_support_form.jsx b/lms/djangoapps/support/static/support/jsx/single_support_form.jsx index 164ca6597321e16de900639d3ccb82aea0505856..bd75f701f425dad7c9da67686e80f5f41879a633 100644 --- a/lms/djangoapps/support/static/support/jsx/single_support_form.jsx +++ b/lms/djangoapps/support/static/support/jsx/single_support_form.jsx @@ -5,6 +5,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import ReactDOM from 'react-dom'; +import { StatusAlert } from '@edx/paragon'; import StringUtils from 'edx-ui-toolkit/js/utils/string-utils'; @@ -13,109 +14,166 @@ import LoggedInUser from './logged_in_user'; import LoggedOutUser from './logged_out_user'; import Success from './success'; +const initialFormErrors = { + course: undefined, + subject: undefined, + message: undefined, + request: undefined, +}; class RenderForm extends React.Component { constructor(props) { super(props); + this.submitFormUrl = this.props.context.submitFormUrl; + this.userInformation = this.props.context.user; + const course = this.userInformation ? this.userInformation.course_id : ''; + this.courseDiscussionURL = '/courses/{course_id}/discussion/forum'; + this.submitButton = null; this.state = { currentRequest: null, - errorList: [], + errorList: initialFormErrors, success: false, + formData: { + course, + subject: '', + message: '', + }, + }; + this.formValidationErrors = { + course: gettext('Select a course or select "Not specific to a course" for your support request.'), + subject: gettext('Select a subject for your support request.'), + message: gettext('Enter some details for your support request.'), + request: gettext('Something went wrong. Please try again later.'), }; - this.submitForm = this.submitForm.bind(this); - this.setErrorState = this.setErrorState.bind(this); + this.handleClick = this.handleClick.bind(this); + this.reDirectUser = this.reDirectUser.bind(this); + this.formOnChangeCallback = this.formOnChangeCallback.bind(this); } - setErrorState(errors) { - this.setState({ - errorList: errors, - }); + getFormDataFromState() { + return this.state.formData; } - submitForm() { - const url = this.props.context.submitFormUrl, - $userInfo = $('.user-info'), - request = new XMLHttpRequest(), - $course = $('#course'), - $subject = $('#subject'), - data = { - comment: { - body: $('#message').val(), - }, - tags: this.props.context.tags, - }, - errors = []; + getFormErrorsFromState() { + return this.state.errorList; + } - let course; - this.clearErrors(); + clearErrorState() { + const formErrorsInState = this.getFormErrorsFromState(); + Object.keys(formErrorsInState).map((index) => { + formErrorsInState[index] = undefined; + return formErrorsInState; + }); + } - data.requester = { - email: $userInfo.data('email'), - name: $userInfo.data('username'), - }; + // eslint-disable-next-line class-methods-use-this + scrollToTop() { + return window.scrollTo(0, 0); + } - course = $course.find(':selected').val(); - if (!course) { - course = $course.val(); - } - if (!course) { - $('#course').closest('.form-group').addClass('has-error'); - errors.push(gettext('Select a course or select "Not specific to a course" for your support request.')); - } - data.custom_fields = [{ - id: this.props.context.customFields.course_id, - value: course, - }]; - - let subject; - subject = $subject.find(':selected').val(); - if (!subject) { - subject = $subject.val(); - } - if (!subject) { - $('#subject').closest('.form-group').addClass('has-error'); - errors.push(gettext('Select a subject for your support request.')); - } - data.subject = subject; + formHasErrors() { + const errorsList = this.getFormErrorsFromState(); + return Object.keys(errorsList).filter(err => errorsList[err] !== undefined).length > 0; + } - if (this.validateData(data, errors)) { - request.open('POST', url, true); - request.setRequestHeader('Content-type', 'application/json;charset=UTF-8'); - request.setRequestHeader('X-CSRFToken', $.cookie('csrftoken')); + updateErrorInState(key, error) { + const errorList = this.getFormErrorsFromState(); + errorList[key] = error; + this.setState({ + errorList, + }); + } - request.send(JSON.stringify(data)); + formOnChangeCallback(event) { + const formData = this.getFormDataFromState(); + formData[event.target.id] = event.target.value; + this.setState({ formData }); + } - request.onreadystatechange = function success() { - if (request.readyState === 4 && request.status === 201) { - this.setState({ - success: true, - }); - } - }.bind(this); + showWarningMessage() { + const formData = this.getFormDataFromState(), + selectedSubject = formData.subject; + return formData && selectedSubject === 'Course Content'; + } - request.onerror = function error() { - this.setErrorState([gettext('Something went wrong. Please try again later.')]); - }.bind(this); - } + showDiscussionButton() { + const formData = this.getFormDataFromState(), + selectedCourse = formData.course; + return formData && (selectedCourse !== '' && selectedCourse !== 'Not specific to a course'); } - clearErrors() { - this.setErrorState([]); - $('.form-group').removeClass('has-error'); + reDirectUser(event) { + event.preventDefault(); + const formData = this.getFormDataFromState(); + window.location.href = this.courseDiscussionURL.replace('{course_id}', formData.course); } - validateData(data, errors) { - if (!data.comment.body) { - errors.push(gettext('Enter some details for your support request.')); - $('#message').closest('.form-group').addClass('has-error'); + handleClick(event) { + event.preventDefault(); + this.submitButton = event.currentTarget; + this.submitButton.setAttribute("disabled", true); + const formData = this.getFormDataFromState(); + this.clearErrorState(); + this.validateFormData(formData); + if (this.formHasErrors()) { + this.submitButton.removeAttribute("disabled"); + return this.scrollToTop(); } + this.createZendeskTicket(formData); + } - if (!errors.length) { - return true; - } + createZendeskTicket(formData) { + const url = this.submitFormUrl, + request = new XMLHttpRequest(), + data = { + comment: { + body: formData.message, + }, + subject: formData.subject, // Zendesk API requires 'subject' + custom_fields: [{ + id: this.props.context.customFields.course_id, + value: formData.course, + }], + tags: this.props.context.tags, + requester: { + email: this.userInformation.email, + name: this.userInformation.username, + }, + }; + request.open('POST', url, true); + request.setRequestHeader('Content-type', 'application/json;charset=UTF-8'); + request.setRequestHeader('X-CSRFToken', $.cookie('csrftoken')); + request.send(JSON.stringify(data)); + request.onreadystatechange = function success() { + if (request.readyState === 4) { + this.submitButton.removeAttribute("disabled"); + if (request.status === 201) { + this.setState({ + success: true, + }); + } + } + }.bind(this); - this.setErrorState(errors); - return false; + request.onerror = function error() { + this.updateErrorInState('request', this.formValidationErrors.request); + this.submitButton.removeAttribute("disabled"); + this.scrollToTop(); + }.bind(this); + } + validateFormData(formData) { + const { course, subject, message } = formData; + + let courseError, + subjectError, + messageError; + + courseError = (course === '') ? this.formValidationErrors.course : undefined; + this.updateErrorInState('course', courseError); + subjectError = (subject === '') ? this.formValidationErrors.subject : undefined; + this.updateErrorInState('subject', subjectError); + messageError = (message === '') ? this.formValidationErrors.message : undefined; + this.updateErrorInState('message', messageError); } renderSuccess() { @@ -124,19 +182,22 @@ class RenderForm extends React.Component { platformName={this.props.context.platformName} homepageUrl={this.props.context.homepageUrl} dashboardUrl={this.props.context.dashboardUrl} - isLoggedIn={this.props.context.user !== undefined} + isLoggedIn={this.userInformation !== undefined} /> ); } renderSupportForm() { let userElement; - if (this.props.context.user) { + if (this.userInformation) { userElement = (<LoggedInUser - userInformation={this.props.context.user} - submitFormUrl={this.props.context.submitFormUrl} - setErrorState={this.setErrorState} - submitForm={this.submitForm} + userInformation={this.userInformation} + onChangeCallback={this.formOnChangeCallback} + handleClick={this.handleClick} + showWarning={this.showWarningMessage()} + showDiscussionButton={this.showDiscussionButton()} + reDirectUser={this.reDirectUser} + errorList={this.getFormErrorsFromState()} />); } else { userElement = (<LoggedOutUser @@ -149,14 +210,19 @@ class RenderForm extends React.Component { return ( <div className="contact-us-wrapper"> + {/* Note: not using Paragon bc component shows in the DOM but not rendered, even when using + version 2.6.4. */} + <div className="alert alert-warning" role="alert" style={{ marginBottom: '1rem', padding: '1.5rem', left: '0px', fontSize: '16px', backgroundColor: '#fffaed', color: '#171C29', border: '1px solid #FFD875', borderRadius: '0.3rem' }}> + <div>{gettext('Due to the recent increase in interest in online education and edX, we are currently experiencing an unusually high volume of support requests. We appreciate your patience as we work to review each request. Please check the ')}<a href="https://support.edx.org/hc/en-us" className="alert-link">Help Center</a>{gettext(' as many questions may have already been answered.')}</div> + </div> + <div className="row"> <div className="col-sm-12"> <h2>{gettext('Contact Us')}</h2> </div> </div> - <div className="row form-errors"> - <ShowErrors errorList={this.state.errorList} /> + <ShowErrors errorList={this.getFormErrorsFromState()} hasErrors={this.formHasErrors()} /> </div> <div className="row"> @@ -188,13 +254,23 @@ class RenderForm extends React.Component { if (this.state.success) { return this.renderSuccess(); } - return this.renderSupportForm(); } } RenderForm.propTypes = { - context: PropTypes.arrayOf(PropTypes.object).isRequired, + context: PropTypes.shape({ + customFields: PropTypes.object, + dashboardUrl: PropTypes.string, + homepageUrl: PropTypes.string, + marketingUrl: PropTypes.string, + loginQuery: PropTypes.string, + platformName: PropTypes.string, + submitFormUrl: PropTypes.string, + supportEmail: PropTypes.string, + tags: PropTypes.arrayOf(PropTypes.string), + user: PropTypes.object, + }).isRequired, }; export class SingleSupportForm { diff --git a/lms/djangoapps/support/static/support/jsx/success.jsx b/lms/djangoapps/support/static/support/jsx/success.jsx index 1b594c9759cd58781236fa446e6b1d1afecc3c4f..92eb4ac8595ff6795e2b968531eb5a3bbf5c9040 100644 --- a/lms/djangoapps/support/static/support/jsx/success.jsx +++ b/lms/djangoapps/support/static/support/jsx/success.jsx @@ -28,7 +28,7 @@ function Success({ platformName, homepageUrl, dashboardUrl, isLoggedIn }) { <div className="row"> <div className="col-sm-12"> - <p>{gettext('Thank you for submitting a request!')}</p> + <p>{gettext('Thank you for submitting a request! We appreciate your patience while we work to review your request.')}</p> </div> </div> diff --git a/lms/djangoapps/support/tests/test_refund.py b/lms/djangoapps/support/tests/test_refund.py deleted file mode 100644 index 51a50541d2edab897f166b8ac27bf540ce260e43..0000000000000000000000000000000000000000 --- a/lms/djangoapps/support/tests/test_refund.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -Tests for refunds on the support dashboard - -DEPRECATION WARNING: -This test suite is deliberately separate from the other view tests -so we can easily deprecate it once the transition from shoppingcart -to the E-Commerce service is complete. - -""" - - -import datetime - -import pytz -from django.test.client import Client -from mock import patch - -from course_modes.models import CourseMode -from shoppingcart.models import CertificateItem, Order -from student.models import CourseEnrollment -from student.roles import SupportStaffRole -from student.tests.factories import UserFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory - - -class RefundTests(ModuleStoreTestCase): - """ - Tests for the manual refund page - """ - - def setUp(self): - super(RefundTests, self).setUp() - - self.course = CourseFactory.create( - org='testorg', number='run1', display_name='refundable course' - ) - self.course_id = self.course.location.course_key - self.client = Client() - self.admin = UserFactory.create( - username='test_admin', - email='test_admin+support@edx.org', - password='foo' - ) - SupportStaffRole().add_users(self.admin) - self.client.login(username=self.admin.username, password='foo') - - self.student = UserFactory.create( - username='student', - email='student+refund@edx.org' - ) - self.course_mode = CourseMode.objects.get_or_create( - course_id=self.course_id, - mode_slug='verified', - min_price=1 - )[0] - - self.order = None - self.form_pars = {'course_id': str(self.course_id), 'user': self.student.email} - - def tearDown(self): - self.course_mode.delete() - Order.objects.filter(user=self.student).delete() - super(RefundTests, self).tearDown() - - def _enroll(self, purchase=True): - # pylint: disable=missing-docstring - CourseEnrollment.enroll(self.student, self.course_id, self.course_mode.mode_slug) - if purchase: - self.order = Order.get_cart_for_user(self.student) - CertificateItem.add_to_order(self.order, self.course_id, 1, self.course_mode.mode_slug) - self.order.purchase() - self.course_mode.expiration_datetime = datetime.datetime(1983, 4, 6, tzinfo=pytz.UTC) - self.course_mode.save() - - def test_support_access(self): - response = self.client.get('/support/') - self.assertTrue(response.status_code, 200) - self.assertContains(response, 'Manual Refund') - response = self.client.get('/support/refund/') - self.assertTrue(response.status_code, 200) - - # users without the permission can't access support - SupportStaffRole().remove_users(self.admin) - response = self.client.get('/support/') - self.assertTrue(response.status_code, 302) - - response = self.client.get('/support/refund/') - self.assertTrue(response.status_code, 302) - - def test_bad_courseid(self): - response = self.client.post('/support/refund/', {'course_id': 'foo', 'user': self.student.email}) - self.assertContains(response, 'Course id invalid') - - def test_bad_user(self): - response = self.client.post('/support/refund/', {'course_id': str(self.course_id), 'user': 'unknown@foo.com'}) - self.assertContains(response, 'User not found') - - @patch('student.models.CourseEnrollment.refund_cutoff_date') - def test_not_refundable(self, cutoff_date): - self._enroll() - self.course_mode.expiration_datetime = datetime.datetime(2033, 4, 6, tzinfo=pytz.UTC) - self.course_mode.save() - cutoff_date.return_value = datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=1) - response = self.client.post('/support/refund/', self.form_pars) - self.assertContains(response, 'not past the refund window') - - def test_no_order(self): - self._enroll(purchase=False) - response = self.client.post('/support/refund/', self.form_pars) - self.assertContains(response, u'No order found for %s' % self.student.username) - - def test_valid_order(self): - self._enroll() - response = self.client.post('/support/refund/', self.form_pars) - self.assertContains(response, "About to refund this order") - self.assertContains(response, "enrolled") - self.assertContains(response, "CertificateItem Status") - - def test_do_refund(self): - self._enroll() - pars = self.form_pars - pars['confirmed'] = 'true' - response = self.client.post('/support/refund/', pars) - self.assertTrue(response.status_code, 302) - response = self.client.get(response.get('location')) - - self.assertContains(response, u"Unenrolled %s from" % self.student) - self.assertContains(response, "Refunded 1.00 for order id") - - self.assertFalse(CourseEnrollment.is_enrolled(self.student, self.course_id)) diff --git a/lms/djangoapps/support/tests/test_views.py b/lms/djangoapps/support/tests/test_views.py index 04d2dcd91b6b326cadf91f50affb5793cf4cd137..babfa2f94fef3b04f97a1eedc6134b3c1727fb83 100644 --- a/lms/djangoapps/support/tests/test_views.py +++ b/lms/djangoapps/support/tests/test_views.py @@ -65,6 +65,22 @@ class SupportViewManageUserTests(SupportViewTestCase): super(SupportViewManageUserTests, self).setUp() SupportStaffRole().add_users(self.user) + def test_get_contact_us(self): + """ + Tests Support View contact us Page + """ + url = reverse('support:contact_us') + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + + def test_get_password_assistance(self): + """ + Tests password assistance + """ + url = '/password_assistance' + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + def test_get_support_form(self): """ Tests Support View to return Manage User Form @@ -112,7 +128,6 @@ class SupportViewAccessTests(SupportViewTestCase): in itertools.product(( 'support:index', 'support:certificates', - 'support:refund', 'support:enrollment', 'support:enrollment_list', 'support:manage_user', @@ -140,7 +155,6 @@ class SupportViewAccessTests(SupportViewTestCase): @ddt.data( "support:index", "support:certificates", - "support:refund", "support:enrollment", "support:enrollment_list", "support:manage_user", @@ -169,7 +183,6 @@ class SupportViewIndexTests(SupportViewTestCase): EXPECTED_URL_NAMES = [ "support:certificates", - "support:refund", "support:link_program_enrollments", ] @@ -550,6 +563,74 @@ class SupportViewLinkProgramEnrollmentsTests(SupportViewTestCase): render_call_dict = mocked_render.call_args[0][1] assert render_call_dict['errors'] == [msg] + def _setup_user_from_username(self, username): + """ + Setup a user from the passed in username. + If username passed in is falsy, return None + """ + created_user = None + if username: + created_user = UserFactory(username=username, password=self.PASSWORD) + return created_user + + def _setup_enrollments(self, external_user_key, linked_user=None): + """ + Create enrollments for testing linking. + The enrollments can be create with already linked edX user. + """ + program_enrollment = ProgramEnrollmentFactory.create( + external_user_key=external_user_key, + program_uuid=self.program_uuid, + user=linked_user + ) + course_enrollment = None + if linked_user: + course_enrollment = CourseEnrollmentFactory.create( + course_id=self.course.id, + user=linked_user, + mode=CourseMode.MASTERS, + is_active=True + ) + program_course_enrollment = ProgramCourseEnrollmentFactory.create( + program_enrollment=program_enrollment, + course_key=self.course.id, + course_enrollment=course_enrollment, + status='active' + ) + + return program_enrollment, program_course_enrollment + + @ddt.data( + ('', None), + ('linked_user', None), + ('linked_user', 'original_user') + ) + @ddt.unpack + @patch_render + def test_linking_program_enrollment(self, username, original_username, mocked_render): + external_user_key = '0001' + linked_user = self._setup_user_from_username(username) + original_user = self._setup_user_from_username(original_username) + program_enrollment, program_course_enrollment = self._setup_enrollments( + external_user_key, + original_user + ) + self.client.post(self.url, data={ + 'program_uuid': self.program_uuid, + 'text': external_user_key + ',' + username + }) + render_call_dict = mocked_render.call_args[0][1] + if username: + expected_success = "('{}', '{}')".format(external_user_key, username) + assert render_call_dict['successes'] == [expected_success] + program_enrollment.refresh_from_db() + assert program_enrollment.user == linked_user + program_course_enrollment.refresh_from_db() + assert program_course_enrollment.course_enrollment.user == linked_user + else: + error = u"All linking lines must be in the format 'external_user_key,lms_username'" + assert render_call_dict['errors'] == [error] + @ddt.ddt class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase): diff --git a/lms/djangoapps/support/urls.py b/lms/djangoapps/support/urls.py index 6dcbe5a06380e0dc5af6e5d2652339d709dd3941..5ebd6a7bcb5d3b500bdd2daf6d041fcb601bc19a 100644 --- a/lms/djangoapps/support/urls.py +++ b/lms/djangoapps/support/urls.py @@ -13,7 +13,6 @@ from support.views.feature_based_enrollments import FeatureBasedEnrollmentsSuppo from support.views.index import index from support.views.manage_user import ManageUserDetailView, ManageUserSupportView from support.views.program_enrollments import LinkProgramEnrollmentSupportView, ProgramEnrollmentsInspectorView -from support.views.refund import RefundSupportView COURSE_ENTITLEMENTS_VIEW = EntitlementSupportView.as_view() @@ -21,7 +20,6 @@ app_name = 'support' urlpatterns = [ url(r'^$', index, name="index"), url(r'^certificates/?$', CertificatesSupportView.as_view(), name="certificates"), - url(r'^refund/?$', RefundSupportView.as_view(), name="refund"), url(r'^enrollment/?$', EnrollmentSupportView.as_view(), name="enrollment"), url(r'^course_entitlement/?$', COURSE_ENTITLEMENTS_VIEW, name="course_entitlement"), url(r'^contact_us/?$', ContactUsView.as_view(), name="contact_us"), diff --git a/lms/djangoapps/support/views/index.py b/lms/djangoapps/support/views/index.py index 87a4d5e1c8eb423ba2b6f46e771531ce8a7edf2d..47d925d4e4b01cb37c32d0c361a611fac87808ee 100644 --- a/lms/djangoapps/support/views/index.py +++ b/lms/djangoapps/support/views/index.py @@ -15,14 +15,6 @@ SUPPORT_INDEX_URLS = [ "name": _("Certificates"), "description": _("View and regenerate certificates."), }, - - # DEPRECATION WARNING: We can remove this end-point - # once shoppingcart has been replaced by the E-Commerce service. - { - "url": reverse_lazy("support:refund"), - "name": _("Manual Refund"), - "description": _("Track refunds issued directly through CyberSource."), - }, { "url": reverse_lazy("support:enrollment"), "name": _("Enrollment"), @@ -57,7 +49,7 @@ SUPPORT_INDEX_URLS = [ @require_support_permission -def index(request): # pylint: disable=unused-argument +def index(request): """Render the support index view. """ context = { "urls": SUPPORT_INDEX_URLS diff --git a/lms/djangoapps/support/views/refund.py b/lms/djangoapps/support/views/refund.py deleted file mode 100644 index b7385414b9abb76f779085d7e72024617b8ee79f..0000000000000000000000000000000000000000 --- a/lms/djangoapps/support/views/refund.py +++ /dev/null @@ -1,142 +0,0 @@ -""" -Views for manual refunds in the student support UI. - -This interface is used by the support team to track refunds -entered manually in CyberSource (our payment gateway). - -DEPRECATION WARNING: -We are currently in the process of replacing lms/djangoapps/shoppingcart -with an E-Commerce service that supports automatic refunds. Once that -transition is complete, we can remove this view. - -""" - - -import logging - -from django import forms -from django.contrib import messages -from django.contrib.auth.models import User -from django.http import HttpResponseRedirect -from django.utils.decorators import method_decorator -from django.utils.translation import ugettext as _ -from django.views.generic.edit import FormView - -from openedx.core.lib.courses import clean_course_id -from student.models import CourseEnrollment -from support.decorators import require_support_permission - -log = logging.getLogger(__name__) - - -class RefundForm(forms.Form): - """ - Form for manual refunds - """ - user = forms.EmailField(label=_("Email Address"), required=True) - course_id = forms.CharField(label=_("Course ID"), required=True) - confirmed = forms.CharField(widget=forms.HiddenInput, required=False) - - def clean_user(self): - """ - validate user field - """ - user_email = self.cleaned_data['user'] - try: - user = User.objects.get(email=user_email) - except User.DoesNotExist: - raise forms.ValidationError(_("User not found")) - return user - - def clean_course_id(self): - """ - Validate the course id - """ - return clean_course_id(self) - - def clean(self): - """ - clean form - """ - user, course_id = self.cleaned_data.get('user'), self.cleaned_data.get('course_id') - if user and course_id: - self.cleaned_data['enrollment'] = enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id) - if enrollment.refundable(): - msg = _(u"Course {course_id} not past the refund window.").format(course_id=course_id) - raise forms.ValidationError(msg) - try: - self.cleaned_data['cert'] = enrollment.certificateitem_set.filter( - mode='verified', - status='purchased' - )[0] - except IndexError: - msg = _(u"No order found for {user} in course {course_id}").format(user=user, course_id=course_id) - raise forms.ValidationError(msg) - return self.cleaned_data - - def is_valid(self): - """ - returns whether form is valid - """ - is_valid = super(RefundForm, self).is_valid() - if is_valid and self.cleaned_data.get('confirmed') != 'true': - # this is a two-step form: first look up the data, then issue the refund. - # first time through, set the hidden "confirmed" field to true and then redisplay the form - # second time through, do the unenrollment/refund. - data = dict(list(self.data.items())) - self.cleaned_data['confirmed'] = data['confirmed'] = 'true' - self.data = data - is_valid = False - return is_valid - - -class RefundSupportView(FormView): - """ - Refund form view - """ - template_name = 'support/refund.html' - form_class = RefundForm - success_url = '/support/' - - @method_decorator(require_support_permission) - def dispatch(self, *args, **kwargs): - return super(RefundSupportView, self).dispatch(*args, **kwargs) - - def get_context_data(self, **kwargs): - """ - extra context data to add to page - """ - kwargs = super(RefundSupportView, self).get_context_data(**kwargs) - form = getattr(kwargs['form'], 'cleaned_data', {}) - if form.get('confirmed') == 'true': - kwargs['cert'] = form.get('cert') - kwargs['enrollment'] = form.get('enrollment') - return kwargs - - def form_valid(self, form): - """ - unenrolls student, issues refund - """ - user = form.cleaned_data['user'] - course_id = form.cleaned_data['course_id'] - enrollment = form.cleaned_data['enrollment'] - cert = form.cleaned_data['cert'] - enrollment.can_refund = True - enrollment.update_enrollment(is_active=False) - - log.info(u"%s manually refunded %s %s", self.request.user, user, course_id) - messages.success( - self.request, - _(u"Unenrolled {user} from {course_id}").format( - user=user, - course_id=course_id - ) - ) - messages.success( - self.request, - _(u"Refunded {cost} for order id {order_id}").format( - cost=cert.unit_cost, - order_id=cert.order.id - ) - ) - return HttpResponseRedirect('/support/refund/') diff --git a/lms/djangoapps/survey/apps.py b/lms/djangoapps/survey/apps.py index d1bd7b91c1ae8cbe28d992001b1e8eac3877f7b5..4cb55c84a9ad7fce208c5103e39c3c3ea83f6624 100644 --- a/lms/djangoapps/survey/apps.py +++ b/lms/djangoapps/survey/apps.py @@ -17,4 +17,4 @@ class SurveyConfig(AppConfig): """ Connect signal handlers. """ - from . import signals # pylint: disable=unused-variable + from . import signals # pylint: disable=unused-import diff --git a/lms/djangoapps/survey/tests/factories.py b/lms/djangoapps/survey/tests/factories.py index f8f3bbf21745213ef61480d9a753111ada3fde23..dedca7073a08b7f80bffe716563a2e0bacc3c151 100644 --- a/lms/djangoapps/survey/tests/factories.py +++ b/lms/djangoapps/survey/tests/factories.py @@ -1,6 +1,3 @@ -# pylint:disable=missing-docstring - - import factory from student.tests.factories import UserFactory diff --git a/lms/djangoapps/teams/api.py b/lms/djangoapps/teams/api.py index c2b82b84ecba231ac372769946e37d64d2673f28..362eea60d83a56c8e7ededf8e5b0442c00d496b7 100644 --- a/lms/djangoapps/teams/api.py +++ b/lms/djangoapps/teams/api.py @@ -6,11 +6,12 @@ The Python API other app should use to work with Teams feature import logging from enum import Enum -from django.db.models import Count +from django.db.models import Count, Q from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey from course_modes.models import CourseMode +from lms.djangoapps.courseware.courses import has_access from lms.djangoapps.discussion.django_comment_client.utils import has_discussion_privileges from lms.djangoapps.teams.models import CourseTeam, CourseTeamMembership from openedx.core.lib.teams_config import TeamsetType @@ -251,7 +252,7 @@ def user_protection_status_matches_team(user, team): return OrganizationProtectionStatus.unprotected == protection_status -def get_team_count_query_set(topic_id_set, course_id, organization_protection_status): +def _get_team_filter_query(topic_id_set, course_id, organization_protection_status): """ Helper function to get the team count query set based on the filters provided """ filter_query = {'course_id': course_id} @@ -264,16 +265,34 @@ def get_team_count_query_set(topic_id_set, course_id, organization_protection_st filter_query.update( {'organization_protected': organization_protection_status == OrganizationProtectionStatus.protected} ) - return CourseTeam.objects.filter(**filter_query) + return filter_query -def add_team_count(topics, course_id, organization_protection_status): +def get_teams_accessible_by_user(user, topic_id_set, course_id, organization_protection_status): + """ Get teams taking for a user, taking into account user visibility privileges """ + # Filter by topics, course, and protection status + filter_query = _get_team_filter_query(topic_id_set, course_id, organization_protection_status) + + # Staff gets unfiltered list of teams + if has_access(user, 'staff', course_id): + return CourseTeam.objects.filter(**filter_query) + + # Private teams should be hidden unless the student is a member + course_module = modulestore().get_course(course_id) + private_teamset_ids = [ts.teamset_id for ts in course_module.teamsets if ts.is_private_managed] + return CourseTeam.objects.filter(**filter_query).exclude( + Q(topic_id__in=private_teamset_ids), ~Q(membership__user=user) + ) + + +def add_team_count(user, topics, course_id, organization_protection_status): """ Helper method to add team_count for a list of topics. This allows for a more efficient single query. """ topic_ids = [topic['id'] for topic in topics] - teams_query_set = get_team_count_query_set( + teams_query_set = get_teams_accessible_by_user( + user, topic_ids, course_id, organization_protection_status @@ -365,3 +384,20 @@ def anonymous_user_ids_for_team(user, team): anonymous_id_for_user(user=team_member, course_id=team.course_id, save=False) for team_member in team.users.all() ]) + + +def get_assignments_for_team(user, team): + """ Get openassessment XBlocks configured for the current teamset """ + # Confirm access + if not has_specific_team_access(user, team): + raise Exception("User {user} is not permitted to access team info for {team}".format( + user=user.username, + team=team.team_id + )) + + # Limit to team-enabled ORAs for the matching teamset in the course + return modulestore().get_items( + team.course_id, + qualifiers={'category': 'openassessment'}, + settings={'teams_enabled': True, 'selected_teamset_id': team.topic_id} + ) diff --git a/lms/djangoapps/teams/api_urls.py b/lms/djangoapps/teams/api_urls.py index 8c8f905d1471b0eec64c19ffab338bd8720f628a..e36cb69a65f70eaf14fd0a90c645c9d94b86a12b 100644 --- a/lms/djangoapps/teams/api_urls.py +++ b/lms/djangoapps/teams/api_urls.py @@ -10,6 +10,7 @@ from .views import ( MembershipBulkManagementView, MembershipDetailView, MembershipListView, + TeamsAssignmentsView, TeamsDetailView, TeamsListView, TopicDetailView, @@ -32,6 +33,13 @@ urlpatterns = [ TeamsDetailView.as_view(), name="teams_detail" ), + url( + r'^v0/teams/{team_id_pattern}/assignments$'.format( + team_id_pattern=TEAM_ID_PATTERN, + ), + TeamsAssignmentsView.as_view(), + name="teams_assignments_list" + ), url( r'^v0/topics/$', TopicListView.as_view(), diff --git a/lms/djangoapps/teams/csv.py b/lms/djangoapps/teams/csv.py index 657b8c7e35c7ff039e4917cba004d9972beb1610..f4a873b3511eb39f869316d3f0936720a20b1549 100644 --- a/lms/djangoapps/teams/csv.py +++ b/lms/djangoapps/teams/csv.py @@ -6,9 +6,16 @@ import csv from collections import Counter from django.contrib.auth.models import User - -from lms.djangoapps.teams.api import OrganizationProtectionStatus, user_organization_protection_status +from django.db.models import Prefetch + +from lms.djangoapps.teams.api import ( + OrganizationProtectionStatus, + user_organization_protection_status, + ORGANIZATION_PROTECTED_MODES, + user_protection_status_matches_team +) from lms.djangoapps.teams.models import CourseTeam, CourseTeamMembership +from lms.djangoapps.program_enrollments.models import ProgramCourseEnrollment, ProgramEnrollment from student.models import CourseEnrollment from .utils import emit_team_event @@ -46,29 +53,69 @@ def _lookup_team_membership_data(course): Returns a list of dicts, in the following form: [ { - 'user': <username>, + 'user': If the user is enrolled in this course as a part of a program, + this will be <external_user_key> if the user has one, otherwise <username>, 'mode': <student enrollment mode for the given course>, <teamset id>: <team name> for each teamset in which the given user is on a team } for student in course ] """ - course_students = CourseEnrollment.objects.users_enrolled_in(course.id).order_by('username') - CourseEnrollment.bulk_fetch_enrollment_states(course_students, course.id) - + # Get course enrollments and team memberships for the given course + course_enrollments = _fetch_course_enrollments_with_related_models(course.id) course_team_memberships = CourseTeamMembership.objects.filter( team__course_id=course.id ).select_related('team', 'user').all() teamset_memberships_by_user = _group_teamset_memberships_by_user(course_team_memberships) + team_membership_data = [] - for user in course_students: - student_row = teamset_memberships_by_user.get(user, dict()) - student_row['user'] = user.username - student_row['mode'], _ = CourseEnrollment.enrollment_mode_for_user(user, course.id) + for course_enrollment in course_enrollments: + # This dict contains all the user's team memberships keyed by teamset + student_row = teamset_memberships_by_user.get(course_enrollment.user, dict()) + student_row['user'] = _get_displayed_user_identifier(course_enrollment) + student_row['mode'] = course_enrollment.mode team_membership_data.append(student_row) return team_membership_data +def _fetch_course_enrollments_with_related_models(course_id): + """ + Look up active course enrollments for this course. Fetch the user. + Fetch the ProgramCourseEnrollment and ProgramEnrollment if any of the CourseEnrollments are associated with + a program enrollment (so we have access to an external_user_id if it exists). + Order by the username of the enrolled user. + + Returns a QuerySet + """ + return CourseEnrollment.objects.filter( + course_id=course_id, + is_active=True + ).prefetch_related( + Prefetch( + 'programcourseenrollment_set', + queryset=ProgramCourseEnrollment.objects.select_related('program_enrollment') + ) + ).select_related( + 'user' + ).order_by('user__username') + + +def _get_displayed_user_identifier(course_enrollment): + """ + If a user is enrolled in the course as a part of a program and the program identifies them + with an external_user_key, use that as the value of the 'user' column. + Otherwise, use the user's username. + """ + program_course_enrollments = course_enrollment.programcourseenrollment_set + if program_course_enrollments.exists(): + # A user should only have one or zero ProgramCourseEnrollments associated with a given CourseEnrollment + program_course_enrollment = program_course_enrollments.all()[0] + external_user_key = program_course_enrollment.program_enrollment.external_user_key + if external_user_key: + return external_user_key + return course_enrollment.user.username + + def _group_teamset_memberships_by_user(course_team_memberships): """ Parameters: @@ -103,13 +150,14 @@ class TeamMembershipImportManager(object): def __init__(self, course): self.validation_errors = [] self.teamset_ids = [] - self.user_ids_by_teamset_id = {} self.course = course self.max_errors = 0 self.existing_course_team_memberships = {} self.existing_course_teams = {} self.user_count_by_team = Counter() + self.user_enrollment_by_team = {} self.number_of_learners_assigned = 0 + self.user_to_actual_enrollment_mode = {} @property def import_succeeded(self): @@ -120,22 +168,32 @@ class TeamMembershipImportManager(object): def set_team_membership_from_csv(self, input_file): """ - Assigns team membership based on the content of an uploaded CSV file. + Parse an input CSV file and pass to `set_team_memberships` for processing + """ + csv_reader = csv.DictReader((line.decode('utf-8-sig').strip() for line in input_file.readlines())) + return self.set_team_memberships(csv_reader) + + def set_team_memberships(self, csv_reader): + """ + Assigns team membership based on the data from an uploaded CSV file. Returns true if there were no issues. """ - reader = csv.DictReader((line.decode('utf-8-sig').strip() for line in input_file.readlines())) - self.teamset_ids = reader.fieldnames[2:] - row_dictionaries = [] - csv_usernames = set() - if not self.validate_header(reader.fieldnames): + # File-level validation + if not self.validate_header(csv_reader): return False - if not self.validate_teamsets(): + if not self.validate_teamsets(csv_reader): return False - self.load_user_ids_by_teamset_id() + + self.teamset_ids = csv_reader.fieldnames[2:] + row_dictionaries = [] + csv_usernames = set() + + # Get existing team membership data self.load_course_team_memberships() self.load_course_teams() + # process student rows: - for row in reader: + for row in csv_reader: if not self.validate_teams_have_matching_teamsets(row): return False username = row['user'] @@ -151,13 +209,16 @@ class TeamMembershipImportManager(object): row['user'] = None continue row['user'] = user - if not self.validate_user_assignment_to_team_and_teamset(row): return False row_dictionaries.append(row) + if not self.validate_team_sizes_not_exceeded(): + return False + if not self.validation_errors: for row in row_dictionaries: + self.remove_user_from_team_for_reassignment(row) self.add_user_to_team(row) self.number_of_learners_assigned = len(row_dictionaries) return True @@ -171,20 +232,23 @@ class TeamMembershipImportManager(object): for membership in CourseTeamMembership.get_memberships(course_ids=[self.course.id]): user_id = membership.user_id teamset_id = membership.team.topic_id - self.existing_course_team_memberships[(user_id, teamset_id)] = membership.team.id + self.existing_course_team_memberships[(user_id, teamset_id)] = membership.team def load_course_teams(self): """ Caches existing course teams by (team_name, topic_id) + and existing membership counts by (topic_id, team_name) """ - for team in CourseTeam.objects.filter(course_id=self.course.id): + for team in CourseTeam.objects.filter(course_id=self.course.id).prefetch_related('users'): self.existing_course_teams[(team.name, team.topic_id)] = team + self.user_count_by_team[(team.topic_id, team.name)] = team.users.count() - def validate_header(self, header): + def validate_header(self, csv_reader): """ Validates header row to ensure that it contains at a minimum columns called 'user', 'mode'. Teamset validation is handled separately """ + header = csv_reader.fieldnames if 'user' not in header: self.validation_errors.append("Header must contain column 'user'.") return False @@ -193,16 +257,18 @@ class TeamMembershipImportManager(object): return False return True - def validate_teamsets(self): + def validate_teamsets(self, csv_reader): """ Validates team set ids. Returns true if there are no errors. The following conditions result in errors: Teamset does not exist Teamset id is duplicated """ + teamset_ids = csv_reader.fieldnames[2:] valid_teamset_ids = {ts.teamset_id for ts in self.course.teams_configuration.teamsets} + dupe_set = set() - for teamset_id in self.teamset_ids: + for teamset_id in teamset_ids: if teamset_id in dupe_set: self.validation_errors.append("Teamset with id " + teamset_id + " is duplicated.") return False @@ -212,19 +278,6 @@ class TeamMembershipImportManager(object): return False return True - def load_user_ids_by_teamset_id(self): - """ - Get users associations with each teamset in a course and - save to `self.user_ids_by_teamset_id` - """ - for teamset_id in self.teamset_ids: - self.user_ids_by_teamset_id[teamset_id] = { - membership.user_id for membership in - CourseTeamMembership.objects.filter( - team__course_id=self.course.id, team__topic_id=teamset_id - ) - } - def validate_user_enrollment_is_valid(self, user, supplied_enrollment): """ Invalid states: @@ -238,7 +291,7 @@ class TeamMembershipImportManager(object): if actual_enrollment_mode != supplied_enrollment.strip(): self.validation_errors.append('User ' + user.username + ' enrollment mismatch.') return False - + self.user_to_actual_enrollment_mode[user.id] = actual_enrollment_mode return True def is_username_unique(self, username, usernames_found_so_far): @@ -277,50 +330,173 @@ class TeamMembershipImportManager(object): """ user = row['user'] for teamset_id in self.teamset_ids: + # See if the user is already on a team in the teamset + if (user.id, teamset_id) in self.existing_course_team_memberships: + current_team_name = self.existing_course_team_memberships[(user.id, teamset_id)].name + else: + current_team_name = None + team_name = row[teamset_id] + + # We don't need to do anything if the user isn't moving to a different team + if current_team_name == team_name: + continue + + # If the user is on a team currently, remove them in from the updated count + if current_team_name is not None: + self.user_count_by_team[(teamset_id, current_team_name)] -= 1 + + # If we aren't moving them to a new team, we can go to the next team-set if not team_name: continue - try: - # checks for a team inside a specific team set. This way team names can be duplicated across - # teamsets - team = self.existing_course_teams[(team_name, teamset_id)] - if (teamset_id, team_name) not in self.user_count_by_team: - self.user_count_by_team[(teamset_id, team_name)] = team.users.count() - if (user.id, team.topic_id) in self.existing_course_team_memberships: - error_message = 'User {0} is already on a team in teamset {1}.'.format( - user.username, team.topic_id - ) - if self.add_error_and_check_if_max_exceeded(error_message): - return False - except KeyError: - all_teamset_user_ids = self.user_ids_by_teamset_id[teamset_id] - error_message = 'User {0} is already on a team in teamset {1}.'.format( - user.username, teamset_id - ) - if user.id in all_teamset_user_ids and self.add_error_and_check_if_max_exceeded(error_message): - return False - else: - self.user_ids_by_teamset_id[teamset_id].add(user.id) - if not self.validate_proposed_team_size_wont_exceed_maximum(team_name, teamset_id): + + # Check that user enrollment mode is compatible for the target team + if not self.validate_compatible_enrollment_modes(user, team_name, teamset_id): return False + + # Update proposed team counts, initializing the team count if it doesn't exist + if (teamset_id, team_name) not in self.user_count_by_team: + self.user_count_by_team[(teamset_id, team_name)] = 1 + else: + self.user_count_by_team[(teamset_id, team_name)] += 1 + return True - def validate_proposed_team_size_wont_exceed_maximum(self, team_name, teamset_id): + def validate_compatible_enrollment_modes(self, user, team_name, teamset_id): """ - Validates that the number of users we want to add to a team won't exceed maximum team size. + Validates that only students enrolled in a masters track are on a single team. Disallows mixing of masters + with other enrollment modes on a single team. + Masters track students can't be added to existing non-protected teams + """ + if(teamset_id, team_name) not in self.user_enrollment_by_team: + self.user_enrollment_by_team[teamset_id, team_name] = set() + self.user_enrollment_by_team[teamset_id, team_name].add(self.user_to_actual_enrollment_mode[user.id]) + if self.is_FERPA_bubble_breached(teamset_id, team_name): + error_message = \ + 'Team {} cannot have Master’s track users mixed with users in other tracks.'.format(team_name) + self.add_error_and_check_if_max_exceeded(error_message) + return False + if not self.is_enrollment_protection_for_existing_team_matches_user(user, team_name, teamset_id): + error_message = \ + 'User {} does not have access to team {}.'.format(user.username, team_name) + self.add_error_and_check_if_max_exceeded(error_message) + return False + return True + + def is_enrollment_protection_for_existing_team_matches_user(self, user, team_name, teamset_id): + """ + Applies only to existing teams. + Returns True if no violations + False if there is a mismatch + """ + try: + team = self.existing_course_teams[(team_name, teamset_id)] + return user_protection_status_matches_team(user, team) + except KeyError: + return True + + def is_FERPA_bubble_breached(self, teamset_id, team_name): + """ + Ensures that FERPA bubble is not breached. + Checks that we are not trying to violate FERPA proctection by mixing masters + track students with other enrollment tracks. """ - if self.course.teams_configuration.teamsets_by_id[teamset_id].max_team_size is None: - max_team_size = self.course.teams_configuration.default_max_team_size + + team_enrollment_modes = self.user_enrollment_by_team[teamset_id, team_name] + protected_modes = set(ORGANIZATION_PROTECTED_MODES) + + if team_enrollment_modes.isdisjoint(protected_modes): + return False + elif team_enrollment_modes.issubset(protected_modes): + return False else: - max_team_size = self.course.teams_configuration.teamsets_by_id[teamset_id].max_team_size + return True + + def validate_team_sizes_not_exceeded(self): + """ + Validates that the number of users we want to add to a team won't exceed maximum team size. + """ + for teamset_id in self.teamset_ids: + # Get max size for team-set + if self.course.teams_configuration.teamsets_by_id[teamset_id].max_team_size is None: + max_team_size = self.course.teams_configuration.default_max_team_size + else: + max_team_size = self.course.teams_configuration.teamsets_by_id[teamset_id].max_team_size + + # Get teams in team-set + team_names = [ + teamset_to_team[1] for teamset_to_team in self.user_count_by_team + if teamset_to_team[0] == teamset_id + ] + + # Calculate proposed team size and return False if it exceeds capacity + for team_name in team_names: + key = (teamset_id, team_name) + if self.user_count_by_team[key] > max_team_size: + self.add_error_and_check_if_max_exceeded( + 'New membership for team {} would exceed max size of {}.'.format( + team_name, max_team_size + ) + ) + return False - if max_team_size is not None: - if self.user_count_by_team[(teamset_id, team_name)] + 1 > max_team_size: - self.add_error_and_check_if_max_exceeded('Team ' + team_name + ' is full.') - return False - self.user_count_by_team[(teamset_id, team_name)] += 1 return True + def remove_user_from_team_for_reassignment(self, row): + """ + Remove a user from a team if: + a. The user's current team is different from the team specified in csv for the same teamset (this user will + then be assigned to a new team in 'add_user_to_team`. + b. The team value in the CSV is blank - the user should be removed from the current team in teamset. + Also, if there is no change in user's membership, the input row's team name will be nulled out so that no + action will take place further in the processing chain. + """ + for ts_id in self.teamset_ids: + if row[ts_id] is None: + # remove this student from the teamset + try: + self._remove_user_from_teamset_and_emit_signal(row['user'].id, ts_id, self.course.id) + except CourseTeamMembership.DoesNotExist: + pass + else: + # reassignment happens only if proposed team membership is different from existing team membership + if (row['user'].id, ts_id) in self.existing_course_team_memberships: + current_user_teams_name = self.existing_course_team_memberships[row['user'].id, ts_id].name + if current_user_teams_name != row[ts_id]: + try: + self._remove_user_from_teamset_and_emit_signal(row['user'].id, ts_id, self.course.id) + del self.existing_course_team_memberships[row['user'].id, ts_id] + except CourseTeamMembership.DoesNotExist: + pass + else: + # the user will remain in the same team. In order to avoid validation/attempting + # to readd the user, null out the team name + row[ts_id] = None + + def _remove_user_from_teamset_and_emit_signal(self, user_id, ts_id, course_id): + """ + If a team membership exists for the specified user, in the specified course and teamset, delete it. + This removes the user from the team. + Then, emit an event. + + If the membership doesn't exist, don't emit the event and instead raise CourseTeamMembership.DoesNotExist + """ + membership = CourseTeamMembership.objects.select_related('team').get( + user_id=user_id, + team__topic_id=ts_id, + team__course_id=course_id + ) + membership.delete() + emit_team_event( + 'edx.team.learner_removed', + course_id, + { + 'team_id': membership.team.team_id, + 'user_id': membership.user_id, + 'remove_method': 'team_csv_import' + } + ) + def add_error_and_check_if_max_exceeded(self, error_message): """ Adds an error to the error collection. @@ -379,6 +555,11 @@ class TeamMembershipImportManager(object): try: return User.objects.get(email=user_name) except User.DoesNotExist: - self.validation_errors.append('User ' + user_name + ' does not exist.') - return None - # TODO - handle user key case + try: + user = ProgramEnrollment.objects.get(external_user_key=user_name).user + if user is None: + return None + return user + except ProgramEnrollment.DoesNotExist: + self.validation_errors.append('User name/email/external key: ' + user_name + ' does not exist.') + return None diff --git a/lms/djangoapps/teams/serializers.py b/lms/djangoapps/teams/serializers.py index c79c4d2fb6b37f5b40961b460834028a0705670f..37d1f40f6b5553839bb7b0aee70f1a7fea6062bb 100644 --- a/lms/djangoapps/teams/serializers.py +++ b/lms/djangoapps/teams/serializers.py @@ -11,7 +11,7 @@ from django.contrib.auth.models import User from django_countries import countries from rest_framework import serializers -from lms.djangoapps.teams.api import add_team_count, get_team_count_query_set +from lms.djangoapps.teams.api import add_team_count, get_teams_accessible_by_user from lms.djangoapps.teams.models import CourseTeam, CourseTeamMembership from openedx.core.djangoapps.user_api.accounts.serializers import UserReadOnlySerializer from openedx.core.lib.api.fields import ExpandableField @@ -194,7 +194,8 @@ class TopicSerializer(BaseTopicSerializer): # pylint: disable=abstract-method if 'team_count' in topic: return topic['team_count'] else: - return get_team_count_query_set( + return get_teams_accessible_by_user( + self.context.get('user'), [topic['id']], self.context['course_id'], self.context.get('organization_protection_status') @@ -209,7 +210,12 @@ class BulkTeamCountTopicListSerializer(serializers.ListSerializer): # pylint: d def to_representation(self, obj): # pylint: disable=arguments-differ """Adds team_count to each topic. """ data = super(BulkTeamCountTopicListSerializer, self).to_representation(obj) - add_team_count(data, self.context['course_id'], self.context.get('organization_protection_status')) + add_team_count( + self.context['request'].user, + data, + self.context['course_id'], + self.context.get('organization_protection_status') + ) return data diff --git a/lms/djangoapps/teams/static/teams/js/.eslintrc.json b/lms/djangoapps/teams/static/teams/js/.eslintrc.json new file mode 100644 index 0000000000000000000000000000000000000000..0ab11857aea07a6e3844ef83abfbc02745160008 --- /dev/null +++ b/lms/djangoapps/teams/static/teams/js/.eslintrc.json @@ -0,0 +1,7 @@ +{ + "rules": { + "comma-dangle": "off", + "object-curly-spacing": "off", + "no-underscore-dangle": "off" + } +} diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js index 8d8ce68a65bae9380ded0f2272bd22751d9c352c..2d3a3d826b046a9bf48e10424bb740fade481c5b 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js @@ -48,7 +48,7 @@ define([ el: $('.profile-view'), teamEvents: TeamSpecHelpers.teamEvents, courseID: TeamSpecHelpers.testCourseID, - context: TeamSpecHelpers.testContext, + context: options.context || TeamSpecHelpers.testContext, model: teamModel, topic: isInstructorManagedTopic ? TeamSpecHelpers.createMockInstructorManagedTopic() : @@ -72,6 +72,23 @@ define([ ) ); AjaxHelpers.respondWithJson(requests, TeamSpecHelpers.createMockDiscussionResponse()); + + // Assignments are feature-flagged + if (profileView.context.teamsAssignmentsUrl) { + AjaxHelpers.expectRequest( + requests, + 'GET', + interpolate( // eslint-disable-line no-undef + '/api/team/v0/teams/%(teamId)s/assignments', + { + teamId: teamModel.id + }, + true + ) + ); + AjaxHelpers.respondWithJson(requests, TeamSpecHelpers.createMockTeamAssignments(options.assignments)); + } + return profileView; }; @@ -101,6 +118,76 @@ define([ } }; + describe('TeamAssignmentsView', function() { + it('can render itself', function() { + // Given a member of a team with team assignments + var mockAssignments = TeamSpecHelpers.createMockTeamAssignments(), + options = { + membership: DEFAULT_MEMBERSHIP + }, + requests = AjaxHelpers.requests(this); + + // When they go to the team profile view + var view = createTeamProfileView(requests, options); + + // The Assignments section renders with their assignments + expect(view.$('.team-assignment').length).toEqual(mockAssignments.length); + }); + + it('displays a message when no assignments are found', function() { + // Given a member viewing a team with no assignments + var mockAssignments = [], + options = { + assignments: mockAssignments, + membership: DEFAULT_MEMBERSHIP + }, + requests = AjaxHelpers.requests(this); + + // When they view the team + var view = createTeamProfileView(requests, options); + + // There should be filler text that says there are no assignments + expect(view.$('#assignments').text()).toEqual('No assignments for team'); + expect(view.$('.team-assignment').length).toEqual(0); + }); + + it('does not show at all for someone who is not on the team or staff', function() { + // Given a user who is not on a team viewing a team with assignments + var mockAssignments = TeamSpecHelpers.createMockTeamAssignments(), + options = { + assignments: mockAssignments + }, + requests = AjaxHelpers.requests(this); + + // When the user goes to the team detail page + var view = createTeamProfileView(requests, options); + + // Then then assignments view does not appear on the page + expect(view.$('.team-assignments').length).toBe(0); + }); + + it('does not show at all when the feature flag is turned off', function() { + // Given the team submissions feature is turned off + // (teamAsssignmentsUrl isn't surfaced to user) + var mockAssignments = TeamSpecHelpers.createMockTeamAssignments(), + options = { + assignments: mockAssignments, + membership: DEFAULT_MEMBERSHIP, + context: Object.assign({}, TeamSpecHelpers.testContext) + }, + requests = AjaxHelpers.requests(this), + view; + + delete options.context.teamsAssignmentsUrl; + + // When the user goes to the team detail page + view = createTeamProfileView(requests, options); + + // Then then assignments view does not appear on the page + expect(view.$('.team-assignments').length).toBe(0); + }); + }); + describe('DiscussionsView', function() { it('can render itself', function() { var requests = AjaxHelpers.requests(this), @@ -124,6 +211,16 @@ define([ clickLeaveTeam(requests, view, {cancel: false}); expect(view.$('.new-post-btn.is-hidden').length).toEqual(0); }); + + it('shows New Post button when user is a staff member or admin', function() { + var requests = AjaxHelpers.requests(this), + view = createTeamProfileView( + requests, {userInfo: TeamSpecHelpers.createMockUserInfo({staff: true})} + ); + + view.render(); + expect(view.$('.btn-link.new-post-btn.is-hidden').length).toEqual(0); + }); }); describe('TeamDetailsView', function() { diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/teams_tab_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/teams_tab_spec.js index 8866c2ef55eb06817ea39b2b313ae7f060b0a576..de4d13b8ac0c438002854bf8e8acb04207ea455f 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/teams_tab_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/teams_tab_spec.js @@ -38,14 +38,14 @@ define([ )); }; - var createTeamsTabView = function(test, options) { + var createTeamsTabView = function(options) { var teamsTabView = new TeamsTabView( { el: $('.teams-content'), context: TeamSpecHelpers.createMockContext(options) } ); - requests = AjaxHelpers.requests(test); + requests = AjaxHelpers.requests(); PageHelpers.preventBackboneChangingUrl(); teamsTabView.start(); return teamsTabView; @@ -65,7 +65,7 @@ define([ describe('Navigation', function() { it('does not render breadcrumbs for the top level tabs', function() { - var teamsTabView = createTeamsTabView(this); + var teamsTabView = createTeamsTabView(); teamsTabView.router.navigate('#my-teams', {trigger: true}); expect(teamsTabView.$('.breadcrumbs').length).toBe(0); teamsTabView.router.navigate('#browse', {trigger: true}); @@ -73,20 +73,20 @@ define([ }); it('does not interfere with anchor links to #main', function() { - var teamsTabView = createTeamsTabView(this); + var teamsTabView = createTeamsTabView(); teamsTabView.router.navigate('#main', {trigger: true}); expect(teamsTabView.$('.wrapper-msg')).toHaveClass('is-hidden'); }); it('displays and focuses an error message when trying to navigate to a nonexistent page', function() { - var teamsTabView = createTeamsTabView(this); + var teamsTabView = createTeamsTabView(); teamsTabView.router.navigate('no_such_page', {trigger: true}); expectError(teamsTabView, 'The page "no_such_page" could not be found.'); expectFocus(teamsTabView.$('.warning')); }); it('displays and focuses an error message when trying to navigate to a nonexistent topic', function() { - var teamsTabView = createTeamsTabView(this); + var teamsTabView = createTeamsTabView(); teamsTabView.router.navigate('topics/no_such_topic', {trigger: true}); AjaxHelpers.expectRequest(requests, 'GET', '/api/team/v0/topics/no_such_topic,course/1', null); AjaxHelpers.respondWithError(requests, 404); @@ -95,7 +95,7 @@ define([ }); it('displays and focuses an error message when trying to navigate to a nonexistent team', function() { - var teamsTabView = createTeamsTabView(this); + var teamsTabView = createTeamsTabView(); teamsTabView.router.navigate('teams/' + TeamSpecHelpers.testTopicID + '/no_such_team', {trigger: true}); AjaxHelpers.expectRequest(requests, 'GET', '/api/team/v0/teams/no_such_team?expand=user', null); AjaxHelpers.respondWithError(requests, 404); @@ -104,7 +104,7 @@ define([ }); it('displays and focuses an error message when it receives a 401 AJAX response', function() { - var teamsTabView = createTeamsTabView(this).render(); + var teamsTabView = createTeamsTabView().render(); teamsTabView.router.navigate('topics/' + TeamSpecHelpers.testTopicID, {trigger: true}); AjaxHelpers.respondWithError(requests, 401); expectError(teamsTabView, 'Your request could not be completed. Reload the page and try again.'); @@ -112,7 +112,7 @@ define([ }); it('displays and focuses an error message when it receives a 500 AJAX response', function() { - var teamsTabView = createTeamsTabView(this).render(); + var teamsTabView = createTeamsTabView().render(); teamsTabView.router.navigate('topics/' + TeamSpecHelpers.testTopicID, {trigger: true}); AjaxHelpers.respondWithError(requests, 500); expectError( @@ -124,7 +124,7 @@ define([ }); it('does not navigate to the topics page when syncing its collection if not on search page', function() { - var teamsTabView = createTeamsTabView(this), + var teamsTabView = createTeamsTabView(), collection = TeamSpecHelpers.createMockTeams(); teamsTabView.createTeamsListView({ collection: collection, @@ -179,7 +179,7 @@ define([ } ] }, function(url, expectedEvent) { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ userInfo: TeamSpecHelpers.createMockUserInfo({staff: true}) }); teamsTabView.teamsCollection = TeamSpecHelpers.createMockTeams(); @@ -193,7 +193,7 @@ define([ describe('Discussion privileges', function() { it('allows privileged access to any team', function() { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true}) }); // Note: using `undefined` here to ensure that we @@ -203,7 +203,7 @@ define([ }); it('allows access to a team which an unprivileged user is a member of', function() { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ userInfo: TeamSpecHelpers.createMockUserInfo({ username: TeamSpecHelpers.testUser, privileged: false @@ -221,7 +221,7 @@ define([ }); it('does not allow access if the user is neither privileged nor a team member', function() { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ userInfo: TeamSpecHelpers.createMockUserInfo({privileged: false, staff: true}) }); expect(teamsTabView.readOnlyDiscussion({ @@ -233,7 +233,7 @@ define([ describe('Manage Tab', function() { var manageTabSelector = '.page-content-nav>.nav-item[data-url=manage]'; it('is not visible to unprivileged users', function() { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ userInfo: TeamSpecHelpers.createMockUserInfo({privileged: false}), hasManagedTopic: true }); @@ -241,7 +241,7 @@ define([ }); it('is not visible when there are no managed topics', function() { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true}), hasManagedTopic: false }); @@ -249,7 +249,7 @@ define([ }); it('is visible to privileged users when there is a managed topic', function() { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true}), hasManagedTopic: true }); @@ -260,7 +260,7 @@ define([ describe('Browse Tab', function() { var browseTabSelector = '.page-content-nav>.nav-item[data-url=browse]'; it('is not visible if there are no open and no public teamsets', function() { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ hasOpenTopic: false, hasPublicManagedTopic: false }); @@ -268,7 +268,7 @@ define([ }); it('is visible if there are open teamsets', function() { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ hasOpenTopic: true, hasPublicManagedTopic: false }); @@ -276,7 +276,7 @@ define([ }); it('is visible if there are public teamsets', function() { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ hasOpenTopic: false, hasPublicManagedTopic: true }); @@ -284,7 +284,7 @@ define([ }); it('is visible if there are both public and open teamsets', function() { - var teamsTabView = createTeamsTabView(this, { + var teamsTabView = createTeamsTabView({ hasOpenTopic: true, hasPublicManagedTopic: true }); @@ -293,39 +293,46 @@ define([ }); describe('Search', function() { - var performSearch = function(reqs, teamsTabView) { + var teamsTabView; + + var performSearch = function() { teamsTabView.$('.search-field').val('foo'); teamsTabView.$('.action-search').click(); verifyTeamsRequest({ order_by: '', text_search: 'foo' }); - AjaxHelpers.respondWithJson(reqs, TeamSpecHelpers.createMockTeamsResponse({results: []})); - - // Expect exactly one search request to be fired - AjaxHelpers.expectNoRequests(reqs); + AjaxHelpers.respondWithJson( + requests, + TeamSpecHelpers.createMockTeamsResponse({ results: [] } + )); + AjaxHelpers.respondWithJson(requests, { count: 0 }); + + // Expect exactly one search request to be fired, and one request to see if the user is + // in a team in the current teamset + AjaxHelpers.expectNoRequests(requests); }; - it('can search teams', function() { - var teamsTabView = createTeamsTabView(this); + beforeEach(function() { + teamsTabView = createTeamsTabView(); teamsTabView.browseTopic(TeamSpecHelpers.testTopicID); verifyTeamsRequest({ order_by: 'last_activity_at', text_search: '' }); AjaxHelpers.respondWithJson(requests, {}); - performSearch(requests, teamsTabView); + AjaxHelpers.respondWithJson(requests, { count: 0 }); + }); + + it('can search teams', function() { + performSearch(); expect(teamsTabView.$('.page-title').text()).toBe('Team Search'); expect(teamsTabView.$('.page-description').text()).toBe('Showing results for "foo"'); }); it('can clear a search', function() { - var teamsTabView = createTeamsTabView(this); - teamsTabView.browseTopic(TeamSpecHelpers.testTopicID); - AjaxHelpers.respondWithJson(requests, {}); - // Perform a search - performSearch(requests, teamsTabView); + performSearch(); // Clear the search and submit it again teamsTabView.$('.search-field').val(''); @@ -335,17 +342,14 @@ define([ order_by: 'last_activity_at' }); AjaxHelpers.respondWithJson(requests, {}); + AjaxHelpers.respondWithJson(requests, { count: 0 }); expect(teamsTabView.$('.page-title').text()).toBe('Test Topic 1'); expect(teamsTabView.$('.page-description').text()).toBe('Test description 1'); }); it('can navigate back to all teams from a search', function() { - var teamsTabView = createTeamsTabView(this); - teamsTabView.browseTopic(TeamSpecHelpers.testTopicID); - AjaxHelpers.respondWithJson(requests, {}); - // Perform a search - performSearch(requests, teamsTabView); + performSearch(); // Verify the breadcrumbs have a link back to the teams list, and click on it expect(teamsTabView.$('.breadcrumbs a').length).toBe(2); @@ -355,15 +359,12 @@ define([ text_search: '' }); AjaxHelpers.respondWithJson(requests, {}); + AjaxHelpers.respondWithJson(requests, { count: 0 }); expect(teamsTabView.$('.page-title').text()).toBe('Test Topic 1'); expect(teamsTabView.$('.page-description').text()).toBe('Test description 1'); }); it('does not switch to showing results when the search returns an error', function() { - var teamsTabView = createTeamsTabView(this); - teamsTabView.browseTopic(TeamSpecHelpers.testTopicID); - AjaxHelpers.respondWithJson(requests, {}); - // Perform a search but respond with a 500 teamsTabView.$('.search-field').val('foo'); teamsTabView.$('.action-search').click(); diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/topic_teams_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/topic_teams_spec.js index 13b385677a57d5ced2706466448dee0525f2b588..50484220127bd8bec357e2c66bc6ec9977fa7483 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/topic_teams_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/topic_teams_spec.js @@ -2,37 +2,69 @@ define([ 'backbone', 'underscore', 'teams/js/views/topic_teams', + 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'teams/js/spec_helpers/team_spec_helpers', 'common/js/spec_helpers/page_helpers' -], function(Backbone, _, TopicTeamsView, TeamSpecHelpers, PageHelpers) { +], function(Backbone, _, TopicTeamsView, AjaxHelpers, TeamSpecHelpers, PageHelpers) { 'use strict'; describe('Topic Teams View', function() { - var createTopicTeamsView = function(options, isInstructorManagedTopic) { - var myTeamsCollection; - options = options || {}; // eslint-disable-line no-param-reassign - myTeamsCollection = options.myTeamsCollection || TeamSpecHelpers.createMockTeams({results: []}); - return new TopicTeamsView({ + var requests, teamsView; + + var verifyTeamsetTeamsRequest = function(hasTeams) { + AjaxHelpers.expectRequestURL( + requests, + TeamSpecHelpers.testContext.teamMembershipsUrl, + { + username: TeamSpecHelpers.testUser, + course_id: TeamSpecHelpers.testCourseID, + teamset_id: TeamSpecHelpers.testTopicID, + } + ); + AjaxHelpers.respondWithJson( + requests, + { count: hasTeams ? 1 : 0 } + ); + AjaxHelpers.expectNoRequests(requests); + }; + + var createTopicTeamsView = function(_options) { + var options = _options || {}; + var onTeamInTeamset = options.onTeamInTeamset || false, + isInstructorManagedTopic = options.isInstructorManagedTopic || false; + + var result, topicTeamsView; + + requests = AjaxHelpers.requests(this); + topicTeamsView = new TopicTeamsView({ el: '.teams-container', model: isInstructorManagedTopic ? TeamSpecHelpers.createMockInstructorManagedTopic() : TeamSpecHelpers.createMockTopic(), - collection: options.teams || TeamSpecHelpers.createMockTeams(), - myTeamsCollection: myTeamsCollection, - showActions: true, + collection: options.teams || TeamSpecHelpers.createMockTeams({results: []}), context: _.extend({}, TeamSpecHelpers.testContext, options) - }).render(); + }); + result = topicTeamsView.render(); + + if ( + topicTeamsView.context.userInfo.staff || + topicTeamsView.context.userInfo.privileged || + isInstructorManagedTopic + ) { + AjaxHelpers.expectNoRequests(requests); + } else { + verifyTeamsetTeamsRequest(onTeamInTeamset); + } + return result; }; - var verifyActions = function(teamsView, options) { + var verifyActions = function(showActions) { var expectedTitle = 'Are you having trouble finding a team to join?', expectedMessage = 'Browse teams in other topics or search teams in this topic. ' + 'If you still can\'t find a team to join, create a new team in this topic.', title = teamsView.$('.title').text().trim(), - message = teamsView.$('.copy').text().trim(); - if (!options) { - options = {showActions: true}; // eslint-disable-line no-param-reassign - } + message = teamsView.$('.copy').text().trim(), + _showActions = showActions === undefined ? true : showActions; - if (options.showActions) { + if (_showActions) { expect(title).toBe(expectedTitle); expect(message).toBe(expectedMessage); } else { @@ -47,37 +79,41 @@ define([ }); it('can render itself', function() { - var testTeamData = TeamSpecHelpers.createMockTeamData(1, 5), - teamsView = createTopicTeamsView({ - teams: TeamSpecHelpers.createMockTeams({ - results: testTeamData - }) - }); - var footerEl = teamsView.$('.teams-paging-footer'); + var testTeamData = TeamSpecHelpers.createMockTeamData(1, 5); + var options = { + teams: TeamSpecHelpers.createMockTeams({ + results: testTeamData + }) + }; + var footerEl; + + teamsView = createTopicTeamsView(options); + footerEl = teamsView.$('.teams-paging-footer'); + expect(teamsView.$('.teams-paging-header').text()).toMatch('Showing 1-5 out of 6 total'); expect(footerEl.text()).toMatch('1\\s+out of\\s+\/\\s+2'); // eslint-disable-line no-useless-escape expect(footerEl).not.toHaveClass('hidden'); TeamSpecHelpers.verifyCards(teamsView, testTeamData); - verifyActions(teamsView); + verifyActions(); }); it('can browse all teams', function() { - var teamsView = createTopicTeamsView(); + teamsView = createTopicTeamsView(); spyOn(Backbone.history, 'navigate'); teamsView.$('.browse-teams').click(); expect(Backbone.history.navigate.calls.mostRecent().args[0]).toBe('browse'); }); it('gives the search field focus when clicking on the search teams link', function() { - var teamsView = createTopicTeamsView(); + teamsView = createTopicTeamsView(); spyOn($.fn, 'focus').and.callThrough(); teamsView.$('.search-teams').click(); expect(teamsView.$('.search-field').first().focus).toHaveBeenCalled(); }); it('can show the create team modal', function() { - var teamsView = createTopicTeamsView(); + teamsView = createTopicTeamsView(); spyOn(Backbone.history, 'navigate'); teamsView.$('a.create-team').click(); expect(Backbone.history.navigate.calls.mostRecent().args[0]).toBe( @@ -85,15 +121,14 @@ define([ ); }); - it('does not show actions for a user already in a team', function() { - var options = {myTeamsCollection: TeamSpecHelpers.createMockTeams()}; - var teamsView = createTopicTeamsView(options); - verifyActions(teamsView, {showActions: false}); + it('does not show actions for a user already in a team in the teamset', function() { + teamsView = createTopicTeamsView({ onTeamInTeamset: true }); + verifyActions(false); }); it('does not show actions for a student in an instructor managed topic', function() { - var teamsView = createTopicTeamsView({}, true); - verifyActions(teamsView, {showActions: false}); + teamsView = createTopicTeamsView({ isInstructorManagedTopic: true }); + verifyActions(false); }); it('shows actions for a privileged user already in a team', function() { @@ -102,10 +137,10 @@ define([ privileged: true, staff: false }, - myTeamsCollection: TeamSpecHelpers.createMockTeams() + onTeamInTeamset: true, }; - var teamsView = createTopicTeamsView(options); - verifyActions(teamsView, {showActions: true}); + teamsView = createTopicTeamsView(options); + verifyActions(); }); it('shows actions for a staff user already in a team', function() { @@ -114,10 +149,10 @@ define([ privileged: false, staff: true }, - myTeamsCollection: TeamSpecHelpers.createMockTeams() + onTeamInTeamset: true, }; - var teamsView = createTopicTeamsView(options); - verifyActions(teamsView, {showActions: true}); + teamsView = createTopicTeamsView(options); + verifyActions(); }); /* @@ -126,7 +161,7 @@ define([ var requests = AjaxHelpers.requests(this), teamMemberships = TeamSpecHelpers.createMockTeamMemberships([]), teamsView = createTopicTeamsView({ teamMemberships: teamMemberships }); - verifyActions(teamsView, {showActions: true}); + verifyActions({showActions: true}); teamMemberships.teamEvents.trigger('teams:update', { action: 'create' }); teamsView.render(); AjaxHelpers.expectRequestURL( @@ -141,7 +176,7 @@ define([ } ); AjaxHelpers.respondWithJson(requests, {}); - verifyActions(teamsView, {showActions: false}); + verifyActions({showActions: false}); }); */ }); diff --git a/lms/djangoapps/teams/static/teams/js/spec_helpers/team_spec_helpers.js b/lms/djangoapps/teams/static/teams/js/spec_helpers/team_spec_helpers.js index 2ecd83a27abcaa3c809e1861553ae379c6a1429f..65914993f94819b8266632e86abb5ac4f38a730c 100644 --- a/lms/djangoapps/teams/static/teams/js/spec_helpers/team_spec_helpers.js +++ b/lms/djangoapps/teams/static/teams/js/spec_helpers/team_spec_helpers.js @@ -73,6 +73,18 @@ define([ ); }; + var createMockTeamAssignments = function(assignments, options) { + if (_.isUndefined(assignments)) { + assignments = [ // eslint-disable-line no-param-reassign + { + display_name: 'Send me', + location: 'your location' + } + ]; + } + return _.extend(assignments, options); + }; + var createMockTeamMembershipsData = function(startIndex, stopIndex) { var teams = createMockTeamData(startIndex, stopIndex); return _.map(_.range(startIndex, stopIndex + 1), function(i) { @@ -282,6 +294,7 @@ define([ countries: testCountries, topicUrl: '/api/team/v0/topics/topic_id,' + testCourseID, teamsUrl: '/api/team/v0/teams/', + teamsAssignmentsUrl: '/api/team/v0/teams/team_id/assignments', teamsDetailUrl: '/api/team/v0/teams/team_id', teamMembershipsUrl: '/api/team/v0/team_memberships/', teamMembershipDetailUrl: '/api/team/v0/team_membership/team_id,' + testUser, @@ -327,6 +340,7 @@ define([ createMockTeamData: createMockTeamData, createMockTeamsResponse: createMockTeamsResponse, createMockTeams: createMockTeams, + createMockTeamAssignments: createMockTeamAssignments, createMockUserInfo: createMockUserInfo, createMockContext: createMockContext, createMockTopic: createMockTopic, diff --git a/lms/djangoapps/teams/static/teams/js/views/edit_team_members.js b/lms/djangoapps/teams/static/teams/js/views/edit_team_members.js index 425d82e4773ca6adcc2c261443c2b3c9af992b3d..16aadbde49e4a80396899e0fccb0a7dc38fc58f2 100644 --- a/lms/djangoapps/teams/static/teams/js/views/edit_team_members.js +++ b/lms/djangoapps/teams/static/teams/js/views/edit_team_members.js @@ -52,7 +52,7 @@ _.each(this.model.get('membership'), function(membership) { // eslint-disable-next-line no-undef - dateJoined = interpolate( // xss-lint: disable=javascript-interpolate + dateJoined = interpolate( /* Translators: 'date' is a placeholder for a fuzzy, * relative timestamp (see: https://github.com/rmm5t/jquery-timeago) */ @@ -62,7 +62,7 @@ ); // eslint-disable-next-line no-undef - lastActivity = interpolate( // xss-lint: disable=javascript-interpolate + lastActivity = interpolate( /* Translators: 'date' is a placeholder for a fuzzy, * relative timestamp (see: https://github.com/rmm5t/jquery-timeago) */ diff --git a/lms/djangoapps/teams/static/teams/js/views/manage.js b/lms/djangoapps/teams/static/teams/js/views/manage.js index 6c3903217beba407cf94fe722f901a2adfe4fa3d..d742bc5513a35e2f4edf987f874e8d830f3e0e52 100644 --- a/lms/djangoapps/teams/static/teams/js/views/manage.js +++ b/lms/djangoapps/teams/static/teams/js/views/manage.js @@ -33,6 +33,7 @@ this.$el, HtmlUtils.template(manageTemplate)({}) ); + this.delegateEvents(this.events); return this; }, diff --git a/lms/djangoapps/teams/static/teams/js/views/team_profile.js b/lms/djangoapps/teams/static/teams/js/views/team_profile.js index dd5c794fb59d2093c94007539f91df14ff4dfdf0..30909ee7fac09c690021de76f32705a4f50c42fe 100644 --- a/lms/djangoapps/teams/static/teams/js/views/team_profile.js +++ b/lms/djangoapps/teams/static/teams/js/views/team_profile.js @@ -12,10 +12,11 @@ 'common/js/components/utils/view_utils', 'teams/js/views/team_utils', 'text!teams/templates/team-profile.underscore', - 'text!teams/templates/team-member.underscore' + 'text!teams/templates/team-member.underscore', + 'text!teams/templates/team-assignment.underscore' ], function(Backbone, _, gettext, HtmlUtils, TeamDiscussionView, ViewUtils, TeamUtils, - teamTemplate, teamMemberTemplate) { + teamTemplate, teamMemberTemplate, teamAssignmentTemplate) { var TeamProfileView = Backbone.View.extend({ errorMessage: gettext('An error occurred. Try again.'), @@ -44,6 +45,10 @@ isInstructorManagedTopic = TeamUtils.isInstructorManagedTopic(this.topic.attributes.type), maxTeamSize = this.topic.getMaxTeamSize(this.context.courseMaxTeamSize); + // Assignments URL isn't provided if team assignments shouldn't be shown + // so we can treat it like a toggle + var showAssignments = !!this.context.teamsAssignmentsUrl; + var showLeaveLink = isMember && (isAdminOrStaff || !isInstructorManagedTopic); HtmlUtils.setHtml( @@ -56,23 +61,61 @@ language: this.languages[this.model.get('language')], membershipText: TeamUtils.teamCapacityText(memberships.length, maxTeamSize), isMember: isMember, + isAdminOrStaff: isAdminOrStaff, showLeaveLink: showLeaveLink, + showAssignments: showAssignments, hasCapacity: maxTeamSize && (memberships.length < maxTeamSize), hasMembers: memberships.length >= 1 }) ); this.discussionView = new TeamDiscussionView({ el: this.$('.discussion-module'), - readOnly: !isMember + readOnly: (!isMember && !isAdminOrStaff) }); this.discussionView.render(); + if (showAssignments) { + this.getTeamAssignments(); + } + this.renderTeamMembers(); this.setFocusToHeaderFunc(); return this; }, + getTeamAssignments: function() { + var view = this; + + $.ajax({ + type: 'GET', + url: view.context.teamsAssignmentsUrl.replace('team_id', view.model.get('id')) + }).done(function(data) { + view.renderTeamAssignments(data); + }).fail(function(data) { + TeamUtils.parseAndShowMessage(data, view.errorMessage); + }); + }, + + renderTeamAssignments: function(assignments) { + var view = this; + + if (!assignments || !assignments.length) { + view.$('#assignments').text(gettext('No assignments for team')); + return; + } + + _.each(assignments, function(assignment) { + HtmlUtils.append( + view.$('#assignments'), + HtmlUtils.template(teamAssignmentTemplate)({ + displayName: assignment.display_name, + linkLocation: assignment.location + }) + ); + }); + }, + renderTeamMembers: function() { var view = this; _.each(this.model.get('membership'), function(membership) { diff --git a/lms/djangoapps/teams/static/teams/js/views/teams_tab.js b/lms/djangoapps/teams/static/teams/js/views/teams_tab.js index a199c976f01299754e2a641d1abb24059e292b54..6f1a08952e16fbe0055396735606384a2abb377b 100644 --- a/lms/djangoapps/teams/static/teams/js/views/teams_tab.js +++ b/lms/djangoapps/teams/static/teams/js/views/teams_tab.js @@ -385,7 +385,6 @@ context: this.context, model: topic, collection: collection, - myTeamsCollection: this.myTeamsCollection, showSortControls: options.showSortControls }), searchFieldView = new SearchFieldView({ diff --git a/lms/djangoapps/teams/static/teams/js/views/topic_teams.js b/lms/djangoapps/teams/static/teams/js/views/topic_teams.js index b512c17a6675be02d8cc04f225e38ee934dcf2fe..f49d772918e5a5f128dc035a05993a5967a35b2f 100644 --- a/lms/djangoapps/teams/static/teams/js/views/topic_teams.js +++ b/lms/djangoapps/teams/static/teams/js/views/topic_teams.js @@ -1,6 +1,7 @@ (function(define) { 'use strict'; define([ + 'jquery', 'underscore', 'backbone', 'gettext', @@ -9,7 +10,34 @@ 'common/js/components/views/paging_header', 'text!teams/templates/team-actions.underscore', 'teams/js/views/team_utils' - ], function(_, Backbone, gettext, HtmlUtils, TeamsView, PagingHeader, teamActionsTemplate, TeamUtils) { + ], function($, _, Backbone, gettext, HtmlUtils, TeamsView, PagingHeader, teamActionsTemplate, TeamUtils) { + // Translators: this string is shown at the bottom of the teams page + // to find a team to join or else to create a new one. There are three + // links that need to be included in the message: + // 1. Browse teams in other topics + // 2. search teams + // 3. create a new team + // Be careful to start each link with the appropriate start indicator + // (e.g. {browse_span_start} for #1) and finish it with {span_end}. + var actionMessage = interpolate_text( // eslint-disable-line no-undef + _.escape(gettext( + '{browse_span_start}Browse teams in other ' + + 'topics{span_end} or {search_span_start}search teams{span_end} ' + + 'in this topic. If you still can\'t find a team to join, ' + + '{create_span_start}create a new team in this topic{span_end}.' + )), + { + browse_span_start: '<a class="browse-teams" href="">', + search_span_start: '<a class="search-teams" href="">', + create_span_start: '<a class="create-team" href="">', + span_end: '</a>' + } + ); + + var canUserCreateTeamErrorMessage = gettext( + 'An error occurred while looking up team membership. Try refreshing the page.' + ); + var TopicTeamsView = TeamsView.extend({ events: { 'click a.browse-teams': 'browseTeams', @@ -21,55 +49,51 @@ this.options = _.extend({}, options); this.showSortControls = options.showSortControls; this.context = options.context; - this.myTeamsCollection = options.myTeamsCollection; TeamsView.prototype.initialize.call(this, options); }, - canUserCreateTeam: function() { - // Note: non-staff and non-privileged users are automatically added to any team - // that they create. This means that if multiple team membership is - // disabled that they cannot create a new team when they already - // belong to one. - return this.context.userInfo.staff - || this.context.userInfo.privileged - || (!TeamUtils.isInstructorManagedTopic(this.model.attributes.type) - && this.myTeamsCollection.length === 0); + checkIfUserCanCreateTeam: function() { + var deferred = $.Deferred(); + if (this.context.userInfo.staff || this.context.userInfo.privileged) { + deferred.resolve(true); + } else if (TeamUtils.isInstructorManagedTopic(this.model.attributes.type)) { + deferred.resolve(false); + } else { + $.ajax({ + type: 'GET', + url: this.context.teamMembershipsUrl, + data: { + username: this.context.userInfo.username, + course_id: this.context.courseID, + teamset_id: this.model.get('id') + } + }).done(function(data) { + deferred.resolve(data.count === 0); + }).fail(function(data) { + TeamUtils.parseAndShowMessage(data, canUserCreateTeamErrorMessage); + deferred.resolve(false); + }); + } + return deferred.promise(); + }, + + + showActions: function() { + HtmlUtils.append( + this.$el, + HtmlUtils.template(teamActionsTemplate)({message: actionMessage}) + ); }, render: function() { - var self = this; - this.collection.refresh().done(function() { - var message; - TeamsView.prototype.render.call(self); - if (self.canUserCreateTeam()) { - message = interpolate_text( // eslint-disable-line no-undef - // Translators: this string is shown at the bottom of the teams page - // to find a team to join or else to create a new one. There are three - // links that need to be included in the message: - // 1. Browse teams in other topics - // 2. search teams - // 3. create a new team - // Be careful to start each link with the appropriate start indicator - // (e.g. {browse_span_start} for #1) and finish it with {span_end}. - _.escape(gettext( - '{browse_span_start}Browse teams in other ' + - 'topics{span_end} or {search_span_start}search teams{span_end} ' + - 'in this topic. If you still can\'t find a team to join, ' + - '{create_span_start}create a new team in this topic{span_end}.' - )), - { - browse_span_start: '<a class="browse-teams" href="">', - search_span_start: '<a class="search-teams" href="">', - create_span_start: '<a class="create-team" href="">', - span_end: '</a>' - } - ); - HtmlUtils.append( - self.$el, - HtmlUtils.template(teamActionsTemplate)({message: message}) - ); - } - }); + this.collection.refresh().done(_.bind(function() { + TeamsView.prototype.render.call(this); + this.checkIfUserCanCreateTeam().done(_.bind(function(canUserCreateTeam) { + if (canUserCreateTeam) { + this.showActions(); + } + }, this)); + }, this)); return this; }, diff --git a/lms/djangoapps/teams/static/teams/templates/team-assignment.underscore b/lms/djangoapps/teams/static/teams/templates/team-assignment.underscore new file mode 100644 index 0000000000000000000000000000000000000000..a20d10f2beaaebfdc6462a2a04d9f69dae50163a --- /dev/null +++ b/lms/djangoapps/teams/static/teams/templates/team-assignment.underscore @@ -0,0 +1,3 @@ +<li class="team-assignment"> + <a href="<%- linkLocation %>"><%- displayName %></a> +</li> diff --git a/lms/djangoapps/teams/static/teams/templates/team-profile.underscore b/lms/djangoapps/teams/static/teams/templates/team-profile.underscore index 6bb3621c03345ce79f663a44176fa16faa824cb2..d6df083c9d7451f994f010b03deec4ecbc1ce55c 100644 --- a/lms/djangoapps/teams/static/teams/templates/team-profile.underscore +++ b/lms/djangoapps/teams/static/teams/templates/team-profile.underscore @@ -1,5 +1,12 @@ <div class="team-profile"> <div class="page-content-main"> + <% if (showAssignments && (isMember || isAdminOrStaff)) { %> + <div class="team-assignments"> + <h3><%- gettext("Team Assignments") %></h3> + <ul id="assignments"></ul> + </div> + <hr></hr> + <% } %> <div class="discussion-module" data-course-id="<%- courseID %>" data-discussion-id="<%- discussionTopicID %>" data-read-only="<%- readOnly %>" data-user-create-comment="<%- !readOnly %>" diff --git a/lms/djangoapps/teams/templates/teams/teams.html b/lms/djangoapps/teams/templates/teams/teams.html index 7ee2c56f6e9c1b138382bcb24293b4ad0621eaa0..65d25f8d1f95cc56a6fbe3153999ad02a7f5850d 100644 --- a/lms/djangoapps/teams/templates/teams/teams.html +++ b/lms/djangoapps/teams/templates/teams/teams.html @@ -50,6 +50,9 @@ from openedx.core.djangolib.js_utils import ( topicUrl: '${topic_url | n, js_escaped_string}', topicsUrl: '${topics_url | n, js_escaped_string}', teamsUrl: '${teams_url | n, js_escaped_string}', + % if teams_assignments_url: + teamsAssignmentsUrl: '${teams_assignments_url | n, js_escaped_string}', + % endif teamsDetailUrl: '${teams_detail_url | n, js_escaped_string}', teamMembershipsUrl: '${team_memberships_url | n, js_escaped_string}', teamMembershipDetailUrl: '${team_membership_detail_url | n, js_escaped_string}', diff --git a/lms/djangoapps/teams/tests/test_api.py b/lms/djangoapps/teams/tests/test_api.py index 9baa4aaccf4a393d3db162efa7f7576e5f4ebdfa..86876f567ed61eabddd9a7593133c64c28ad2261 100644 --- a/lms/djangoapps/teams/tests/test_api.py +++ b/lms/djangoapps/teams/tests/test_api.py @@ -351,7 +351,7 @@ class TeamAccessTests(SharedModuleStoreTestCase): ('user_unenrolled', 3), ) @ddt.unpack - def test_team_counter_get_team_count_query_set(self, username, expected_count): + def test_team_counter_get_teams_accessible_by_user(self, username, expected_count): user = self.users[username] try: organization_protection_status = teams_api.user_organization_protection_status( @@ -361,7 +361,8 @@ class TeamAccessTests(SharedModuleStoreTestCase): except ValueError: self.assertFalse(CourseEnrollment.is_enrolled(user, COURSE_KEY1)) return - teams_query_set = teams_api.get_team_count_query_set( + teams_query_set = teams_api.get_teams_accessible_by_user( + user, [self.topic_id], COURSE_KEY1, organization_protection_status @@ -392,6 +393,7 @@ class TeamAccessTests(SharedModuleStoreTestCase): 'id': self.topic_id } teams_api.add_team_count( + user, [topic], COURSE_KEY1, organization_protection_status diff --git a/lms/djangoapps/teams/tests/test_csv.py b/lms/djangoapps/teams/tests/test_csv.py index b639f7aefa6051993bf4dd3218c70b5d8d1b97fd..4fc18db8de679d877267ec2204ba00fdc45c0e1b 100644 --- a/lms/djangoapps/teams/tests/test_csv.py +++ b/lms/djangoapps/teams/tests/test_csv.py @@ -1,20 +1,77 @@ """ Tests for the functionality in csv """ +from csv import DictWriter, DictReader +from io import BytesIO, StringIO, TextIOWrapper -from io import StringIO +from django.contrib.auth.models import User +from lms.djangoapps.program_enrollments.tests.factories import ProgramEnrollmentFactory, ProgramCourseEnrollmentFactory from lms.djangoapps.teams import csv -from lms.djangoapps.teams.models import CourseTeam +from lms.djangoapps.teams.models import CourseTeam, CourseTeamMembership from lms.djangoapps.teams.tests.factories import CourseTeamFactory +from openedx.core.lib.teams_config import TeamsConfig from student.tests.factories import CourseEnrollmentFactory, UserFactory +from util.testing import EventTestMixin from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory -from openedx.core.lib.teams_config import TeamsConfig + + +def csv_import(course, csv_dict_rows): + """ + Create a csv file with the given contents and pass it to the csv import manager to test the full + csv import flow + + Parameters: + - csv_dict_rows: list of dicts, representing a row of the csv file + """ + # initialize import manager + import_manager = csv.TeamMembershipImportManager(course) + import_manager.teamset_ids = {ts.teamset_id for ts in course.teamsets} + + with BytesIO() as mock_csv_file: + with TextIOWrapper(mock_csv_file, write_through=True) as text_wrapper: + # pylint: disable=protected-access + header_fields = csv._get_team_membership_csv_headers(course) + csv_writer = DictWriter(text_wrapper, fieldnames=header_fields) + csv_writer.writeheader() + csv_writer.writerows(csv_dict_rows) + mock_csv_file.seek(0) + import_manager.set_team_membership_from_csv(mock_csv_file) + + +def csv_export(course): + """ + Call csv.load_team_membership_csv for the given course, and return the result. + The result is returned in the form of a dictionary keyed by the 'user' identifiers for each row, + mapping to the full parsed dictionary for that row of the csv. + + Returns: DictReader for the returned csv file + """ + with StringIO() as read_buf: + csv.load_team_membership_csv(course, read_buf) + read_buf.seek(0) + return DictReader(read_buf.readlines()) + + +def _user_keyed_dict(reader): + """ create a dict of the rows of the csv, keyed by the "user" value """ + return {row['user']: row for row in reader} + + +def _csv_dict_row(user, mode, **kwargs): + """ + Convenience method to create dicts to pass to csv_import + """ + csv_dict_row = dict(kwargs) + csv_dict_row['user'] = user + csv_dict_row['mode'] = mode + return csv_dict_row class TeamMembershipCsvTests(SharedModuleStoreTestCase): """ Tests for functionality related to the team membership csv report """ @classmethod def setUpClass(cls): + # pylint: disable=no-member super(TeamMembershipCsvTests, cls).setUpClass() teams_config = TeamsConfig({ 'team_sets': [ @@ -68,10 +125,6 @@ class TeamMembershipCsvTests(SharedModuleStoreTestCase): team3_2.add_user(user4) - def setUp(self): - super(TeamMembershipCsvTests, self).setUp() - self.buf = StringIO() - def test_get_headers(self): # pylint: disable=protected-access headers = csv._get_team_membership_csv_headers(self.course) @@ -121,17 +174,66 @@ class TeamMembershipCsvTests(SharedModuleStoreTestCase): self.assertEqual(user_row.get('teamset_3'), expected_teamset_3_team) def test_load_team_membership_csv(self): - expected_csv_output = ('user,mode,teamset_1,teamset_2,teamset_3,teamset_4\r\n' - 'user1,audit,team_1_1,team_2_2,team_3_1,\r\n' - 'user2,verified,team_1_1,team_2_2,team_3_1,\r\n' - 'user3,honors,,team_2_1,team_3_1,\r\n' - 'user4,masters,,,team_3_2,\r\n' - 'user5,masters,,,,\r\n') - csv.load_team_membership_csv(self.course, self.buf) - self.assertEqual(expected_csv_output, self.buf.getvalue()) + expected_csv_headers = ['user', 'mode', 'teamset_1', 'teamset_2', 'teamset_3', 'teamset_4'] + expected_data = {} + expected_data['user1'] = _csv_dict_row( + 'user1', + 'audit', + teamset_1='team_1_1', + teamset_2='team_2_2', + teamset_3='team_3_1', + ) + expected_data['user2'] = _csv_dict_row( + 'user2', + 'verified', + teamset_1='team_1_1', + teamset_2='team_2_2', + teamset_3='team_3_1', + ) + expected_data['user3'] = _csv_dict_row('user3', 'honors', teamset_2='team_2_1', teamset_3='team_3_1') + expected_data['user4'] = _csv_dict_row('user4', 'masters', teamset_3='team_3_2') + expected_data['user5'] = _csv_dict_row('user5', 'masters') + self._add_blanks_to_expected_data(expected_data, expected_csv_headers) + + reader = csv_export(self.course) + self.assertEqual(expected_csv_headers, reader.fieldnames) + self.assertDictEqual(expected_data, _user_keyed_dict(reader)) + def _add_blanks_to_expected_data(self, expected_data, headers): + """ Helper method to fill in the "blanks" in test data """ + for user in expected_data: + user_row = expected_data[user] + for header in headers: + if header not in user_row: + user_row[header] = '' + + +class TeamMembershipEventTestMixin(EventTestMixin): + """ Mixin to provide functionality for testing signals emitted by csv code """ + + def setUp(self): + # pylint: disable=arguments-differ + super().setUp('lms.djangoapps.teams.utils.tracker') -class TeamMembershipImportManagerTests(SharedModuleStoreTestCase): + def assert_learner_added_emitted(self, team_id, user_id): + self.assert_event_emitted( + 'edx.team.learner_added', + team_id=team_id, + user_id=user_id, + add_method='team_csv_import' + ) + + def assert_learner_removed_emitted(self, team_id, user_id): + self.assert_event_emitted( + 'edx.team.learner_removed', + team_id=team_id, + user_id=user_id, + remove_method='team_csv_import' + ) + + +# pylint: disable=no-member +class TeamMembershipImportManagerTests(TeamMembershipEventTestMixin, SharedModuleStoreTestCase): """ Tests for TeamMembershipImportManager """ @classmethod def setUpClass(cls): @@ -141,13 +243,31 @@ class TeamMembershipImportManagerTests(SharedModuleStoreTestCase): 'id': 'teamset_1', 'name': 'teamset_name', 'description': 'teamset_desc', + 'max_team_size': 3, }] }) cls.course = CourseFactory(teams_configuration=teams_config) + cls.second_course = CourseFactory(teams_configuration=teams_config) + cls.import_manager = None + + def setUp(self): + """ Initialize import manager """ + super(TeamMembershipImportManagerTests, self).setUp() + self.import_manager = csv.TeamMembershipImportManager(self.course) + self.import_manager.teamset_ids = {ts.teamset_id for ts in self.course.teamsets} - # initialize import manager - cls.import_manager = csv.TeamMembershipImportManager(cls.course) - cls.import_manager.teamset_ids = {ts.teamset_id for ts in cls.course.teamsets} + def test_load_course_teams(self): + """ + Lodaing course teams shold get the users by team with only 2 queries + 1 for teams, 1 for user count + """ + team1 = CourseTeamFactory.create(course_id=self.course.id) + team2 = CourseTeamFactory.create(course_id=self.course.id) + team3 = CourseTeamFactory.create(course_id=self.course.id) + team4 = CourseTeamFactory.create(course_id=self.course.id) + + with self.assertNumQueries(2): + self.import_manager.load_course_teams() def test_add_user_to_new_protected_team(self): """Adding a masters learner to a new team should create a team with organization protected status""" @@ -160,7 +280,9 @@ class TeamMembershipImportManagerTests(SharedModuleStoreTestCase): } self.import_manager.add_user_to_team(row) - self.assertTrue(CourseTeam.objects.get(team_id__startswith='new_protected_team').organization_protected) + team = CourseTeam.objects.get(team_id__startswith='new_protected_team') + self.assertTrue(team.organization_protected) + self.assert_learner_added_emitted(team.team_id, masters_learner.id) def test_add_user_to_new_unprotected_team(self): """Adding a non-masters learner to a new team should create a team with no organization protected status""" @@ -173,4 +295,293 @@ class TeamMembershipImportManagerTests(SharedModuleStoreTestCase): } self.import_manager.add_user_to_team(row) - self.assertFalse(CourseTeam.objects.get(team_id__startswith='new_unprotected_team').organization_protected) + team = CourseTeam.objects.get(team_id__startswith='new_unprotected_team') + self.assertFalse(team.organization_protected) + self.assert_learner_added_emitted(team.team_id, audit_learner.id) + + def test_team_removals_are_scoped_correctly(self): + """ Team memberships should not search across topics in different courses """ + # Given a learner enrolled in similarly named teamsets across 2 courses + audit_learner = UserFactory.create(username='audit_learner') + + CourseEnrollmentFactory.create(user=audit_learner, course_id=self.course.id, mode='audit') + course_1_team = CourseTeamFactory(course_id=self.course.id, name='cross_course_test', topic_id='teamset_1') + course_1_team.add_user(audit_learner) + + CourseEnrollmentFactory.create(user=audit_learner, course_id=self.second_course.id, mode='audit') + course_2_team = CourseTeamFactory( + course_id=self.second_course.id, + name='cross_course_test', + topic_id='teamset_1' + ) + course_2_team.add_user(audit_learner) + + self.assertTrue(CourseTeamMembership.is_user_on_team(audit_learner, course_1_team)) + + # When I try to remove them from the team + row = { + 'mode': 'audit', + 'teamset_1': None, + 'user': audit_learner + } + self.import_manager.remove_user_from_team_for_reassignment(row) + + # They are successfully removed from the team + self.assertFalse(CourseTeamMembership.is_user_on_team(audit_learner, course_1_team)) + self.assert_learner_removed_emitted(course_1_team.team_id, audit_learner.id) + + def test_user_moved_to_another_team(self): + """ We should be able to move a user from one team to another """ + # Create a learner, enroll in course + audit_learner = UserFactory.create(username='audit_learner') + CourseEnrollmentFactory.create(user=audit_learner, course_id=self.course.id, mode='audit') + # Make two teams in the same teamset, enroll the user in one + team_1 = CourseTeamFactory(course_id=self.course.id, name='test_team_1', topic_id='teamset_1') + team_2 = CourseTeamFactory(course_id=self.course.id, name='test_team_2', topic_id='teamset_1') + team_1.add_user(audit_learner) + + csv_row = _csv_dict_row(audit_learner, 'audit', teamset_1=team_2.name) + csv_import(self.course, [csv_row]) + + self.assertFalse(CourseTeamMembership.is_user_on_team(audit_learner, team_1)) + self.assertTrue(CourseTeamMembership.is_user_on_team(audit_learner, team_2)) + + self.assert_learner_removed_emitted(team_1.team_id, audit_learner.id) + self.assert_learner_added_emitted(team_2.team_id, audit_learner.id) + + def test_exceed_max_size(self): + # Given a bunch of students enrolled in a course + users = [] + for i in range(5): + user = UserFactory.create(username='max_size_{id}'.format(id=i)) + CourseEnrollmentFactory.create(user=user, course_id=self.course.id, mode='audit') + users.append(user) + + # When a team is already near capaciy + team = CourseTeam.objects.create( + name='team_1', + course_id=self.course.id, + topic_id='teamset_1', + description='Team 1!', + ) + for i in range(2): + user = users[i] + team.add_user(user) + + # ... and I try to add members in excess of capacity + csv_data = self._csv_reader_from_array([ + ['user', 'mode', 'teamset_1'], + ['max_size_0', 'audit', ''], + ['max_size_2', 'audit', 'team_1'], + ['max_size_3', 'audit', 'team_1'], + ['max_size_4', 'audit', 'team_1'], + ]) + + result = self.import_manager.set_team_memberships(csv_data) + + # Then the import fails with no events emitted and a "team is full" error + self.assertFalse(result) + self.assert_no_events_were_emitted() + self.assertEqual( + self.import_manager.validation_errors[0], + 'New membership for team team_1 would exceed max size of 3.' + ) + + # Confirm that memberships were not altered + for i in range(2): + self.assertTrue(CourseTeamMembership.is_user_on_team(user, team)) + + def test_remove_from_team(self): + # Given a user already in a course and on a team + user = UserFactory.create(username='learner_1') + mode = 'audit' + CourseEnrollmentFactory.create(user=user, course_id=self.course.id, mode=mode) + team = CourseTeamFactory(course_id=self.course.id, name='team_1', topic_id='teamset_1') + team.add_user(user) + self.assertTrue(CourseTeamMembership.is_user_on_team(user, team)) + + # When I try to remove them from the team + csv_data = self._csv_reader_from_array([ + ['user', 'mode', 'teamset_1'], + [user.username, mode, ''], + ]) + result = self.import_manager.set_team_memberships(csv_data) + + # Then they are removed from the team and the correct events are issued + self.assertFalse(CourseTeamMembership.is_user_on_team(user, team)) + self.assert_learner_removed_emitted(team.team_id, user.id) + + def test_switch_memberships(self): + # Given a bunch of students enrolled in a course + users = [] + for i in range(5): + user = UserFactory.create(username='learner_{id}'.format(id=i)) + CourseEnrollmentFactory.create(user=user, course_id=self.course.id, mode='audit') + users.append(user) + + # When a team is already at/near capaciy + for i in range(3): + user = users[i] + row = {'user': user, 'teamset_1': 'team_1', 'mode': 'audit'} + self.import_manager.add_user_to_team(row) + + # ... and I try to switch membership (add/remove) + csv_data = self._csv_reader_from_array([ + ['user', 'mode', 'teamset_1'], + ['learner_4', 'audit', 'team_1'], + ['learner_0', 'audit', 'team_2'], + ]) + + result = self.import_manager.set_team_memberships(csv_data) + + # Then membership size is calculated correctly, import finishes w/out error + self.assertTrue(result) + + # ... and the users are assigned to the correct teams + team_1 = CourseTeam.objects.get(course_id=self.course.id, topic_id='teamset_1', name='team_1') + self.assertTrue(CourseTeamMembership.is_user_on_team(users[4], team_1)) + self.assert_learner_added_emitted(team_1.team_id, users[4].id) + + team_2 = CourseTeam.objects.get(course_id=self.course.id, topic_id='teamset_1', name='team_2') + self.assertTrue(CourseTeamMembership.is_user_on_team(users[0], team_2)) + self.assert_learner_added_emitted(team_2.team_id, users[0].id) + + def test_create_new_team_from_import(self): + # Given a user in a course + user = UserFactory.create(username='learner_1') + mode = 'audit' + CourseEnrollmentFactory.create(user=user, course_id=self.course.id, mode=mode) + + # When I add them to a team that does not exist + self.assertEquals(CourseTeam.objects.all().count(), 0) + csv_data = self._csv_reader_from_array([ + ['user', 'mode', 'teamset_1'], + [user.username, mode, 'new_exciting_team'], + ]) + result = self.import_manager.set_team_memberships(csv_data) + + # Then a new team is created + self.assertEqual(CourseTeam.objects.all().count(), 1) + + # ... and the user is assigned to the team + new_team = CourseTeam.objects.get(topic_id='teamset_1', name='new_exciting_team') + self.assertTrue(CourseTeamMembership.is_user_on_team(user, new_team)) + self.assert_learner_added_emitted(new_team.team_id, user.id) + + def _csv_reader_from_array(self, rows): + """ + Given a 2D array, treat each element as a cell of a CSV file and construct a reader + + Example: + [['header1', 'header2'], ['r1:c1', 'r1:c2'], ['r2:c2', 'r3:c3'] ... ] + """ + return DictReader((','.join(row) for row in rows)) + + +class ExternalKeyCsvTests(TeamMembershipEventTestMixin, SharedModuleStoreTestCase): + """ Tests for functionality related to external_user_keys""" + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.teamset_id = 'teamset_id' + teams_config = TeamsConfig({ + 'team_sets': [ + { + 'id': cls.teamset_id, + 'name': 'teamset_name', + 'description': 'teamset_desc', + } + ] + }) + cls.course = CourseFactory(teams_configuration=teams_config) + # pylint: disable=protected-access + cls.header_fields = csv._get_team_membership_csv_headers(cls.course) + + cls.team = CourseTeamFactory(course_id=cls.course.id, name='team_name', topic_id=cls.teamset_id) + + cls.user_no_program = UserFactory.create() + cls.user_in_program = UserFactory.create() + cls.user_in_program_no_external_id = UserFactory.create() + cls.user_in_program_not_enrolled_through_program = UserFactory.create() + + # user_no_program is only enrolled in the course + cls.add_user_to_course_program_team(cls.user_no_program, enroll_in_program=False) + + # user_in_program is enrolled in the course and the program, with an external_id + cls.external_user_key = 'externalProgramUserId-123' + cls.add_user_to_course_program_team(cls.user_in_program, external_user_key=cls.external_user_key) + + # user_in_program is enrolled in the course and the program, with no external_id + cls.add_user_to_course_program_team(cls.user_in_program_no_external_id) + + # user_in_program_not_enrolled_through_program is enrolled in a program and the course, but they not connected + cls.add_user_to_course_program_team( + cls.user_in_program_not_enrolled_through_program, connect_enrollments=False + ) + + @classmethod + def add_user_to_course_program_team( + cls, user, add_to_team=True, enroll_in_program=True, connect_enrollments=True, external_user_key=None + ): + """ + Set up a test user by enrolling them in self.course, and then optionaly: + - enroll them in a program + - link their program and course enrollments + - give their program enrollment an external_user_key + """ + course_enrollment = CourseEnrollmentFactory.create(user=user, course_id=cls.course.id) + if add_to_team: + cls.team.add_user(user) + if enroll_in_program: + program_enrollment = ProgramEnrollmentFactory.create(user=user, external_user_key=external_user_key) + if connect_enrollments: + ProgramCourseEnrollmentFactory.create( + program_enrollment=program_enrollment, course_enrollment=course_enrollment + ) + + def assert_user_on_team(self, user): + self.assertTrue(CourseTeamMembership.is_user_on_team(user, self.team)) + + def assert_user_not_on_team(self, user): + self.assertFalse(CourseTeamMembership.is_user_on_team(user, self.team)) + + def test_add_user_to_team_with_external_key(self): + # Make a new user with an external_user_key who is enrolled in the course and program, with an external_key, + # but is not on the team + new_user = UserFactory.create() + new_ext_key = "another-external-user-id-FKQP12345" + self.add_user_to_course_program_team(new_user, add_to_team=False, external_user_key=new_ext_key) + self.assert_user_not_on_team(new_user) + + csv_import_row = _csv_dict_row(new_ext_key, 'audit', teamset_id=self.team.name) + csv_import(self.course, [csv_import_row]) + self.assert_user_on_team(new_user) + self.assert_learner_added_emitted(self.team.team_id, new_user.id) + + def test_lookup_team_membership_data(self): + with self.assertNumQueries(3): + # pylint: disable=protected-access + data = csv._lookup_team_membership_data(self.course) + self._assert_test_users_on_team(_user_keyed_dict(data)) + + def test_get_csv(self): + reader = csv_export(self.course) + self._assert_test_users_on_team(_user_keyed_dict(reader)) + + def _assert_test_users_on_team(self, data): + """ + Assert that the four test users should be listed as members of the team, + and user_in_program should be identified by their external_user_key + """ + self.assertEqual(len(data), 4) + expected_data = { + user_identifier: _csv_dict_row(user_identifier, 'audit', teamset_id=self.team.name) + for user_identifier in [ + self.user_no_program.username, + self.user_in_program_no_external_id.username, + self.user_in_program_not_enrolled_through_program.username, + self.external_user_key + ] + } + self.assertDictEqual(expected_data, data) diff --git a/lms/djangoapps/teams/tests/test_serializers.py b/lms/djangoapps/teams/tests/test_serializers.py index 082a802157f0ff706d490bd04eb3cb8e2959d084..e3de6e73fcba0f46c58972acdf00c1a543c42d0c 100644 --- a/lms/djangoapps/teams/tests/test_serializers.py +++ b/lms/djangoapps/teams/tests/test_serializers.py @@ -79,9 +79,9 @@ class TopicSerializerTestCase(SerializerTestCase): def test_topic_with_no_team_count(self): """ Verifies that the `TopicSerializer` correctly displays a topic with a - team count of 0, and that it only takes one SQL query. + team count of 0, and that it takes a known number of SQL queries. """ - with self.assertNumQueries(1): + with self.assertNumQueries(2): serializer = TopicSerializer( self.course.teamsets[0].cleaned_data, context={'course_id': self.course.id}, @@ -101,12 +101,12 @@ class TopicSerializerTestCase(SerializerTestCase): def test_topic_with_team_count(self): """ Verifies that the `TopicSerializer` correctly displays a topic with a - positive team count, and that it only takes one SQL query. + positive team count, and that it takes a known number of SQL queries. """ CourseTeamFactory.create( course_id=self.course.id, topic_id=self.course.teamsets[0].teamset_id ) - with self.assertNumQueries(1): + with self.assertNumQueries(2): serializer = TopicSerializer( self.course.teamsets[0].cleaned_data, context={'course_id': self.course.id}, @@ -134,7 +134,7 @@ class TopicSerializerTestCase(SerializerTestCase): ) CourseTeamFactory.create(course_id=self.course.id, topic_id=duplicate_topic[u'id']) CourseTeamFactory.create(course_id=second_course.id, topic_id=duplicate_topic[u'id']) - with self.assertNumQueries(1): + with self.assertNumQueries(2): serializer = TopicSerializer( self.course.teamsets[0].cleaned_data, context={'course_id': self.course.id}, @@ -198,7 +198,7 @@ class BaseTopicSerializerTestCase(SerializerTestCase): """ with self.assertNumQueries(num_queries): page = Paginator( - self.course.teams_configuration.cleaned_data_old_format['topics'], + self.course.teams_configuration.cleaned_data['teamsets'], self.PAGE_SIZE, ).page(1) # pylint: disable=not-callable @@ -227,13 +227,18 @@ class BulkTeamCountTopicSerializerTestCase(BaseTopicSerializerTestCase): NUM_TOPICS = 6 + def setUp(self): + super().setUp() + self.user = UserFactory.create() + CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id) + def test_topics_with_no_team_counts(self): """ Verify that we serialize topics with no team count, making only one SQL query. """ topics = self.setup_topics(teams_per_topic=0) - self.assert_serializer_output(topics, num_teams_per_topic=0, num_queries=1) + self.assert_serializer_output(topics, num_teams_per_topic=0, num_queries=2) def test_topics_with_team_counts(self): """ @@ -242,7 +247,7 @@ class BulkTeamCountTopicSerializerTestCase(BaseTopicSerializerTestCase): """ teams_per_topic = 10 topics = self.setup_topics(teams_per_topic=teams_per_topic) - self.assert_serializer_output(topics, num_teams_per_topic=teams_per_topic, num_queries=1) + self.assert_serializer_output(topics, num_teams_per_topic=teams_per_topic, num_queries=2) def test_subset_of_topics(self): """ @@ -251,7 +256,7 @@ class BulkTeamCountTopicSerializerTestCase(BaseTopicSerializerTestCase): """ teams_per_topic = 10 topics = self.setup_topics(num_topics=self.NUM_TOPICS, teams_per_topic=teams_per_topic) - self.assert_serializer_output(topics, num_teams_per_topic=teams_per_topic, num_queries=1) + self.assert_serializer_output(topics, num_teams_per_topic=teams_per_topic, num_queries=2) def test_scoped_within_course(self): """Verify that team counts are scoped within a course.""" @@ -265,7 +270,7 @@ class BulkTeamCountTopicSerializerTestCase(BaseTopicSerializerTestCase): }), ) CourseTeamFactory.create(course_id=second_course.id, topic_id=duplicate_topic[u'id']) - self.assert_serializer_output(first_course_topics, num_teams_per_topic=teams_per_topic, num_queries=1) + self.assert_serializer_output(first_course_topics, num_teams_per_topic=teams_per_topic, num_queries=2) def _merge_dicts(self, first, second): """Convenience method to merge two dicts in a single expression""" @@ -277,8 +282,19 @@ class BulkTeamCountTopicSerializerTestCase(BaseTopicSerializerTestCase): """ Verify that the serializer produced the expected topics. """ + # Set a request user + request = RequestFactory().get('/api/team/v0/topics') + request.user = self.user + with self.assertNumQueries(num_queries): - serializer = self.serializer(topics, context={'course_id': self.course.id}, many=True) + serializer = self.serializer( + topics, + context={ + 'course_id': self.course.id, + 'request': request + }, + many=True + ) self.assertEqual( serializer.data, [self._merge_dicts(topic, {u'team_count': num_teams_per_topic}) for topic in topics] @@ -290,4 +306,4 @@ class BulkTeamCountTopicSerializerTestCase(BaseTopicSerializerTestCase): with no topics. """ self.course.teams_configuration = TeamsConfig({'topics': []}) - self.assert_serializer_output([], num_teams_per_topic=0, num_queries=0) + self.assert_serializer_output([], num_teams_per_topic=0, num_queries=1) diff --git a/lms/djangoapps/teams/tests/test_views.py b/lms/djangoapps/teams/tests/test_views.py index d5e8173a0d7b4eee0073a7f9a7241f6b69bcc1ec..4b110a05fd98a4524df6733a0fda0f30a70177e1 100644 --- a/lms/djangoapps/teams/tests/test_views.py +++ b/lms/djangoapps/teams/tests/test_views.py @@ -7,6 +7,7 @@ Tests for the teams API at the HTTP request level. import json import unittest from datetime import datetime +from uuid import UUID import ddt import pytz @@ -29,10 +30,11 @@ from openedx.core.djangoapps.django_comment_common.models import FORUM_ROLE_COMM from openedx.core.djangoapps.django_comment_common.utils import seed_permissions_roles from openedx.core.lib.teams_config import TeamsConfig from student.models import CourseEnrollment +from lms.djangoapps.program_enrollments.tests.factories import ProgramEnrollmentFactory from student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory from util.testing import EventTestMixin from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from ..models import CourseTeamMembership from ..search_indexes import CourseTeam, CourseTeamIndexer, course_team_post_save_callback @@ -240,10 +242,58 @@ class TestDashboard(SharedModuleStoreTestCase): expected_has_open = "hasOpenTopic: " + "true" if has_open else "false" expected_has_public = "hasPublicManagedTopic: " + "true" if has_public else "false" - expected_has_managed = "hasManagedTopic: " + "true" if has_public or has_private else "false" self.assertContains(response, expected_has_open) self.assertContains(response, expected_has_public) + + @ddt.unpack + @ddt.data( + (True, False, False), + (False, True, False), + (False, False, True), + (True, True, True), + (False, True, True), + ) + def test_has_managed_topic(self, has_open, has_private, has_public): + topics = [] + if has_open: + topics.append({ + "name": "test topic 1", + "id": 1, + "description": "Desc1", + "type": "open" + }) + if has_private: + topics.append({ + "name": "test topic 2", + "id": 2, + "description": "Desc2", + "type": "private_managed" + }) + if has_public: + topics.append({ + "name": "test topic 3", + "id": 3, + "description": "Desc3", + "type": "public_managed" + }) + + # Given a staff user browsing the teams tab + course = CourseFactory.create( + teams_configuration=TeamsConfig({"topics": topics}) + ) + teams_url = reverse('teams_dashboard', args=[course.id]) + + staff_user = UserFactory(is_staff=True, password=self.test_password) + staff_client = APIClient() + staff_client.login(username=staff_user.username, password=self.test_password) + + # When I browse to the team tab + response = staff_client.get(teams_url) + + # Then "hasManagedTopic" (which is used to show the "Manage" tab) + # is shown if there are managed team-sets + expected_has_managed = "hasManagedTopic: " + "true" if has_public or has_private else "false" self.assertContains(response, expected_has_managed) @@ -323,7 +373,8 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase): cls.topics_count = 6 cls.users = { 'staff': AdminFactory.create(password=cls.test_password), - 'course_staff': StaffFactory.create(course_key=cls.test_course_1.id, password=cls.test_password) + 'course_staff': StaffFactory.create(course_key=cls.test_course_1.id, password=cls.test_password), + 'admin': AdminFactory.create(password=cls.test_password) } cls.create_and_enroll_student(username='student_enrolled') cls.create_and_enroll_student(username='student_on_team_1_private_set_1', mode=CourseMode.MASTERS) @@ -500,7 +551,7 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase): return self.build_membership_data_raw(self.users[username].username, team.team_id) @classmethod - def create_and_enroll_student(cls, courses=None, username=None, mode=None): + def create_and_enroll_student(cls, courses=None, username=None, mode=None, external_key=None): """ Creates a new student and enrolls that student in the course. Adds the new user to the cls.users dictionary with the username as the key. @@ -516,6 +567,15 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase): CourseEnrollment.enroll(user, course.id, mode=mode, check_access=True) cls.users[user.username] = user + if external_key is not None: + ProgramEnrollmentFactory( + user=user, + external_user_key=external_key, + program_uuid=UUID("88888888-4444-3333-1111-000000000000"), + curriculum_uuid=UUID("77777777-4444-2222-1111-000000000000"), + status='enrolled' + ) + return user.username def login(self, user): @@ -636,6 +696,14 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase): **kwargs ) + def get_team_assignments(self, team_id, expected_status=200, **kwargs): + """ Get the open response assessments assigned to a team """ + return self.make_call( + reverse('teams_assignments_list', args=[team_id]), + expected_status, + **kwargs + ) + def get_topics_list(self, expected_status=200, data=None, **kwargs): """Gets the list of topics, passing data as query params. Verifies expected_status.""" return self.make_call(reverse('topics_list'), expected_status, 'get', data, **kwargs) @@ -810,6 +878,15 @@ class TestListTeamsAPI(EventTestMixin, TeamAPITestCase): self.assertEqual('private_topic_1_id', result['results'][0]['topic_id']) self.assertNotEqual([], result['results']) + def test_course_staff_getting_information_on_private_topic(self): + """ + Verifies that when an admin browses to a private team set, + information about the teams in the teamset is returned even if the admin is not in any teams. + """ + result = self.get_teams_list(data={'topic_id': 'private_topic_1_id'}, + user='course_staff') + self.assertEqual(2, len(result['results'])) + @ddt.unpack @ddt.data( ('student_masters_not_on_team', 1), @@ -955,6 +1032,43 @@ class TestListTeamsAPI(EventTestMixin, TeamAPITestCase): user='staff' ) + def test_duplicates_and_nontopic_private_teamsets(self): + """ + Test for a bug where non-admin users would have their private memberships returned from this endpoint + despite the topic, and duplicate entries for teams in the topic that was being queried (EDUCATOR-5042) + """ + # create a team in a private teamset and add a user + unprotected_team_in_private_teamset = CourseTeamFactory.create( + name='unprotected_team_in_private_teamset', + description='unprotected_team_in_private_teamset', + course_id=self.test_course_1.id, + topic_id='private_topic_1_id', + ) + unprotected_team_in_private_teamset.add_user(self.users['student_enrolled']) + + # make some more users and put them in the solar team. + another_student_username = 'another_student' + yet_another_student_username = 'yet_another_student' + self.create_and_enroll_student(username=another_student_username) + self.create_and_enroll_student(username=yet_another_student_username) + self.solar_team.add_user(self.users[another_student_username]) + self.solar_team.add_user(self.users[yet_another_student_username]) + + teams = self.get_teams_list(data={'topic_id': self.solar_team.topic_id}, user='student_enrolled') + team_names = [team['name'] for team in teams['results']] + team_names.sort() + self.assertEqual(team_names, [ + self.solar_team.name, + ]) + + teams = self.get_teams_list(data={'topic_id': self.solar_team.topic_id}, user='staff') + team_names = [team['name'] for team in teams['results']] + team_names.sort() + self.assertEqual(team_names, [ + self.solar_team.name, + self.masters_only_team.name, + ]) + @ddt.ddt class TestCreateTeamAPI(EventTestMixin, TeamAPITestCase): @@ -1282,28 +1396,54 @@ class TestDeleteTeamAPI(EventTestMixin, TeamAPITestCase): super(TestDeleteTeamAPI, self).setUp('lms.djangoapps.teams.utils.tracker') @ddt.data( - (None, 401), - ('student_inactive', 401), - ('student_unenrolled', 403), - ('student_enrolled', 403), ('staff', 204), ('course_staff', 204), - ('community_ta', 204) + ('community_ta', 204), + ('admin', 204) ) @ddt.unpack def test_access(self, user, status): + team_list = self.get_teams_list(user='course_staff', expected_status=200) + previous_count = team_list['count'] + self.assertIn(self.solar_team.team_id, [result['id'] for result in team_list.get('results')]) + self.delete_team(self.solar_team.team_id, status, user=user) + + team_list = self.get_teams_list(user='course_staff', expected_status=200) + self.assertEqual(team_list['count'], previous_count - 1) + self.assertNotIn(self.solar_team.team_id, [result['id'] for result in team_list.get('results')]) + self.assert_event_emitted( + 'edx.team.deleted', + team_id=self.solar_team.team_id, + ) + self.assert_event_emitted( + 'edx.team.learner_removed', + team_id=self.solar_team.team_id, + remove_method='team_deleted', + user_id=self.users['student_enrolled'].id + ) + + @ddt.data( + ('student_unenrolled', 403), + ('student_enrolled', 403), + ) + @ddt.unpack + def test_access_forbidden(self, user, status): + team_list = self.get_teams_list(user='course_staff', expected_status=200) + previous_count = team_list['count'] + self.assertIn(self.solar_team.team_id, [result['id'] for result in team_list.get('results')]) + self.delete_team(self.solar_team.team_id, status, user=user) + + team_list = self.get_teams_list(user='course_staff', expected_status=200) + self.assertEqual(team_list['count'], previous_count) + self.assertIn(self.solar_team.team_id, [result['id'] for result in team_list.get('results')]) + + @ddt.data( + (None, 401), + ('student_inactive', 401), + ) + @ddt.unpack + def test_access_unauthorized(self, user, status): self.delete_team(self.solar_team.team_id, status, user=user) - if status == 204: - self.assert_event_emitted( - 'edx.team.deleted', - team_id=self.solar_team.team_id, - ) - self.assert_event_emitted( - 'edx.team.learner_removed', - team_id=self.solar_team.team_id, - remove_method='team_deleted', - user_id=self.users['student_enrolled'].id - ) def test_does_not_exist(self): self.delete_team('nonexistent', 404) @@ -1486,6 +1626,100 @@ class TestUpdateTeamAPI(EventTestMixin, TeamAPITestCase): self.assertEqual(team['name'], 'foo') +@patch.dict(settings.FEATURES, {'ENABLE_ORA_TEAM_SUBMISSIONS': True}) +@ddt.ddt +class TestTeamAssignmentsView(TeamAPITestCase): + """ Tests for the TeamAssignmentsView """ + + @classmethod + def setUpClass(cls): + """ Create an openassessment block for testing """ + super().setUpClass() + + course = cls.test_course_1 + teamset_id = cls.solar_team.topic_id + other_teamset_id = cls.wind_team.topic_id + + section = ItemFactory.create( + parent=course, + category='chapter', + display_name='Test Section' + ) + subsection = ItemFactory.create( + parent=section, + category="sequential" + ) + unit_1 = ItemFactory.create( + parent=subsection, + category="vertical" + ) + open_assessment = ItemFactory.create( + parent=unit_1, + category="openassessment", + teams_enabled=True, + selected_teamset_id=teamset_id + ) + unit_2 = ItemFactory.create( + parent=subsection, + category="vertical" + ) + off_team_open_assessment = ItemFactory.create( # pylint: disable=unused-variable + parent=unit_2, + category="openassessment", + teams_enabled=True, + selected_teamset_id=other_teamset_id + ) + + cls.team_assignments = [open_assessment] + + @ddt.unpack + @ddt.data( + (None, 401), + ('student_inactive', 401), + ('student_unenrolled', 403), + ('student_on_team_2_private_set_1', 404), + ('student_enrolled', 200), + ('staff', 200), + ('course_staff', 200), + ('community_ta', 200), + ) + def test_get_assignments(self, user, expected_status): + # Given a course with team-enabled open responses + team_id = self.solar_team.team_id + + # When I get the assignments for a team + assignments = self.get_team_assignments(team_id, expected_status, user=user) + + if expected_status == 200: + # I successful, I get back the assignments for a team + self.assertEqual(len(assignments), len(self.team_assignments)) + + # ... with the right data structure + for assignment in assignments: + self.assertIn('display_name', assignment.keys()) + self.assertIn('location', assignment.keys()) + + def test_get_assignments_bad_team(self): + # Given a bad team is supplied + user = 'student_enrolled' + team_id = 'bogus-team' + + # When I run the query, I get back a 404 error + expected_status = 404 + self.get_team_assignments(team_id, expected_status, user=user) + + @patch.dict(settings.FEATURES, {'ENABLE_ORA_TEAM_SUBMISSIONS': False}) + def test_get_assignments_feature_not_enabled(self): + # Given the team submissions feature is not enabled + user = 'student_enrolled' + team_id = self.solar_team.team_id + + # When I try to get assignments + # Then I get back a 503 error + expected_status = 503 + self.get_team_assignments(team_id, expected_status, user=user) + + @ddt.ddt class TestListTopicsAPI(TeamAPITestCase): """Test cases for the topic listing endpoint.""" @@ -1539,7 +1773,7 @@ class TestListTopicsAPI(TeamAPITestCase): data = {'course_id': str(self.test_course_1.id)} if field: data['order_by'] = field - topics = self.get_topics_list(status, data) + topics = self.get_topics_list(status, data, user='student_enrolled') if status == 200: self.assertEqual(names, [topic['name'] for topic in topics['results']]) self.assertEqual(topics['sort_order'], expected_ordering) @@ -1572,28 +1806,37 @@ class TestListTopicsAPI(TeamAPITestCase): ) # Wind power has the most teams, followed by Solar - topics = self.get_topics_list(data={ - 'course_id': str(self.test_course_1.id), - 'page_size': 2, - 'page': 1, - 'order_by': 'team_count' - }) + topics = self.get_topics_list( + data={ + 'course_id': str(self.test_course_1.id), + 'page_size': 2, + 'page': 1, + 'order_by': 'team_count' + }, + user='student_enrolled' + ) self.assertEqual(["Wind Power", u'Sólar power'], [topic['name'] for topic in topics['results']]) # Coal and Nuclear are tied, so they are alphabetically sorted. - topics = self.get_topics_list(data={ - 'course_id': str(self.test_course_1.id), - 'page_size': 2, - 'page': 2, - 'order_by': 'team_count' - }) + topics = self.get_topics_list( + data={ + 'course_id': str(self.test_course_1.id), + 'page_size': 2, + 'page': 2, + 'order_by': 'team_count' + }, + user='student_enrolled' + ) self.assertEqual(["Coal Power", "Nuclear Power"], [topic['name'] for topic in topics['results']]) def test_pagination(self): - response = self.get_topics_list(data={ - 'course_id': str(self.test_course_1.id), - 'page_size': 2, - }) + response = self.get_topics_list( + data={ + 'course_id': str(self.test_course_1.id), + 'page_size': 2, + }, + user='student_enrolled' + ) self.assertEqual(2, len(response['results'])) self.assertIn('next', response) @@ -1607,7 +1850,10 @@ class TestListTopicsAPI(TeamAPITestCase): def test_team_count(self): """Test that team_count is included for each topic""" - response = self.get_topics_list(data={'course_id': str(self.test_course_1.id)}) + response = self.get_topics_list( + data={'course_id': str(self.test_course_1.id)}, + user='student_enrolled' + ) for topic in response['results']: self.assertIn('team_count', topic) if topic['id'] in ('topic_0', 'topic_1', 'topic_2'): @@ -1641,13 +1887,13 @@ class TestListTopicsAPI(TeamAPITestCase): @ddt.unpack @ddt.data( - ('student_on_team_1_private_set_1', 2), - ('student_on_team_2_private_set_1', 2), + ('student_on_team_1_private_set_1', 1), + ('student_on_team_2_private_set_1', 1), ('staff', 2) ) def test_private_teamset_team_count(self, requesting_user, expected_team_count): """ - TODO: the two students should probably not see that there's another team that they don't see + Students should only see teams they are members of in private team-sets """ topics = self.get_topics_list( data={'course_id': str(self.test_course_1.id)}, @@ -1701,8 +1947,8 @@ class TestDetailTopicAPI(TeamAPITestCase): @ddt.unpack @ddt.data( ('student_enrolled', 404, None), - ('student_on_team_1_private_set_1', 200, 2), - ('student_on_team_2_private_set_1', 200, 2), + ('student_on_team_1_private_set_1', 200, 1), + ('student_on_team_2_private_set_1', 200, 1), ('student_masters', 404, None), ('staff', 200, 2) ) @@ -2496,7 +2742,7 @@ class TestBulkMembershipManagement(TeamAPITestCase): # This strategy allows us to test with invalid course IDs return reverse('team_membership_bulk_management', args=[course_id]) - def test_upload_valid_csv_simple(self): + def test_create_membership_via_upload(self): self.create_and_enroll_student(username='a_user') csv_content = 'user,mode,topic_0' + '\n' csv_content += 'a_user,audit,team wind power' @@ -2510,7 +2756,7 @@ class TestBulkMembershipManagement(TeamAPITestCase): user='staff' ) response_text = json.loads(response.content.decode('utf-8')) - self.assertEqual(response_text['message'], '1 learners were assigned to teams.') + self.assertEqual(response_text['message'], '1 learners were affected.') def test_upload_invalid_teamset(self): self.create_and_enroll_student(username='a_user') @@ -2555,7 +2801,7 @@ class TestBulkMembershipManagement(TeamAPITestCase): 1 ) response_text = json.loads(response.content.decode('utf-8')) - self.assertEqual(response_text['message'], '3 learners were assigned to teams.') + self.assertEqual(response_text['message'], '3 learners were affected.') def test_upload_non_existing_user(self): csv_content = 'user,mode,topic_0' + '\n' @@ -2638,6 +2884,30 @@ class TestBulkMembershipManagement(TeamAPITestCase): data={'csv': csv_file}, user='staff' ) + def test_upload_invalid_multiple_student_enrollment_mismatch(self): + audit_username = 'audit_user' + masters_username_a = 'masters_a' + masters_username_b = 'masters_b' + self.create_and_enroll_student(username=audit_username, mode=CourseMode.AUDIT) + self.create_and_enroll_student(username=masters_username_a, mode=CourseMode.MASTERS) + self.create_and_enroll_student(username=masters_username_b, mode=CourseMode.MASTERS) + + csv_content = 'user,mode,topic_1' + '\n' + csv_content += '{},audit,team wind power'.format(audit_username) + '\n' + csv_content += '{},masters,team wind power'.format(masters_username_a) + '\n' + csv_content += '{},masters,team wind power'.format(masters_username_b) + '\n' + csv_file = SimpleUploadedFile('test_file.csv', csv_content.encode('utf8'), content_type='text/csv') + self.client.login(username=self.users['course_staff'].username, password=self.users['course_staff'].password) + response = self.make_call(reverse( + 'team_membership_bulk_management', + args=[self.good_course_id]), + 400, method='post', + data={'csv': csv_file}, user='staff' + ) + response_text = json.loads(response.content.decode('utf-8')) + expected_error = 'Team team wind power cannot have Master’s track users mixed with users in other tracks.' + self.assertEqual(response_text['errors'][0], expected_error) + def test_upload_learners_exceed_max_team_size(self): csv_content = 'user,mode,topic_0,topic_1' + '\n' team1 = 'team wind power' @@ -2656,4 +2926,183 @@ class TestBulkMembershipManagement(TeamAPITestCase): data={'csv': csv_file}, user='staff' ) response_text = json.loads(response.content.decode('utf-8')) - self.assertEqual(response_text['errors'][0], 'Team {} is full.'.format(team1)) + self.assertEqual( + response_text['errors'][0], + 'New membership for team {} would exceed max size of {}.'.format(team1, 3) + ) + + def test_deletion_via_upload_csv(self): + # create a team membership that will be used further down + self.test_create_membership_via_upload() + username = 'a_user' + topic_0_id = 'topic_0' + self.assertTrue(CourseTeamMembership.objects.filter( + user_id=self.users[username].id, + team__topic_id=topic_0_id + ).exists()) + + csv_content = 'user,mode,{},topic_1'.format(topic_0_id) + '\n' + csv_content += '{},audit'.format(username) + csv_file = SimpleUploadedFile('test_file.csv', csv_content.encode('utf8'), content_type='text/csv') + self.client.login(username=self.users['course_staff'].username, password=self.users['course_staff'].password) + self.make_call( + reverse('team_membership_bulk_management', args=[self.good_course_id]), + 201, + method='post', + data={'csv': csv_file}, + user='staff' + ) + self.assertFalse(CourseTeamMembership.objects.filter( + user_id=self.users[username].id, + team__topic_id=topic_0_id + ).exists()) + + def test_reassignment_via_upload_csv(self): + # create a team membership that will be used further down + self.test_create_membership_via_upload() + username = 'a_user' + topic_0_id = 'topic_0' + nuclear_team_name = 'team nuclear power' + windpower_team_name = 'team wind power' + self.assertTrue(CourseTeamMembership.objects.filter( + user_id=self.users[username].id, + team__topic_id=topic_0_id, + team__name=windpower_team_name + ).exists()) + csv_content = 'user,mode,{}'.format(topic_0_id) + '\n' + csv_content += '{0},audit,{1}'.format(username, nuclear_team_name) + csv_file = SimpleUploadedFile('test_file.csv', csv_content.encode('utf8'), content_type='text/csv') + self.client.login(username=self.users['course_staff'].username, password=self.users['course_staff'].password) + self.make_call( + reverse('team_membership_bulk_management', args=[self.good_course_id]), + 201, + method='post', + data={'csv': csv_file}, + user='staff' + ) + self.assertFalse(CourseTeamMembership.objects.filter( + user_id=self.users[username].id, + team__topic_id=topic_0_id, + team__name=windpower_team_name + ).exists()) + self.assertTrue(CourseTeamMembership.objects.filter( + user_id=self.users[username].id, + team__topic_id=topic_0_id, + team__name=nuclear_team_name + ).exists()) + + def test_upload_file_not_changed_csv(self): + # create a team membership that will be used further down + self.test_create_membership_via_upload() + username = 'a_user' + topic_0_id = 'topic_0' + nuclear_team_name = 'team wind power' + self.assertEqual(len(CourseTeamMembership.objects.filter( + user_id=self.users[username].id, + team__topic_id=topic_0_id + )), 1) + csv_content = 'user,mode,{}'.format(topic_0_id) + '\n' + csv_content += '{0},audit,{1}'.format(username, nuclear_team_name) + csv_file = SimpleUploadedFile('test_file.csv', csv_content.encode('utf8'), content_type='text/csv') + self.client.login(username=self.users['course_staff'].username, + password=self.users['course_staff'].password) + self.make_call( + reverse('team_membership_bulk_management', args=[self.good_course_id]), + 201, + method='post', + data={'csv': csv_file}, + user='staff' + ) + self.assertEqual(len(CourseTeamMembership.objects.filter( + user_id=self.users[username].id, + team__name=nuclear_team_name + )), 1) + self.assertTrue(CourseTeamMembership.objects.filter( + user_id=self.users[username].id, + team__name=nuclear_team_name + ).exists()) + + def test_create_membership_via_upload_using_external_key(self): + self.create_and_enroll_student(username='a_user', external_key='a_user_external_key') + csv_content = 'user,mode,topic_0' + '\n' + csv_content += 'a_user_external_key,audit,team wind power' + csv_file = SimpleUploadedFile('test_file.csv', csv_content.encode('utf8'), content_type='text/csv') + self.client.login(username=self.users['course_staff'].username, password=self.users['course_staff'].password) + response = self.make_call( + reverse('team_membership_bulk_management', args=[self.good_course_id]), + 201, + method='post', + data={'csv': csv_file}, + user='staff' + ) + response_text = json.loads(response.content.decode('utf-8')) + self.assertEqual(response_text['message'], '1 learners were affected.') + + def test_create_membership_via_upload_using_external_key_invalid(self): + self.create_and_enroll_student(username='a_user', external_key='a_user_external_key') + csv_content = 'user,mode,topic_0' + '\n' + csv_content += 'a_user_external_key_invalid,audit,team wind power' + csv_file = SimpleUploadedFile('test_file.csv', csv_content.encode('utf8'), content_type='text/csv') + self.client.login(username=self.users['course_staff'].username, password=self.users['course_staff'].password) + response = self.make_call( + reverse('team_membership_bulk_management', args=[self.good_course_id]), + 400, + method='post', + data={'csv': csv_file}, + user='staff' + ) + response_text = json.loads(response.content.decode('utf-8')) + self.assertEqual( + response_text['errors'], + ['User name/email/external key: a_user_external_key_invalid does not exist.'] + ) + + def test_upload_non_ascii(self): + csv_content = 'user,mode,topic_0' + '\n' + team_name = 'è‘—æ–‡ä¼è‡ºå€‹' + user_name = 'è‘—è‘—æ–‡ä¼è‡ºå€‹æ–‡ä¼è‡ºå€‹' + self.create_and_enroll_student(username=user_name) + csv_content += '{},audit,{}'.format(user_name, team_name) + csv_file = SimpleUploadedFile('test_file.csv', csv_content.encode('utf8'), content_type='text/csv') + self.client.login(username=self.users['course_staff'].username, password=self.users['course_staff'].password) + self.make_call( + reverse('team_membership_bulk_management', args=[self.good_course_id]), + 201, method='post', + data={'csv': csv_file}, + user='staff' + ) + team = self.users[user_name].teams.first() + self.assertEqual( + team.name, + team_name + ) + self.assertEqual( + [user.username for user in team.users.all()], + [user_name] + ) + + def test_upload_assign_masters_learner_to_non_protected_team(self): + """ + Scenario: Attempt to add a learner enrolled in masters track to an existing, non-org protected team. + Outcome: Must fail + """ + masters_a = 'masters_a' + team = self.wind_team + self.create_and_enroll_student(username=masters_a, mode=CourseMode.MASTERS) + csv_content = 'user,mode,{}'.format(team.topic_id) + '\n' + csv_content += 'masters_a, masters,{}'.format(team.name) + csv_file = SimpleUploadedFile('test_file.csv', csv_content.encode('utf8'), content_type='text/csv') + self.client.login(username=self.users['course_staff'].username, password=self.users['course_staff'].password) + + response = self.make_call( + reverse('team_membership_bulk_management', args=[self.good_course_id]), + 400, method='post', + data={'csv': csv_file}, + user='staff' + ) + response_text = json.loads(response.content.decode('utf-8')) + expected_message = 'User {} does not have access to team {}.'.format( + masters_a, + team.name + ) + self.assertEqual(response_text['errors'][0], expected_message) diff --git a/lms/djangoapps/teams/views.py b/lms/djangoapps/teams/views.py index e802413c46fadd760289b4f0b66a3b18513bf102..bd1dc26478a12084c18545ab7e321a94d6a768ee 100644 --- a/lms/djangoapps/teams/views.py +++ b/lms/djangoapps/teams/views.py @@ -13,7 +13,7 @@ from django.core.exceptions import PermissionDenied from django.db.models.signals import post_save from django.dispatch import receiver from django.http import Http404, HttpResponse, JsonResponse -from django.shortcuts import get_object_or_404, render_to_response +from django.shortcuts import get_object_or_404, render from django.utils.functional import cached_property from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_noop @@ -34,7 +34,7 @@ from lms.djangoapps.discussion.django_comment_client.utils import has_discussion from lms.djangoapps.teams.models import CourseTeam, CourseTeamMembership from openedx.core.lib.teams_config import TeamsetType from openedx.core.lib.api.parsers import MergePatchParser -from openedx.core.lib.api.permissions import IsStaffOrReadOnly +from openedx.core.lib.api.permissions import IsCourseStaffInstructor, IsStaffOrReadOnly from openedx.core.lib.api.view_utils import ( ExpandableFieldViewMixin, RetrievePatchAPIView, @@ -51,6 +51,7 @@ from .api import ( add_team_count, can_user_modify_team, can_user_create_team_in_topic, + get_assignments_for_team, has_course_staff_privileges, has_specific_team_access, has_specific_teamset_access, @@ -68,6 +69,7 @@ from .serializers import ( TopicSerializer ) from .utils import emit_team_event +from .waffle import are_team_submissions_enabled TEAM_MEMBERSHIPS_PER_PAGE = 5 TOPICS_PER_PAGE = 12 @@ -137,6 +139,7 @@ class TeamsDashboardView(GenericAPIView): # to the serializer so that the paginated results indicate how they were sorted. sort_order = 'name' topics = get_alphabetical_topics(course) + topics = _filter_hidden_private_teamsets(user, topics, course) organization_protection_status = user_organization_protection_status(request.user, course_key) # We have some frontend logic that needs to know if we have any open, public, or managed teamsets, @@ -210,7 +213,12 @@ class TeamsDashboardView(GenericAPIView): "disable_courseware_js": True, "teams_base_url": reverse('teams_dashboard', request=request, kwargs={'course_id': course_id}), } - return render_to_response("teams/teams.html", context) + + # Assignments are feature-flagged + if are_team_submissions_enabled(course_key): + context["teams_assignments_url"] = reverse('teams_assignments_list', args=['team_id']) + + return render(request, "teams/teams.html", context) def _serialize_and_paginate(self, pagination_cls, queryset, request, serializer_cls, serializer_ctx): """ @@ -436,8 +444,6 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): ) return Response(error, status=status.HTTP_400_BAD_REQUEST) - if course_module.teamsets_by_id[topic_id].is_private_managed: - result_filter.update({'membership__user__username': request.user}) result_filter.update({'topic_id': topic_id}) organization_protection_status = user_organization_protection_status( @@ -470,22 +476,11 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): # Non-staff users should not be able to see private_managed teams that they are not on. # Staff shouldn't have any excluded teams. - - if not has_access(request.user, 'staff', course_key): - private_teamset_ids = [ts.teamset_id for ts in course_module.teamsets if ts.is_private_managed] - excluded_team_ids = CourseTeam.objects.filter( - course_id=course_key, - topic_id__in=private_teamset_ids - ).exclude( - membership__user=request.user - ).values_list('team_id', flat=True) - excluded_team_ids = set(excluded_team_ids) - else: - excluded_team_ids = set() + excluded_private_team_ids = self._get_private_team_ids_to_exclude(course_module) search_results['results'] = [ result for result in search_results['results'] - if result['data']['id'] not in excluded_team_ids + if result['data']['id'] not in excluded_private_team_ids ] search_results['total'] = len(search_results['results']) @@ -511,18 +506,10 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): 'last_activity_at': ('-last_activity_at', 'team_size'), } - if not has_access(request.user, 'staff', course_key): - # hide private_managed courses from non-admin users that aren't members of those teams - private_topic_ids = [ts.teamset_id for ts in course_module.teamsets if - ts.is_private_managed] - public_teams = CourseTeam.objects.filter(**result_filter).exclude( - topic_id__in=private_topic_ids) - private_managed_teams_of_user = CourseTeam.objects.filter(topic_id__in=private_topic_ids, - membership__user__username=request.user) - queryset = public_teams | private_managed_teams_of_user - else: - queryset = CourseTeam.objects.filter(**result_filter) + # hide private_managed courses from non-staff users that aren't members of those teams + excluded_private_team_ids = self._get_private_team_ids_to_exclude(course_module) + queryset = CourseTeam.objects.filter(**result_filter).exclude(team_id__in=excluded_private_team_ids) order_by_input = request.query_params.get('order_by', 'name') if order_by_input not in ordering_schemes: return Response( @@ -651,6 +638,24 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): page_query_param = self.request.query_params.get(self.paginator.page_query_param) return page_kwarg or page_query_param or 1 + def _get_private_team_ids_to_exclude(self, course_module): + """ + Get the list of team ids that should be excluded from the response. + Staff can see all private teams. + Users should not be able to see teams in private teamsets that they are not a member of. + """ + if has_access(self.request.user, 'staff', course_module.id): + return set() + + private_teamset_ids = [ts.teamset_id for ts in course_module.teamsets if ts.is_private_managed] + excluded_team_ids = CourseTeam.objects.filter( + course_id=course_module.id, + topic_id__in=private_teamset_ids + ).exclude( + membership__user=self.request.user + ).values_list('team_id', flat=True) + return set(excluded_team_ids) + class IsEnrolledOrIsStaff(permissions.BasePermission): """Permission that checks to see if the user is enrolled in the course or is staff.""" @@ -663,13 +668,14 @@ class IsEnrolledOrIsStaff(permissions.BasePermission): class IsStaffOrPrivilegedOrReadOnly(IsStaffOrReadOnly): """ Permission that checks to see if the user is global staff, course - staff, or has discussion privileges. If none of those conditions are + staff, course admin, or has discussion privileges. If none of those conditions are met, only read access will be granted. """ def has_object_permission(self, request, view, obj): return ( has_discussion_privileges(request.user, obj.course_id) or + IsCourseStaffInstructor.has_object_permission(self, request, view, obj) or super(IsStaffOrPrivilegedOrReadOnly, self).has_object_permission(request, view, obj) ) @@ -821,6 +827,87 @@ class TeamsDetailView(ExpandableFieldViewMixin, RetrievePatchAPIView): return Response(status=status.HTTP_204_NO_CONTENT) +class TeamsAssignmentsView(GenericAPIView): + """ + **Use Cases** + + Get a team's assignments + + **Example Requests**: + + GET /api/team/v0/teams/{team_id}/assignments + + **Response Values for GET** + + If the user is logged in, the response is an array of the following data strcuture: + + * display_name: The name of the assignment to display (currently the Unit title) + + * location: The jump link to a specific assignments + + 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 team assignments are not enabled for course, a 503 is returned. + + If the user is not logged in, a 401 error is returned. + + If the user is unenrolled or does not have API access, a 403 error is returned. + + If the supplied course/team is bad or the user is not permitted to + search in a protected team, a 404 error is returned as if the team does not exist. + + """ + authentication_classes = (BearerAuthentication, SessionAuthentication) + permission_classes = ( + permissions.IsAuthenticated, + IsEnrolledOrIsStaff, + HasSpecificTeamAccess, + IsStaffOrPrivilegedOrReadOnly, + ) + + def get(self, request, team_id): + """GET v0/teams/{team_id_pattern}/assignments""" + course_team = get_object_or_404(CourseTeam, team_id=team_id) + user = request.user + course_id = course_team.course_id + + if not are_team_submissions_enabled(course_id): + return Response(status=status.HTTP_503_SERVICE_UNAVAILABLE) + + if not has_team_api_access(request.user, course_id): + return Response(status=status.HTTP_403_FORBIDDEN) + + if not has_specific_team_access(user, course_team): + return Response(status=status.HTTP_404_NOT_FOUND) + + teamset_ora_blocks = get_assignments_for_team(user, course_team) + + # Serialize info for display + assignments = [{ + 'display_name': self._display_name_for_ora_block(block), + 'location': self._jump_location_for_block(course_id, block.location) + } for block in teamset_ora_blocks] + + return Response(assignments) + + def _display_name_for_ora_block(self, block): + """ Get the unit name where the ORA is located for better display naming """ + unit = modulestore().get_item(block.parent) + section = modulestore().get_item(unit.parent) + + return "{section}: {unit}".format( + section=section.display_name, + unit=unit.display_name + ) + + def _jump_location_for_block(self, course_id, location): + """ Get the URL for jumping to a designated XBlock in a course """ + return reverse('jump_to', kwargs={'course_id': str(course_id), 'location': str(location)}) + + class TopicListView(GenericAPIView): """ **Use Cases** @@ -930,15 +1017,15 @@ class TopicListView(GenericAPIView): # in the case of "team_count". organization_protection_status = user_organization_protection_status(request.user, course_id) topics = get_alphabetical_topics(course_module) - topics = self._filter_hidden_private_teamsets(topics, course_module) + topics = _filter_hidden_private_teamsets(request.user, topics, course_module) if ordering == 'team_count': - add_team_count(topics, course_id, organization_protection_status) + add_team_count(request.user, topics, course_id, organization_protection_status) topics.sort(key=lambda t: t['team_count'], reverse=True) page = self.paginate_queryset(topics) serializer = TopicSerializer( page, - context={'course_id': course_id}, + context={'course_id': course_id, 'user': request.user}, many=True, ) else: @@ -947,6 +1034,7 @@ class TopicListView(GenericAPIView): serializer = BulkTeamCountTopicSerializer( page, context={ + 'request': request, 'course_id': course_id, 'organization_protection_status': organization_protection_status }, @@ -958,25 +1046,26 @@ class TopicListView(GenericAPIView): return response - def _filter_hidden_private_teamsets(self, teamsets, course_module): - """ - Return a filtered list of teamsets, removing any private teamsets that a user doesn't have access to. - Follows the same logic as `has_specific_teamset_access` but in bulk rather than for one teamset at a time - """ - if has_course_staff_privileges(self.request.user, course_module.id): - return teamsets - private_teamset_ids = [teamset.teamset_id for teamset in course_module.teamsets if teamset.is_private_managed] - teamset_ids_user_has_access_to = set( - CourseTeam.objects.filter( - course_id=course_module.id, - topic_id__in=private_teamset_ids, - membership__user=self.request.user - ).values_list('topic_id', flat=True) - ) - return [ - teamset for teamset in teamsets - if teamset['type'] != TeamsetType.private_managed.value or teamset['id'] in teamset_ids_user_has_access_to - ] + +def _filter_hidden_private_teamsets(user, teamsets, course_module): + """ + Return a filtered list of teamsets, removing any private teamsets that a user doesn't have access to. + Follows the same logic as `has_specific_teamset_access` but in bulk rather than for one teamset at a time + """ + if has_course_staff_privileges(user, course_module.id): + return teamsets + private_teamset_ids = [teamset.teamset_id for teamset in course_module.teamsets if teamset.is_private_managed] + teamset_ids_user_has_access_to = set( + CourseTeam.objects.filter( + course_id=course_module.id, + topic_id__in=private_teamset_ids, + membership__user=user + ).values_list('topic_id', flat=True) + ) + return [ + teamset for teamset in teamsets + if teamset['type'] != TeamsetType.private_managed.value or teamset['id'] in teamset_ids_user_has_access_to + ] def get_alphabetical_topics(course_module): @@ -1069,7 +1158,8 @@ class TopicDetailView(APIView): topic.cleaned_data, context={ 'course_id': course_id, - 'organization_protection_status': organization_protection_status + 'organization_protection_status': organization_protection_status, + 'user': request.user } ) return Response(serializer.data) @@ -1558,7 +1648,7 @@ class MembershipBulkManagementView(GenericAPIView): team_import_manager.set_team_membership_from_csv(inputfile_handle) if team_import_manager.import_succeeded: - msg = "{} learners were assigned to teams.".format(team_import_manager.number_of_learners_assigned) + msg = "{} learners were affected.".format(team_import_manager.number_of_learners_assigned) return JsonResponse({'message': msg}, status=status.HTTP_201_CREATED) else: return JsonResponse({ diff --git a/lms/djangoapps/teams/waffle.py b/lms/djangoapps/teams/waffle.py new file mode 100644 index 0000000000000000000000000000000000000000..8486d17b93117a81886117863342b0cd1bfd4949 --- /dev/null +++ b/lms/djangoapps/teams/waffle.py @@ -0,0 +1,26 @@ +""" +Togglable settings for Teams behavior +""" +from django.conf import settings +from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag + + +# Course Waffle inherited from edx/edx-ora2 +WAFFLE_NAMESPACE = 'openresponseassessment' +TEAM_SUBMISSIONS_FLAG = 'team_submissions' + +# edx/edx-platform feature +TEAM_SUBMISISONS_FEATURE = 'ENABLE_ORA_TEAM_SUBMISSIONS' + + +def are_team_submissions_enabled(course_key): + """ + Checks to see if the CourseWaffleFlag or Django setting for team submissions is enabled + """ + if CourseWaffleFlag(WAFFLE_NAMESPACE, TEAM_SUBMISSIONS_FLAG).is_enabled(course_key): + return True + + if settings.FEATURES.get(TEAM_SUBMISISONS_FEATURE, False): + return True + + return False diff --git a/lms/djangoapps/verify_student/apps.py b/lms/djangoapps/verify_student/apps.py index 32febff4c0d3f39182da0441cf4eadbb7f81c74f..ec786b82c35f33089741983a531b35a9ad83c565 100644 --- a/lms/djangoapps/verify_student/apps.py +++ b/lms/djangoapps/verify_student/apps.py @@ -17,4 +17,5 @@ class VerifyStudentConfig(AppConfig): """ Connect signal handlers. """ - from . import signals # pylint: disable=unused-variable + from . import signals # pylint: disable=unused-import + from . import tasks # pylint: disable=unused-import diff --git a/lms/djangoapps/verify_student/message_types.py b/lms/djangoapps/verify_student/message_types.py index 2d55d04f1f710fdb1bab6ca2ea95dfabd2e9217d..24097b434ad5ce4c4b1bd9b1c4df3ad284d414e2 100644 --- a/lms/djangoapps/verify_student/message_types.py +++ b/lms/djangoapps/verify_student/message_types.py @@ -13,4 +13,4 @@ class VerificationExpiry(BaseMessageType): def __init__(self, *args, **kwargs): super(VerificationExpiry, self).__init__(*args, **kwargs) - self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + self.options['transactional'] = True diff --git a/lms/djangoapps/verify_student/models.py b/lms/djangoapps/verify_student/models.py index 3f27affb7f9640dcdfb881dce87766adb5dbb623..6a838e0697721d5629da73719559f3a807b73abd 100644 --- a/lms/djangoapps/verify_student/models.py +++ b/lms/djangoapps/verify_student/models.py @@ -44,7 +44,7 @@ from lms.djangoapps.verify_student.ssencrypt import ( from openedx.core.djangoapps.signals.signals import LEARNER_NOW_VERIFIED from openedx.core.storage import get_storage -from .utils import auto_verify_for_testing_enabled, earliest_allowed_verification_date +from .utils import auto_verify_for_testing_enabled, earliest_allowed_verification_date, submit_request_to_ss log = logging.getLogger(__name__) @@ -741,7 +741,7 @@ class SoftwareSecurePhotoVerification(PhotoVerification): def submit(self, copy_id_photo_from=None): """ Submit our verification attempt to Software Secure for validation. This - will set our status to "submitted" if the post is successful, and + will set our status to "submitted", if the post is successful or will set to "must_retry" if the post fails. Keyword Arguments: @@ -749,7 +749,6 @@ class SoftwareSecurePhotoVerification(PhotoVerification): data from this attempt. This is used for re-verification, in which new face photos are sent with previously-submitted ID photos. """ - from .tasks import send_request_to_ss_for_user if auto_verify_for_testing_enabled(): self.mark_submit() fake_response = requests.Response() @@ -764,9 +763,9 @@ class SoftwareSecurePhotoVerification(PhotoVerification): self.receipt_id, copy_id_photo_from.receipt_id, ) + transaction.on_commit( - lambda: - send_request_to_ss_for_user.delay(user_verification_id=self.id, copy_id_photo_from=copy_id_photo_from) + lambda: submit_request_to_ss(user_verification=self, copy_id_photo_from=copy_id_photo_from) ) def parsed_error_msg(self): diff --git a/lms/djangoapps/verify_student/tasks.py b/lms/djangoapps/verify_student/tasks.py index cee2c0838d7b05cc7250ba04a20f484606152322..081e241f22aa11abb30ee6c9d8296c3a4b0b6085 100644 --- a/lms/djangoapps/verify_student/tasks.py +++ b/lms/djangoapps/verify_student/tasks.py @@ -11,8 +11,8 @@ from celery import Task, task from celery.states import FAILURE from django.conf import settings from django.core.mail import EmailMessage + from edxmako.shortcuts import render_to_string -from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers ACE_ROUTING_KEY = getattr(settings, 'ACE_ROUTING_KEY', None) @@ -41,8 +41,9 @@ class BaseSoftwareSecureTask(Task): 'response_ok': boolean, indicating if the response was ok 'response_text': string, indicating the response text in case of failure. """ - user_verification_id = kwargs['user_verification_id'] - user_verification = SoftwareSecurePhotoVerification.objects.get(id=user_verification_id) + from .models import SoftwareSecurePhotoVerification + + user_verification = SoftwareSecurePhotoVerification.objects.get(id=kwargs['user_verification_id']) if retval['response_ok']: user_verification.mark_submit() log.info( @@ -60,6 +61,8 @@ class BaseSoftwareSecureTask(Task): with "must_retry" so that it can be retried latter. """ if self.max_retries == self.request.retries and status == FAILURE: + from .models import SoftwareSecurePhotoVerification + user_verification_id = kwargs['user_verification_id'] user_verification = SoftwareSecurePhotoVerification.objects.get(id=user_verification_id) user_verification.mark_must_retry() @@ -110,6 +113,8 @@ def send_request_to_ss_for_user(self, user_verification_id, copy_id_photo_from): Returns: request.Response """ + from .models import SoftwareSecurePhotoVerification + user_verification = SoftwareSecurePhotoVerification.objects.get(id=user_verification_id) log.info('=>New Verification Task Received %r', user_verification.user.username) try: @@ -125,7 +130,7 @@ def send_request_to_ss_for_user(self, user_verification_id, copy_id_photo_from): 'response_ok': getattr(response, 'ok', False), 'response_text': getattr(response, 'text', '') } - except Exception as exc: # pylint: disable=bare-except + except Exception as exc: # pylint: disable=broad-except log.error( ( 'Retrying sending request to Software Secure for user: %r, Receipt ID: %r ' diff --git a/lms/djangoapps/verify_student/tests/test_utils.py b/lms/djangoapps/verify_student/tests/test_utils.py index 5418e068c95f6f756a9021328799f2cf1d7e64eb..a340968019a53c549ab6abe209fc41443cb0e9c7 100644 --- a/lms/djangoapps/verify_student/tests/test_utils.py +++ b/lms/djangoapps/verify_student/tests/test_utils.py @@ -8,13 +8,18 @@ import unittest from datetime import timedelta import ddt +import mock from django.conf import settings from django.utils import timezone from mock import patch from pytest import mark from lms.djangoapps.verify_student.models import ManualVerification, SoftwareSecurePhotoVerification, SSOVerification -from lms.djangoapps.verify_student.utils import most_recent_verification, verification_for_datetime +from lms.djangoapps.verify_student.utils import ( + most_recent_verification, + submit_request_to_ss, + verification_for_datetime +) from student.tests.factories import UserFactory FAKE_SETTINGS = { @@ -143,3 +148,21 @@ class TestVerifyStudentUtils(unittest.TestCase): self.assertEqual(most_recent, sso_verification) else: self.assertEqual(most_recent, manual_verification) + + @mock.patch('lms.djangoapps.verify_student.utils.log') + @mock.patch( + 'lms.djangoapps.verify_student.tasks.send_request_to_ss_for_user.delay', mock.Mock(side_effect=Exception('error')) + ) + def test_submit_request_to_ss(self, mock_log): + """Tests that we log appropriate information when celery task creation fails.""" + user = UserFactory.create() + attempt = SoftwareSecurePhotoVerification.objects.create(user=user) + attempt.mark_ready() + submit_request_to_ss(user_verification=attempt, copy_id_photo_from=None) + + mock_log.error.assert_called_with( + "Software Secure submit request %r failed, result: %s", + user.username, + 'error' + ) + self.assertTrue(attempt.status, SoftwareSecurePhotoVerification.STATUS.must_retry) diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index c4219bc3cf04dc81dac47a91899dc270e0cf236b..7ba3d90ed71eb47d2f7e039be4ce790f3548c98b 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -11,9 +11,6 @@ import httpretty import mock import simplejson as json import six -import six.moves.urllib.error # pylint: disable=import-error -import six.moves.urllib.parse # pylint: disable=import-error -import six.moves.urllib.request # pylint: disable=import-error from bs4 import BeautifulSoup from django.conf import settings from django.core import mail @@ -40,7 +37,6 @@ from lms.djangoapps.verify_student.views import PayAndVerifyView, checkout_with_ from openedx.core.djangoapps.embargo.test_utils import restrict_course from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme from openedx.core.djangoapps.user_api.accounts.api import get_account_settings -from shoppingcart.models import CertificateItem, Order from student.models import CourseEnrollment from student.tests.factories import CourseEnrollmentFactory, UserFactory from util.testing import UrlResetMixin @@ -1003,7 +999,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin, Tes def _get_page_data(self, response): """Retrieve the data attributes rendered on the page. """ - soup = BeautifulSoup(response.content) + soup = BeautifulSoup(markup=response.content, features="lxml") pay_and_verify_div = soup.find(id="pay-and-verify-container") self.assertIsNot( @@ -1228,21 +1224,6 @@ class CheckoutTestMixin(object): self.assertEqual(data, {'foo': 'bar'}) -@patch('lms.djangoapps.verify_student.views.checkout_with_shoppingcart', return_value=TEST_PAYMENT_DATA, autospec=True) -class TestCreateOrderShoppingCart(CheckoutTestMixin, ModuleStoreTestCase): - """ Test view behavior when the shoppingcart is used. """ - - def make_sku(self): - """ Checkout is handled by shoppingcart when the course mode's sku is empty. """ - return '' - - def _get_checkout_args(self, patched_create_order): - """ Assuming patched_create_order was called, return a mapping containing the call arguments.""" - return dict( - list(zip(('request', 'user', 'course_key', 'course_mode', 'amount'), patched_create_order.call_args[0])) - ) - - @override_settings(ECOMMERCE_API_URL=TEST_API_URL) @patch( 'lms.djangoapps.verify_student.views.checkout_with_ecommerce_service', @@ -1307,113 +1288,6 @@ class TestCheckoutWithEcommerceService(ModuleStoreTestCase): self.assertEqual(actual_payment_data, expected_payment_data) -class TestCreateOrderView(ModuleStoreTestCase): - """ - Tests for the create_order view of verified course enrollment process. - """ - - def setUp(self): - super(TestCreateOrderView, self).setUp() - - self.user = UserFactory.create(username="rusty", password="test") - self.client.login(username="rusty", password="test") - self.course_id = 'Robot/999/Test_Course' - self.course = CourseFactory.create(org='Robot', number='999', display_name='Test Course') - verified_mode = CourseMode( - course_id=CourseKey.from_string("Robot/999/Test_Course"), - mode_slug="verified", - mode_display_name="Verified Certificate", - min_price=50 - ) - verified_mode.save() - course_mode_post_data = { - 'certificate_mode': 'Select Certificate', - 'contribution': 50, - 'contribution-other-amt': '', - 'explain': '' - } - self.client.post( - reverse("course_modes_choose", kwargs={'course_id': self.course_id}), - course_mode_post_data - ) - - @patch.dict(settings.FEATURES, {'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': True}) - def test_invalid_amount(self): - response = self._create_order('1.a', self.course_id, expect_status_code=400) - self.assertContains(response, 'Selected price is not valid number.', status_code=400) - - @patch.dict(settings.FEATURES, {'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': True}) - def test_invalid_mode(self): - # Create a course that does not have a verified mode - course_id = 'Fake/999/Test_Course' - CourseFactory.create(org='Fake', number='999', display_name='Test Course') - response = self._create_order('50', course_id, expect_status_code=400) - self.assertContains( - response, - 'This course doesn\'t support paid certificates', - status_code=400, - ) - - @patch.dict(settings.FEATURES, {'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': True}) - def test_create_order_fail_with_get(self): - create_order_post_data = { - 'contribution': 50, - 'course_id': self.course_id, - } - - # Use the wrong HTTP method - response = self.client.get(reverse('verify_student_create_order'), create_order_post_data) - self.assertEqual(response.status_code, 405) - - @patch.dict(settings.FEATURES, {'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': True}) - def test_create_order_success(self): - response = self._create_order(50, self.course_id) - json_response = json.loads(response.content.decode('utf-8')) - self.assertIsNotNone(json_response['payment_form_data'].get('orderNumber')) # TODO not canonical - - # Verify that the order exists and is configured correctly - order = Order.objects.get(user=self.user) - self.assertEqual(order.status, 'paying') - item = CertificateItem.objects.get(order=order) - self.assertEqual(item.status, 'paying') - self.assertEqual(item.course_id, self.course.id) - self.assertEqual(item.mode, 'verified') - - def _create_order(self, contribution, course_id, expect_success=True, expect_status_code=200): - """Create a new order. - - Arguments: - contribution (int): The contribution amount. - course_id (CourseKey): The course to purchase. - - Keyword Arguments: - expect_success (bool): If True, verify that the response was successful. - expect_status_code (int): The expected HTTP status code - - Returns: - HttpResponse - - """ - url = reverse('verify_student_create_order') - data = { - 'contribution': contribution, - 'course_id': course_id, - 'processor': '', - } - - response = self.client.post(url, data) - self.assertEqual(response.status_code, expect_status_code) - - if expect_status_code == 200: - json_response = json.loads(response.content.decode('utf-8')) - if expect_success: - self.assertEqual(set(json_response.keys()), PAYMENT_DATA_KEYS) - else: - self.assertFalse(json_response['success']) - - return response - - @ddt.ddt @patch.dict(settings.FEATURES, {'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': True}) class TestSubmitPhotosForVerification(MockS3BotoMixin, TestVerificationBase): @@ -1749,7 +1623,7 @@ class TestPhotoVerificationResultsCallback(ModuleStoreTestCase, TestVerification mock.Mock(side_effect=mocked_has_valid_signature) ) @patch('lms.djangoapps.verify_student.views.log.error') - @patch('lms.djangoapps.verify_student.utils.SailthruClient.send') + @patch('sailthru.sailthru_client.SailthruClient.send') def test_passed_status_template(self, mock_sailthru_send, mock_log_error): """ Test for verification passed. @@ -1791,7 +1665,7 @@ class TestPhotoVerificationResultsCallback(ModuleStoreTestCase, TestVerification mock.Mock(side_effect=mocked_has_valid_signature) ) @patch('lms.djangoapps.verify_student.views.log.error') - @patch('lms.djangoapps.verify_student.utils.SailthruClient.send') + @patch('sailthru.sailthru_client.SailthruClient.send') def test_first_time_verification(self, mock_sailthru_send, mock_log_error): # pylint: disable=unused-argument """ Test for verification passed if the learner does not have any previous verification diff --git a/lms/djangoapps/verify_student/utils.py b/lms/djangoapps/verify_student/utils.py index 0e754e8ffa0a2ee117d00fe202b12e95f1e5308f..768f6ca9b76cf6cb1a2e8087bf2b5d1f384ffbc9 100644 --- a/lms/djangoapps/verify_student/utils.py +++ b/lms/djangoapps/verify_student/utils.py @@ -3,24 +3,42 @@ Common Utilities for the verify_student application. """ - import datetime import logging from django.conf import settings from django.utils.timezone import now -from sailthru import SailthruClient +from six import text_type + +from lms.djangoapps.verify_student.tasks import send_request_to_ss_for_user log = logging.getLogger(__name__) +def submit_request_to_ss(user_verification, copy_id_photo_from): + """ + Submit our verification attempt to Software Secure for validation. + + Submits the task to software secure and If the task creation fails, + set the verification status to "must_retry". + """ + try: + send_request_to_ss_for_user.delay( + user_verification_id=user_verification.id, copy_id_photo_from=copy_id_photo_from + ) + except Exception as error: + log.error( + "Software Secure submit request %r failed, result: %s", user_verification.user.username, text_type(error) + ) + user_verification.mark_must_retry() + + def is_verification_expiring_soon(expiration_datetime): """ Returns True if verification is expiring within EXPIRING_SOON_WINDOW. """ if expiration_datetime: - if (expiration_datetime - now()).days <= settings.VERIFY_STUDENT.get( - "EXPIRING_SOON_WINDOW"): + if (expiration_datetime - now()).days <= settings.VERIFY_STUDENT.get("EXPIRING_SOON_WINDOW"): return True return False diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index bab54f8fd20f2191fc6853c1bf9a9f052d0ddbaa..ab7e0ed70551059b1f7da0f57c7f70b89e8009fc 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -47,8 +47,6 @@ from openedx.core.djangoapps.user_api.accounts import NAME_MIN_LENGTH from openedx.core.djangoapps.user_api.accounts.api import update_account_settings from openedx.core.djangoapps.user_api.errors import AccountValidationError, UserNotFound from openedx.core.lib.log_utils import audit_log -from shoppingcart.models import CertificateItem, Order -from shoppingcart.processors import get_purchase_endpoint, get_signed_purchase_params from student.models import CourseEnrollment from track import segment from util.db import outer_atomic @@ -443,10 +441,10 @@ class PayAndVerifyView(View): # utm_params is [(u'utm_content', u'course-v1:IDBx IDB20.1x 1T2017'),... utm_params = [item for item in self.request.GET.items() if 'utm_' in item[0]] # utm_params is utm_content=course-v1%3AIDBx+IDB20.1x+1T2017&... - utm_params = six.moves.urllib.parse.urlencode(utm_params, True) # pylint: disable=too-many-function-args + utm_params = six.moves.urllib.parse.urlencode(utm_params, True) # utm_params is utm_content=course-v1:IDBx+IDB20.1x+1T2017&... # (course-keys do not have url encoding) - utm_params = six.moves.urllib.parse.unquote(utm_params) # pylint: disable=too-many-function-args + utm_params = six.moves.urllib.parse.unquote(utm_params) if utm_params: if '?' in url: url = url + '&' + utm_params @@ -757,38 +755,6 @@ def checkout_with_ecommerce_service(user, course_key, course_mode, processor): ) -def checkout_with_shoppingcart(request, user, course_key, course_mode, amount): - """ Create an order and trigger checkout using shoppingcart.""" - cart = Order.get_cart_for_user(user) - cart.clear() - enrollment_mode = course_mode.slug - CertificateItem.add_to_order(cart, course_key, amount, enrollment_mode) - - # Change the order's status so that we don't accidentally modify it later. - # We need to do this to ensure that the parameters we send to the payment system - # match what we store in the database. - # (Ordinarily we would do this client-side when the user submits the form, but since - # the JavaScript on this page does that immediately, we make the change here instead. - # This avoids a second AJAX call and some additional complication of the JavaScript.) - # If a user later re-enters the verification / payment flow, she will create a new order. - cart.start_purchase() - - callback_url = request.build_absolute_uri( - reverse("shoppingcart.views.postpay_callback") - ) - - payment_data = { - 'payment_processor_name': settings.CC_PROCESSOR_NAME, - 'payment_page_url': get_purchase_endpoint(), - 'payment_form_data': get_signed_purchase_params( - cart, - callback_url=callback_url, - extra_data=[six.text_type(course_key), course_mode.slug] - ), - } - return payment_data - - @require_POST @login_required def create_order(request): @@ -835,16 +801,13 @@ def create_order(request): if amount < current_mode.min_price: return HttpResponseBadRequest(_("No selected price or selected price is below minimum.")) - if current_mode.sku: - # if request.POST doesn't contain 'processor' then the service's default payment processor will be used. - payment_data = checkout_with_ecommerce_service( - request.user, - course_id, - current_mode, - request.POST.get('processor') - ) - else: - payment_data = checkout_with_shoppingcart(request, request.user, course_id, current_mode, amount) + # if request.POST doesn't contain 'processor' then the service's default payment processor will be used. + payment_data = checkout_with_ecommerce_service( + request.user, + course_id, + current_mode, + request.POST.get('processor') + ) if 'processor' not in request.POST: # (XCOM-214) To be removed after release. diff --git a/lms/envs/bok_choy.py b/lms/envs/bok_choy.py index 029449bb1117a9c7ed9bb1023d1937fb7fd71e07..513dbf4928c575b2e21e529e02655cc0be89d5e8 100644 --- a/lms/envs/bok_choy.py +++ b/lms/envs/bok_choy.py @@ -58,23 +58,11 @@ update_module_store_settings( default_store=os.environ.get('DEFAULT_STORE', 'draft'), ) -# Capture the console log via template includes, until webdriver supports log capture again -CAPTURE_CONSOLE_LOG = True - PLATFORM_NAME = ugettext_lazy(u"édX") PLATFORM_DESCRIPTION = ugettext_lazy(u"Open édX Platform") -# We need to test different scenarios, following setting effectively disbale rate limiting -PASSWORD_RESET_EMAIL_RATE_LIMIT = { - 'no_of_emails': 1, - 'per_seconds': 1 -} - ############################ STATIC FILES ############################# -# Enable debug so that static assets are served by Django -DEBUG = True - # 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/" @@ -92,22 +80,6 @@ WEBPACK_LOADER['DEFAULT']['STATS_FILE'] = TEST_ROOT / "staticfiles" / "lms" / "w # Don't use compression during tests PIPELINE['JS_COMPRESSOR'] = None -################################# CELERY ###################################### - -CELERY_ALWAYS_EAGER = True -CELERY_RESULT_BACKEND = 'djcelery.backends.cache:CacheBackend' - -BLOCK_STRUCTURES_SETTINGS = dict( - # We have CELERY_ALWAYS_EAGER set to True, so there's no asynchronous - # code running and the celery routing is unimportant. - # It does not make sense to retry. - TASK_MAX_RETRIES=0, - # course publish task delay is irrelevant is because the task is run synchronously - COURSE_PUBLISH_TASK_DELAY=0, - # retry delay is irrelevent because we never retry - TASK_DEFAULT_RETRY_DELAY=0, -) - ###################### Grades ###################### GRADES_DOWNLOAD = { 'STORAGE_TYPE': 'localfs', @@ -115,21 +87,6 @@ GRADES_DOWNLOAD = { 'ROOT_PATH': os.path.join(mkdtemp(), 'edx-s3', 'grades'), } -FEATURES['PERSISTENT_GRADES_ENABLED_FOR_ALL_TESTS'] = True -FEATURES['ASSUME_ZERO_GRADE_IF_ABSENT_FOR_ALL_TESTS'] = True - - -# Configure the LMS to use our stub XQueue implementation -XQUEUE_INTERFACE['url'] = 'http://localhost:8040' - -# Configure the LMS to use our stub EdxNotes implementation -EDXNOTES_PUBLIC_API = 'http://localhost:8042/api/v1' -EDXNOTES_INTERNAL_API = 'http://localhost:8042/api/v1' - -EDXNOTES_CONNECT_TIMEOUT = 10 # time in seconds -EDXNOTES_READ_TIMEOUT = 10 # time in seconds - -NOTES_DISABLED_TABS = [] LOG_OVERRIDES = [ ('track.middleware', logging.CRITICAL), @@ -139,45 +96,6 @@ LOG_OVERRIDES = [ for log_name, log_level in LOG_OVERRIDES: logging.getLogger(log_name).setLevel(log_level) -# Enable milestones app -FEATURES['MILESTONES_APP'] = True - -# Enable oauth authentication, which we test. -FEATURES['ENABLE_OAUTH2_PROVIDER'] = True -OAUTH_ENFORCE_SECURE = False - -# Enable pre-requisite course -FEATURES['ENABLE_PREREQUISITE_COURSES'] = True - -# Enable Course Discovery -FEATURES['ENABLE_COURSE_DISCOVERY'] = True - -# Enable student notes -FEATURES['ENABLE_EDXNOTES'] = True - -# Enable teams feature -FEATURES['ENABLE_TEAMS'] = True - -# Enable custom content licensing -FEATURES['LICENSING'] = True - -# Use the auto_auth workflow for creating users and logging them in -FEATURES['AUTOMATIC_AUTH_FOR_TESTING'] = True -FEATURES['RESTRICT_AUTOMATIC_AUTH'] = False - -# Open up endpoint for faking Software Secure responses -FEATURES['ENABLE_SOFTWARE_SECURE_FAKE'] = True - -# Disable instructor dash buttons for downloading course data when enrollment exceeds this number -FEATURES['MAX_ENROLLMENT_INSTR_BUTTONS'] = 4 - -FEATURES['ENABLE_ENROLLMENT_TRACK_USER_PARTITION'] = True - -########################### Entrance Exams ################################# -FEATURES['ENTRANCE_EXAMS'] = True - -FEATURES['ENABLE_SPECIAL_EXAMS'] = True - YOUTUBE_HOSTNAME = os.environ.get('BOK_CHOY_HOSTNAME', '127.0.0.1') # Point the URL used to test YouTube availability to our stub YouTube server @@ -190,44 +108,7 @@ YOUTUBE['TEXT_API']['url'] = "{0}:{1}/test_transcripts_youtube/".format(YOUTUBE_ ############################# SECURITY SETTINGS ################################ # Default to advanced security in common.py, so tests can reset here to use # a simpler security model -FEATURES['ENABLE_MAX_FAILED_LOGIN_ATTEMPTS'] = False -FEATURES['SQUELCH_PII_IN_LOGS'] = False -FEATURES['PREVENT_CONCURRENT_LOGINS'] = False - -FEATURES['ENABLE_MOBILE_REST_API'] = True # Show video bumper in LMS -FEATURES['ENABLE_VIDEO_BUMPER'] = True # Show video bumper in LMS -FEATURES['SHOW_BUMPER_PERIODICITY'] = 1 - -# Enable courseware search for tests -FEATURES['ENABLE_COURSEWARE_SEARCH'] = True - -# Enable dashboard search for tests -FEATURES['ENABLE_DASHBOARD_SEARCH'] = True - -# discussion home panel, which includes a subscription on/off setting for discussion digest emails. -FEATURES['ENABLE_DISCUSSION_HOME_PANEL'] = True - -# Enable support for OpenBadges accomplishments -FEATURES['ENABLE_OPENBADGES'] = True -FEATURES['ENABLE_LTI_PROVIDER'] = True -INSTALLED_APPS.append('lti_provider.apps.LtiProviderConfig') -AUTHENTICATION_BACKENDS.append('lti_provider.users.LtiBackend') - -FEATURES['ENABLE_THIRD_PARTY_AUTH'] = True -THIRD_PARTY_AUTH = { - "Google": { - "SOCIAL_AUTH_GOOGLE_OAUTH2_KEY": "test", - "SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET": "test" - }, - "Facebook": { - "SOCIAL_AUTH_FACEBOOK_KEY": "test", - "SOCIAL_AUTH_FACEBOOK_SECRET": "test" - } -} - -# Use MockSearchEngine as the search engine for test scenario -SEARCH_ENGINE = "search.tests.mock_search_engine.MockSearchEngine" # Path at which to store the mock index MOCK_SEARCH_BACKING_FILE = ( TEST_ROOT / "index_file.dat" @@ -239,9 +120,6 @@ VERIFY_STUDENT["SOFTWARE_SECURE"] = { "API_SECRET_KEY": "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC", } -# this secret key should be the same as cms/envs/bok_choy.py's -SECRET_KEY = "very_secret_bok_choy_key" - # Set dummy values for profile image settings. PROFILE_IMAGE_BACKEND = { 'class': 'openedx.core.storage.OverwriteStorage', @@ -251,11 +129,6 @@ PROFILE_IMAGE_BACKEND = { }, } -BADGING_BACKEND = 'lms.djangoapps.badges.backends.tests.dummy_backend.DummyBackend' - -# Configure the LMS to use our stub eCommerce implementation -ECOMMERCE_API_URL = 'http://localhost:8043/api/v2/' - LMS_ROOT_URL = "http://localhost:{}".format(os.environ.get('BOK_CHOY_LMS_PORT', 8003)) CMS_BASE = "localhost:{}".format(os.environ.get('BOK_CHOY_CMS_PORT', 8031)) LOGIN_REDIRECT_WHITELIST = [CMS_BASE] @@ -269,11 +142,6 @@ if RELEASE_LINE == "master": 'course_author': 'https://edx.readthedocs.io/projects/edx-partner-course-staff', } -WAFFLE_OVERRIDE = True - -############## Settings for Completion API ######################### - -COMPLETION_BY_VIEWING_DELAY_MS = 1000 ##################################################################### # Lastly, see if the developer has any local overrides. diff --git a/lms/envs/bok_choy.yml b/lms/envs/bok_choy.yml index 6c36a617ffcb0888c1aa5298cc8fbc554d5bb40f..9e555ebaaac9547eb7f64668f2e8094a49ccc707 100644 --- a/lms/envs/bok_choy.yml +++ b/lms/envs/bok_choy.yml @@ -6,6 +6,17 @@ AWS_ACCESS_KEY_ID: '' AWS_SECRET_ACCESS_KEY: '' BUGS_EMAIL: bugs@example.com BULK_EMAIL_DEFAULT_FROM_EMAIL: no-reply@example.com +BADGING_BACKEND: 'lms.djangoapps.badges.backends.tests.dummy_backend.DummyBackend' +BLOCK_STRUCTURES_SETTINGS: + # We have CELERY_ALWAYS_EAGER set to True, so there's no asynchronous + # code running and the celery routing is unimportant. + # It does not make sense to retry. + TASK_MAX_RETRIES: 0 + # course publish task delay is irrelevant is because the task is run synchronously + COURSE_PUBLISH_TASK_DELAY: 0 + # retry delay is irrelevent because we never retry + TASK_DEFAULT_RETRY_DELAY: 0 + CACHES: celery: BACKEND: django.core.cache.backends.memcached.MemcachedCache @@ -32,6 +43,10 @@ CACHES: KEY_FUNCTION: util.memcache.safe_key KEY_PREFIX: integration_static_files LOCATION: ['localhost:11211'] + +# Capture the console log via template includes, until webdriver supports log capture again +CAPTURE_CONSOLE_LOG: True + CC_PROCESSOR: CyberSource2: {ACCESS_KEY: abcd123, PROFILE_ID: edx, PURCHASE_ENDPOINT: /shoppingcart/payment_fake, SECRET_KEY: abcd123} @@ -40,12 +55,16 @@ CELERY_BROKER_HOSTNAME: localhost CELERY_BROKER_PASSWORD: celery CELERY_BROKER_TRANSPORT: amqp CELERY_BROKER_USER: celery +CELERY_ALWAYS_EAGER: True +CELERY_RESULT_BACKEND: 'djcelery.backends.cache:CacheBackend' + CERT_QUEUE: certificates CMS_BASE: localhost:8031 CODE_JAIL: limits: {REALTIME: 3, VMEM: 0} COMMENTS_SERVICE_KEY: password COMMENTS_SERVICE_URL: http://localhost:4567 +COMPLETION_BY_VIEWING_DELAY_MS: 1000 CONTACT_EMAIL: info@example.com CONTENTSTORE: DOC_STORE_CONFIG: @@ -65,6 +84,9 @@ DATABASES: PASSWORD: '', PORT: '3306', USER: root} DEFAULT_FEEDBACK_EMAIL: feedback@example.com DEFAULT_FROM_EMAIL: registration@example.com + +# Enable debug so that static assets are served by Django +DEBUG: True DJFS: {aws_access_key_id: test, aws_secret_access_key: test, bucket: test, prefix: test, type: s3fs} DOC_STORE_CONFIG: @@ -72,18 +94,80 @@ DOC_STORE_CONFIG: db: test host: [localhost] port: 27017 +# Configure the LMS to use our stub eCommerce implementation +ECOMMERCE_API_URL: 'http://localhost:8043/api/v2/' +# Configure the LMS to use our stub EdxNotes implementation +EDXNOTES_PUBLIC_API: 'http://localhost:8042/api/v1' +EDXNOTES_INTERNAL_API: 'http://localhost:8042/api/v1' + +EDXNOTES_CONNECT_TIMEOUT: 10 # time in seconds +EDXNOTES_READ_TIMEOUT: 10 # time in seconds + +NOTES_DISABLED_TABS: [] + EMAIL_BACKEND: django.core.mail.backends.dummy.EmailBackend EVENT_TRACKING_BACKENDS: mongo: ENGINE: eventtracking.backends.mongodb.MongoBackend OPTIONS: {collection: events, database: test} -FEATURES: {ALLOW_AUTOMATED_SIGNUPS: true, AUTOMATIC_AUTH_FOR_TESTING: true, - AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING: true, CERTIFICATES_HTML_VIEW: true, - CERTIFICATES_INSTRUCTOR_GENERATION: true, CUSTOM_COURSES_EDX: true, - ENABLE_COURSE_DISCOVERY: true, ENABLE_DISCUSSION_SERVICE: true, ENABLE_GRADE_DOWNLOADS: true, - ENABLE_PAYMENT_FAKE: true, ENABLE_SPECIAL_EXAMS: true, ENABLE_THIRD_PARTY_AUTH: true, - ENABLE_VERIFIED_CERTIFICATES: true, EXPOSE_CACHE_PROGRAMS_ENDPOINT: true, MODE_CREATION_FOR_TESTING: true, - PREVIEW_LMS_BASE: 'preview.localhost:8003', RESTRICT_AUTOMATIC_AUTH: false, SHOW_HEADER_LANGUAGE_SELECTOR: true} +FEATURES: + ALLOW_AUTOMATED_SIGNUPS: true + AUTOMATIC_AUTH_FOR_TESTING: true + AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING: true + CERTIFICATES_HTML_VIEW: true + CERTIFICATES_INSTRUCTOR_GENERATION: true + CUSTOM_COURSES_EDX: true, + ENABLE_COURSE_DISCOVERY: true + ENABLE_DISCUSSION_SERVICE: true + ENABLE_GRADE_DOWNLOADS: true + ENABLE_PAYMENT_FAKE: true + ENABLE_SPECIAL_EXAMS: true + ENABLE_THIRD_PARTY_AUTH: true + ENABLE_VERIFIED_CERTIFICATES: true + EXPOSE_CACHE_PROGRAMS_ENDPOINT: true + MODE_CREATION_FOR_TESTING: true + PREVIEW_LMS_BASE: 'preview.localhost:8003' + RESTRICT_AUTOMATIC_AUTH: false + SHOW_HEADER_LANGUAGE_SELECTOR: true + ENABLE_MAX_FAILED_LOGIN_ATTEMPTS: False + SQUELCH_PII_IN_LOGS: False + PREVENT_CONCURRENT_LOGINS: False + ENABLE_MOBILE_REST_API: True # Show video bumper in LMS + ENABLE_VIDEO_BUMPER: True # Show video bumper in LMS + SHOW_BUMPER_PERIODICITY: 1 + # Enable courseware search for tests + ENABLE_COURSEWARE_SEARCH: True + # Enable dashboard search for tests + ENABLE_DASHBOARD_SEARCH: True + # discussion home panel, which includes a subscription on/off setting for discussion digest emails. + ENABLE_DISCUSSION_HOME_PANEL: True + # Enable support for OpenBadges accomplishments + ENABLE_OPENBADGES: True + ENABLE_LTI_PROVIDER: True + # Enable milestones app + MILESTONES_APP: True + # Enable oauth authentication, which we test. + ENABLE_OAUTH2_PROVIDER: True + OAUTH_ENFORCE_SECURE: False + ENABLE_PREREQUISITE_COURSES: True + ENABLE_COURSE_DISCOVERY: True + ENABLE_EDXNOTES: True + ENABLE_TEAMS: True + LICENSING: True + # Use the auto_auth workflow for creating users and logging them in + AUTOMATIC_AUTH_FOR_TESTING: True + RESTRICT_AUTOMATIC_AUTH: False + # Open up endpoint for faking Software Secure responses + ENABLE_SOFTWARE_SECURE_FAKE: True + # Disable instructor dash buttons for downloading course data when enrollment exceeds this number + MAX_ENROLLMENT_INSTR_BUTTONS: 4 + ENABLE_ENROLLMENT_TRACK_USER_PARTITION: True + ENTRANCE_EXAMS: True + ENABLE_SPECIAL_EXAMS: True + PERSISTENT_GRADES_ENABLED_FOR_ALL_TESTS: True + ASSUME_ZERO_GRADE_IF_ABSENT_FOR_ALL_TESTS: True + + GITHUB_REPO_ROOT: '** OVERRIDDEN **' JWT_AUTH: {JWT_PRIVATE_SIGNING_JWK: '{"e": "AQAB", "d": "HIiV7KNjcdhVbpn3KT-I9n3JPf5YbGXsCIedmPqDH1d4QhBofuAqZ9zebQuxkRUpmqtYMv0Zi6ECSUqH387GYQF_XvFUFcjQRPycISd8TH0DAKaDpGr-AYNshnKiEtQpINhcP44I1AYNPCwyoxXA1fGTtmkKChsuWea7o8kytwU5xSejvh5-jiqu2SF4GEl0BEXIAPZsgbzoPIWNxgO4_RzNnWs6nJZeszcaDD0CyezVSuH9QcI6g5QFzAC_YuykSsaaFJhZ05DocBsLczShJ9Omf6PnK9xlm26I84xrEh_7x4fVmNBg3xWTLh8qOnHqGko93A1diLRCrKHOvnpvgQ", "n": "o5cn3ljSRi6FaDEKTn0PS-oL9EFyv1pI7dRgffQLD1qf5D6sprmYfWWokSsrWig8u2y0HChSygR6Jn5KXBqQn6FpM0dDJLnWQDRXHLl3Ey1iPYgDSmOIsIGrV9ZyNCQwk03wAgWbfdBTig3QSDYD-sTNOs3pc4UD_PqAvU2nz_1SS2ZiOwOn5F6gulE1L0iE3KEUEvOIagfHNVhz0oxa_VRZILkzV-zr6R_TW1m97h4H8jXl_VJyQGyhMGGypuDrQ9_vaY_RLEulLCyY0INglHWQ7pckxBtI5q55-Vio2wgewe2_qYcGsnBGaDNbySAsvYcWRrqDiFyzrJYivodqTQ", @@ -126,12 +210,20 @@ MODULESTORE: - ENGINE: xmodule.modulestore.xml.XMLModuleStore NAME: xml OPTIONS: {data_dir: '** OVERRIDDEN **', default_class: xmodule.hidden_module.HiddenDescriptor} +# We need to test different scenarios, following setting effectively disbale rate limiting +PASSWORD_RESET_EMAIL_RATE_LIMIT: + no_of_emails: 1 + per_seconds: 1 PASSWORD_RESET_SUPPORT_LINK: https://support.example.com/password-reset-help.html REGISTRATION_EXTENSION_FORM: openedx.core.djangoapps.user_api.tests.test_helpers.TestCaseForm REGISTRATION_EXTRA_FIELDS: {city: hidden, country: required, gender: optional, goals: optional, honor_code: required, level_of_education: optional, mailing_address: optional, terms_of_service: hidden, year_of_birth: optional} -SECRET_KEY: '' +# Use MockSearchEngine as the search engine for test scenario +SEARCH_ENGINE: "search.tests.mock_search_engine.MockSearchEngine" +# this secret key should be the same as cms/envs/bok_choy.py's +SECRET_KEY: "very_secret_bok_choy_key" + SERVER_EMAIL: devops@example.com SESSION_COOKIE_DOMAIN: null SITE_NAME: localhost:8003 @@ -145,16 +237,26 @@ TECH_SUPPORT_EMAIL: technical@example.com THIRD_PARTY_AUTH_BACKENDS: [social_core.backends.google.GoogleOAuth2, social_core.backends.linkedin.LinkedinOAuth2, social_core.backends.facebook.FacebookOAuth2, third_party_auth.dummy.DummyBackend, third_party_auth.saml.SAMLAuthBackend] +THIRD_PARTY_AUTH: + Google: + SOCIAL_AUTH_GOOGLE_OAUTH2_KEY": "test" + SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET": "test" + Facebook: + SOCIAL_AUTH_FACEBOOK_KEY": "test" + SOCIAL_AUTH_FACEBOOK_SECRET": "test" TIME_ZONE: America/New_York TRACKING_BACKENDS: mongo: ENGINE: track.backends.mongodb.MongoBackend OPTIONS: {collection: events, database: test} WIKI_ENABLED: true +WAFFLE_OVERRIDE: True XQUEUE_INTERFACE: basic_auth: [edx, edx] django_auth: {password: password, username: lms} - url: '** OVERRIDDEN **' + # Configure the LMS to use our stub XQueue implementation + url: 'http://localhost:8040' + ZENDESK_API_KEY: '' ZENDESK_USER: '' diff --git a/lms/envs/common.py b/lms/envs/common.py index 26917415039e498bdfc7328c3a755dfc08e618d6..e3210d4dacbcfc74b1684127e91c626d71d6eb05 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -26,10 +26,10 @@ Longer TODO: # Pylint gets confused by path.py instances, which report themselves as class # objects. As a result, pylint applies the wrong regex in validating names, # and throws spurious errors. Therefore, we disable invalid-name checking. -# pylint: disable=invalid-name, wrong-import-position +# pylint: disable=invalid-name -import imp +import importlib.util import sys import os @@ -478,6 +478,19 @@ FEATURES = { # .. toggle_status: supported # .. toggle_warnings: None 'ENABLE_ORA_USER_STATE_UPLOAD_DATA': False, + + # .. toggle_name: ENABLE_ORA_USERNAMES_ON_DATA_EXPORT + # .. toggle_implementation: DjangoSetting + # .. toggle_default: False + # .. toggle_description: Set to True to add deanonymized usernames to ORA data report. + # .. toggle_category: ora + # .. toggle_use_cases: incremental_release + # .. toggle_creation_date: 2020-06-11 + # .. toggle_expiration_date: None + # .. toggle_tickets: https://openedx.atlassian.net/browse/TNL-7273 + # .. toggle_status: supported + # .. toggle_warnings: None + 'ENABLE_ORA_USERNAMES_ON_DATA_EXPORT': False, } # Settings for the course reviews tool template and identification key, set either to None to disable course reviews @@ -527,7 +540,7 @@ RETRY_CALENDAR_SYNC_EMAIL_MAX_ATTEMPTS = 5 COURSE_MESSAGE_ALERT_DURATION_IN_DAYS = 14 ############################# SET PATH INFORMATION ############################# -PROJECT_ROOT = path(__file__).abspath().dirname().dirname() # /edx-platform/lms pylint: disable=no-value-for-parameter +PROJECT_ROOT = path(__file__).abspath().dirname().dirname() # /edx-platform/lms REPO_ROOT = PROJECT_ROOT.dirname() COMMON_ROOT = REPO_ROOT / "common" OPENEDX_ROOT = REPO_ROOT / "openedx" @@ -1152,6 +1165,10 @@ SESSION_SERIALIZER = 'openedx.core.lib.session_serializers.PickleSerializer' SESSION_COOKIE_DOMAIN = "" SESSION_COOKIE_NAME = 'sessionid' +# django-session-cookie middleware +DCS_SESSION_COOKIE_SAMESITE = 'None' +DCS_SESSION_COOKIE_SAMESITE_FORCE_ALL = True + # CMS base CMS_BASE = 'localhost:18010' @@ -1327,7 +1344,7 @@ STATICI18N_OUTPUT_DIR = "js/i18n" # Localization strings (e.g. django.po) are under these directories -def _make_locale_paths(settings): # pylint: disable=missing-docstring +def _make_locale_paths(settings): # pylint: disable=missing-function-docstring locale_paths = [settings.REPO_ROOT + '/conf/locale'] # edx-platform/conf/locale/ if settings.ENABLE_COMPREHENSIVE_THEMING: # Add locale paths to settings for comprehensive theming. @@ -1341,7 +1358,8 @@ derived('LOCALE_PATHS') MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' # Guidelines for translators -TRANSLATORS_GUIDE = 'https://edx.readthedocs.org/projects/edx-developer-guide/en/latest/conventions/internationalization/i18n_translators_guide.html' # pylint: disable=line-too-long +TRANSLATORS_GUIDE = 'https://edx.readthedocs.org/projects/edx-developer-guide/en/latest/' \ + 'conventions/internationalization/i18n_translators_guide.html' #################################### AWS ####################################### # S3BotoStorage insists on a timeout for uploaded assets. We should make it @@ -1479,12 +1497,19 @@ CREDIT_NOTIFICATION_CACHE_TIMEOUT = 5 * 60 * 60 MIDDLEWARE = [ 'openedx.core.lib.x_forwarded_for.middleware.XForwardedForMiddleware', + # Avoid issue with https://blog.heroku.com/chrome-changes-samesite-cookie + # Override was found here https://github.com/django/django/pull/11894 + 'django_cookies_samesite.middleware.CookiesSameSite', + 'crum.CurrentRequestUserMiddleware', # A newer and safer request cache. 'edx_django_utils.cache.middleware.RequestCacheMiddleware', 'edx_django_utils.monitoring.middleware.MonitoringCustomMetricsMiddleware', + # Generate code ownership metrics. Keep this immediately after RequestCacheMiddleware. + 'lms.djangoapps.monitoring.middleware.CodeOwnerMetricMiddleware', + # Cookie monitoring 'openedx.core.lib.request_utils.CookieMetricsMiddleware', @@ -1822,18 +1847,6 @@ PIPELINE['STYLESHEETS'] = { ], 'output_filename': 'css/lms-style-student-notes.css', }, - 'style-discussion-main': { - 'source_filenames': [ - 'css/discussion/lms-discussion-main.css', - ], - 'output_filename': 'css/discussion/lms-discussion-main.css', - }, - 'style-discussion-main-rtl': { - 'source_filenames': [ - 'css/discussion/lms-discussion-main-rtl.css', - ], - 'output_filename': 'css/discussion/lms-discussion-main-rtl.css', - }, 'style-inline-discussion': { 'source_filenames': [ 'css/discussion/inline-discussion.css', @@ -2072,7 +2085,8 @@ REQUIRE_JS_PATH_OVERRIDES = { 'js/student_account/logistration_factory': 'js/student_account/logistration_factory.js', 'js/courseware/courseware_factory': 'js/courseware/courseware_factory.js', 'js/groups/views/cohorts_dashboard_factory': 'js/groups/views/cohorts_dashboard_factory.js', - 'js/groups/discussions_management/discussions_dashboard_factory': 'js/discussions_management/views/discussions_dashboard_factory.js', # pylint: disable=line-too-long + 'js/groups/discussions_management/discussions_dashboard_factory': + 'js/discussions_management/views/discussions_dashboard_factory.js', 'draggabilly': 'js/vendor/draggabilly.js', 'hls': 'common/js/vendor/hls.js' } @@ -2552,6 +2566,12 @@ INSTALLED_APPS = [ # Management of per-user schedules 'openedx.core.djangoapps.schedules', 'rest_framework_jwt', + + # Monitoring utilities for LMS + 'lms.djangoapps.monitoring.apps.MonitoringConfig', + + # Learning Sequence Navigation + 'openedx.core.djangoapps.content.learning_sequences.apps.LearningSequencesConfig', ] ######################### CSRF ######################################### @@ -2807,6 +2827,8 @@ REGISTRATION_FIELD_ORDER = [ "gender", "year_of_birth", "level_of_education", + "specialty", + "profession" "company", "title", "mailing_address", @@ -3171,10 +3193,8 @@ OPTIONAL_APPS = [ for app_name, insert_before in OPTIONAL_APPS: # First attempt to only find the module rather than actually importing it, # to avoid circular references - only try to import if it can't be found - # by find_module, which doesn't work with import hooks - try: - imp.find_module(app_name) - except ImportError: + # by find_spec, which doesn't work with import hooks + if importlib.util.find_spec(app_name) is None: try: __import__(app_name) except ImportError: @@ -3292,6 +3312,7 @@ ACCOUNT_VISIBILITY_CONFIGURATION["admin_fields"] = ( "email", "extended_profile", "gender", + "state", "goals", "is_active", "mailing_address", @@ -3355,7 +3376,8 @@ FIELD_OVERRIDE_PROVIDERS = () # Modulestore-level field override providers. These field override providers don't # require student context. -MODULESTORE_FIELD_OVERRIDE_PROVIDERS = ('openedx.features.content_type_gating.field_override.ContentTypeGatingFieldOverride',) # pylint: disable=line-too-long +MODULESTORE_FIELD_OVERRIDE_PROVIDERS = ('openedx.features.content_type_gating.' + 'field_override.ContentTypeGatingFieldOverride',) # PROFILE IMAGE CONFIG # WARNING: Certain django storage backends do not support atomic @@ -3671,6 +3693,9 @@ DATA_CONSENT_SHARE_CACHE_TIMEOUT = 8 * 60 * 60 # 8 hours ENTERPRISE_MARKETING_FOOTER_QUERY_PARAMS = {} ENTERPRISE_TAGLINE = '' +# List of enterprise customer uuids to exclude from transition to use of enterprise-catalog +ENTERPRISE_CUSTOMERS_EXCLUDED_FROM_CATALOG = [] + ############## Settings for Course Enrollment Modes ###################### # The min_price key refers to the minimum price allowed for an instance # of a particular type of course enrollment mode. This is not to be confused @@ -3748,6 +3773,9 @@ COMPLETION_BY_VIEWING_DELAY_MS = 5000 RATELIMIT_ENABLE = True RATELIMIT_RATE = '120/m' +##### LOGISTRATION RATE LIMIT SETTINGS ##### +LOGISTRATION_RATELIMIT_RATE = '500/5m' + ############### Settings for Retirement ##################### RETIRED_USERNAME_PREFIX = 'retired__user_' RETIRED_EMAIL_PREFIX = 'retired__user_' @@ -3853,6 +3881,7 @@ DEPRECATED_ADVANCED_COMPONENT_TYPES = [] ############### Settings for video pipeline ################## VIDEO_UPLOAD_PIPELINE = { + 'VEM_S3_BUCKET': '', 'BUCKET': '', 'ROOT_PATH': '', } diff --git a/lms/envs/devstack.py b/lms/envs/devstack.py index 0e131f5d012f147dc9dd5a95ba4817fd938fdd0b..aecb9d45bba943c7e580b703c8bc66cc52df45b4 100644 --- a/lms/envs/devstack.py +++ b/lms/envs/devstack.py @@ -263,10 +263,14 @@ CORS_ALLOW_HEADERS = corsheaders_default_headers + ( LOGIN_REDIRECT_WHITELIST = [CMS_BASE] ###################### JWTs ###################### -# pylint: disable=unicode-format-string JWT_AUTH.update({ - 'JWT_ISSUER': '{}/oauth2'.format(LMS_ROOT_URL), 'JWT_AUDIENCE': 'lms-key', + 'JWT_ISSUER': '{}/oauth2'.format(LMS_ROOT_URL), + 'JWT_ISSUERS': [{ + 'AUDIENCE': 'lms-key', + 'ISSUER': '{}/oauth2'.format(LMS_ROOT_URL), + 'SECRET_KEY': 'lms-secret', + }], 'JWT_SECRET_KEY': 'lms-secret', 'JWT_SIGNING_ALGORITHM': 'RS512', 'JWT_PRIVATE_SIGNING_JWK': ( @@ -367,6 +371,9 @@ SYSTEM_WIDE_ROLE_CLASSES.extend(['system_wide_roles.SystemWideRoleAssignment']) if FEATURES['ENABLE_ENTERPRISE_INTEGRATION']: SYSTEM_WIDE_ROLE_CLASSES.extend(['enterprise.SystemWideEnterpriseUserRoleAssignment']) +# List of enterprise customer uuids to exclude from transition to use of enterprise-catalog +ENTERPRISE_CUSTOMERS_EXCLUDED_FROM_CATALOG = () + ##################################################################### # See if the developer has any local overrides. if os.path.isfile(join(dirname(abspath(__file__)), 'private.py')): diff --git a/lms/envs/devstack_with_worker.py b/lms/envs/devstack_with_worker.py index 2b87fdf42ba3aa92c2d5728ad117b9d7fb9b9cf3..4844a188ee41382a8f450270f36b21ead09ba4e3 100644 --- a/lms/envs/devstack_with_worker.py +++ b/lms/envs/devstack_with_worker.py @@ -21,7 +21,7 @@ from lms.envs.devstack import * # Require a separate celery worker CELERY_ALWAYS_EAGER = False - +BROKER_URL = 'redis://:password@edx.devstack.redis:6379/' # Disable transaction management because we are using a worker. Views # that request a task and wait for the result will deadlock otherwise. for database_name in DATABASES: diff --git a/lms/envs/docs/README.rst b/lms/envs/docs/README.rst index 77427b54c29a62bbf9258314165ade8eabaaa86e..351945be01a1ef04d3937716d8bcd6562689c0a0 100644 --- a/lms/envs/docs/README.rst +++ b/lms/envs/docs/README.rst @@ -13,20 +13,16 @@ as shown in the diagram below. .. image:: images/lms_settings.png -JSON Configuration Files +YAML Configuration Files ------------------------ -In addition, there is a mechanism for reading and overriding configuration -settings from JSON files on-disk. The :file:`/lms/envs/production.py` module loads -settings from ``lms.env.json`` and ``lms.auth.json`` files. All -security-sensitive settings and data belong in the ``lms.auth.json`` file, while -the rest are configured via the ``lms.env.json`` file. +In addition, there is a mechanism for reading and overriding configuration settings from YAML files on-disk. The :file:`/lms/envs/production.py` module loads settings from a YAML file. The location of the YAML file is pulled from the value of the ``LMS_CFG`` environment variable. Except for a limited set of exceptions, if a key exists in the YAML file, it will be injected into the settings module as it is defined in the YAML file. -These JSON files allow open edX operators to configure the django runtime +The YAML file allow open edX operators to configure the Django runtime without needing to make any changes to source-controlled python files in edx-platform. Therefore, they are not checked into the edx-platform repo. Rather, they are generated from the `edxapp playbook in the configuration -repo`_ and available in the ``/edx/app/edxapp/`` folder on edX servers. +repo`_ and available in the ``/edx/etc/`` folder on edX servers. .. _edxapp playbook in the configuration repo: https://github.com/edx/configuration/tree/master/playbooks/roles/edxapp diff --git a/lms/envs/load_test.py b/lms/envs/load_test.py deleted file mode 100644 index 94b042924d75c72578193b721d8e8939f15a9528..0000000000000000000000000000000000000000 --- a/lms/envs/load_test.py +++ /dev/null @@ -1,22 +0,0 @@ -""" -Settings for load testing. -""" - -# We intentionally define lots of variables that aren't used, and -# want to import all variables from base settings files -# pylint: disable=wildcard-import, unused-wildcard-import - - -from six.moves import filter - -from .production import * - -# Disable CSRF for load testing -EXCLUDE_CSRF = lambda elem: elem not in [ - 'django.template.context_processors.csrf', - 'django.middleware.csrf.CsrfViewMiddleware' -] -DEFAULT_TEMPLATE_ENGINE['OPTIONS']['context_processors'] = list(filter( - EXCLUDE_CSRF, DEFAULT_TEMPLATE_ENGINE['OPTIONS']['context_processors'] -)) -MIDDLEWARE = list(filter(EXCLUDE_CSRF, MIDDLEWARE)) diff --git a/lms/envs/production.py b/lms/envs/production.py index 7ff5b138392d1771c645a4d7abe8ab76f66de87f..e451166a431c14f3888bf09ca3df289ea02100ae 100644 --- a/lms/envs/production.py +++ b/lms/envs/production.py @@ -45,6 +45,22 @@ def get_env_setting(setting): error_msg = u"Set the %s env variable" % setting raise ImproperlyConfigured(error_msg) +################################ ALWAYS THE SAME ############################## + +DEBUG = False +DEFAULT_TEMPLATE_ENGINE['OPTIONS']['debug'] = False + +SESSION_ENGINE = 'django.contrib.sessions.backends.cache' + +# IMPORTANT: With this enabled, the server must always be behind a proxy that +# strips the header HTTP_X_FORWARDED_PROTO from client requests. Otherwise, +# a user can fool our server into thinking it was an https connection. +# See +# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header +# for other warnings. +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +################################ END ALWAYS THE SAME ############################## + # A file path to a YAML file from which to load all the configuration for the edx platform CONFIG_FILE = get_env_setting('LMS_CFG') @@ -76,10 +92,10 @@ with codecs.open(CONFIG_FILE, encoding='utf-8') as f: vars().update(__config_copy__) -# A file path to a YAML file from which to load all the code revisions currently deployed -REVISION_CONFIG_FILE = get_env_setting('REVISION_CFG') - try: + # A file path to a YAML file from which to load all the code revisions currently deployed + REVISION_CONFIG_FILE = get_env_setting('REVISION_CFG') + with codecs.open(REVISION_CONFIG_FILE, encoding='utf-8') as f: REVISION_CONFIG = yaml.safe_load(f) except Exception: # pylint: disable=broad-except @@ -102,22 +118,6 @@ CONFIG_ROOT = path(os.environ.get('CONFIG_ROOT', ENV_ROOT)) # prefix. CONFIG_PREFIX = SERVICE_VARIANT + "." if SERVICE_VARIANT else "" -################################ ALWAYS THE SAME ############################## - -DEBUG = False -DEFAULT_TEMPLATE_ENGINE['OPTIONS']['debug'] = False - -EMAIL_BACKEND = 'django_ses.SESBackend' -SESSION_ENGINE = 'django.contrib.sessions.backends.cache' - -# IMPORTANT: With this enabled, the server must always be behind a proxy that -# strips the header HTTP_X_FORWARDED_PROTO from client requests. Otherwise, -# a user can fool our server into thinking it was an https connection. -# See -# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header -# for other warnings. -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') - ###################################### CELERY ################################ # Don't use a connection pool, since connections are dropped by ELB. @@ -173,15 +173,9 @@ if STATIC_URL_BASE: if not STATIC_URL.endswith("/"): STATIC_URL += "/" -# DEFAULT_COURSE_ABOUT_IMAGE_URL specifies the default image to show for courses that don't provide one -DEFAULT_COURSE_ABOUT_IMAGE_URL = ENV_TOKENS.get('DEFAULT_COURSE_ABOUT_IMAGE_URL', DEFAULT_COURSE_ABOUT_IMAGE_URL) - -# COURSE_MODE_DEFAULTS specifies the course mode to use for courses that do not set one -COURSE_MODE_DEFAULTS = ENV_TOKENS.get('COURSE_MODE_DEFAULTS', COURSE_MODE_DEFAULTS) - -# MEDIA_ROOT specifies the directory where user-uploaded files are stored. -MEDIA_ROOT = ENV_TOKENS.get('MEDIA_ROOT', MEDIA_ROOT) -MEDIA_URL = ENV_TOKENS.get('MEDIA_URL', MEDIA_URL) +# Allow overriding build profile used by RequireJS with one +# contained on a custom theme +REQUIRE_BUILD_PROFILE = ENV_TOKENS.get('REQUIRE_BUILD_PROFILE', REQUIRE_BUILD_PROFILE) # The following variables use (or) instead of the default value inside (get). This is to enforce using the Lazy Text # values when the varibale is an empty string. Therefore, setting these variable as empty text in related @@ -189,42 +183,22 @@ MEDIA_URL = ENV_TOKENS.get('MEDIA_URL', MEDIA_URL) PLATFORM_NAME = ENV_TOKENS.get('PLATFORM_NAME') or PLATFORM_NAME PLATFORM_DESCRIPTION = ENV_TOKENS.get('PLATFORM_DESCRIPTION') or PLATFORM_DESCRIPTION -# For displaying on the receipt. At Stanford PLATFORM_NAME != MERCHANT_NAME, but PLATFORM_NAME is a fine default -PLATFORM_TWITTER_ACCOUNT = ENV_TOKENS.get('PLATFORM_TWITTER_ACCOUNT', PLATFORM_TWITTER_ACCOUNT) -PLATFORM_FACEBOOK_ACCOUNT = ENV_TOKENS.get('PLATFORM_FACEBOOK_ACCOUNT', PLATFORM_FACEBOOK_ACCOUNT) - -SOCIAL_SHARING_SETTINGS = ENV_TOKENS.get('SOCIAL_SHARING_SETTINGS', SOCIAL_SHARING_SETTINGS) - -# Social media links for the page footer -SOCIAL_MEDIA_FOOTER_URLS = ENV_TOKENS.get('SOCIAL_MEDIA_FOOTER_URLS', SOCIAL_MEDIA_FOOTER_URLS) - CC_MERCHANT_NAME = ENV_TOKENS.get('CC_MERCHANT_NAME', PLATFORM_NAME) -EMAIL_BACKEND = ENV_TOKENS.get('EMAIL_BACKEND', EMAIL_BACKEND) EMAIL_FILE_PATH = ENV_TOKENS.get('EMAIL_FILE_PATH', None) EMAIL_HOST = ENV_TOKENS.get('EMAIL_HOST', 'localhost') # django default is localhost EMAIL_PORT = ENV_TOKENS.get('EMAIL_PORT', 25) # django default is 25 EMAIL_USE_TLS = ENV_TOKENS.get('EMAIL_USE_TLS', False) # django default is False SITE_NAME = ENV_TOKENS['SITE_NAME'] -HTTPS = ENV_TOKENS.get('HTTPS', HTTPS) -SESSION_ENGINE = ENV_TOKENS.get('SESSION_ENGINE', SESSION_ENGINE) SESSION_COOKIE_DOMAIN = ENV_TOKENS.get('SESSION_COOKIE_DOMAIN') SESSION_COOKIE_HTTPONLY = ENV_TOKENS.get('SESSION_COOKIE_HTTPONLY', True) -SESSION_COOKIE_SECURE = ENV_TOKENS.get('SESSION_COOKIE_SECURE', SESSION_COOKIE_SECURE) -SESSION_SAVE_EVERY_REQUEST = ENV_TOKENS.get('SESSION_SAVE_EVERY_REQUEST', SESSION_SAVE_EVERY_REQUEST) + +DCS_SESSION_COOKIE_SAMESITE = ENV_TOKENS.get('DCS_SESSION_COOKIE_SAMESITE', DCS_SESSION_COOKIE_SAMESITE) +DCS_SESSION_COOKIE_SAMESITE_FORCE_ALL = ENV_TOKENS.get('DCS_SESSION_COOKIE_SAMESITE_FORCE_ALL', DCS_SESSION_COOKIE_SAMESITE_FORCE_ALL) AWS_SES_REGION_NAME = ENV_TOKENS.get('AWS_SES_REGION_NAME', 'us-east-1') AWS_SES_REGION_ENDPOINT = ENV_TOKENS.get('AWS_SES_REGION_ENDPOINT', 'email.us-east-1.amazonaws.com') -REGISTRATION_EXTRA_FIELDS = ENV_TOKENS.get('REGISTRATION_EXTRA_FIELDS', REGISTRATION_EXTRA_FIELDS) -REGISTRATION_EXTENSION_FORM = ENV_TOKENS.get('REGISTRATION_EXTENSION_FORM', REGISTRATION_EXTENSION_FORM) REGISTRATION_EMAIL_PATTERNS_ALLOWED = ENV_TOKENS.get('REGISTRATION_EMAIL_PATTERNS_ALLOWED') -REGISTRATION_FIELD_ORDER = ENV_TOKENS.get('REGISTRATION_FIELD_ORDER', REGISTRATION_FIELD_ORDER) - -# Set the names of cookies shared with the marketing site -# These have the same cookie domain as the session, which in production -# usually includes subdomains. -EDXMKTG_LOGGED_IN_COOKIE_NAME = ENV_TOKENS.get('EDXMKTG_LOGGED_IN_COOKIE_NAME', EDXMKTG_LOGGED_IN_COOKIE_NAME) -EDXMKTG_USER_INFO_COOKIE_NAME = ENV_TOKENS.get('EDXMKTG_USER_INFO_COOKIE_NAME', EDXMKTG_USER_INFO_COOKIE_NAME) LMS_ROOT_URL = ENV_TOKENS.get('LMS_ROOT_URL') LMS_INTERNAL_ROOT_URL = ENV_TOKENS.get('LMS_INTERNAL_ROOT_URL', LMS_ROOT_URL) @@ -270,7 +244,6 @@ if 'staticfiles' in CACHES: # Once we have migrated to service assets off S3, then we can convert this back to # managed by the yaml file contents STATICFILES_STORAGE = os.environ.get('STATICFILES_STORAGE', ENV_TOKENS.get('STATICFILES_STORAGE', STATICFILES_STORAGE)) -STATICFILES_STORAGE_KWARGS = ENV_TOKENS.get('STATICFILES_STORAGE_KWARGS', STATICFILES_STORAGE_KWARGS) # Load all AWS_ prefixed variables to allow an S3Boto3Storage to be configured _locals = locals() @@ -278,42 +251,10 @@ for key, value in ENV_TOKENS.items(): if key.startswith('AWS_'): _locals[key] = value -# Email overrides -DEFAULT_FROM_EMAIL = ENV_TOKENS.get('DEFAULT_FROM_EMAIL', DEFAULT_FROM_EMAIL) -DEFAULT_FEEDBACK_EMAIL = ENV_TOKENS.get('DEFAULT_FEEDBACK_EMAIL', DEFAULT_FEEDBACK_EMAIL) -ADMINS = ENV_TOKENS.get('ADMINS', ADMINS) -SERVER_EMAIL = ENV_TOKENS.get('SERVER_EMAIL', SERVER_EMAIL) -TECH_SUPPORT_EMAIL = ENV_TOKENS.get('TECH_SUPPORT_EMAIL', TECH_SUPPORT_EMAIL) -CONTACT_EMAIL = ENV_TOKENS.get('CONTACT_EMAIL', CONTACT_EMAIL) -BUGS_EMAIL = ENV_TOKENS.get('BUGS_EMAIL', BUGS_EMAIL) -PAYMENT_SUPPORT_EMAIL = ENV_TOKENS.get('PAYMENT_SUPPORT_EMAIL', PAYMENT_SUPPORT_EMAIL) -FINANCE_EMAIL = ENV_TOKENS.get('FINANCE_EMAIL', FINANCE_EMAIL) -UNIVERSITY_EMAIL = ENV_TOKENS.get('UNIVERSITY_EMAIL', UNIVERSITY_EMAIL) -PRESS_EMAIL = ENV_TOKENS.get('PRESS_EMAIL', PRESS_EMAIL) - -CONTACT_MAILING_ADDRESS = ENV_TOKENS.get('CONTACT_MAILING_ADDRESS', CONTACT_MAILING_ADDRESS) - -# Account activation email sender address -ACTIVATION_EMAIL_FROM_ADDRESS = ENV_TOKENS.get('ACTIVATION_EMAIL_FROM_ADDRESS', ACTIVATION_EMAIL_FROM_ADDRESS) - # Currency PAID_COURSE_REGISTRATION_CURRENCY = ENV_TOKENS.get('PAID_COURSE_REGISTRATION_CURRENCY', PAID_COURSE_REGISTRATION_CURRENCY) -# Payment Report Settings -PAYMENT_REPORT_GENERATOR_GROUP = ENV_TOKENS.get('PAYMENT_REPORT_GENERATOR_GROUP', PAYMENT_REPORT_GENERATOR_GROUP) - -# Bulk Email overrides -BULK_EMAIL_DEFAULT_FROM_EMAIL = ENV_TOKENS.get('BULK_EMAIL_DEFAULT_FROM_EMAIL', BULK_EMAIL_DEFAULT_FROM_EMAIL) -BULK_EMAIL_EMAILS_PER_TASK = ENV_TOKENS.get('BULK_EMAIL_EMAILS_PER_TASK', BULK_EMAIL_EMAILS_PER_TASK) -BULK_EMAIL_DEFAULT_RETRY_DELAY = ENV_TOKENS.get('BULK_EMAIL_DEFAULT_RETRY_DELAY', BULK_EMAIL_DEFAULT_RETRY_DELAY) -BULK_EMAIL_MAX_RETRIES = ENV_TOKENS.get('BULK_EMAIL_MAX_RETRIES', BULK_EMAIL_MAX_RETRIES) -BULK_EMAIL_INFINITE_RETRY_CAP = ENV_TOKENS.get('BULK_EMAIL_INFINITE_RETRY_CAP', BULK_EMAIL_INFINITE_RETRY_CAP) -BULK_EMAIL_LOG_SENT_EMAILS = ENV_TOKENS.get('BULK_EMAIL_LOG_SENT_EMAILS', BULK_EMAIL_LOG_SENT_EMAILS) -BULK_EMAIL_RETRY_DELAY_BETWEEN_SENDS = ENV_TOKENS.get( - 'BULK_EMAIL_RETRY_DELAY_BETWEEN_SENDS', - BULK_EMAIL_RETRY_DELAY_BETWEEN_SENDS -) # We want Bulk Email running on the high-priority queue, so we define the # routing key that points to it. At the moment, the name is the same. # We have to reset the value here, since we have changed the value of the queue name. @@ -352,7 +293,6 @@ CELERY_QUEUES.update( if ENV_TOKENS.get('COMPREHENSIVE_THEME_DIR', None): COMPREHENSIVE_THEME_DIR = ENV_TOKENS.get('COMPREHENSIVE_THEME_DIR') -COMPREHENSIVE_THEME_DIRS = ENV_TOKENS.get('COMPREHENSIVE_THEME_DIRS', COMPREHENSIVE_THEME_DIRS) or [] # COMPREHENSIVE_THEME_LOCALE_PATHS contain the paths to themes locale directories e.g. # "COMPREHENSIVE_THEME_LOCALE_PATHS" : [ @@ -360,8 +300,6 @@ COMPREHENSIVE_THEME_DIRS = ENV_TOKENS.get('COMPREHENSIVE_THEME_DIRS', COMPREHENS # ], COMPREHENSIVE_THEME_LOCALE_PATHS = ENV_TOKENS.get('COMPREHENSIVE_THEME_LOCALE_PATHS', []) -DEFAULT_SITE_THEME = ENV_TOKENS.get('DEFAULT_SITE_THEME', DEFAULT_SITE_THEME) -ENABLE_COMPREHENSIVE_THEMING = ENV_TOKENS.get('ENABLE_COMPREHENSIVE_THEMING', ENABLE_COMPREHENSIVE_THEMING) MKTG_URL_LINK_MAP.update(ENV_TOKENS.get('MKTG_URL_LINK_MAP', {})) ENTERPRISE_MARKETING_FOOTER_QUERY_PARAMS = ENV_TOKENS.get( @@ -372,34 +310,22 @@ ENTERPRISE_MARKETING_FOOTER_QUERY_PARAMS = ENV_TOKENS.get( MKTG_URL_OVERRIDES.update(ENV_TOKENS.get('MKTG_URL_OVERRIDES', MKTG_URL_OVERRIDES)) # Intentional defaults. -SUPPORT_SITE_LINK = ENV_TOKENS.get('SUPPORT_SITE_LINK', SUPPORT_SITE_LINK) ID_VERIFICATION_SUPPORT_LINK = ENV_TOKENS.get('ID_VERIFICATION_SUPPORT_LINK', SUPPORT_SITE_LINK) PASSWORD_RESET_SUPPORT_LINK = ENV_TOKENS.get('PASSWORD_RESET_SUPPORT_LINK', SUPPORT_SITE_LINK) ACTIVATION_EMAIL_SUPPORT_LINK = ENV_TOKENS.get( 'ACTIVATION_EMAIL_SUPPORT_LINK', SUPPORT_SITE_LINK ) -# Mobile store URL overrides -MOBILE_STORE_URLS = ENV_TOKENS.get('MOBILE_STORE_URLS', MOBILE_STORE_URLS) - # Timezone overrides TIME_ZONE = ENV_TOKENS.get('CELERY_TIMEZONE', CELERY_TIMEZONE) # Translation overrides -LANGUAGES = ENV_TOKENS.get('LANGUAGES', LANGUAGES) -CERTIFICATE_TEMPLATE_LANGUAGES = ENV_TOKENS.get('CERTIFICATE_TEMPLATE_LANGUAGES', CERTIFICATE_TEMPLATE_LANGUAGES) LANGUAGE_DICT = dict(LANGUAGES) -LANGUAGE_CODE = ENV_TOKENS.get('LANGUAGE_CODE', LANGUAGE_CODE) -LANGUAGE_COOKIE = ENV_TOKENS.get('LANGUAGE_COOKIE', LANGUAGE_COOKIE) -ALL_LANGUAGES = ENV_TOKENS.get('ALL_LANGUAGES', ALL_LANGUAGES) - -USE_I18N = ENV_TOKENS.get('USE_I18N', USE_I18N) # Additional installed apps for app in ENV_TOKENS.get('ADDL_INSTALLED_APPS', []): INSTALLED_APPS.append(app) -WIKI_ENABLED = ENV_TOKENS.get('WIKI_ENABLED', WIKI_ENABLED) local_loglevel = ENV_TOKENS.get('LOCAL_LOGLEVEL', 'INFO') LOG_DIR = ENV_TOKENS['LOG_DIR'] @@ -413,20 +339,7 @@ LOGGING = get_logger_config(LOG_DIR, COURSE_LISTINGS = ENV_TOKENS.get('COURSE_LISTINGS', {}) COMMENTS_SERVICE_URL = ENV_TOKENS.get("COMMENTS_SERVICE_URL", '') COMMENTS_SERVICE_KEY = ENV_TOKENS.get("COMMENTS_SERVICE_KEY", '') -CERT_NAME_SHORT = ENV_TOKENS.get('CERT_NAME_SHORT', CERT_NAME_SHORT) -CERT_NAME_LONG = ENV_TOKENS.get('CERT_NAME_LONG', CERT_NAME_LONG) CERT_QUEUE = ENV_TOKENS.get("CERT_QUEUE", 'test-pull') -ZENDESK_URL = ENV_TOKENS.get('ZENDESK_URL', ZENDESK_URL) -ZENDESK_CUSTOM_FIELDS = ENV_TOKENS.get('ZENDESK_CUSTOM_FIELDS', ZENDESK_CUSTOM_FIELDS) -ZENDESK_GROUP_ID_MAPPING = ENV_TOKENS.get('ZENDESK_GROUP_ID_MAPPING', ZENDESK_GROUP_ID_MAPPING) - -MKTG_URLS = ENV_TOKENS.get('MKTG_URLS', MKTG_URLS) - -# Badgr API -BADGR_API_TOKEN = ENV_TOKENS.get('BADGR_API_TOKEN', BADGR_API_TOKEN) -BADGR_BASE_URL = ENV_TOKENS.get('BADGR_BASE_URL', BADGR_BASE_URL) -BADGR_ISSUER_SLUG = ENV_TOKENS.get('BADGR_ISSUER_SLUG', BADGR_ISSUER_SLUG) -BADGR_TIMEOUT = ENV_TOKENS.get('BADGR_TIMEOUT', BADGR_TIMEOUT) # git repo loading environment GIT_REPO_DIR = ENV_TOKENS.get('GIT_REPO_DIR', '/edx/var/edxapp/course_repos') @@ -444,8 +357,6 @@ for name, value in ENV_TOKENS.get("CODE_JAIL", {}).items(): COURSES_WITH_UNSAFE_CODE = ENV_TOKENS.get("COURSES_WITH_UNSAFE_CODE", []) -ASSET_IGNORE_REGEX = ENV_TOKENS.get('ASSET_IGNORE_REGEX', ASSET_IGNORE_REGEX) - # Event Tracking if "TRACKING_IGNORE_URL_PATTERNS" in ENV_TOKENS: TRACKING_IGNORE_URL_PATTERNS = ENV_TOKENS.get("TRACKING_IGNORE_URL_PATTERNS") @@ -461,17 +372,6 @@ SSL_AUTH_DN_FORMAT_STRING = ENV_TOKENS.get( # Example: {'CN': 'http://api.xuetangx.com/edx/video?s3_url='} VIDEO_CDN_URL = ENV_TOKENS.get('VIDEO_CDN_URL', {}) -# Branded footer -FOOTER_OPENEDX_URL = ENV_TOKENS.get('FOOTER_OPENEDX_URL', FOOTER_OPENEDX_URL) -FOOTER_OPENEDX_LOGO_IMAGE = ENV_TOKENS.get('FOOTER_OPENEDX_LOGO_IMAGE', FOOTER_OPENEDX_LOGO_IMAGE) -FOOTER_ORGANIZATION_IMAGE = ENV_TOKENS.get('FOOTER_ORGANIZATION_IMAGE', FOOTER_ORGANIZATION_IMAGE) -FOOTER_CACHE_TIMEOUT = ENV_TOKENS.get('FOOTER_CACHE_TIMEOUT', FOOTER_CACHE_TIMEOUT) -FOOTER_BROWSER_CACHE_MAX_AGE = ENV_TOKENS.get('FOOTER_BROWSER_CACHE_MAX_AGE', FOOTER_BROWSER_CACHE_MAX_AGE) - -# Credit notifications settings -NOTIFICATION_EMAIL_CSS = ENV_TOKENS.get('NOTIFICATION_EMAIL_CSS', NOTIFICATION_EMAIL_CSS) -NOTIFICATION_EMAIL_EDX_LOGO = ENV_TOKENS.get('NOTIFICATION_EMAIL_EDX_LOGO', NOTIFICATION_EMAIL_EDX_LOGO) - # Determines whether the CSRF token can be transported on # unencrypted channels. It is set to False here for backward compatibility, # but it is highly recommended that this is True for enviroments accessed @@ -481,9 +381,6 @@ CSRF_COOKIE_SECURE = ENV_TOKENS.get('CSRF_COOKIE_SECURE', False) # Determines which origins are trusted for unsafe requests eg. POST requests. CSRF_TRUSTED_ORIGINS = ENV_TOKENS.get('CSRF_TRUSTED_ORIGINS', []) -# Whitelist of domains to which the login/logout pages will redirect. -LOGIN_REDIRECT_WHITELIST = ENV_TOKENS.get('LOGIN_REDIRECT_WHITELIST', LOGIN_REDIRECT_WHITELIST) - ############# CORS headers for cross-domain requests ################# if FEATURES.get('ENABLE_CORS_HEADERS') or FEATURES.get('ENABLE_CROSS_DOMAIN_CSRF_COOKIE'): @@ -559,9 +456,6 @@ XBLOCK_FIELD_DATA_WRAPPERS = ENV_TOKENS.get( ############### Mixed Related(Secure/Not-Secure) Items ########## LMS_SEGMENT_KEY = AUTH_TOKENS.get('SEGMENT_KEY') -CC_PROCESSOR_NAME = AUTH_TOKENS.get('CC_PROCESSOR_NAME', CC_PROCESSOR_NAME) -CC_PROCESSOR = AUTH_TOKENS.get('CC_PROCESSOR', CC_PROCESSOR) - SECRET_KEY = AUTH_TOKENS['SECRET_KEY'] AWS_ACCESS_KEY_ID = AUTH_TOKENS["AWS_ACCESS_KEY_ID"] @@ -586,10 +480,6 @@ elif AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY: else: DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' -# Specific setting for the File Upload Service to store media in a bucket. -FILE_UPLOAD_STORAGE_BUCKET_NAME = ENV_TOKENS.get('FILE_UPLOAD_STORAGE_BUCKET_NAME', FILE_UPLOAD_STORAGE_BUCKET_NAME) -FILE_UPLOAD_STORAGE_PREFIX = ENV_TOKENS.get('FILE_UPLOAD_STORAGE_PREFIX', FILE_UPLOAD_STORAGE_PREFIX) - # If there is a database called 'read_replica', you can use the use_read_replica_if_available # function in util/query.py, which is useful for very large database reads DATABASES = AUTH_TOKENS['DATABASES'] @@ -613,8 +503,6 @@ XQUEUE_INTERFACE = AUTH_TOKENS['XQUEUE_INTERFACE'] # Get the MODULESTORE from auth.json, but if it doesn't exist, # use the one from common.py MODULESTORE = convert_module_store_setting_if_needed(AUTH_TOKENS.get('MODULESTORE', MODULESTORE)) -CONTENTSTORE = AUTH_TOKENS.get('CONTENTSTORE', CONTENTSTORE) -DOC_STORE_CONFIG = AUTH_TOKENS.get('DOC_STORE_CONFIG', DOC_STORE_CONFIG) MONGODB_LOG = AUTH_TOKENS.get('MONGODB_LOG', {}) EMAIL_HOST_USER = AUTH_TOKENS.get('EMAIL_HOST_USER', '') # django default is '' @@ -659,7 +547,6 @@ BROKER_URL = "{0}://{1}:{2}@{3}/{4}".format(CELERY_BROKER_TRANSPORT, BROKER_USE_SSL = ENV_TOKENS.get('CELERY_BROKER_USE_SSL', False) # Block Structures -BLOCK_STRUCTURES_SETTINGS = ENV_TOKENS.get('BLOCK_STRUCTURES_SETTINGS', BLOCK_STRUCTURES_SETTINGS) # upload limits STUDENT_FILEUPLOAD_MAX_SIZE = ENV_TOKENS.get("STUDENT_FILEUPLOAD_MAX_SIZE", STUDENT_FILEUPLOAD_MAX_SIZE) @@ -680,11 +567,6 @@ TRACKING_SEGMENTIO_DISALLOWED_SUBSTRING_NAMES = ENV_TOKENS.get( ) TRACKING_SEGMENTIO_SOURCE_MAP = ENV_TOKENS.get("TRACKING_SEGMENTIO_SOURCE_MAP", TRACKING_SEGMENTIO_SOURCE_MAP) -# Heartbeat -HEARTBEAT_CHECKS = ENV_TOKENS.get('HEARTBEAT_CHECKS', HEARTBEAT_CHECKS) -HEARTBEAT_EXTENDED_CHECKS = ENV_TOKENS.get('HEARTBEAT_EXTENDED_CHECKS', HEARTBEAT_EXTENDED_CHECKS) -HEARTBEAT_CELERY_TIMEOUT = ENV_TOKENS.get('HEARTBEAT_CELERY_TIMEOUT', HEARTBEAT_CELERY_TIMEOUT) - # Student identity verification settings VERIFY_STUDENT = AUTH_TOKENS.get("VERIFY_STUDENT", VERIFY_STUDENT) DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH = ENV_TOKENS.get( @@ -698,7 +580,6 @@ GRADES_DOWNLOAD_ROUTING_KEY = ENV_TOKENS.get('GRADES_DOWNLOAD_ROUTING_KEY', HIGH GRADES_DOWNLOAD = ENV_TOKENS.get("GRADES_DOWNLOAD", GRADES_DOWNLOAD) # Rate limit for regrading tasks that a grading policy change can kick off -POLICY_CHANGE_TASK_RATE_LIMIT = ENV_TOKENS.get('POLICY_CHANGE_TASK_RATE_LIMIT', POLICY_CHANGE_TASK_RATE_LIMIT) # financial reports FINANCIAL_REPORTS = ENV_TOKENS.get("FINANCIAL_REPORTS", FINANCIAL_REPORTS) @@ -718,6 +599,9 @@ MAX_FAILED_LOGIN_ATTEMPTS_LOCKOUT_PERIOD_SECS = ENV_TOKENS.get( "MAX_FAILED_LOGIN_ATTEMPTS_LOCKOUT_PERIOD_SECS", MAX_FAILED_LOGIN_ATTEMPTS_LOCKOUT_PERIOD_SECS ) +##### LOGISTRATION RATE LIMIT SETTINGS ##### +LOGISTRATION_RATELIMIT_RATE = ENV_TOKENS.get('LOGISTRATION_RATELIMIT_RATE', LOGISTRATION_RATELIMIT_RATE) + #### PASSWORD POLICY SETTINGS ##### AUTH_PASSWORD_VALIDATORS = ENV_TOKENS.get("AUTH_PASSWORD_VALIDATORS", AUTH_PASSWORD_VALIDATORS) @@ -728,9 +612,6 @@ SESSION_INACTIVITY_TIMEOUT_IN_SECONDS = AUTH_TOKENS.get("SESSION_INACTIVITY_TIME TIME_ZONE_DISPLAYED_FOR_DEADLINES = ENV_TOKENS.get("TIME_ZONE_DISPLAYED_FOR_DEADLINES", TIME_ZONE_DISPLAYED_FOR_DEADLINES) -##### X-Frame-Options response header settings ##### -X_FRAME_OPTIONS = ENV_TOKENS.get('X_FRAME_OPTIONS', X_FRAME_OPTIONS) - ##### Third-party auth options ################################################ if FEATURES.get('ENABLE_THIRD_PARTY_AUTH'): tmp_backends = ENV_TOKENS.get('THIRD_PARTY_AUTH_BACKENDS', [ @@ -786,8 +667,6 @@ if FEATURES.get('ENABLE_OAUTH2_PROVIDER'): OAUTH_EXPIRE_DELTA_PUBLIC = datetime.timedelta( days=ENV_TOKENS.get('OAUTH_EXPIRE_PUBLIC_CLIENT_DAYS', OAUTH_EXPIRE_PUBLIC_CLIENT_DAYS) ) - OAUTH_ID_TOKEN_EXPIRATION = ENV_TOKENS.get('OAUTH_ID_TOKEN_EXPIRATION', OAUTH_ID_TOKEN_EXPIRATION) - OAUTH_DELETE_EXPIRED = ENV_TOKENS.get('OAUTH_DELETE_EXPIRED', OAUTH_DELETE_EXPIRED) ##### GOOGLE ANALYTICS IDS ##### @@ -799,16 +678,9 @@ GOOGLE_SITE_VERIFICATION_ID = ENV_TOKENS.get('GOOGLE_SITE_VERIFICATION_ID') ##### BRANCH.IO KEY ##### BRANCH_IO_KEY = AUTH_TOKENS.get('BRANCH_IO_KEY') -##### OPTIMIZELY PROJECT ID ##### -OPTIMIZELY_PROJECT_ID = AUTH_TOKENS.get('OPTIMIZELY_PROJECT_ID', OPTIMIZELY_PROJECT_ID) - #### Course Registration Code length #### REGISTRATION_CODE_LENGTH = ENV_TOKENS.get('REGISTRATION_CODE_LENGTH', 8) -# REGISTRATION CODES DISPLAY INFORMATION -INVOICE_CORP_ADDRESS = ENV_TOKENS.get('INVOICE_CORP_ADDRESS', INVOICE_CORP_ADDRESS) -INVOICE_PAYMENT_INSTRUCTIONS = ENV_TOKENS.get('INVOICE_PAYMENT_INSTRUCTIONS', INVOICE_PAYMENT_INSTRUCTIONS) - # Which access.py permission names to check; # We default this to the legacy permission 'see_exists'. COURSE_CATALOG_VISIBILITY_PERMISSION = ENV_TOKENS.get( @@ -830,30 +702,16 @@ DEFAULT_MOBILE_AVAILABLE = ENV_TOKENS.get( DEFAULT_MOBILE_AVAILABLE ) - # Enrollment API Cache Timeout ENROLLMENT_COURSE_DETAILS_CACHE_TIMEOUT = ENV_TOKENS.get('ENROLLMENT_COURSE_DETAILS_CACHE_TIMEOUT', 60) -# PDF RECEIPT/INVOICE OVERRIDES -PDF_RECEIPT_TAX_ID = ENV_TOKENS.get('PDF_RECEIPT_TAX_ID', PDF_RECEIPT_TAX_ID) -PDF_RECEIPT_FOOTER_TEXT = ENV_TOKENS.get('PDF_RECEIPT_FOOTER_TEXT', PDF_RECEIPT_FOOTER_TEXT) -PDF_RECEIPT_DISCLAIMER_TEXT = ENV_TOKENS.get('PDF_RECEIPT_DISCLAIMER_TEXT', PDF_RECEIPT_DISCLAIMER_TEXT) -PDF_RECEIPT_BILLING_ADDRESS = ENV_TOKENS.get('PDF_RECEIPT_BILLING_ADDRESS', PDF_RECEIPT_BILLING_ADDRESS) -PDF_RECEIPT_TERMS_AND_CONDITIONS = ENV_TOKENS.get('PDF_RECEIPT_TERMS_AND_CONDITIONS', PDF_RECEIPT_TERMS_AND_CONDITIONS) -PDF_RECEIPT_TAX_ID_LABEL = ENV_TOKENS.get('PDF_RECEIPT_TAX_ID_LABEL', PDF_RECEIPT_TAX_ID_LABEL) -PDF_RECEIPT_LOGO_PATH = ENV_TOKENS.get('PDF_RECEIPT_LOGO_PATH', PDF_RECEIPT_LOGO_PATH) -PDF_RECEIPT_COBRAND_LOGO_PATH = ENV_TOKENS.get('PDF_RECEIPT_COBRAND_LOGO_PATH', PDF_RECEIPT_COBRAND_LOGO_PATH) -PDF_RECEIPT_LOGO_HEIGHT_MM = ENV_TOKENS.get('PDF_RECEIPT_LOGO_HEIGHT_MM', PDF_RECEIPT_LOGO_HEIGHT_MM) -PDF_RECEIPT_COBRAND_LOGO_HEIGHT_MM = ENV_TOKENS.get( - 'PDF_RECEIPT_COBRAND_LOGO_HEIGHT_MM', PDF_RECEIPT_COBRAND_LOGO_HEIGHT_MM -) - if FEATURES.get('ENABLE_COURSEWARE_SEARCH') or \ FEATURES.get('ENABLE_DASHBOARD_SEARCH') or \ FEATURES.get('ENABLE_COURSE_DISCOVERY') or \ FEATURES.get('ENABLE_TEAMS'): # Use ElasticSearch as the search engine herein SEARCH_ENGINE = "search.elastic.ElasticSearchEngine" + SEARCH_FILTER_GENERATOR = ENV_TOKENS.get('SEARCH_FILTER_GENERATOR', SEARCH_FILTER_GENERATOR) ELASTIC_SEARCH_CONFIG = ENV_TOKENS.get('ELASTIC_SEARCH_CONFIG', [{}]) @@ -865,25 +723,6 @@ FACEBOOK_APP_ID = AUTH_TOKENS.get("FACEBOOK_APP_ID") XBLOCK_SETTINGS = ENV_TOKENS.get('XBLOCK_SETTINGS', {}) XBLOCK_SETTINGS.setdefault("VideoBlock", {})["licensing_enabled"] = FEATURES.get("LICENSING", False) XBLOCK_SETTINGS.setdefault("VideoBlock", {})['YOUTUBE_API_KEY'] = AUTH_TOKENS.get('YOUTUBE_API_KEY', YOUTUBE_API_KEY) -YOUTUBE_API_KEY = AUTH_TOKENS.get('YOUTUBE_API_KEY', YOUTUBE_API_KEY) - -##### VIDEO IMAGE STORAGE ##### -VIDEO_IMAGE_SETTINGS = ENV_TOKENS.get('VIDEO_IMAGE_SETTINGS', VIDEO_IMAGE_SETTINGS) - -##### VIDEO TRANSCRIPTS STORAGE ##### -VIDEO_TRANSCRIPTS_SETTINGS = ENV_TOKENS.get('VIDEO_TRANSCRIPTS_SETTINGS', VIDEO_TRANSCRIPTS_SETTINGS) - -##### ECOMMERCE API CONFIGURATION SETTINGS ##### -ECOMMERCE_PUBLIC_URL_ROOT = ENV_TOKENS.get('ECOMMERCE_PUBLIC_URL_ROOT', ECOMMERCE_PUBLIC_URL_ROOT) -ECOMMERCE_API_URL = ENV_TOKENS.get('ECOMMERCE_API_URL', ECOMMERCE_API_URL) -ECOMMERCE_API_TIMEOUT = ENV_TOKENS.get('ECOMMERCE_API_TIMEOUT', ECOMMERCE_API_TIMEOUT) - -COURSE_CATALOG_API_URL = ENV_TOKENS.get('COURSE_CATALOG_API_URL', COURSE_CATALOG_API_URL) - -ECOMMERCE_SERVICE_WORKER_USERNAME = ENV_TOKENS.get( - 'ECOMMERCE_SERVICE_WORKER_USERNAME', - ECOMMERCE_SERVICE_WORKER_USERNAME -) ##### Custom Courses for EdX ##### if FEATURES.get('CUSTOM_COURSES_EDX'): @@ -891,7 +730,6 @@ if FEATURES.get('CUSTOM_COURSES_EDX'): MODULESTORE_FIELD_OVERRIDE_PROVIDERS += ( 'lms.djangoapps.ccx.overrides.CustomCoursesForEdxOverrideProvider', ) -CCX_MAX_STUDENTS_ALLOWED = ENV_TOKENS.get('CCX_MAX_STUDENTS_ALLOWED', CCX_MAX_STUDENTS_ALLOWED) ##### Individual Due Date Extensions ##### if FEATURES.get('INDIVIDUAL_DUE_DATES'): @@ -909,25 +747,12 @@ MODULESTORE_FIELD_OVERRIDE_PROVIDERS += ( ) # PROFILE IMAGE CONFIG -PROFILE_IMAGE_BACKEND = ENV_TOKENS.get('PROFILE_IMAGE_BACKEND', PROFILE_IMAGE_BACKEND) -PROFILE_IMAGE_HASH_SEED = AUTH_TOKENS.get('PROFILE_IMAGE_HASH_SEED', PROFILE_IMAGE_HASH_SEED) -PROFILE_IMAGE_MAX_BYTES = ENV_TOKENS.get('PROFILE_IMAGE_MAX_BYTES', PROFILE_IMAGE_MAX_BYTES) -PROFILE_IMAGE_MIN_BYTES = ENV_TOKENS.get('PROFILE_IMAGE_MIN_BYTES', PROFILE_IMAGE_MIN_BYTES) PROFILE_IMAGE_DEFAULT_FILENAME = 'images/profiles/default' PROFILE_IMAGE_SIZES_MAP = ENV_TOKENS.get( 'PROFILE_IMAGE_SIZES_MAP', PROFILE_IMAGE_SIZES_MAP ) -# EdxNotes config - -EDXNOTES_PUBLIC_API = ENV_TOKENS.get('EDXNOTES_PUBLIC_API', EDXNOTES_PUBLIC_API) -EDXNOTES_INTERNAL_API = ENV_TOKENS.get('EDXNOTES_INTERNAL_API', EDXNOTES_INTERNAL_API) -EDXNOTES_CLIENT_NAME = ENV_TOKENS.get('EDXNOTES_CLIENT_NAME', EDXNOTES_CLIENT_NAME) - -EDXNOTES_CONNECT_TIMEOUT = ENV_TOKENS.get('EDXNOTES_CONNECT_TIMEOUT', EDXNOTES_CONNECT_TIMEOUT) -EDXNOTES_READ_TIMEOUT = ENV_TOKENS.get('EDXNOTES_READ_TIMEOUT', EDXNOTES_READ_TIMEOUT) - ##### Credit Provider Integration ##### CREDIT_PROVIDER_SECRET_KEYS = AUTH_TOKENS.get("CREDIT_PROVIDER_SECRET_KEYS", {}) @@ -945,7 +770,6 @@ LTI_AGGREGATE_SCORE_PASSBACK_DELAY = ENV_TOKENS.get( ) ##################### Credit Provider help link #################### -CREDIT_HELP_LINK_URL = ENV_TOKENS.get('CREDIT_HELP_LINK_URL', CREDIT_HELP_LINK_URL) #### JWT configuration #### JWT_AUTH.update(ENV_TOKENS.get('JWT_AUTH', {})) @@ -974,16 +798,6 @@ SOFTWARE_SECURE_VERIFICATION_ROUTING_KEY = ENV_TOKENS.get( API_ACCESS_MANAGER_EMAIL = ENV_TOKENS.get('API_ACCESS_MANAGER_EMAIL') API_ACCESS_FROM_EMAIL = ENV_TOKENS.get('API_ACCESS_FROM_EMAIL') -# Mobile App Version Upgrade config -APP_UPGRADE_CACHE_TIMEOUT = ENV_TOKENS.get('APP_UPGRADE_CACHE_TIMEOUT', APP_UPGRADE_CACHE_TIMEOUT) - -AFFILIATE_COOKIE_NAME = ENV_TOKENS.get('AFFILIATE_COOKIE_NAME', AFFILIATE_COOKIE_NAME) - -############## Settings for LMS Context Sensitive Help ############## - -HELP_TOKENS_BOOKS = ENV_TOKENS.get('HELP_TOKENS_BOOKS', HELP_TOKENS_BOOKS) - - ############## OPEN EDX ENTERPRISE SERVICE CONFIGURATION ###################### # The Open edX Enterprise service is currently hosted via the LMS container/process. # However, for all intents and purposes this service is treated as a standalone IDA. @@ -1056,6 +870,8 @@ ENTERPRISE_CATALOG_INTERNAL_ROOT_URL = ENV_TOKENS.get( ENTERPRISE_CATALOG_INTERNAL_ROOT_URL ) +# List of enterprise customer uuids to exclude from transition to use of enterprise-catalog +ENTERPRISE_CUSTOMERS_EXCLUDED_FROM_CATALOG = ENV_TOKENS.get('ENTERPRISE_CUSTOMERS_EXCLUDED_FROM_CATALOG', ()) ############## ENTERPRISE SERVICE LMS CONFIGURATION ################################## # The LMS has some features embedded that are related to the Enterprise service, but @@ -1089,13 +905,6 @@ SYSTEM_TO_FEATURE_ROLE_MAPPING = ENV_TOKENS.get( SYSTEM_TO_FEATURE_ROLE_MAPPING ) -############## CATALOG/DISCOVERY SERVICE API CLIENT CONFIGURATION ###################### -# The LMS communicates with the Catalog service via the EdxRestApiClient class -# The below environmental settings are utilized by the LMS when interacting with -# the service, and override the default parameters which are defined in common.py - -COURSES_API_CACHE_TIMEOUT = ENV_TOKENS.get('COURSES_API_CACHE_TIMEOUT', COURSES_API_CACHE_TIMEOUT) - # Add an ICP license for serving content in China if your organization is registered to do so ICP_LICENSE = ENV_TOKENS.get('ICP_LICENSE', None) ICP_LICENSE_INFO = ENV_TOKENS.get('ICP_LICENSE_INFO', {}) @@ -1120,50 +929,11 @@ PARENTAL_CONSENT_AGE_LIMIT = ENV_TOKENS.get( # Allow extra middleware classes to be added to the app through configuration. MIDDLEWARE.extend(ENV_TOKENS.get('EXTRA_MIDDLEWARE_CLASSES', [])) -########################## Settings for Completion API ##################### - -# Once a user has watched this percentage of a video, mark it as complete: -# (0.0 = 0%, 1.0 = 100%) -COMPLETION_VIDEO_COMPLETE_PERCENTAGE = ENV_TOKENS.get( - 'COMPLETION_VIDEO_COMPLETE_PERCENTAGE', - COMPLETION_VIDEO_COMPLETE_PERCENTAGE, -) -# The time a block needs to be viewed to be considered complete, in milliseconds. -COMPLETION_BY_VIEWING_DELAY_MS = ENV_TOKENS.get('COMPLETION_BY_VIEWING_DELAY_MS', COMPLETION_BY_VIEWING_DELAY_MS) - -############### Settings for django-fernet-fields ################## -FERNET_KEYS = AUTH_TOKENS.get('FERNET_KEYS', FERNET_KEYS) - ################# Settings for the maintenance banner ################# MAINTENANCE_BANNER_TEXT = ENV_TOKENS.get('MAINTENANCE_BANNER_TEXT', None) -############### Settings for Retirement ##################### -RETIRED_USERNAME_PREFIX = ENV_TOKENS.get('RETIRED_USERNAME_PREFIX', RETIRED_USERNAME_PREFIX) -RETIRED_EMAIL_PREFIX = ENV_TOKENS.get('RETIRED_EMAIL_PREFIX', RETIRED_EMAIL_PREFIX) -RETIRED_EMAIL_DOMAIN = ENV_TOKENS.get('RETIRED_EMAIL_DOMAIN', RETIRED_EMAIL_DOMAIN) -RETIRED_USER_SALTS = ENV_TOKENS.get('RETIRED_USER_SALTS', RETIRED_USER_SALTS) -RETIREMENT_SERVICE_WORKER_USERNAME = ENV_TOKENS.get( - 'RETIREMENT_SERVICE_WORKER_USERNAME', - RETIREMENT_SERVICE_WORKER_USERNAME -) -RETIREMENT_STATES = ENV_TOKENS.get('RETIREMENT_STATES', RETIREMENT_STATES) - -############### Settings for Username Replacement ############### -USERNAME_REPLACEMENT_WORKER = ENV_TOKENS.get('USERNAME_REPLACEMENT_WORKER', USERNAME_REPLACEMENT_WORKER) - -############## Settings for Course Enrollment Modes ###################### -COURSE_ENROLLMENT_MODES = ENV_TOKENS.get('COURSE_ENROLLMENT_MODES', COURSE_ENROLLMENT_MODES) - -############## Settings for Microfrontend URLS ######################### -WRITABLE_GRADEBOOK_URL = ENV_TOKENS.get('WRITABLE_GRADEBOOK_URL', WRITABLE_GRADEBOOK_URL) -PROFILE_MICROFRONTEND_URL = ENV_TOKENS.get('PROFILE_MICROFRONTEND_URL', PROFILE_MICROFRONTEND_URL) -ORDER_HISTORY_MICROFRONTEND_URL = ENV_TOKENS.get('ORDER_HISTORY_MICROFRONTEND_URL', ORDER_HISTORY_MICROFRONTEND_URL) -ACCOUNT_MICROFRONTEND_URL = ENV_TOKENS.get('ACCOUNT_MICROFRONTEND_URL', ACCOUNT_MICROFRONTEND_URL) -LEARNING_MICROFRONTEND_URL = ENV_TOKENS.get('LEARNING_MICROFRONTEND_URL', LEARNING_MICROFRONTEND_URL) -LEARNER_PORTAL_URL_ROOT = ENV_TOKENS.get('LEARNER_PORTAL_URL_ROOT', LEARNER_PORTAL_URL_ROOT) - -############### Settings for edx-rbac ############### -SYSTEM_WIDE_ROLE_CLASSES = ENV_TOKENS.get('SYSTEM_WIDE_ROLE_CLASSES') or SYSTEM_WIDE_ROLE_CLASSES +########################## limiting dashboard courses ###################### +DASHBOARD_COURSE_LIMIT = ENV_TOKENS.get('DASHBOARD_COURSE_LIMIT', None) ############################### Plugin Settings ############################### @@ -1176,13 +946,11 @@ plugin_settings.add_plugins(__name__, plugin_constants.ProjectType.LMS, plugin_c derive_settings(__name__) -######################### Overriding custom enrollment roles ############### - -MANUAL_ENROLLMENT_ROLE_CHOICES = ENV_TOKENS.get('MANUAL_ENROLLMENT_ROLE_CHOICES', MANUAL_ENROLLMENT_ROLE_CHOICES) +############## Settings for Completion API ######################### -########################## limiting dashboard courses ###################### - -DASHBOARD_COURSE_LIMIT = ENV_TOKENS.get('DASHBOARD_COURSE_LIMIT', None) - -##################### SUPPORT URL ############################ -SUPPORT_HOW_TO_UNENROLL_LINK = ENV_TOKENS.get('SUPPORT_HOW_TO_UNENROLL_LINK', SUPPORT_HOW_TO_UNENROLL_LINK) +# Once a user has watched this percentage of a video, mark it as complete: +# (0.0 = 0%, 1.0 = 100%) +COMPLETION_VIDEO_COMPLETE_PERCENTAGE = ENV_TOKENS.get('COMPLETION_VIDEO_COMPLETE_PERCENTAGE', + COMPLETION_VIDEO_COMPLETE_PERCENTAGE) +COMPLETION_VIDEO_COMPLETE_PERCENTAGE = ENV_TOKENS.get('COMPLETION_BY_VIEWING_DELAY_MS', + COMPLETION_BY_VIEWING_DELAY_MS) diff --git a/lms/envs/test.py b/lms/envs/test.py index 6a998548ed706cc8addc2c2ba01406d8f73bcf25..1fb77e7352c3927bc7772e1457989218ebe81108 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -193,11 +193,6 @@ DATABASES = { }, } -if os.environ.get('DISABLE_MIGRATIONS'): - # Create tables directly from apps' models. This can be removed once we upgrade - # to Django 1.9, which allows setting MIGRATION_MODULES to None in order to skip migrations. - MIGRATION_MODULES = NoOpMigrationModules() - CACHES = { # This is the cache used for most things. # In staging/prod envs, the sessions also live here. @@ -529,7 +524,6 @@ VIDEO_TRANSCRIPTS_SETTINGS = dict( ) ####################### Authentication Settings ########################## -# pylint: disable=unicode-format-string JWT_AUTH.update({ 'JWT_PUBLIC_SIGNING_JWK_SET': ( '{"keys": [{"kid": "BTZ9HA6K", "e": "AQAB", "kty": "RSA", "n": "o5cn3ljSRi6FaDEKTn0PS-oL9EFyv1pI7dRgffQLD1qf5D6' @@ -596,3 +590,6 @@ PROCTORING_SETTINGS = {} ############### Settings for Django Rate limit ##################### RATELIMIT_RATE = '2/m' + +##### LOGISTRATION RATE LIMIT SETTINGS ##### +LOGISTRATION_RATELIMIT_RATE = '5/5m' diff --git a/lms/static/certificates/sass/_base.scss b/lms/static/certificates/sass/_base.scss index 5705480da9be2c460588998e47b9f6e666abcc1a..bf2b0aa4e2afed5065f1e056f3f5fa6b7f4f024b 100644 --- a/lms/static/certificates/sass/_base.scss +++ b/lms/static/certificates/sass/_base.scss @@ -10,7 +10,8 @@ // ------------------------------ // #BASE // ------------------------------ -html, body { +html, +body { height: 100%; margin: 0; padding: 0; diff --git a/lms/static/certificates/sass/_components.scss b/lms/static/certificates/sass/_components.scss index 55e37fc6df24a1fffdf3305e6b5486f9b63b65e7..f87ec557225f8f057e7120e924aec47df01ae245 100644 --- a/lms/static/certificates/sass/_components.scss +++ b/lms/static/certificates/sass/_components.scss @@ -80,10 +80,6 @@ background: $white; } -.header-app { - -} - // ------------------------------ // #BANNER // ------------------------------ @@ -112,7 +108,9 @@ .message-actions .action { // STATE: hover, active, focus - &:hover, &:active, &:focus { + &:hover, + &:active, + &:focus { // customizations from UXPL color: palette(grayscale, dark); } @@ -166,7 +164,8 @@ .accomplishment-brief { @extend %depth-card; - .accomplishment-type-symbol, .accomplishment-details { + .accomplishment-type-symbol, + .accomplishment-details { display: inline-block; vertical-align: middle; } @@ -224,7 +223,8 @@ margin-bottom: spacing-vertical(base); } - .accomplishment-type-label, .accomplishment-type-symbol { + .accomplishment-type-label, + .accomplishment-type-symbol { display: block; } @@ -266,12 +266,6 @@ @extend %rendering-accomplishment-line; } - .accomplishment-course-org { - } - - .accomplishment-course-name { - } - .accomplishment-course-description { @extend %rendering-accomplishment-line; } @@ -306,7 +300,8 @@ margin: 0 auto spacing-vertical(x-small) auto; } - .signatory-name, .signatory-credentials { + .signatory-name, + .signatory-credentials { @include text-align(center); } @@ -315,7 +310,8 @@ } .signatory-credentials { - .role, .organization { + .role, + .organization { white-space: pre-line; display: block; } @@ -354,7 +350,8 @@ } } - .recipient-img, .recipient-details { + .recipient-img, + .recipient-details { display: inline-block; vertical-align: middle; } @@ -401,10 +398,6 @@ // ------------------------------ // #ACCOMPLISHMENT RELATED // ------------------------------ -.accomplishment-related { - -} - .accomplishment-related-title { @extend %hd-subsection; } @@ -453,7 +446,8 @@ color: $cert-base-color; } - .accomplishment-signatories-title, .accomplishment-orgs-title { + .accomplishment-signatories-title, + .accomplishment-orgs-title { color: $cert-decorative-color; } @@ -461,8 +455,7 @@ .accomplishment-statement, .accomplishment-statement-lead, .accomplishment-recipient, - .accomplishment-course, - { + .accomplishment-course { font-family: $font-family-serif; } @@ -520,7 +513,6 @@ .deco-corner-bl { @include triangle(20px, $cert-distinguished-color, down-right); - } .deco-corner-br { @@ -537,13 +529,6 @@ } } -// ------------------------------ -// #ABOUT -// ------------------------------ -.about { - -} - // ------------------------------ // #FOOTER // ------------------------------ @@ -602,7 +587,7 @@ display: table; } - .image-container{ + .image-container { // Lines the image up with the content of the above list. @include ltr { @include padding-left(2em); diff --git a/lms/static/certificates/sass/_config.scss b/lms/static/certificates/sass/_config.scss index fc76f17e839164715ddea64c96373f75b22696e5..886e49d78a59f891924516dbf5df65dbeed00e5d 100644 --- a/lms/static/certificates/sass/_config.scss +++ b/lms/static/certificates/sass/_config.scss @@ -18,14 +18,14 @@ $cert-decorative-color-emphasized: palette(grayscale, accent); @include font-face( 'Domine', '../../certificates/fonts/Domine/Domine-Regular-webfont', - 400, - $file-formats: woff woff2 ttf + 400, + $file-formats: woff woff2 ttf ); @include font-face( 'Domine', '../../certificates/fonts/Domine/Domine-Bold-webfont', - 700, - $file-formats: woff woff2 ttf + 700, + $file-formats: woff woff2 ttf ); // typography: config - stacks diff --git a/lms/static/certificates/sass/_layouts.scss b/lms/static/certificates/sass/_layouts.scss index 9aa47a833b2cfde36966c1236226a625b2e688f2..7473b8aa948c1f0b0931551ec470fde60cd96dff 100644 --- a/lms/static/certificates/sass/_layouts.scss +++ b/lms/static/certificates/sass/_layouts.scss @@ -13,7 +13,7 @@ margin-bottom: spacing-vertical(base); padding: 0 5%; - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { padding: 0 2.5%; } } @@ -74,7 +74,7 @@ .banner-user { @include text-align(center); - @media(min-width: $bp-screen-lg) { + @media (min-width: $bp-screen-lg) { @include text-align(left); } @@ -99,7 +99,7 @@ // CASE: icon display only &.icon-only { - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { padding: spacing-vertical(x-small) spacing-horizontal(base); .icon { @@ -108,7 +108,7 @@ } } - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { display: inline-block; vertical-align: middle; min-width: 130px; @@ -135,7 +135,7 @@ } .footer-app-copyright { - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { @include span(6, after); margin-bottom: 0; @@ -143,7 +143,7 @@ } .footer-app-nav { - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { @include span(6, before); } @@ -152,7 +152,7 @@ display: block; margin-bottom: spacing-vertical(x-small); - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { display: inline-block; vertical-align: middle; @@ -164,7 +164,7 @@ } .list-legal { - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { @include text-align(right); } } @@ -228,15 +228,15 @@ @include margin-right(0); } - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { @include span(3); } - @media(min-width: $bp-screen-lg) { + @media (min-width: $bp-screen-lg) { @include span(2); } - @media(min-width: $bp-screen-xl) { + @media (min-width: $bp-screen-xl) { @include span(2); } } @@ -245,7 +245,6 @@ @include size(100%); position: relative; - } .organization-logo { @@ -270,15 +269,15 @@ @include span(12); - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { @include span(4); } - @media(min-width: $bp-screen-lg) { + @media (min-width: $bp-screen-lg) { @include span(3); } - @media(min-width: $bp-screen-xl) { + @media (min-width: $bp-screen-xl) { @include span(3); } @@ -319,7 +318,7 @@ padding-bottom: 0; } - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { @include span(4); border-bottom: none; @@ -339,7 +338,7 @@ .accomplishment-brief { margin-bottom: spacing-vertical(small); - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { @include span(6); } @@ -364,7 +363,7 @@ margin-bottom: 0; } - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { @include span(6); margin-bottom: 0; diff --git a/lms/static/certificates/sass/_print.scss b/lms/static/certificates/sass/_print.scss index 9b368e7d11ae52e6d8e174bb4596932a14d3ed09..882d1678c929612786cdb60b0782da4fea271c68 100644 --- a/lms/static/certificates/sass/_print.scss +++ b/lms/static/certificates/sass/_print.scss @@ -15,7 +15,7 @@ // page set up - only available to modern browsers now @page { - size : landscape; + size: landscape; } @media print { @@ -61,7 +61,8 @@ } // prevent large elements from being split across multiple pages - ul, img { + ul, + img { page-break-inside: avoid; } @@ -79,7 +80,6 @@ .wrapper-view { margin-bottom: 0 !important; - } } @@ -87,7 +87,7 @@ @media print and (color) { * { -webkit-print-color-adjust: exact; - print-color-adjust: exact; + print-color-adjust: exact; /* stylelint-disable-line */ } } @@ -297,7 +297,8 @@ border-bottom: none !important; padding-bottom: 0 !important; - .label, .value { + .label, + .value { display: inline-block; vertical-align: baseline; font-size: font-size(x-small); @@ -325,7 +326,6 @@ @include text-align(right); } - } } diff --git a/lms/static/certificates/sass/_views.scss b/lms/static/certificates/sass/_views.scss index ad37deaba1425f8909f6f3e5d0f95ebeaf1154f6..5c15b8b8c8791dcd4a0d1bbb47c74486aeb420cf 100644 --- a/lms/static/certificates/sass/_views.scss +++ b/lms/static/certificates/sass/_views.scss @@ -26,13 +26,13 @@ .content-main { margin-bottom: spacing-vertical(base); - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { @include span(9, after); } } .content-secondary { - @media(min-width: $bp-screen-md) { + @media (min-width: $bp-screen-md) { @include span(3, before); } } diff --git a/lms/static/js/apiClient/.eslintrc.js b/lms/static/js/apiClient/.eslintrc.js deleted file mode 100644 index 838b853a827720b1be56716b6a7c293cfcd06a4b..0000000000000000000000000000000000000000 --- a/lms/static/js/apiClient/.eslintrc.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - extends: 'eslint-config-edx', - root: true, - settings: { - 'import/resolver': { - webpack: { - config: 'webpack.dev.config.js', - }, - }, - }, -}; diff --git a/lms/static/js/apiClient/index.js b/lms/static/js/apiClient/index.js deleted file mode 100644 index fd1208b35643a093ef4586d049359b76c41afdfd..0000000000000000000000000000000000000000 --- a/lms/static/js/apiClient/index.js +++ /dev/null @@ -1,16 +0,0 @@ -import { getAuthenticatedApiClient } from '@edx/frontend-auth'; -import { NewRelicLoggingService } from '@edx/frontend-logging'; - -const apiClient = getAuthenticatedApiClient({ - appBaseUrl: process.env.LMS_ROOT_URL, - authBaseUrl: process.env.LMS_ROOT_URL, - loginUrl: `${process.env.LMS_ROOT_URL}/login`, - logoutUrl: `${process.env.LMS_ROOT_URL}/logout`, - csrfTokenApiPath: '/csrf/api/v1/token', - refreshAccessTokenEndpoint: `${process.env.LMS_ROOT_URL}/login_refresh`, - accessTokenCookieName: process.env.JWT_AUTH_COOKIE_HEADER_PAYLOAD, - userInfoCookieName: process.env.EDXMKTG_USER_INFO_COOKIE_NAME, - loggingService: NewRelicLoggingService, -}); - -export default apiClient; diff --git a/lms/static/js/commerce/views/receipt_view.js b/lms/static/js/commerce/views/receipt_view.js deleted file mode 100644 index 9e377d7e4095d74212e27247c963733a59006ba3..0000000000000000000000000000000000000000 --- a/lms/static/js/commerce/views/receipt_view.js +++ /dev/null @@ -1,382 +0,0 @@ -/** - * View for the receipt page. - */ - -/* globals _, Backbone */ -var edx = edx || {}; - -(function($, _, Backbone) { - 'use strict'; - - edx.commerce = edx.commerce || {}; - - edx.commerce.ReceiptView = Backbone.View.extend({ - useEcommerceApi: true, - ecommerceBasketId: null, - ecommerceOrderNumber: null, - - initialize: function() { - this.ecommerceBasketId = $.url('?basket_id'); - this.ecommerceOrderNumber = $.url('?orderNum'); - this.useEcommerceApi = this.ecommerceBasketId || this.ecommerceOrderNumber; - _.bindAll(this, 'renderReceipt', 'renderError', 'getProviderData', 'renderProvider', 'getCourseData'); - - this.render(); - }, - - /** - * @param product - * @returns {bool} True if product requires user to be verified by Software Secure. - */ - requiresVerification: function(product) { - function getAttribute(attribute, defaultValue) { - var attr = _.findWhere(product.attribute_values, {name: attribute}); - if (!attr) { - return defaultValue; - } - return attr.value; - } - - return getAttribute('id_verification_required', true); - }, - - renderReceipt: function(data) { - var templateHtml = $('#receipt-tpl').html(), - self = this, - context = { - platformName: this.$el.data('platform-name'), - verified: this.$el.data('verified').toLowerCase() === 'true', - is_request_in_themed_site: this.$el.data('is-request-in-themed-site').toLowerCase() === 'true' - }, - providerId, - courseRequiresVerification; - - // True if any of the courses bought requires verification - courseRequiresVerification = _.any(data.lines, function(line) { - return this.requiresVerification(line.product); - }, this); - - // Add the receipt info to the template context - this.courseKey = this.getOrderCourseKey(data); - this.username = this.$el.data('username'); - $.ajax({ - type: 'GET', - url: '/commerce/checkout/verification_status/', - data: {course_id: this.courseKey} - }).success(function(response) { - _.extend(context, { - receipt: self.receiptContext(data), - courseKey: self.courseKey, - is_verification_required: response.is_verification_required && courseRequiresVerification - }); - - self.$el.html(_.template(templateHtml)(context)); - - self.trackLinks(); - - self.trackPurchase(data); - - self.renderCourseNamePlaceholder(self.courseKey); - - self.renderUserFullNamePlaceholder(self.username); - - providerId = self.getCreditProviderId(data); - if (providerId) { - self.getProviderData(providerId).then(self.renderProvider, self.renderError); - } - }).error(function() { - self.renderError(); - }); - }, - renderCourseNamePlaceholder: function(courseId) { - // Display the course Id or name (if available) in the placeholder - var $courseNamePlaceholder = $('.course_name_placeholder'); - $courseNamePlaceholder.text(courseId); - - this.getCourseData(courseId).then(function(responseData) { - $courseNamePlaceholder.text(responseData.name); - }); - }, - renderUserFullNamePlaceholder: function(username) { - var userModel = Backbone.Model.extend({ - urlRoot: '/api/user/v1/accounts/', - url: function() { - return this.urlRoot + this.id; - } - }); - this.user = new userModel({id: username}); - this.user.fetch({success: function(userData) { - $('.full_name_placeholder').text(userData.get('name')); - }}); - }, - renderProvider: function(context) { - var templateHtml = $('#provider-tpl').html(), - providerDiv = this.$el.find('#receipt-provider'); - context.course_key = this.courseKey; - context.username = this.username; - context.platformName = this.$el.data('platform-name'); - providerDiv.html(_.template(templateHtml)(context)).removeClass('hidden'); - }, - - renderError: function() { - // Display an error - $('#error-container').removeClass('hidden'); - }, - - trackPurchase: function(order) { - window.analytics.track('Completed Purchase', { - orderId: order.number, - total: order.total_excl_tax, - currency: order.currency - }); - }, - - render: function() { - var self = this, - orderId = this.ecommerceOrderNumber || this.ecommerceBasketId || $.url('?payment-order-num'); - - if (orderId && this.$el.data('is-payment-complete') === 'True') { - // Get the order details - self.$el.removeClass('hidden'); - self.getReceiptData(orderId).then(self.renderReceipt, self.renderError); - } else { - self.renderError(); - } - }, - - trackLinks: function() { - var $verifyNowButton = $('#verify_now_button'), - $verifyLaterButton = $('#verify_later_button'); - - // Track a virtual pageview, for easy funnel reconstruction. - window.analytics.page('payment', 'receipt'); - - // Track the user's decision to verify immediately - window.analytics.trackLink($verifyNowButton, 'edx.bi.user.verification.immediate', { - category: 'verification' - }); - - // Track the user's decision to defer their verification - window.analytics.trackLink($verifyLaterButton, 'edx.bi.user.verification.deferred', { - category: 'verification' - }); - }, - - /** - * Retrieve receipt data from Oscar (via LMS). - * @param {string} orderId Identifier of the order that was purchased. - * @return {object} JQuery Promise. - */ - getReceiptData: function(orderId) { - var urlFormat = '/shoppingcart/receipt/{orderId}/'; - - if (this.ecommerceOrderNumber) { - urlFormat = '/api/commerce/v1/orders/{orderId}/'; - } else if (this.ecommerceBasketId) { - urlFormat = '/api/commerce/v0/baskets/{orderId}/order/'; - } - - return $.ajax({ - url: edx.StringUtils.interpolate(urlFormat, {orderId: orderId}), - type: 'GET', - dataType: 'json' - }).retry({times: 5, timeout: 2000, statusCodes: [404]}); - }, - /** - * Retrieve credit provider data from LMS. - * @param {string} providerId The providerId of the credit provider. - * @return {object} JQuery Promise. - */ - getProviderData: function(providerId) { - var providerUrl = '/api/credit/v1/providers/{providerId}/'; - - return $.ajax({ - url: edx.StringUtils.interpolate(providerUrl, {providerId: providerId}), - type: 'GET', - dataType: 'json', - contentType: 'application/json', - headers: { - 'X-CSRFToken': $.cookie('csrftoken') - } - }).retry({times: 5, timeout: 2000, statusCodes: [404]}); - }, - /** - * Retrieve course data from LMS. - * @param {string} courseId The courseId of the course. - * @return {object} JQuery Promise. - */ - getCourseData: function(courseId) { - var courseDetailUrl = '/api/courses/v1/courses/{courseId}/'; - return $.ajax({ - url: edx.StringUtils.interpolate(courseDetailUrl, {courseId: courseId}), - type: 'GET', - dataType: 'json' - }); - }, - - /** - * Construct the template context from data received - * from the E-Commerce API. - * - * @param {object} order Receipt data received from the server - * @return {object} Receipt template context. - */ - receiptContext: function(order) { - var self = this, - receiptContext; - - if (this.useEcommerceApi) { - receiptContext = { - orderNum: order.number, - currency: order.currency, - purchasedDatetime: order.date_placed, - totalCost: self.formatMoney(order.total_excl_tax), - isRefunded: false, - items: [], - billedTo: null - }; - - if (order.billing_address) { - receiptContext.billedTo = { - firstName: order.billing_address.first_name, - lastName: order.billing_address.last_name, - city: order.billing_address.city, - state: order.billing_address.state, - postalCode: order.billing_address.postcode, - country: order.billing_address.country - }; - } - - receiptContext.items = _.map( - order.lines, - function(line) { - return { - lineDescription: line.description, - cost: self.formatMoney(line.line_price_excl_tax) - }; - } - ); - } else { - receiptContext = { - orderNum: order.orderNum, - currency: order.currency, - purchasedDatetime: order.purchase_datetime, - totalCost: self.formatMoney(order.total_cost), - isRefunded: order.status === 'refunded', - billedTo: { - firstName: order.billed_to.first_name, - lastName: order.billed_to.last_name, - city: order.billed_to.city, - state: order.billed_to.state, - postalCode: order.billed_to.postal_code, - country: order.billed_to.country - }, - items: [] - }; - - receiptContext.items = _.map( - order.items, - function(item) { - return { - lineDescription: item.line_desc, - cost: self.formatMoney(item.line_cost) - }; - } - ); - } - - return receiptContext; - }, - - getOrderCourseKey: function(order) { - var length, items; - if (this.useEcommerceApi) { - length = order.lines.length; - for (var i = 0; i < length; i++) { - var line = order.lines[i], - attributeValues = _.find(line.product.attribute_values, function(attribute) { - // If the attribute has a 'code' property, compare its value, otherwise compare 'name' - var value_to_match = 'course_key'; - if (attribute.code) { - return attribute.code === value_to_match; - } else { - return attribute.name === value_to_match; - } - }); - - // This method assumes that all items in the order are related to a single course. - if (attributeValues != undefined) { - return attributeValues.value; - } - } - } else { - items = _.filter(order.items, function(item) { - return item.course_key; - }); - - if (items.length > 0) { - return items[0].course_key; - } - } - - return null; - }, - - formatMoney: function(moneyStr) { - return Number(moneyStr).toFixed(2); - }, - - /** - * Check whether the payment is for the credit course or not. - * - * @param {object} order Receipt data received from the server - * @return {string} String of the provider_id or null. - */ - getCreditProviderId: function(order) { - var attributeValues, - line = order.lines[0]; - if (this.useEcommerceApi) { - attributeValues = _.find(line.product.attribute_values, function(attribute) { - return attribute.name === 'credit_provider'; - }); - - // This method assumes that all items in the order are related to a single course. - if (attributeValues != undefined) { - return attributeValues.value; - } - } - - return null; - } - }); - - new edx.commerce.ReceiptView({ - el: $('#receipt-container') - }); -}(jQuery, _, Backbone)); - -function completeOrder(event) { - 'use strict'; - var courseKey = $(event).data('course-key'), - username = $(event).data('username'), - providerId = $(event).data('provider'), - $errorContainer = $('#error-container'); - - try { - event.preventDefault(); - } catch (err) { - // Ignore the error as not all event inputs have the preventDefault method. - } - - analytics.track( - 'edx.bi.credit.clicked_complete_credit', - { - category: 'credit', - label: courseKey - } - ); - - edx.commerce.credit.createCreditRequest(providerId, courseKey, username).fail(function() { - $errorContainer.removeClass('hidden'); - }); -} diff --git a/lms/static/js/custom_user_menu_links/.eslintrc.js b/lms/static/js/custom_user_menu_links/.eslintrc.js deleted file mode 100644 index 838b853a827720b1be56716b6a7c293cfcd06a4b..0000000000000000000000000000000000000000 --- a/lms/static/js/custom_user_menu_links/.eslintrc.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - extends: 'eslint-config-edx', - root: true, - settings: { - 'import/resolver': { - webpack: { - config: 'webpack.dev.config.js', - }, - }, - }, -}; diff --git a/lms/static/js/custom_user_menu_links/CustomUserMenuLinks.js b/lms/static/js/custom_user_menu_links/CustomUserMenuLinks.js deleted file mode 100644 index f4f068d5802020fcefa7e504db4d59f5705c86a2..0000000000000000000000000000000000000000 --- a/lms/static/js/custom_user_menu_links/CustomUserMenuLinks.js +++ /dev/null @@ -1,22 +0,0 @@ -import { getAuthenticatedUser } from '@edx/frontend-auth'; -import { getLearnerPortalLinks } from '@edx/frontend-enterprise'; - -import apiClient from '../apiClient'; - -function CustomUserMenuLinks() { - const authenticatedUser = getAuthenticatedUser(); - // Inject enterprise learner portal links - getLearnerPortalLinks(apiClient, authenticatedUser).then((learnerPortalLinks) => { - const $dashboardLink = $('#user-menu .dashboard'); - const classNames = 'mobile-nav-item dropdown-item dropdown-nav-item'; - for (let i = 0; i < learnerPortalLinks.length; i += 1) { - const link = learnerPortalLinks[i]; - - $dashboardLink.after( // xss-lint: disable=javascript-jquery-insertion - `<div class="${classNames}"><a href="${link.url}" role="menuitem">${link.title} Dashboard</a></div>`, - ); - } - }); -} - -export { CustomUserMenuLinks }; // eslint-disable-line import/prefer-default-export diff --git a/lms/static/js/fixtures/commerce/checkout_receipt.html b/lms/static/js/fixtures/commerce/checkout_receipt.html deleted file mode 100644 index 9c0809a701c1ac5bad718f6fe8cf9096a21205b7..0000000000000000000000000000000000000000 --- a/lms/static/js/fixtures/commerce/checkout_receipt.html +++ /dev/null @@ -1,28 +0,0 @@ -<div id="error-container" class="hidden"> - <div id="error" class="wrapper-msg wrapper-msg-activate"> - <div class=" msg msg-activate"> - <span class="msg-icon icon fa fa-exclamation-triangle" aria-hidden="true"></span> - - <div class="msg-content"> - <h3 class="title"> - Error - </h3> - <div class="copy"> - <p>dummy error text</p> - </div> - </div> - </div> - </div> -</div> - -<div class="container"> - <section class="wrapper carousel"> - <div id="receipt-container" class="pay-and-verify hidden" data-is-payment-complete='True' - data-platform-name='edx-platform' data-verified='True' data-username='user-1' - data-is-request-in-themed-site='True'> - <h2>Loading Order Data...</h2> - <span>Please wait while we retrieve your order details.</span> - </div> - </section> -</div> - diff --git a/lms/static/js/i18n/am/djangojs.js b/lms/static/js/i18n/am/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/lms/static/js/i18n/am/djangojs.js +++ b/lms/static/js/i18n/am/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/ar/djangojs.js b/lms/static/js/i18n/ar/djangojs.js index 54175c3ad3e73370ce03f0c5a08ae14896b53e40..a45f7bdba901fde7e0b001b06d1c01a6798775d6 100644 --- a/lms/static/js/i18n/ar/djangojs.js +++ b/lms/static/js/i18n/ar/djangojs.js @@ -1674,7 +1674,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1738,9 +1738,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "d\u200f/m\u200f/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/az/djangojs.js b/lms/static/js/i18n/az/djangojs.js index f659651f1bde4c7d76a607caf0e369bebdedbd58..21e2b8b0a6f66b5d800200a713f29dd3d03eddf0 100644 --- a/lms/static/js/i18n/az/djangojs.js +++ b/lms/static/js/i18n/az/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -157,9 +157,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/bg-bg/djangojs.js b/lms/static/js/i18n/bg-bg/djangojs.js index 846386a8dc94b4e5fd49323b533e7111f1702e12..4957525842b0502f4540407c4142de3c2154852a 100644 --- a/lms/static/js/i18n/bg-bg/djangojs.js +++ b/lms/static/js/i18n/bg-bg/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -165,9 +165,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/bn-bd/djangojs.js b/lms/static/js/i18n/bn-bd/djangojs.js index 48275730fbad40c445dacecf723441dfcd59619c..93c75995021e16ad78d612d8e6d2a1709ac59bec 100644 --- a/lms/static/js/i18n/bn-bd/djangojs.js +++ b/lms/static/js/i18n/bn-bd/djangojs.js @@ -68,7 +68,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -120,9 +120,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "6", + "FIRST_DAY_OF_WEEK": 6, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M, Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/bn-in/djangojs.js b/lms/static/js/i18n/bn-in/djangojs.js index 48275730fbad40c445dacecf723441dfcd59619c..93c75995021e16ad78d612d8e6d2a1709ac59bec 100644 --- a/lms/static/js/i18n/bn-in/djangojs.js +++ b/lms/static/js/i18n/bn-in/djangojs.js @@ -68,7 +68,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -120,9 +120,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "6", + "FIRST_DAY_OF_WEEK": 6, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M, Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/bs/djangojs.js b/lms/static/js/i18n/bs/djangojs.js index 65b677c3e9642faebc318bd6f2ab17558b7dd3c1..e891be783fb01879c30e9b066eda87fd0de230cc 100644 --- a/lms/static/js/i18n/bs/djangojs.js +++ b/lms/static/js/i18n/bs/djangojs.js @@ -53,7 +53,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -117,9 +117,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "Y M j", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/ca/djangojs.js b/lms/static/js/i18n/ca/djangojs.js index 516431f9f4a641e17cd4fc7ceed68c710161b112..7f4e006f5d8ead95d6189af13355fb36bf363fbd 100644 --- a/lms/static/js/i18n/ca/djangojs.js +++ b/lms/static/js/i18n/ca/djangojs.js @@ -1345,7 +1345,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1399,9 +1399,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y G:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/ca@valencia/djangojs.js b/lms/static/js/i18n/ca@valencia/djangojs.js index 8da83a3094bdc2b97fa8ff0b3d6ae7d85ef5505f..0dcde6cbfb4a657fb75b9bcb0aae70e94ec5b41c 100644 --- a/lms/static/js/i18n/ca@valencia/djangojs.js +++ b/lms/static/js/i18n/ca@valencia/djangojs.js @@ -1345,7 +1345,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1409,9 +1409,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/cs/djangojs.js b/lms/static/js/i18n/cs/djangojs.js index f42e092c9af37584f8f0a9e7a56c594628631dae..d7c010ffa892e4b1dc765f422365607f96d0e0c1 100644 --- a/lms/static/js/i18n/cs/djangojs.js +++ b/lms/static/js/i18n/cs/djangojs.js @@ -6,7 +6,7 @@ django.pluralidx = function(n) { - var v=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2; + var v=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3; if (typeof(v) == 'boolean') { return v ? 1 : 0; } else { @@ -23,6 +23,7 @@ "%(sel)s of %(cnt)s selected": [ "Vybr\u00e1na je %(sel)s polo\u017eka z celkem %(cnt)s.", "Vybr\u00e1ny jsou %(sel)s polo\u017eky z celkem %(cnt)s.", + "Vybran\u00fdch je %(sel)s polo\u017eek z celkem %(cnt)s.", "Vybran\u00fdch je %(sel)s polo\u017eek z celkem %(cnt)s." ], "6 a.m.": "6h r\u00e1no", @@ -53,11 +54,13 @@ "Note: You are %s hour ahead of server time.": [ "Pozn\u00e1mka: V\u00e1\u0161 \u010das o %s hodinu p\u0159edstihuje \u010das na serveru.", "Pozn\u00e1mka: V\u00e1\u0161 \u010das o %s hodiny p\u0159edstihuje \u010das na serveru.", + "Pozn\u00e1mka: V\u00e1\u0161 \u010das o %s hodin p\u0159edstihuje \u010das na serveru.", "Pozn\u00e1mka: V\u00e1\u0161 \u010das o %s hodin p\u0159edstihuje \u010das na serveru." ], "Note: You are %s hour behind server time.": [ "Pozn\u00e1mka: V\u00e1\u0161 \u010das se o %s hodinu zpo\u017e\u010fuje za \u010dasem na serveru.", "Pozn\u00e1mka: V\u00e1\u0161 \u010das se o %s hodiny zpo\u017e\u010fuje za \u010dasem na serveru.", + "Pozn\u00e1mka: V\u00e1\u0161 \u010das se o %s hodin zpo\u017e\u010fuje za \u010dasem na serveru.", "Pozn\u00e1mka: V\u00e1\u0161 \u010das se o %s hodin zpo\u017e\u010fuje za \u010dasem na serveru." ], "November": "listopad", @@ -104,7 +107,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -165,9 +168,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y G:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/cy/djangojs.js b/lms/static/js/i18n/cy/djangojs.js index ef5365ad7560a94d66988f9901b68485fdefa178..4ca4e208fe5fd6530a19458d792030fa6e582723 100644 --- a/lms/static/js/i18n/cy/djangojs.js +++ b/lms/static/js/i18n/cy/djangojs.js @@ -85,7 +85,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -141,9 +141,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y P", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/da/djangojs.js b/lms/static/js/i18n/da/djangojs.js index f68db68a6d30234b94e006d5335cea16bcc199b3..fdd09ee464bd7f14df17b1dd4a9341dfa2df9d1d 100644 --- a/lms/static/js/i18n/da/djangojs.js +++ b/lms/static/js/i18n/da/djangojs.js @@ -50,12 +50,12 @@ "Midnight": "Midnat", "Noon": "Middag", "Note: You are %s hour ahead of server time.": [ - "Obs: Du er %s time forud i forhold servertiden.", - "Obs: Du er %s timer forud i forhold servertiden." + "Obs: Du er %s time forud i forhold til servertiden.", + "Obs: Du er %s timer forud i forhold til servertiden." ], "Note: You are %s hour behind server time.": [ - "Obs: Du er %s time bagud i forhold servertiden.", - "Obs: Du er %s timer forud i forhold servertiden." + "Obs: Du er %s time bagud i forhold til servertiden.", + "Obs: Du er %s timer bagud i forhold til servertiden." ], "November": "November", "Now": "Nu", @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -151,9 +151,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/de-de/djangojs.js b/lms/static/js/i18n/de-de/djangojs.js index 6ce6baf54cba45fcab5fa4f5d1984d6b3d0c3a29..0a063ff19091133493cb91aba5d75e870666b48d 100644 --- a/lms/static/js/i18n/de-de/djangojs.js +++ b/lms/static/js/i18n/de-de/djangojs.js @@ -324,6 +324,7 @@ "Are you having trouble finding a team to join?": "Hast Du Probleme ein Team zum Beitreten zu finden?", "Are you sure that you want to leave this session?": "Sind Sie sicher, dass Sie diese Sitzung verlassen m\u00f6chten?", "Are you sure you want to change to a different session?": "Sind Sie sicher, dass Sie zu einer anderen Sitzung wechseln m\u00f6chten?", + "Are you sure you want to delete the following file? It cannot be restored.\nFile: ": "Wollen Sie die folgende Datei wirklich l\u00f6schen? Sie kann nicht wiederhergestellt werden.", "Are you sure you want to delete this comment?": "Bist du dir sicher, dass du diesen Kommentar l\u00f6schen m\u00f6chtest?", "Are you sure you want to delete this page? This action cannot be undone.": "Sind Sie sicher, dass Sie diese Seite l\u00f6schen wollen? Dies kann nicht r\u00fcckg\u00e4ngig gemacht werden.", "Are you sure you want to delete this post?": "Bist du dir sicher, dass du diesen Beitrag l\u00f6schen m\u00f6chtest?", @@ -623,7 +624,6 @@ "Default (Local Time Zone)": "Standard (Lokale Zeitzone)", "Default Timed Transcript": "Standard, zeitbehaftetes Transkript", "Delete": "L\u00f6schen", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "L\u00f6sche \"<%= signatoryName %>\" von der Liste der Unterzeichner?", "Delete File Confirmation": "Dateibest\u00e4tigung l\u00f6schen", "Delete My Account": "Meinen Account l\u00f6schen", "Delete Page Confirmation": "Seitenbest\u00e4tigung l\u00f6schen", @@ -668,7 +668,6 @@ "Do you want to upload your file before submitting?": "M\u00f6chten Sie die Datei hochladen, bevor Sie Ihre Antwort einreichen?", "Document properties": "Dokumenteneigenschaften", "Does the name on your ID match your account name: %(fullName)s?": "Passt der Name auf ihr Ausweis zu ihr Kontoname: %(fullName)s?", - "Does the photo of you match your ID photo?": "Passt das Foto zu das Foto auf ihr Ausweis?", "Does the photo of you show your whole face?": "Zeiget das Foto ihr vollst\u00e4ndiges Gesicht?", "Doing so means that you are no longer eligible for academic credit.": "Die Konsequenz hieraus ist, dass Sie nicht l\u00e4nger zum Erwerb akademische Kreditpunkte berechtigt sind.", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Wir sehen dein Bild nicht? Vergewissere dich, deinem Browser die Nutzung der Kamera zu erlauben, wenn er nach der Genehmigung fragt.", @@ -842,7 +841,6 @@ "Fill browser": "Vollbild im Browser", "Filter": "Filter", "Filter and sort topics": "Filter und sortiere Themen", - "Final Grade": "Finale Auswertung", "Final Grade Received": "Erhaltene Endnote", "Financial Aid": "Finanzielle Unterst\u00fctzung", "Financial Assistance": "Finanzielle Unterst\u00fctzung", @@ -876,7 +874,6 @@ "Generate": "Erstellen", "Generate Exception Certificates": "Ausnahmezertifikate erstellen", "Generate the user's certificate": "Zertifikat f\u00fcr den Nutzer erstellen", - "Get Credit": "Credit bekommen", "Go Back": "Gehe zur\u00fcck", "Go to Dashboard": "Zu \"Meine Kurse\"", "Go to my Dashboard": "Zu \"Meine Kurse\"", @@ -957,10 +954,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "Wenn der Unterabschnitt kein F\u00e4lligkeitsdatum hat, sehen die Lernenden immer ihre Ergebnisse, wenn sie Antworten zur Bewertung abgeben.", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "Wenn die Lerneinheit zuvor ver\u00f6ffentlicht und an die Lernenden freigegeben wurde, sind alle \u00c4nderungen, die Sie an der Lerneinheit vorgenommen haben, als sie noch ausgeblendet war, nun f\u00fcr alle Lernenden sichtbar.", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "Falls die Lerneinheit bereits vorher ver\u00f6ffentlicht und f\u00fcr die Teilnehmer freigeben war, werden jetzt alle Anderungen, die du w\u00e4hrend die Einheit versteckt war, vorgenommen hast, f\u00fcr die Teilnehmer sichtbar. M\u00f6chtest du fortfahren?", - "If you are unable to access your account contact us via email using {email}.": "Wenn Sie keinen Zugang zu Ihrem Account haben, kontaktieren Sie uns via E-Mail {email}.", "If you do not yet have an account, use the button below to register.": "Wenn Sie noch kein Account haben, nutzen Sie den unteren Button, um sich zu registrieren.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "Wenn Sie Ihre Identit\u00e4t jetzt nicht \u00fcberpr\u00fcfen k\u00f6nnen Sie immer noch Ihren Kurs erkunden von Ihrem Armaturenbrett. Sie werden regelm\u00e4\u00dfigen Erinnerungen von %(platformName)s erhalten um Ihre Identit\u00e4t zu \u00fcberpr\u00fcfen.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "Wenn Sie Ihre Identit\u00e4t jetzt nicht verifizieren, k\u00f6nnen Sie Ihren Kurs trotzdem \u00fcber 'Meine Kurse' erkunden. Sie erhalten von {platformName} regelm\u00e4\u00dfig Erinnerungen, um Ihre Identit\u00e4t zu \u00fcberpr\u00fcfen.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "Wenn Sie diese Seite ohne vorheriges Speichern oder Einreichen der Antwort verlassen, geht die Arbeit an dieser Antwort verloren.", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "Wenn Sie diese Seite verlassen ohne Ihre Partnerbewertung zu \u00fcbermitteln, werden Sie alle Ihre bis jetzt erledigte Arbeit verlieren.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "Wenn Sie diese Seite ohne vorheriges Speichern oder Einreichen der Antwort verlassen, geht die Arbeit an dieser Antwort verloren.", @@ -1165,7 +1160,6 @@ "Name of the signatory": "Name des Unterzeichners", "Name or short description of the configuration": "Name oder Kurzbeschreibung des Aufbaus", "Navigate up": "Aufw\u00e4rts navigieren", - "Need help logging in?": "Brauchen Sie Hilfe beim anmelden?", "Needs verified certificate ": "Ben\u00f6tigt ein verifiziertes Zertifikat", "Never published": "Bisher unver\u00f6ffentlicht", "Never show assessment results": "Auswertungen nie zeigen", @@ -1247,7 +1241,6 @@ "Once your account is deleted, you cannot use it to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "Sobald Ihr Konto gel\u00f6scht ist, k\u00f6nnen Sie es nicht mehr verwenden, um Kurse \u00fcber die App {platformName}, {siteName} oder eine andere von {platformName} gehostete Website zu besuchen.", "One or more rescheduling tasks failed.": "Eine oder mehrere Neuterminierungsaufgaben sind fehlgeschlagen.", "Only ": "Nur", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "Nur <%= fileTypes %> Dateien k\u00f6nnen hochgeladen werden. Bitte w\u00e4hlen Sie eine Datei mit der Dateiendung <%= fileExtensions %> zum hochladen aus.", "Only properly formatted .csv files will be accepted.": "Nur korrekt formatierte .csv Dateien werden hier akzeptiert.", "Only the parent course staff of a CCX can create content groups.": "Nur die \u00fcbergeordneten Kursleiter eines CCX k\u00f6nnen Inhaltsgruppen erstellen.", "Open Calculator": "Taschenrechner \u00f6ffnen", @@ -1524,7 +1517,6 @@ "Select a prerequisite subsection and enter a minimum score percentage and minimum completion percentage to limit access to this subsection. Allowed values are 0-100": "W\u00e4hlen Sie einen vorausgesetzten Unterabschnitt aus und geben Sie einen Mindestpunktzahlanteil und einen Mindestprozentsatz der Vollst\u00e4ndigkeit ein, um den Zugang zu diesem Unterabschnitt einzuschr\u00e4nken. Erlaubte Werte sind 0-100", "Select a section or problem": "W\u00e4hlen Sie einen Abschnitt oder eine Aufgabe", "Select a session:": "W\u00e4hlen Sie eine Sitzung aus:", - "Select a subject for your support request.": "W\u00e4hlen Sie ein Thema f\u00fcr Ihre Supportanfrage aus.", "Select a time allotment for the exam. If it is over 24 hours, type in the amount of time. You can grant individual learners extra time to complete the exam through the Instructor Dashboard.": "W\u00e4hlen Sie eine Zeitzuteilung f\u00fcr die Pr\u00fcfung aus. Wenn es mehr als 24 Stunden sind, geben Sie die Zeitspanne ein. Sie k\u00f6nnen einzelnen Lernenden \u00fcber das Lehrer-Dashboard zus\u00e4tzliche Zeit geben, um die Pr\u00fcfung abzuschlie\u00dfen.", "Select all": "Alles ausw\u00e4hlen", "Select fidelity": "Treue ausw\u00e4hlen", @@ -1726,9 +1718,7 @@ "Textbook Name": "Lehrbuch Name", "Textbook information": "Lehrbuch Information", "Textbook name is required": "Name f\u00fcr das Textbook wird ben\u00f6tigt", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Viele Dank %(full_name)s! Wir haben Ihre Zahlung f\u00fcr %(course_name)s erhalten.", "Thank you for setting your course goal to {goal}!": "Danke, f\u00fcr das definieren eines Kursziels zu {goal}!", - "Thank you for submitting a request! We will contact you within 24 hours.": "Vielen Dank f\u00fcr Ihre Anfrage! Wir werden Sie innerhalb von 24 Stunden kontaktieren.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Vielen Dank, dass Sie Ihren Antrag auf finanzielle Unterst\u00fctzung f\u00fcr {course_name} gestellt haben! Sie k\u00f6nnen mit einer Antwort in 2-4 Werktagen rechnen.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Danke f\u00fcr das Einsenden ihre Fotos. Wir werden diese zeitnah pr\u00fcfen. Sie k\u00f6nnen sich jetzt f\u00fcr jeden von %(platformName)s Kurse mit gepr\u00fcftem Zertifikat anmelden. Ihre \u00dcberpr\u00fcfung ist g\u00fcltig f\u00fcr ein Jahr. Nach einem Jahr m\u00fcssen Sie ihre Fotos wieder zur \u00dcberpr\u00fcfungeinsenden. ", "Thank you! We have received your payment for {courseName}.": "Dankesch\u00f6n! Wir haben Ihre Zahlung f\u00fcr {courseName} bekommen", @@ -1740,8 +1730,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Das Zertifikat f\u00fcr diesen Lerner wurde erneut validiert und das System f\u00fchrt die Note f\u00fcr diesen Lerner erneut durch.", "The cohort cannot be added": "Der Kohort kann nicht hinzugef\u00fcgt werden", "The cohort cannot be saved": "Dieser Kohort kann nicht gespeichert werden", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "Die Gesamtl\u00e4nge der Codefelder Organisation und Bibliothek darf nicht mehr als <%=limit%> Zeichen betragen.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "Die Gesamtl\u00e4nge der Felder Organisation, Kursnummer und Kursablauf darf nicht mehr als <%=limit%> Zeichen betragen.", "The country or region where you live.": "Das Land oder die Stadt in der Sie leben.", "The country that team members primarily identify with.": "Das Land mit dem sich die Teammitglieder prim\u00e4r identifizieren", "The course end date must be later than the course start date.": "Das Datum des Kursendes kann nicht vor dem Einschreibedatum des Kurses liegen.", @@ -1757,7 +1745,6 @@ "The following email addresses and/or usernames are invalid:": "Die folgenden E-Mail-Adressen und/oder Nutzernamen sind ung\u00fcltig:", "The following errors were generated:": "Folgende Fehler wurden generiert:", "The following file types are not allowed: ": "Die folgenden Dateitypen sind nicht erlaubt:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "Die folgende Information ist bereits in Ihrem {platform} Profil. Wir haben dies hier eingef\u00fcgt.", "The following message will be displayed at the bottom of the courseware pages within your course:": "Die folgende Nachricht wird im unteren Bereich Ihrers Kurses angezeigt. ", "The following options are available for the {license_name} license.": "Die folgenden Optionen sind f\u00fcr die {license_name} Lizenz verf\u00fcgbar.", "The following users are no longer enrolled in the course:": "Die folgenden Nutzer sind nicht l\u00e4nger in den Kurs eingeschrieben:", @@ -1769,7 +1756,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "Die der Prozentsatz der minimalen Fertigstellung der Aufgaben muss eine ganze Nummer zwischen 0 und 100 ergeben.", "The minimum grade for course credit is not set.": "Es ist keine Mindestbenotung definiert.", "The minimum score percentage must be a whole number between 0 and 100.": "Die minimale Punktzahl bei der Benotung muss eine ganze Zahl zwischen 0 und 100 sein.", - "The more you tell us, the more quickly and helpfully we can respond!": "Je mehr Sie uns von Ihrem Anliegen berichten, desto genauer und schneller k\u00f6nnen wir Ihnen helfen!", "The name of this signatory as it should appear on certificates.": "Der Name des Unterzeichners soll auf dem Zertifikat erscheinen.", "The name that identifies you on {platform_name}. You cannot change your username.": "Dies ist Ihr Benutzername auf der {platform_name}. Diesen k\u00f6nnen Sie nicht mehr \u00e4ndern.", "The name that is used for ID verification and that appears on your certificates.": "Dieser Name erscheint auf all Ihren Zertifikaten.", @@ -1777,7 +1763,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Anzahl der Unterabschnitte im Kurs, die Aufgaben dieses typs enthalten.", "The organization that this signatory belongs to, as it should appear on certificates.": "Die Organisation, zu welcher der Unterzeichner geh\u00f6rt, soll auf dem Zertifikat erscheinen.", "The page \"{route}\" could not be found.": "Die Seite \"{route}\" konnte nicht gefunden werden.", - "The photo of your face matches the photo on your ID.": "Das Foto von deinem Gesicht muss mit dem Foto in deinem Identit\u00e4tsnachweis \u00fcbereinstimmen", "The post you selected has been deleted.": "Der Beitrag, den Sie ausgew\u00e4hlt haben, wurde bereits gel\u00f6scht.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "Die ver\u00f6ffentlichte Branch-Version, {published}, wurde auf den Entwurf der Branch-Version, {draft}, zur\u00fcckgesetzt.", "The raw error message is:": "Die urspr\u00fcngliche Fehlermeldung ist:", @@ -1918,7 +1903,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "Um sicherzustellen, dass alle Teilnehmer auf das Video zugreifen k\u00f6nnen, empfehlen wir Ihnen, sowohl eine .mp4- als auch eine .webm Version Ihres Videos bereitzustellen. Klicken Sie unten, um eine URL f\u00fcr eine andere Version hinzuzuf\u00fcgen. Diese URLs k\u00f6nnen keine YouTube-URLs sein. Das erste aufgelistete Video, das mit dem Computer des Teilnehmers kompatibel ist, wird abgespielt.", "To complete the program, you must earn a verified certificate for each course.": "Um das Programm abzuschlie\u00dfen, m\u00fcssen Sie f\u00fcr jeden Kurs ein verifiziertes Zertifikat erwerben.", "To continue learning with this account, sign in below.": "Um mit diesem Konto weiter zu lernen, melden Sie sich unten an.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "Um den Credit-Prozess abzuschlie\u00dfen, %(display_name)s m\u00fcssen die Lernenden von %(platform_name)s einen Kreditantrag stellen.", "To invalidate a certificate for a particular learner, add the username or email address below.": "F\u00fcgen Sie \u00fcber die untenstehenden Eingabefelder den Benutzername oder die E-Mail Adresse des Teilnehmers hinzu, f\u00fcr welchen Sie die Zertifikate ung\u00fcltig machen m\u00f6chten.", "To pass this exam, you must complete the problems in the time allowed.": "Um diese Pr\u00fcfung zu bestehen, m\u00fcssen Sie die Probleme in der vorgegebenen Zeit l\u00f6sen.", "To receive a certificate, you must also verify your identity before {date}.": "Um ein Zertifikat zu erhalten, m\u00fcssen Sie auch Ihre Identit\u00e4t verifizieren vor dem {date}.", @@ -1927,7 +1911,6 @@ "To review learner cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on the {link_start}Data Download{link_end} page.": "Um die Kohortenzuordnungen der Lernenden zu \u00fcberpr\u00fcfen oder die Ergebnisse des Hochladens einer CSV-Datei zu sehen, laden Sie Kursprofilinformationen oder Kohortenergebnisse auf der Seite {link_start}Daten-Download{link_end} herunter.", "To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.": "Um Ihr Zertifikat auf Mozilla Backpack zu teilen, m\u00fcssen Sie zuerst ein Backpack-Konto haben. F\u00fchren Sie die folgenden Schritte aus, um Ihr Zertifikat zum Backpack hinzuzuf\u00fcgen.", "To take a successful photo, make sure that:": "Um ein erfolgreiches Bild zu machen, stell sicher dass:", - "To use the current photo, select the Take Photo button {icon}. To take another photo, select the Retake Photo button {icon}.": "Um das aktuelle Foto zu verwenden, w\u00e4hlen Sie die Kamerataste {icon}. Um ein weiteres Foto aufzunehmen, w\u00e4hlen Sie die Wiederholungs-Taste {icon}.", "To verify your identity, you need a webcam and a government-issued photo ID.": "Um Ihre Identit\u00e4t zu verifizieren, ben\u00f6tigen Sie eine Webcam und einen staatlich ausgestellten Lichtbildausweis.", "Today": "Heute", "Toggle Account Password (Usable/Unusable)": "Passwort des Benutzerkontos einblenden (Verwendbar/nicht verwendbar)", @@ -2008,7 +1991,6 @@ "Upload Videos": "Videos hochladen", "Upload a CSV file": "Hochladen einer CSV-Datei", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "Hochladen einer (.csv) Datei, in welcher die E-Mail Adressen oder der Benutzername der jeweiligen Teilnehmer, welche Sie zu der Ausnahmeliste hinzuf\u00fcgen m\u00f6chten, eingetragen sind. Bitte beachten Sie hierbei, dass die Eintr\u00e4ge durch Komma separiert werden. ", - "Upload a new PDF to \u201c<%= name %>\u201d": "Neues PDf unter \u201c<%= name %>\u201d hochgeladen", "Upload an image": "Ein Bild hochladen", "Upload an image or capture one with your web or phone camera.": "Bitte laden Sie ein Bild hoch oder nehmen Sie ein Foto mit ihr webcam oder Handy.", "Upload completed": "Hochladen fertiggestellt", @@ -2041,7 +2023,6 @@ "Use my university info": "Meine Universit\u00e4tsinformationen verwenden", "Use the All Topics menu to find specific topics.": "Benutzen Sie das Men\u00fc \"Alle Diskussionen\" um bestimmte Themen zu finden. ", "Use the Retake Photo button if you are not pleased with your photo": "Nutzen Sie den Wiederholungsknopf, wenn Sie unzufrieden mit Ihrer Aufnahme sind.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Benutzen Sie ihre webcam um ein Foto von ihr Ausweis zu nehmen. Wir werden dieses Foto mit das Foto von ihr Gesicht und der Name auf ihr Konto vergleichen.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Benutze ihre Webcam um ein Foto von ihren Gesicht aufzunehmen damit wir dieses mit dem Foto ihres Ausweises abgleichen k\u00f6nnen.", "Used": "benutzt", "Used in {count} location": [ @@ -2066,7 +2047,6 @@ "Verified Certificate upgrade": "Upgrade verifizierter Zertifikate", "Verified Status": "Gepr\u00fcfter Status", "Verified mode price": "Kosten der verifizierten Teilnahmeart", - "Verify Now": "Verifiziere Jetzt", "Version": "Version", "Vertical space": "Vertikaler Abstand", "Very loud": "Sehr Laut", @@ -2113,7 +2093,6 @@ "We couldn't find any results for \"%s\".": "Wir konnten leider keine Suchergebnisse f\u00fcr \"%s\" finden. ", "We couldn't sign you in.": "Wir konnten Sie leider nicht einloggen.", "We have encountered an error. Refresh your browser and then try again.": "Wir haben einen Fehler gefunden. Aktualisieren Sie Ihren Browser und versuchen Sie es dann erneut.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Wir haben Ihre Informationen erhalten und verifizieren Ihre Identit\u00e4t. Sie werden eine Meldung auf Ihrer 'Meine Kurse' \u00dcbersicht sehen, wenn der Verifikationsprozess abgeschlossen ist (normalerweise innerhalb von 1-2 Tagen). In der Zwischenzeit k\u00f6nnen Sie noch auf alle verf\u00fcgbaren Kursinhalte zugreifen.", "We just need a little more information before you start learning with %(platformName)s.": "Wir brauchen noch einige weitere Informationen, bevor Sie mit %(platformName)s lernen k\u00f6nnen.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Wir verwenden die h\u00f6chste Sicherheit zur Verf\u00fcgung um das Foto zu verschl\u00fcsseln und senden es an unsere Autorisierungsdienst f\u00fcr Kritik. Ihre Fotos und Daten sind nicht gespeichert und auch nicht sichtbar auf %(platformName)s nach das \u00dcberpr\u00fcfung Prozess.", "We're sorry to see you go! Your account will be deleted shortly.": "Es tut uns leid, dass Sie Ihren Account l\u00f6schen m\u00f6chten!", @@ -2221,14 +2200,10 @@ "You must specify a name": "Sie m\u00fcssen einen Namen auff\u00fchren", "You must specify a name for the cohort": "Sie m\u00fcssen einen Namen f\u00fcr die Gro\u00dfgruppe angeben", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "Sie m\u00fcssen Ihr Geburtsjahr eintragen, bevor Sie Ihr volles Profil teilen k\u00f6nnen. Gehen Sie zur {account_settings_page_link}, um Ihr Geburtsjahr einzutragen.", - "You need a computer or cell phone that has a webcam. When you receive a browser prompt, make sure that you allow access to the camera.": "Sie ben\u00f6tigen ein Computer oder Handy mit integrierter Webcam. Wenn Sie eine Anfrage \u00fcber Ihren Browser bekommen, stellen Sie sicher, dass der Zugriff auf die Kamera aktiviert ist.", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Sie ben\u00f6tigen einen F\u00fchrerschein, Reisepass oder einen anderen staatlich ausgestellten Lichtbildausweis mit Ihrem Namen und Foto.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Sie brauchen ein Ausweis mit ihr Name und Foto. Akzeptierte Identit\u00e4tsnachweise sind F\u00fchrerscheine, Reisep\u00e4sse oder andere Bildausweise mit amtlichen Licht.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Sie m\u00fcssen ihren Konto aktivieren vor Sie sich an ein Kurs anmelden k\u00f6nnen. Bitte kontrollieren Sie Ihr Posteingang f\u00fcr das Aktivierungsmail. ", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Vor Sie sich in Kurse eingeladen k\u00f6nnen, m\u00fcssen Sie ihr Konto aktivieren. Kontrollieren Sie ihr Posteingang f\u00fcr das Aktivierungsmail. Nach Sie ihre Aktivierung best\u00e4tigen, k\u00f6nnen Sie diese Seite neuladen.", "You receive messages from {platform_name} and course teams at this address.": "Auf diese E-Mail Adresse werden Sie alle Benachrichtigungen und Neuigkeiten der {platform_name} zugesandt bekommen.", "You reserve all rights for your work": "Sie behalten sich alle Rechte f\u00fcr Ihre Arbeit vor", - "You still need to visit the %(display_name)s website to complete the credit process.": "Sie m\u00fcssen noch die Website %(display_name)s besuchen, um den Credit-Prozess abzuschlie\u00dfen.", "You submitted {filename}; only {allowedFiles} are allowed.": "Ihre Einreichung {filename}; Es sind nur {allowedFiles} erlaubt.", "You waive some rights for your work, such that others can use it too": "Sie verzichten auf einige Rechte f\u00fcr Ihre Arbeit, so dass auch andere diese nutzen k\u00f6nnen", "You will be refunded the amount you paid.": "Sie werden eine R\u00fcckerstattung f\u00fcr Ihren gezahlten Betrag erhalten. ", @@ -2323,7 +2298,6 @@ "enter code here": "Code hier eingeben", "enter link description here": "Linkbeschreibung hier eingeben", "for": "f\u00fcr", - "for {courseName}": "f\u00fcr {courseName}", "group configuration": "Gruppenkonfiguration", "image omitted": "Bild weggelassen", "incorrect": "falsch", @@ -2500,7 +2474,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2552,9 +2526,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/el/djangojs.js b/lms/static/js/i18n/el/djangojs.js index bff79aa6a61ac0f5cc7cb1ea65bed76de1b6b205..38f03ea55b97cfc60421b5fb6f0060c9673ca909 100644 --- a/lms/static/js/i18n/el/djangojs.js +++ b/lms/static/js/i18n/el/djangojs.js @@ -434,7 +434,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -490,9 +490,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y P", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/en-uk/djangojs.js b/lms/static/js/i18n/en-uk/djangojs.js index 39914281913c92df4d92a324b5a7c9efbb65a380..10c4681968976135c7d32c6632950a5cbe9387a3 100644 --- a/lms/static/js/i18n/en-uk/djangojs.js +++ b/lms/static/js/i18n/en-uk/djangojs.js @@ -71,7 +71,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -127,9 +127,9 @@ "%m/%d/%y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/en/djangojs.js b/lms/static/js/i18n/en/djangojs.js index 46e07902835a61859de1f9ced1ae4c8594db6505..f6ad253896852559d1fd34e602401499533dabac 100644 --- a/lms/static/js/i18n/en/djangojs.js +++ b/lms/static/js/i18n/en/djangojs.js @@ -35,7 +35,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -91,9 +91,9 @@ "%m/%d/%y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/en@lolcat/djangojs.js b/lms/static/js/i18n/en@lolcat/djangojs.js index 09ab0ad1017c413c3bafcb7fa641bef68644a979..f099ebfc1d7e1fb0cc02eda8cbc11276c49368c9 100644 --- a/lms/static/js/i18n/en@lolcat/djangojs.js +++ b/lms/static/js/i18n/en@lolcat/djangojs.js @@ -35,7 +35,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -99,9 +99,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/en@pirate/djangojs.js b/lms/static/js/i18n/en@pirate/djangojs.js index 09ab0ad1017c413c3bafcb7fa641bef68644a979..f099ebfc1d7e1fb0cc02eda8cbc11276c49368c9 100644 --- a/lms/static/js/i18n/en@pirate/djangojs.js +++ b/lms/static/js/i18n/en@pirate/djangojs.js @@ -35,7 +35,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -99,9 +99,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/eo/djangojs.js b/lms/static/js/i18n/eo/djangojs.js index ef77c7b8c7af2fe847507d455e17174130c50e98..074af17a32b3e3f97f740dd1190c807a16e95463 100644 --- a/lms/static/js/i18n/eo/djangojs.js +++ b/lms/static/js/i18n/eo/djangojs.js @@ -27,6 +27,7 @@ " M\u00e9m\u00df\u00e9rs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#" ], " and ": " \u00e4nd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", + " as many questions may have already been answered.": " \u00e4s m\u00e4n\u00fd q\u00fc\u00e9st\u00ef\u00f6ns m\u00e4\u00fd h\u00e4v\u00e9 \u00e4lr\u00e9\u00e4d\u00fd \u00df\u00e9\u00e9n \u00e4nsw\u00e9r\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", " learner does not exist in LMS and not added to the exception list": " l\u00e9\u00e4rn\u00e9r d\u00f6\u00e9s n\u00f6t \u00e9x\u00efst \u00efn LMS \u00e4nd n\u00f6t \u00e4dd\u00e9d t\u00f6 th\u00e9 \u00e9x\u00e7\u00e9pt\u00ef\u00f6n l\u00efst \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", " learner is already white listed and not added to the exception list": " l\u00e9\u00e4rn\u00e9r \u00efs \u00e4lr\u00e9\u00e4d\u00fd wh\u00eft\u00e9 l\u00efst\u00e9d \u00e4nd n\u00f6t \u00e4dd\u00e9d t\u00f6 th\u00e9 \u00e9x\u00e7\u00e9pt\u00ef\u00f6n l\u00efst \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", " learner is not enrolled in course and not added to the exception list": " l\u00e9\u00e4rn\u00e9r \u00efs n\u00f6t \u00e9nr\u00f6ll\u00e9d \u00efn \u00e7\u00f6\u00fcrs\u00e9 \u00e4nd n\u00f6t \u00e4dd\u00e9d t\u00f6 th\u00e9 \u00e9x\u00e7\u00e9pt\u00ef\u00f6n l\u00efst \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", @@ -39,6 +40,8 @@ " records are not in correct format and not added to the exception list": " r\u00e9\u00e7\u00f6rds \u00e4r\u00e9 n\u00f6t \u00efn \u00e7\u00f6rr\u00e9\u00e7t f\u00f6rm\u00e4t \u00e4nd n\u00f6t \u00e4dd\u00e9d t\u00f6 th\u00e9 \u00e9x\u00e7\u00e9pt\u00ef\u00f6n l\u00efst \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "${listPrice}": "${listPrice} \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "%(cohort_name)s (%(user_count)s)": "%(cohort_name)s (%(user_count)s) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", + "%(comments_count)s %(span_sr_open)scomments %(span_close)s": "%(comments_count)s %(span_sr_open)s\u00e7\u00f6mm\u00e9nts %(span_close)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", + "%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s unread comments)%(span_close)s": "%(comments_count)s %(span_sr_open)s\u00e7\u00f6mm\u00e9nts (%(unread_comments_count)s \u00fcnr\u00e9\u00e4d \u00e7\u00f6mm\u00e9nts)%(span_close)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "%(errorCount)s error found in form.": [ "%(errorCount)s \u00e9rr\u00f6r f\u00f6\u00fcnd \u00efn f\u00f6rm. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "%(errorCount)s \u00e9rr\u00f6rs f\u00f6\u00fcnd \u00efn f\u00f6rm. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#" @@ -84,6 +87,7 @@ "%s from now": "%s fr\u00f6m n\u00f6w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "(Add signatories for a certificate)": "(\u00c0dd s\u00efgn\u00e4t\u00f6r\u00ef\u00e9s f\u00f6r \u00e4 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "(Caption will be displayed when you start playing the video.)": "(\u00c7\u00e4pt\u00ef\u00f6n w\u00efll \u00df\u00e9 d\u00efspl\u00e4\u00fd\u00e9d wh\u00e9n \u00fd\u00f6\u00fc st\u00e4rt pl\u00e4\u00fd\u00efng th\u00e9 v\u00efd\u00e9\u00f6.) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "(Community TA)": "(\u00c7\u00f6mm\u00fcn\u00eft\u00fd T\u00c0) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "(Optional)": "(\u00d6pt\u00ef\u00f6n\u00e4l) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "(Read-only)": "(R\u00e9\u00e4d-\u00f6nl\u00fd) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "(Required Field)": "(R\u00e9q\u00fc\u00efr\u00e9d F\u00ef\u00e9ld) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", @@ -91,6 +95,7 @@ "(Self-paced) Ends {end}": "(S\u00e9lf-p\u00e4\u00e7\u00e9d) \u00c9nds {end} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "(Self-paced) Started {start}": "(S\u00e9lf-p\u00e4\u00e7\u00e9d) St\u00e4rt\u00e9d {start} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "(Self-paced) Starts {start}": "(S\u00e9lf-p\u00e4\u00e7\u00e9d) St\u00e4rts {start} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", + "(Staff)": "(St\u00e4ff) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "(contains %(student_count)s student)": [ "(\u00e7\u00f6nt\u00e4\u00efns %(student_count)s st\u00fcd\u00e9nt) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "(\u00e7\u00f6nt\u00e4\u00efns %(student_count)s st\u00fcd\u00e9nts) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#" @@ -152,7 +157,12 @@ "Add URLs for additional versions": "\u00c0dd \u00dbRLs f\u00f6r \u00e4dd\u00eft\u00ef\u00f6n\u00e4l v\u00e9rs\u00ef\u00f6ns \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "Add a Chapter": "\u00c0dd \u00e4 \u00c7h\u00e4pt\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Add a New Cohort": "\u00c0dd \u00e4 N\u00e9w \u00c7\u00f6h\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "Add a Post": "\u00c0dd \u00e4 P\u00f6st \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", + "Add a Response": "\u00c0dd \u00e4 R\u00e9sp\u00f6ns\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", + "Add a clear and descriptive title to encourage participation. (Required)": "\u00c0dd \u00e4 \u00e7l\u00e9\u00e4r \u00e4nd d\u00e9s\u00e7r\u00efpt\u00efv\u00e9 t\u00eftl\u00e9 t\u00f6 \u00e9n\u00e7\u00f6\u00fcr\u00e4g\u00e9 p\u00e4rt\u00ef\u00e7\u00efp\u00e4t\u00ef\u00f6n. (R\u00e9q\u00fc\u00efr\u00e9d) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", + "Add a comment": "\u00c0dd \u00e4 \u00e7\u00f6mm\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Add a learning outcome here": "\u00c0dd \u00e4 l\u00e9\u00e4rn\u00efng \u00f6\u00fct\u00e7\u00f6m\u00e9 h\u00e9r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", + "Add a response:": "\u00c0dd \u00e4 r\u00e9sp\u00f6ns\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Add another group": "\u00c0dd \u00e4n\u00f6th\u00e9r gr\u00f6\u00fcp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Add language": "\u00c0dd l\u00e4ng\u00fc\u00e4g\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Add learners to this cohort": "\u00c0dd l\u00e9\u00e4rn\u00e9rs t\u00f6 th\u00efs \u00e7\u00f6h\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", @@ -162,6 +172,7 @@ "Add your first content group": "\u00c0dd \u00fd\u00f6\u00fcr f\u00efrst \u00e7\u00f6nt\u00e9nt gr\u00f6\u00fcp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Add your first group configuration": "\u00c0dd \u00fd\u00f6\u00fcr f\u00efrst gr\u00f6\u00fcp \u00e7\u00f6nf\u00efg\u00fcr\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "Add your first textbook": "\u00c0dd \u00fd\u00f6\u00fcr f\u00efrst t\u00e9xt\u00df\u00f6\u00f6k \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", + "Add your post to a relevant topic to help others find it. (Required)": "\u00c0dd \u00fd\u00f6\u00fcr p\u00f6st t\u00f6 \u00e4 r\u00e9l\u00e9v\u00e4nt t\u00f6p\u00ef\u00e7 t\u00f6 h\u00e9lp \u00f6th\u00e9rs f\u00efnd \u00eft. (R\u00e9q\u00fc\u00efr\u00e9d) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Add {role} Access": "\u00c0dd {role} \u00c0\u00e7\u00e7\u00e9ss \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Adding": "\u00c0dd\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Adding the selected course to your cart": "\u00c0dd\u00efng th\u00e9 s\u00e9l\u00e9\u00e7t\u00e9d \u00e7\u00f6\u00fcrs\u00e9 t\u00f6 \u00fd\u00f6\u00fcr \u00e7\u00e4rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", @@ -182,6 +193,7 @@ "Align left": "\u00c0l\u00efgn l\u00e9ft \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Align right": "\u00c0l\u00efgn r\u00efght \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Alignment": "\u00c0l\u00efgnm\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", + "All Groups": "\u00c0ll Gr\u00f6\u00fcps \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "All Learners and Staff": "\u00c0ll L\u00e9\u00e4rn\u00e9rs \u00e4nd St\u00e4ff \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "All Posts": "\u00c0ll P\u00f6sts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "All Rights Reserved": "\u00c0ll R\u00efghts R\u00e9s\u00e9rv\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", @@ -267,6 +279,7 @@ "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "\u00c0r\u00e9 \u00fd\u00f6\u00fc s\u00fcr\u00e9 \u00fd\u00f6\u00fc w\u00efsh t\u00f6 d\u00e9l\u00e9t\u00e9 th\u00efs \u00eft\u00e9m. \u00cct \u00e7\u00e4nn\u00f6t \u00df\u00e9 r\u00e9v\u00e9rs\u00e9d!\n\n\u00c0ls\u00f6 \u00e4n\u00fd \u00e7\u00f6nt\u00e9nt th\u00e4t l\u00efnks/r\u00e9f\u00e9rs t\u00f6 th\u00efs \u00eft\u00e9m w\u00efll n\u00f6 l\u00f6ng\u00e9r w\u00f6rk (\u00e9.g. \u00dfr\u00f6k\u00e9n \u00efm\u00e4g\u00e9s \u00e4nd/\u00f6r l\u00efnks) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192#", "Are you sure?": "\u00c0r\u00e9 \u00fd\u00f6\u00fc s\u00fcr\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "As part of the verification process, you take a photo of both your face and a government-issued photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u00c0s p\u00e4rt \u00f6f th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss, \u00fd\u00f6\u00fc t\u00e4k\u00e9 \u00e4 ph\u00f6t\u00f6 \u00f6f \u00df\u00f6th \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9 \u00e4nd \u00e4 g\u00f6v\u00e9rnm\u00e9nt-\u00efss\u00fc\u00e9d ph\u00f6t\u00f6 \u00ccD. \u00d6\u00fcr \u00e4\u00fcth\u00f6r\u00efz\u00e4t\u00ef\u00f6n s\u00e9rv\u00ef\u00e7\u00e9 \u00e7\u00f6nf\u00efrms \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd \u00df\u00fd \u00e7\u00f6mp\u00e4r\u00efng th\u00e9 ph\u00f6t\u00f6 \u00fd\u00f6\u00fc t\u00e4k\u00e9 w\u00efth th\u00e9 ph\u00f6t\u00f6 \u00f6n \u00fd\u00f6\u00fcr \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7#", + "As part of the verification process, you take a photo of both your face and a photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u00c0s p\u00e4rt \u00f6f th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss, \u00fd\u00f6\u00fc t\u00e4k\u00e9 \u00e4 ph\u00f6t\u00f6 \u00f6f \u00df\u00f6th \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9 \u00e4nd \u00e4 ph\u00f6t\u00f6 \u00ccD. \u00d6\u00fcr \u00e4\u00fcth\u00f6r\u00efz\u00e4t\u00ef\u00f6n s\u00e9rv\u00ef\u00e7\u00e9 \u00e7\u00f6nf\u00efrms \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd \u00df\u00fd \u00e7\u00f6mp\u00e4r\u00efng th\u00e9 ph\u00f6t\u00f6 \u00fd\u00f6\u00fc t\u00e4k\u00e9 w\u00efth th\u00e9 ph\u00f6t\u00f6 \u00f6n \u00fd\u00f6\u00fcr \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442#", "As you complete courses, you will see them listed here.": "\u00c0s \u00fd\u00f6\u00fc \u00e7\u00f6mpl\u00e9t\u00e9 \u00e7\u00f6\u00fcrs\u00e9s, \u00fd\u00f6\u00fc w\u00efll s\u00e9\u00e9 th\u00e9m l\u00efst\u00e9d h\u00e9r\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Assessment": "\u00c0ss\u00e9ssm\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Assessment Results Visibility": "\u00c0ss\u00e9ssm\u00e9nt R\u00e9s\u00fclts V\u00efs\u00ef\u00df\u00efl\u00eft\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", @@ -409,6 +422,7 @@ "Click to remove all chosen %s at once.": "Klaku por tuj forigi \u0109iujn %s elektitajn.", "Close": "\u00c7l\u00f6s\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "Close Calculator": "\u00c7l\u00f6s\u00e9 \u00c7\u00e4l\u00e7\u00fcl\u00e4t\u00f6r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "Closed": "\u00c7l\u00f6s\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Code": "\u00c7\u00f6d\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Code Sample (Ctrl+K)": "\u00c7\u00f6d\u00e9 S\u00e4mpl\u00e9 (\u00c7trl+K) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Code block": "\u00c7\u00f6d\u00e9 \u00dfl\u00f6\u00e7k \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", @@ -427,6 +441,7 @@ "Coming Soon": "\u00c7\u00f6m\u00efng S\u00f6\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Commentary": "\u00c7\u00f6mm\u00e9nt\u00e4r\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Common Problem Types": "\u00c7\u00f6mm\u00f6n Pr\u00f6\u00dfl\u00e9m T\u00fdp\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", + "Community TA": "\u00c7\u00f6mm\u00fcn\u00eft\u00fd T\u00c0 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Complete courses on your schedule to ensure you stand out in your field!": "\u00c7\u00f6mpl\u00e9t\u00e9 \u00e7\u00f6\u00fcrs\u00e9s \u00f6n \u00fd\u00f6\u00fcr s\u00e7h\u00e9d\u00fcl\u00e9 t\u00f6 \u00e9ns\u00fcr\u00e9 \u00fd\u00f6\u00fc st\u00e4nd \u00f6\u00fct \u00efn \u00fd\u00f6\u00fcr f\u00ef\u00e9ld! \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "Completed": "\u00c7\u00f6mpl\u00e9t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Component": "\u00c7\u00f6mp\u00f6n\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", @@ -477,6 +492,7 @@ ], "Course Content": "\u00c7\u00f6\u00fcrs\u00e9 \u00c7\u00f6nt\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Course Credit Requirements": "\u00c7\u00f6\u00fcrs\u00e9 \u00c7r\u00e9d\u00eft R\u00e9q\u00fc\u00efr\u00e9m\u00e9nts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", + "Course Discussion Forum": "\u00c7\u00f6\u00fcrs\u00e9 D\u00efs\u00e7\u00fcss\u00ef\u00f6n F\u00f6r\u00fcm \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "Course End": "\u00c7\u00f6\u00fcrs\u00e9 \u00c9nd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Course Handouts": "\u00c7\u00f6\u00fcrs\u00e9 H\u00e4nd\u00f6\u00fcts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Course ID": "\u00c7\u00f6\u00fcrs\u00e9 \u00ccD \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", @@ -499,6 +515,7 @@ "Create": "\u00c7r\u00e9\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Create Account": "\u00c7r\u00e9\u00e4t\u00e9 \u00c0\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Create Re-run": "\u00c7r\u00e9\u00e4t\u00e9 R\u00e9-r\u00fcn \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", + "Create Support Ticket": "\u00c7r\u00e9\u00e4t\u00e9 S\u00fcpp\u00f6rt T\u00ef\u00e7k\u00e9t \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Create a New Team": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4 N\u00e9w T\u00e9\u00e4m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Create a content group": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4 \u00e7\u00f6nt\u00e9nt gr\u00f6\u00fcp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "Create a new team if you can't find an existing team to join, or if you would like to learn with friends you know.": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4 n\u00e9w t\u00e9\u00e4m \u00eff \u00fd\u00f6\u00fc \u00e7\u00e4n't f\u00efnd \u00e4n \u00e9x\u00efst\u00efng t\u00e9\u00e4m t\u00f6 j\u00f6\u00efn, \u00f6r \u00eff \u00fd\u00f6\u00fc w\u00f6\u00fcld l\u00efk\u00e9 t\u00f6 l\u00e9\u00e4rn w\u00efth fr\u00ef\u00e9nds \u00fd\u00f6\u00fc kn\u00f6w. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", @@ -506,6 +523,7 @@ "Create account using %(providerName)s.": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00fcs\u00efng %(providerName)s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "Create an Account": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4n \u00c0\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Create an Account.": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4n \u00c0\u00e7\u00e7\u00f6\u00fcnt. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "Create an account": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4n \u00e4\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Create an account using": "\u00c7r\u00e9\u00e4t\u00e9 \u00e4n \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00fcs\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "Create team.": "\u00c7r\u00e9\u00e4t\u00e9 t\u00e9\u00e4m. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Created": "\u00c7r\u00e9\u00e4t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", @@ -531,6 +549,7 @@ "Date Placed": "D\u00e4t\u00e9 Pl\u00e4\u00e7\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Date added": "D\u00e4t\u00e9 \u00e4dd\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Deactivate": "D\u00e9\u00e4\u00e7t\u00efv\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", + "Deactivating": "D\u00e9\u00e4\u00e7t\u00efv\u00e4t\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Deadlines": "D\u00e9\u00e4dl\u00efn\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "December": "decembro", "Declined": "D\u00e9\u00e7l\u00efn\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", @@ -539,7 +558,7 @@ "Default (Local Time Zone)": "D\u00e9f\u00e4\u00fclt (L\u00f6\u00e7\u00e4l T\u00efm\u00e9 Z\u00f6n\u00e9) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "Default Timed Transcript": "D\u00e9f\u00e4\u00fclt T\u00efm\u00e9d Tr\u00e4ns\u00e7r\u00efpt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "Delete": "D\u00e9l\u00e9t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "D\u00e9l\u00e9t\u00e9 \"<%= signatoryName %>\" fr\u00f6m th\u00e9 l\u00efst \u00f6f s\u00efgn\u00e4t\u00f6r\u00ef\u00e9s? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", + "Delete \"<%- signatoryName %>\" from the list of signatories?": "D\u00e9l\u00e9t\u00e9 \"<%- signatoryName %>\" fr\u00f6m th\u00e9 l\u00efst \u00f6f s\u00efgn\u00e4t\u00f6r\u00ef\u00e9s? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Delete File Confirmation": "D\u00e9l\u00e9t\u00e9 F\u00efl\u00e9 \u00c7\u00f6nf\u00efrm\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "Delete My Account": "D\u00e9l\u00e9t\u00e9 M\u00fd \u00c0\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Delete Page Confirmation": "D\u00e9l\u00e9t\u00e9 P\u00e4g\u00e9 \u00c7\u00f6nf\u00efrm\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", @@ -567,11 +586,14 @@ "Description": "D\u00e9s\u00e7r\u00efpt\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Description of the certificate": "D\u00e9s\u00e7r\u00efpt\u00ef\u00f6n \u00f6f th\u00e9 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", "Details": "D\u00e9t\u00e4\u00efls \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", + "Device with Camera": "D\u00e9v\u00ef\u00e7\u00e9 w\u00efth \u00c7\u00e4m\u00e9r\u00e4 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Dimensions": "D\u00efm\u00e9ns\u00ef\u00f6ns \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Disc": "D\u00efs\u00e7 \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Discard Changes": "D\u00efs\u00e7\u00e4rd \u00c7h\u00e4ng\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Discarding Changes": "D\u00efs\u00e7\u00e4rd\u00efng \u00c7h\u00e4ng\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "Discussion": "D\u00efs\u00e7\u00fcss\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Discussion Home": "D\u00efs\u00e7\u00fcss\u00ef\u00f6n H\u00f6m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", + "Discussion admins, moderators, and TAs can make their posts visible to all students or specify a single group.": "D\u00efs\u00e7\u00fcss\u00ef\u00f6n \u00e4dm\u00efns, m\u00f6d\u00e9r\u00e4t\u00f6rs, \u00e4nd T\u00c0s \u00e7\u00e4n m\u00e4k\u00e9 th\u00e9\u00efr p\u00f6sts v\u00efs\u00ef\u00dfl\u00e9 t\u00f6 \u00e4ll st\u00fcd\u00e9nts \u00f6r sp\u00e9\u00e7\u00eff\u00fd \u00e4 s\u00efngl\u00e9 gr\u00f6\u00fcp. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Discussion topics in the course are not divided.": "D\u00efs\u00e7\u00fcss\u00ef\u00f6n t\u00f6p\u00ef\u00e7s \u00efn th\u00e9 \u00e7\u00f6\u00fcrs\u00e9 \u00e4r\u00e9 n\u00f6t d\u00efv\u00efd\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Discussions are unified; all learners interact with posts from other learners, regardless of the group they are in.": "D\u00efs\u00e7\u00fcss\u00ef\u00f6ns \u00e4r\u00e9 \u00fcn\u00eff\u00ef\u00e9d; \u00e4ll l\u00e9\u00e4rn\u00e9rs \u00efnt\u00e9r\u00e4\u00e7t w\u00efth p\u00f6sts fr\u00f6m \u00f6th\u00e9r l\u00e9\u00e4rn\u00e9rs, r\u00e9g\u00e4rdl\u00e9ss \u00f6f th\u00e9 gr\u00f6\u00fcp th\u00e9\u00fd \u00e4r\u00e9 \u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Display Name": "D\u00efspl\u00e4\u00fd N\u00e4m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", @@ -584,7 +606,6 @@ "Do you want to upload your file before submitting?": "D\u00f6 \u00fd\u00f6\u00fc w\u00e4nt t\u00f6 \u00fcpl\u00f6\u00e4d \u00fd\u00f6\u00fcr f\u00efl\u00e9 \u00df\u00e9f\u00f6r\u00e9 s\u00fc\u00dfm\u00eftt\u00efng? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Document properties": "D\u00f6\u00e7\u00fcm\u00e9nt pr\u00f6p\u00e9rt\u00ef\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Does the name on your ID match your account name: %(fullName)s?": "D\u00f6\u00e9s th\u00e9 n\u00e4m\u00e9 \u00f6n \u00fd\u00f6\u00fcr \u00ccD m\u00e4t\u00e7h \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt n\u00e4m\u00e9: %(fullName)s? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", - "Does the photo of you match your ID photo?": "D\u00f6\u00e9s th\u00e9 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fc m\u00e4t\u00e7h \u00fd\u00f6\u00fcr \u00ccD ph\u00f6t\u00f6? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Does the photo of you show your whole face?": "D\u00f6\u00e9s th\u00e9 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fc sh\u00f6w \u00fd\u00f6\u00fcr wh\u00f6l\u00e9 f\u00e4\u00e7\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "D\u00f6n't s\u00e9\u00e9 \u00fd\u00f6\u00fcr p\u00ef\u00e7t\u00fcr\u00e9? M\u00e4k\u00e9 s\u00fcr\u00e9 t\u00f6 \u00e4ll\u00f6w \u00fd\u00f6\u00fcr \u00dfr\u00f6ws\u00e9r t\u00f6 \u00fcs\u00e9 \u00fd\u00f6\u00fcr \u00e7\u00e4m\u00e9r\u00e4 wh\u00e9n \u00eft \u00e4sks f\u00f6r p\u00e9rm\u00efss\u00ef\u00f6n. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Donate": "D\u00f6n\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", @@ -606,6 +627,7 @@ "Due Date:": "D\u00fc\u00e9 D\u00e4t\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Due Time in UTC:": "D\u00fc\u00e9 T\u00efm\u00e9 \u00efn \u00dbT\u00c7: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Due date cannot be before start date.": "D\u00fc\u00e9 d\u00e4t\u00e9 \u00e7\u00e4nn\u00f6t \u00df\u00e9 \u00df\u00e9f\u00f6r\u00e9 st\u00e4rt d\u00e4t\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", + "Due to the recent increase in interest in online education and edX, we are currently experiencing an unusually high volume of support requests. We appreciate your patience as we work to review each request. Please check the ": "D\u00fc\u00e9 t\u00f6 th\u00e9 r\u00e9\u00e7\u00e9nt \u00efn\u00e7r\u00e9\u00e4s\u00e9 \u00efn \u00efnt\u00e9r\u00e9st \u00efn \u00f6nl\u00efn\u00e9 \u00e9d\u00fc\u00e7\u00e4t\u00ef\u00f6n \u00e4nd \u00e9dX, w\u00e9 \u00e4r\u00e9 \u00e7\u00fcrr\u00e9ntl\u00fd \u00e9xp\u00e9r\u00ef\u00e9n\u00e7\u00efng \u00e4n \u00fcn\u00fcs\u00fc\u00e4ll\u00fd h\u00efgh v\u00f6l\u00fcm\u00e9 \u00f6f s\u00fcpp\u00f6rt r\u00e9q\u00fc\u00e9sts. W\u00e9 \u00e4ppr\u00e9\u00e7\u00ef\u00e4t\u00e9 \u00fd\u00f6\u00fcr p\u00e4t\u00ef\u00e9n\u00e7\u00e9 \u00e4s w\u00e9 w\u00f6rk t\u00f6 r\u00e9v\u00ef\u00e9w \u00e9\u00e4\u00e7h r\u00e9q\u00fc\u00e9st. Pl\u00e9\u00e4s\u00e9 \u00e7h\u00e9\u00e7k th\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 #", "Due:": "D\u00fc\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Duplicate": "D\u00fcpl\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Duplicating": "D\u00fcpl\u00ef\u00e7\u00e4t\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", @@ -625,8 +647,12 @@ "Edit Title": "\u00c9d\u00eft T\u00eftl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Edit Your Name": "\u00c9d\u00eft \u00dd\u00f6\u00fcr N\u00e4m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Edit this certificate?": "\u00c9d\u00eft th\u00efs \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", + "Edit your post below.": "\u00c9d\u00eft \u00fd\u00f6\u00fcr p\u00f6st \u00df\u00e9l\u00f6w. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Editable": "\u00c9d\u00eft\u00e4\u00dfl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Editing access for: {title}": "\u00c9d\u00eft\u00efng \u00e4\u00e7\u00e7\u00e9ss f\u00f6r: {title} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", + "Editing comment": "\u00c9d\u00eft\u00efng \u00e7\u00f6mm\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", + "Editing post": "\u00c9d\u00eft\u00efng p\u00f6st \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", + "Editing response": "\u00c9d\u00eft\u00efng r\u00e9sp\u00f6ns\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Editing: {title}": "\u00c9d\u00eft\u00efng: {title} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Editor": "\u00c9d\u00eft\u00f6r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Education Completed": "\u00c9d\u00fc\u00e7\u00e4t\u00ef\u00f6n \u00c7\u00f6mpl\u00e9t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", @@ -645,6 +671,7 @@ "Encoding": "\u00c9n\u00e7\u00f6d\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "End My Exam": "\u00c9nd M\u00fd \u00c9x\u00e4m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "End of transcript. Skip to the start.": "\u00c9nd \u00f6f tr\u00e4ns\u00e7r\u00efpt. Sk\u00efp t\u00f6 th\u00e9 st\u00e4rt. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", + "Endorse": "\u00c9nd\u00f6rs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "Ends {end}": "\u00c9nds {end} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Engage with posts": "\u00c9ng\u00e4g\u00e9 w\u00efth p\u00f6sts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Enroll Now": "\u00c9nr\u00f6ll N\u00f6w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", @@ -700,6 +727,7 @@ "Error getting the number of ungraded responses": "\u00c9rr\u00f6r g\u00e9tt\u00efng th\u00e9 n\u00fcm\u00df\u00e9r \u00f6f \u00fcngr\u00e4d\u00e9d r\u00e9sp\u00f6ns\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Error importing course": "\u00c9rr\u00f6r \u00efmp\u00f6rt\u00efng \u00e7\u00f6\u00fcrs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "Error listing task history for this student and problem.": "\u00c9rr\u00f6r l\u00efst\u00efng t\u00e4sk h\u00efst\u00f6r\u00fd f\u00f6r th\u00efs st\u00fcd\u00e9nt \u00e4nd pr\u00f6\u00dfl\u00e9m. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "Error posting your message.": "\u00c9rr\u00f6r p\u00f6st\u00efng \u00fd\u00f6\u00fcr m\u00e9ss\u00e4g\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "Error removing user": "\u00c9rr\u00f6r r\u00e9m\u00f6v\u00efng \u00fcs\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Error resetting entrance exam attempts for student '{student_id}'. Make sure student identifier is correct.": "\u00c9rr\u00f6r r\u00e9s\u00e9tt\u00efng \u00e9ntr\u00e4n\u00e7\u00e9 \u00e9x\u00e4m \u00e4tt\u00e9mpts f\u00f6r st\u00fcd\u00e9nt '{student_id}'. M\u00e4k\u00e9 s\u00fcr\u00e9 st\u00fcd\u00e9nt \u00efd\u00e9nt\u00eff\u00ef\u00e9r \u00efs \u00e7\u00f6rr\u00e9\u00e7t. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Error resetting problem attempts for problem '<%= problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "\u00c9rr\u00f6r r\u00e9s\u00e9tt\u00efng pr\u00f6\u00dfl\u00e9m \u00e4tt\u00e9mpts f\u00f6r pr\u00f6\u00dfl\u00e9m '<%= problem_id %>' \u00e4nd st\u00fcd\u00e9nt '<%- student_id %>'. M\u00e4k\u00e9 s\u00fcr\u00e9 th\u00e4t th\u00e9 pr\u00f6\u00dfl\u00e9m \u00e4nd st\u00fcd\u00e9nt \u00efd\u00e9nt\u00eff\u00ef\u00e9rs \u00e4r\u00e9 \u00e7\u00f6mpl\u00e9t\u00e9 \u00e4nd \u00e7\u00f6rr\u00e9\u00e7t. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442 \u03b1\u03b7\u03b9\u043c \u03b9#", @@ -757,7 +785,6 @@ "Fill browser": "F\u00efll \u00dfr\u00f6ws\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Filter": "Filtru", "Filter and sort topics": "F\u00eflt\u00e9r \u00e4nd s\u00f6rt t\u00f6p\u00ef\u00e7s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", - "Final Grade": "F\u00efn\u00e4l Gr\u00e4d\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Final Grade Received": "F\u00efn\u00e4l Gr\u00e4d\u00e9 R\u00e9\u00e7\u00e9\u00efv\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Financial Aid": "F\u00efn\u00e4n\u00e7\u00ef\u00e4l \u00c0\u00efd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Financial Assistance": "F\u00efn\u00e4n\u00e7\u00ef\u00e4l \u00c0ss\u00efst\u00e4n\u00e7\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", @@ -771,12 +798,15 @@ "Find previous": "F\u00efnd pr\u00e9v\u00ef\u00f6\u00fcs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Finish": "F\u00efn\u00efsh \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "First time here?": "F\u00efrst t\u00efm\u00e9 h\u00e9r\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "Follow": "F\u00f6ll\u00f6w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Follow or unfollow posts": "F\u00f6ll\u00f6w \u00f6r \u00fcnf\u00f6ll\u00f6w p\u00f6sts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", + "Following": "F\u00f6ll\u00f6w\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Font Family": "F\u00f6nt F\u00e4m\u00efl\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Font Sizes": "F\u00f6nt S\u00efz\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Footer": "F\u00f6\u00f6t\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "For grading to work, you must change all {oldName} subsections to {newName}.": "F\u00f6r gr\u00e4d\u00efng t\u00f6 w\u00f6rk, \u00fd\u00f6\u00fc m\u00fcst \u00e7h\u00e4ng\u00e9 \u00e4ll {oldName} s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6ns t\u00f6 {newName}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "For inquiries regarding assignments, grades, or structure of a specific course, please post in the discussion forums for that course directly.": "F\u00f6r \u00efnq\u00fc\u00efr\u00ef\u00e9s r\u00e9g\u00e4rd\u00efng \u00e4ss\u00efgnm\u00e9nts, gr\u00e4d\u00e9s, \u00f6r str\u00fc\u00e7t\u00fcr\u00e9 \u00f6f \u00e4 sp\u00e9\u00e7\u00eff\u00ef\u00e7 \u00e7\u00f6\u00fcrs\u00e9, pl\u00e9\u00e4s\u00e9 p\u00f6st \u00efn th\u00e9 d\u00efs\u00e7\u00fcss\u00ef\u00f6n f\u00f6r\u00fcms f\u00f6r th\u00e4t \u00e7\u00f6\u00fcrs\u00e9 d\u00efr\u00e9\u00e7tl\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442 \u03b1\u03b7\u03b9\u043c \u03b9\u2202 \u0454\u0455\u0442#", + "Forgot my password": "F\u00f6rg\u00f6t m\u00fd p\u00e4ssw\u00f6rd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Format": "F\u00f6rm\u00e4t \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Formats": "F\u00f6rm\u00e4ts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "Free text notes": "Fr\u00e9\u00e9 t\u00e9xt n\u00f6t\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", @@ -791,7 +821,6 @@ "Generate": "G\u00e9n\u00e9r\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Generate Exception Certificates": "G\u00e9n\u00e9r\u00e4t\u00e9 \u00c9x\u00e7\u00e9pt\u00ef\u00f6n \u00c7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", "Generate the user's certificate": "G\u00e9n\u00e9r\u00e4t\u00e9 th\u00e9 \u00fcs\u00e9r's \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", - "Get Credit": "G\u00e9t \u00c7r\u00e9d\u00eft \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Go to Dashboard": "G\u00f6 t\u00f6 D\u00e4sh\u00df\u00f6\u00e4rd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Go to my Dashboard": "G\u00f6 t\u00f6 m\u00fd D\u00e4sh\u00df\u00f6\u00e4rd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Go to your Dashboard": "G\u00f6 t\u00f6 \u00fd\u00f6\u00fcr D\u00e4sh\u00df\u00f6\u00e4rd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", @@ -873,10 +902,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "\u00ccf th\u00e9 s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6n d\u00f6\u00e9s n\u00f6t h\u00e4v\u00e9 \u00e4 d\u00fc\u00e9 d\u00e4t\u00e9, l\u00e9\u00e4rn\u00e9rs \u00e4lw\u00e4\u00fds s\u00e9\u00e9 th\u00e9\u00efr s\u00e7\u00f6r\u00e9s wh\u00e9n th\u00e9\u00fd s\u00fc\u00dfm\u00eft \u00e4nsw\u00e9rs t\u00f6 \u00e4ss\u00e9ssm\u00e9nts. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u00ccf th\u00e9 \u00fcn\u00eft w\u00e4s pr\u00e9v\u00ef\u00f6\u00fcsl\u00fd p\u00fc\u00dfl\u00efsh\u00e9d \u00e4nd r\u00e9l\u00e9\u00e4s\u00e9d t\u00f6 l\u00e9\u00e4rn\u00e9rs, \u00e4n\u00fd \u00e7h\u00e4ng\u00e9s \u00fd\u00f6\u00fc m\u00e4d\u00e9 t\u00f6 th\u00e9 \u00fcn\u00eft wh\u00e9n \u00eft w\u00e4s h\u00efdd\u00e9n w\u00efll n\u00f6w \u00df\u00e9 v\u00efs\u00ef\u00dfl\u00e9 t\u00f6 l\u00e9\u00e4rn\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442 \u03b1\u03b7\u03b9\u043c #", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "\u00ccf th\u00e9 \u00fcn\u00eft w\u00e4s pr\u00e9v\u00ef\u00f6\u00fcsl\u00fd p\u00fc\u00dfl\u00efsh\u00e9d \u00e4nd r\u00e9l\u00e9\u00e4s\u00e9d t\u00f6 st\u00fcd\u00e9nts, \u00e4n\u00fd \u00e7h\u00e4ng\u00e9s \u00fd\u00f6\u00fc m\u00e4d\u00e9 t\u00f6 th\u00e9 \u00fcn\u00eft wh\u00e9n \u00eft w\u00e4s h\u00efdd\u00e9n w\u00efll n\u00f6w \u00df\u00e9 v\u00efs\u00ef\u00dfl\u00e9 t\u00f6 st\u00fcd\u00e9nts. D\u00f6 \u00fd\u00f6\u00fc w\u00e4nt t\u00f6 pr\u00f6\u00e7\u00e9\u00e9d? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9#", - "If you are unable to access your account contact us via email using {email}.": "\u00ccf \u00fd\u00f6\u00fc \u00e4r\u00e9 \u00fcn\u00e4\u00dfl\u00e9 t\u00f6 \u00e4\u00e7\u00e7\u00e9ss \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00e7\u00f6nt\u00e4\u00e7t \u00fcs v\u00ef\u00e4 \u00e9m\u00e4\u00efl \u00fcs\u00efng {email}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "If you do not yet have an account, use the button below to register.": "\u00ccf \u00fd\u00f6\u00fc d\u00f6 n\u00f6t \u00fd\u00e9t h\u00e4v\u00e9 \u00e4n \u00e4\u00e7\u00e7\u00f6\u00fcnt, \u00fcs\u00e9 th\u00e9 \u00df\u00fctt\u00f6n \u00df\u00e9l\u00f6w t\u00f6 r\u00e9g\u00efst\u00e9r. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u00ccf \u00fd\u00f6\u00fc d\u00f6n't v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd n\u00f6w, \u00fd\u00f6\u00fc \u00e7\u00e4n st\u00efll \u00e9xpl\u00f6r\u00e9 \u00fd\u00f6\u00fcr \u00e7\u00f6\u00fcrs\u00e9 fr\u00f6m \u00fd\u00f6\u00fcr d\u00e4sh\u00df\u00f6\u00e4rd. \u00dd\u00f6\u00fc w\u00efll r\u00e9\u00e7\u00e9\u00efv\u00e9 p\u00e9r\u00ef\u00f6d\u00ef\u00e7 r\u00e9m\u00efnd\u00e9rs fr\u00f6m %(platformName)s t\u00f6 v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454#", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u00ccf \u00fd\u00f6\u00fc d\u00f6n't v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd n\u00f6w, \u00fd\u00f6\u00fc \u00e7\u00e4n st\u00efll \u00e9xpl\u00f6r\u00e9 \u00fd\u00f6\u00fcr \u00e7\u00f6\u00fcrs\u00e9 fr\u00f6m \u00fd\u00f6\u00fcr d\u00e4sh\u00df\u00f6\u00e4rd. \u00dd\u00f6\u00fc w\u00efll r\u00e9\u00e7\u00e9\u00efv\u00e9 p\u00e9r\u00ef\u00f6d\u00ef\u00e7 r\u00e9m\u00efnd\u00e9rs fr\u00f6m {platformName} t\u00f6 v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454#", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "\u00ccf \u00fd\u00f6\u00fc l\u00e9\u00e4v\u00e9 th\u00efs p\u00e4g\u00e9 w\u00efth\u00f6\u00fct s\u00e4v\u00efng \u00f6r s\u00fc\u00dfm\u00eftt\u00efng \u00fd\u00f6\u00fcr r\u00e9sp\u00f6ns\u00e9, \u00fd\u00f6\u00fc w\u00efll l\u00f6s\u00e9 \u00e4n\u00fd w\u00f6rk \u00fd\u00f6\u00fc h\u00e4v\u00e9 d\u00f6n\u00e9 \u00f6n th\u00e9 r\u00e9sp\u00f6ns\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "\u00ccf \u00fd\u00f6\u00fc l\u00e9\u00e4v\u00e9 th\u00efs p\u00e4g\u00e9 w\u00efth\u00f6\u00fct s\u00fc\u00dfm\u00eftt\u00efng \u00fd\u00f6\u00fcr p\u00e9\u00e9r \u00e4ss\u00e9ssm\u00e9nt, \u00fd\u00f6\u00fc w\u00efll l\u00f6s\u00e9 \u00e4n\u00fd w\u00f6rk \u00fd\u00f6\u00fc h\u00e4v\u00e9 d\u00f6n\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "\u00ccf \u00fd\u00f6\u00fc l\u00e9\u00e4v\u00e9 th\u00efs p\u00e4g\u00e9 w\u00efth\u00f6\u00fct s\u00fc\u00dfm\u00eftt\u00efng \u00fd\u00f6\u00fcr s\u00e9lf \u00e4ss\u00e9ssm\u00e9nt, \u00fd\u00f6\u00fc w\u00efll l\u00f6s\u00e9 \u00e4n\u00fd w\u00f6rk \u00fd\u00f6\u00fc h\u00e4v\u00e9 d\u00f6n\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", @@ -1007,6 +1034,7 @@ "Live view of webcam": "L\u00efv\u00e9 v\u00ef\u00e9w \u00f6f w\u00e9\u00df\u00e7\u00e4m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Load Another File": "L\u00f6\u00e4d \u00c0n\u00f6th\u00e9r F\u00efl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Load all responses": "L\u00f6\u00e4d \u00e4ll r\u00e9sp\u00f6ns\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "Load more": "L\u00f6\u00e4d m\u00f6r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Load next {numResponses} responses": "L\u00f6\u00e4d n\u00e9xt {numResponses} r\u00e9sp\u00f6ns\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "Load next {num_items} result": [ "L\u00f6\u00e4d n\u00e9xt {num_items} r\u00e9s\u00fclt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", @@ -1040,6 +1068,7 @@ "Manual": "M\u00e4n\u00fc\u00e4l \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "March": "marto", "Mark Exam As Completed": "M\u00e4rk \u00c9x\u00e4m \u00c0s \u00c7\u00f6mpl\u00e9t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", + "Mark as Answer": "M\u00e4rk \u00e4s \u00c0nsw\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Mark enrollment code as unused": "M\u00e4rk \u00e9nr\u00f6llm\u00e9nt \u00e7\u00f6d\u00e9 \u00e4s \u00fcn\u00fcs\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", "Markdown Editing Help": "M\u00e4rkd\u00f6wn \u00c9d\u00eft\u00efng H\u00e9lp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Masters": "M\u00e4st\u00e9rs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", @@ -1081,6 +1110,8 @@ "Name or short description of the configuration": "N\u00e4m\u00e9 \u00f6r sh\u00f6rt d\u00e9s\u00e7r\u00efpt\u00ef\u00f6n \u00f6f th\u00e9 \u00e7\u00f6nf\u00efg\u00fcr\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Navigate up": "N\u00e4v\u00efg\u00e4t\u00e9 \u00fcp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Need help logging in?": "N\u00e9\u00e9d h\u00e9lp l\u00f6gg\u00efng \u00efn? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", + "Need help signing in?": "N\u00e9\u00e9d h\u00e9lp s\u00efgn\u00efng \u00efn? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", + "Need other help signing in?": "N\u00e9\u00e9d \u00f6th\u00e9r h\u00e9lp s\u00efgn\u00efng \u00efn? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "Needs verified certificate ": "N\u00e9\u00e9ds v\u00e9r\u00eff\u00ef\u00e9d \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "Never published": "N\u00e9v\u00e9r p\u00fc\u00dfl\u00efsh\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Never show assessment results": "N\u00e9v\u00e9r sh\u00f6w \u00e4ss\u00e9ssm\u00e9nt r\u00e9s\u00fclts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", @@ -1100,6 +1131,7 @@ "No Flash Detected": "N\u00f6 Fl\u00e4sh D\u00e9t\u00e9\u00e7t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "No Timed Transcript": "N\u00f6 T\u00efm\u00e9d Tr\u00e4ns\u00e7r\u00efpt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "No Webcam Detected": "N\u00f6 W\u00e9\u00df\u00e7\u00e4m D\u00e9t\u00e9\u00e7t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "No assignments for team": "N\u00f6 \u00e4ss\u00efgnm\u00e9nts f\u00f6r t\u00e9\u00e4m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "No color": "N\u00f6 \u00e7\u00f6l\u00f6r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "No content-specific discussion topics exist.": "N\u00f6 \u00e7\u00f6nt\u00e9nt-sp\u00e9\u00e7\u00eff\u00ef\u00e7 d\u00efs\u00e7\u00fcss\u00ef\u00f6n t\u00f6p\u00ef\u00e7s \u00e9x\u00efst. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "No description available": "N\u00f6 d\u00e9s\u00e7r\u00efpt\u00ef\u00f6n \u00e4v\u00e4\u00efl\u00e4\u00dfl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", @@ -1163,9 +1195,10 @@ "Once your account is deleted, you cannot use it to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "\u00d6n\u00e7\u00e9 \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00efs d\u00e9l\u00e9t\u00e9d, \u00fd\u00f6\u00fc \u00e7\u00e4nn\u00f6t \u00fcs\u00e9 \u00eft t\u00f6 t\u00e4k\u00e9 \u00e7\u00f6\u00fcrs\u00e9s \u00f6n th\u00e9 {platformName} \u00e4pp, {siteName}, \u00f6r \u00e4n\u00fd \u00f6th\u00e9r s\u00eft\u00e9 h\u00f6st\u00e9d \u00df\u00fd {platformName}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "One or more rescheduling tasks failed.": "\u00d6n\u00e9 \u00f6r m\u00f6r\u00e9 r\u00e9s\u00e7h\u00e9d\u00fcl\u00efng t\u00e4sks f\u00e4\u00efl\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "Only ": "\u00d6nl\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u00d6nl\u00fd <%= fileTypes %> f\u00efl\u00e9s \u00e7\u00e4n \u00df\u00e9 \u00fcpl\u00f6\u00e4d\u00e9d. Pl\u00e9\u00e4s\u00e9 s\u00e9l\u00e9\u00e7t \u00e4 f\u00efl\u00e9 \u00e9nd\u00efng \u00efn <%= fileExtensions %> t\u00f6 \u00fcpl\u00f6\u00e4d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", + "Only <%- fileTypes %> files can be uploaded. Please select a file ending in <%- (fileExtensions) %> to upload.": "\u00d6nl\u00fd <%- fileTypes %> f\u00efl\u00e9s \u00e7\u00e4n \u00df\u00e9 \u00fcpl\u00f6\u00e4d\u00e9d. Pl\u00e9\u00e4s\u00e9 s\u00e9l\u00e9\u00e7t \u00e4 f\u00efl\u00e9 \u00e9nd\u00efng \u00efn <%- (fileExtensions) %> t\u00f6 \u00fcpl\u00f6\u00e4d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "Only properly formatted .csv files will be accepted.": "\u00d6nl\u00fd pr\u00f6p\u00e9rl\u00fd f\u00f6rm\u00e4tt\u00e9d .\u00e7sv f\u00efl\u00e9s w\u00efll \u00df\u00e9 \u00e4\u00e7\u00e7\u00e9pt\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Only the parent course staff of a CCX can create content groups.": "\u00d6nl\u00fd th\u00e9 p\u00e4r\u00e9nt \u00e7\u00f6\u00fcrs\u00e9 st\u00e4ff \u00f6f \u00e4 \u00c7\u00c7X \u00e7\u00e4n \u00e7r\u00e9\u00e4t\u00e9 \u00e7\u00f6nt\u00e9nt gr\u00f6\u00fcps. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "Open": "\u00d6p\u00e9n \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Open Calculator": "\u00d6p\u00e9n \u00c7\u00e4l\u00e7\u00fcl\u00e4t\u00f6r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Open language menu": "\u00d6p\u00e9n l\u00e4ng\u00fc\u00e4g\u00e9 m\u00e9n\u00fc \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Open the certificate you earned for the %(title)s program.": "\u00d6p\u00e9n th\u00e9 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u00fd\u00f6\u00fc \u00e9\u00e4rn\u00e9d f\u00f6r th\u00e9 %(title)s pr\u00f6gr\u00e4m. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -1186,6 +1219,7 @@ "Organization of the signatory": "\u00d6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n \u00f6f th\u00e9 s\u00efgn\u00e4t\u00f6r\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Organization:": "\u00d6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Other": "\u00d6th\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", + "Other sign-in issues": "\u00d6th\u00e9r s\u00efgn-\u00efn \u00efss\u00fc\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Overall Score": "\u00d6v\u00e9r\u00e4ll S\u00e7\u00f6r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "PDF Chapters": "PDF \u00c7h\u00e4pt\u00e9rs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Page break": "P\u00e4g\u00e9 \u00dfr\u00e9\u00e4k \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", @@ -1215,6 +1249,8 @@ "Photo of %(fullName)s's ID": "Ph\u00f6t\u00f6 \u00f6f %(fullName)s's \u00ccD \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Photo requirements:": "Ph\u00f6t\u00f6 r\u00e9q\u00fc\u00efr\u00e9m\u00e9nts: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Photos don't meet the requirements?": "Ph\u00f6t\u00f6s d\u00f6n't m\u00e9\u00e9t th\u00e9 r\u00e9q\u00fc\u00efr\u00e9m\u00e9nts? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", + "Pin": "P\u00efn \u2c60'\u03c3\u044f\u0454\u043c#", + "Pinned": "P\u00efnn\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Placeholder": "Pl\u00e4\u00e7\u00e9h\u00f6ld\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Play": "Pl\u00e4\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Play video": "Pl\u00e4\u00fd v\u00efd\u00e9\u00f6 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", @@ -1259,6 +1295,7 @@ "Please wait": "Pl\u00e9\u00e4s\u00e9 w\u00e4\u00eft \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Plugins": "Pl\u00fcg\u00efns \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "Post": "P\u00f6st \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", + "Post type": "P\u00f6st t\u00fdp\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Poster": "P\u00f6st\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Practice": "Pr\u00e4\u00e7t\u00ef\u00e7\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Practice Exam": "Pr\u00e4\u00e7t\u00ef\u00e7\u00e9 \u00c9x\u00e4m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", @@ -1315,6 +1352,8 @@ "Published and Live": "P\u00fc\u00dfl\u00efsh\u00e9d \u00e4nd L\u00efv\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Publishing": "P\u00fc\u00dfl\u00efsh\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Publishing Status": "P\u00fc\u00dfl\u00efsh\u00efng St\u00e4t\u00fcs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", + "Question": "Q\u00fc\u00e9st\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", + "Questions raise issues that need answers. Discussions share ideas and start conversations. (Required)": "Q\u00fc\u00e9st\u00ef\u00f6ns r\u00e4\u00efs\u00e9 \u00efss\u00fc\u00e9s th\u00e4t n\u00e9\u00e9d \u00e4nsw\u00e9rs. D\u00efs\u00e7\u00fcss\u00ef\u00f6ns sh\u00e4r\u00e9 \u00efd\u00e9\u00e4s \u00e4nd st\u00e4rt \u00e7\u00f6nv\u00e9rs\u00e4t\u00ef\u00f6ns. (R\u00e9q\u00fc\u00efr\u00e9d) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Queued": "Q\u00fc\u00e9\u00fc\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "REMAINING COURSES": "R\u00c9M\u00c0\u00ccN\u00ccNG \u00c7\u00d6\u00dbRS\u00c9S \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Re-run Course": "R\u00e9-r\u00fcn \u00c7\u00f6\u00fcrs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", @@ -1337,6 +1376,7 @@ "Regenerate the user's certificate": "R\u00e9g\u00e9n\u00e9r\u00e4t\u00e9 th\u00e9 \u00fcs\u00e9r's \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "Register with Institution/Campus Credentials": "R\u00e9g\u00efst\u00e9r w\u00efth \u00ccnst\u00eft\u00fct\u00ef\u00f6n/\u00c7\u00e4mp\u00fcs \u00c7r\u00e9d\u00e9nt\u00ef\u00e4ls \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Rejected": "R\u00e9j\u00e9\u00e7t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", + "Related to: %(courseware_title_linked)s": "R\u00e9l\u00e4t\u00e9d t\u00f6: %(courseware_title_linked)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Release Date and Time": "R\u00e9l\u00e9\u00e4s\u00e9 D\u00e4t\u00e9 \u00e4nd T\u00efm\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Release Date:": "R\u00e9l\u00e9\u00e4s\u00e9 D\u00e4t\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Release Status:": "R\u00e9l\u00e9\u00e4s\u00e9 St\u00e4t\u00fcs: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", @@ -1365,7 +1405,10 @@ "Replace all": "R\u00e9pl\u00e4\u00e7\u00e9 \u00e4ll \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Replace with": "R\u00e9pl\u00e4\u00e7\u00e9 w\u00efth \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Reply to Annotation": "R\u00e9pl\u00fd t\u00f6 \u00c0nn\u00f6t\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", + "Report": "R\u00e9p\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", + "Report abuse": "R\u00e9p\u00f6rt \u00e4\u00df\u00fcs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Report abuse, topics, and responses": "R\u00e9p\u00f6rt \u00e4\u00df\u00fcs\u00e9, t\u00f6p\u00ef\u00e7s, \u00e4nd r\u00e9sp\u00f6ns\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", + "Reported": "R\u00e9p\u00f6rt\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Requester": "R\u00e9q\u00fc\u00e9st\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Required": "R\u00e9q\u00fc\u00efr\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Required field": "R\u00e9q\u00fc\u00efr\u00e9d f\u00ef\u00e9ld \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", @@ -1385,6 +1428,7 @@ "Return and add email address": "R\u00e9t\u00fcrn \u00e4nd \u00e4dd \u00e9m\u00e4\u00efl \u00e4ddr\u00e9ss \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Return to Export": "R\u00e9t\u00fcrn t\u00f6 \u00c9xp\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Return to Your Dashboard": "R\u00e9t\u00fcrn t\u00f6 \u00dd\u00f6\u00fcr D\u00e4sh\u00df\u00f6\u00e4rd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", + "Return to all posts": "R\u00e9t\u00fcrn t\u00f6 \u00e4ll p\u00f6sts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Return to team listing": "R\u00e9t\u00fcrn t\u00f6 t\u00e9\u00e4m l\u00efst\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "Review Policy Exception": "R\u00e9v\u00ef\u00e9w P\u00f6l\u00ef\u00e7\u00fd \u00c9x\u00e7\u00e9pt\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "Review Rules": "R\u00e9v\u00ef\u00e9w R\u00fcl\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", @@ -1469,6 +1513,10 @@ "Show": "Montru", "Show All": "Sh\u00f6w \u00c0ll \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Show Annotations": "Sh\u00f6w \u00c0nn\u00f6t\u00e4t\u00ef\u00f6ns \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "Show Comment (%(num_comments)s)": [ + "Sh\u00f6w \u00c7\u00f6mm\u00e9nt (%(num_comments)s) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "Sh\u00f6w \u00c7\u00f6mm\u00e9nts (%(num_comments)s) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#" + ], "Show Deprecated Settings": "Sh\u00f6w D\u00e9pr\u00e9\u00e7\u00e4t\u00e9d S\u00e9tt\u00efngs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "Show Discussion": "Sh\u00f6w D\u00efs\u00e7\u00fcss\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Show Less": "Sh\u00f6w L\u00e9ss \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", @@ -1505,6 +1553,7 @@ "Sign in using %(providerName)s": "S\u00efgn \u00efn \u00fcs\u00efng %(providerName)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Sign in with %(providerName)s": "S\u00efgn \u00efn w\u00efth %(providerName)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Sign in with Institution/Campus Credentials": "S\u00efgn \u00efn w\u00efth \u00ccnst\u00eft\u00fct\u00ef\u00f6n/\u00c7\u00e4mp\u00fcs \u00c7r\u00e9d\u00e9nt\u00ef\u00e4ls \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", + "Sign in with your company or school": "S\u00efgn \u00efn w\u00efth \u00fd\u00f6\u00fcr \u00e7\u00f6mp\u00e4n\u00fd \u00f6r s\u00e7h\u00f6\u00f6l \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "Sign in.": "S\u00efgn \u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Signatory": "S\u00efgn\u00e4t\u00f6r\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Signatory field(s) has invalid data.": "S\u00efgn\u00e4t\u00f6r\u00fd f\u00ef\u00e9ld(s) h\u00e4s \u00efnv\u00e4l\u00efd d\u00e4t\u00e4. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", @@ -1613,6 +1662,7 @@ "Task inputs": "T\u00e4sk \u00efnp\u00fcts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Teaching Assistant": "T\u00e9\u00e4\u00e7h\u00efng \u00c0ss\u00efst\u00e4nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "Team \"{team}\" successfully deleted.": "T\u00e9\u00e4m \"{team}\" s\u00fc\u00e7\u00e7\u00e9ssf\u00fcll\u00fd d\u00e9l\u00e9t\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", + "Team Assignments": "T\u00e9\u00e4m \u00c0ss\u00efgnm\u00e9nts \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Team Description (Required) *": "T\u00e9\u00e4m D\u00e9s\u00e7r\u00efpt\u00ef\u00f6n (R\u00e9q\u00fc\u00efr\u00e9d) * \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Team Details": "T\u00e9\u00e4m D\u00e9t\u00e4\u00efls \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Team Name (Required) *": "T\u00e9\u00e4m N\u00e4m\u00e9 (R\u00e9q\u00fc\u00efr\u00e9d) * \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", @@ -1631,9 +1681,8 @@ "Textbook Name": "T\u00e9xt\u00df\u00f6\u00f6k N\u00e4m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Textbook information": "T\u00e9xt\u00df\u00f6\u00f6k \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Textbook name is required": "T\u00e9xt\u00df\u00f6\u00f6k n\u00e4m\u00e9 \u00efs r\u00e9q\u00fc\u00efr\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Th\u00e4nk \u00fd\u00f6\u00fc %(full_name)s! W\u00e9 h\u00e4v\u00e9 r\u00e9\u00e7\u00e9\u00efv\u00e9d \u00fd\u00f6\u00fcr p\u00e4\u00fdm\u00e9nt f\u00f6r %(course_name)s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Thank you for setting your course goal to {goal}!": "Th\u00e4nk \u00fd\u00f6\u00fc f\u00f6r s\u00e9tt\u00efng \u00fd\u00f6\u00fcr \u00e7\u00f6\u00fcrs\u00e9 g\u00f6\u00e4l t\u00f6 {goal}! \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", - "Thank you for submitting a request! We will contact you within 24 hours.": "Th\u00e4nk \u00fd\u00f6\u00fc f\u00f6r s\u00fc\u00dfm\u00eftt\u00efng \u00e4 r\u00e9q\u00fc\u00e9st! W\u00e9 w\u00efll \u00e7\u00f6nt\u00e4\u00e7t \u00fd\u00f6\u00fc w\u00efth\u00efn 24 h\u00f6\u00fcrs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", + "Thank you for submitting a request! We appreciate your patience while we work to review your request.": "Th\u00e4nk \u00fd\u00f6\u00fc f\u00f6r s\u00fc\u00dfm\u00eftt\u00efng \u00e4 r\u00e9q\u00fc\u00e9st! W\u00e9 \u00e4ppr\u00e9\u00e7\u00ef\u00e4t\u00e9 \u00fd\u00f6\u00fcr p\u00e4t\u00ef\u00e9n\u00e7\u00e9 wh\u00efl\u00e9 w\u00e9 w\u00f6rk t\u00f6 r\u00e9v\u00ef\u00e9w \u00fd\u00f6\u00fcr r\u00e9q\u00fc\u00e9st. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Th\u00e4nk \u00fd\u00f6\u00fc f\u00f6r s\u00fc\u00dfm\u00eftt\u00efng \u00fd\u00f6\u00fcr f\u00efn\u00e4n\u00e7\u00ef\u00e4l \u00e4ss\u00efst\u00e4n\u00e7\u00e9 \u00e4ppl\u00ef\u00e7\u00e4t\u00ef\u00f6n f\u00f6r {course_name}! \u00dd\u00f6\u00fc \u00e7\u00e4n \u00e9xp\u00e9\u00e7t \u00e4 r\u00e9sp\u00f6ns\u00e9 \u00efn 2-4 \u00df\u00fcs\u00efn\u00e9ss d\u00e4\u00fds. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c#", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Th\u00e4nk \u00fd\u00f6\u00fc f\u00f6r s\u00fc\u00dfm\u00eftt\u00efng \u00fd\u00f6\u00fcr ph\u00f6t\u00f6s. W\u00e9 w\u00efll r\u00e9v\u00ef\u00e9w th\u00e9m sh\u00f6rtl\u00fd. \u00dd\u00f6\u00fc \u00e7\u00e4n n\u00f6w s\u00efgn \u00fcp f\u00f6r \u00e4n\u00fd %(platformName)s \u00e7\u00f6\u00fcrs\u00e9 th\u00e4t \u00f6ff\u00e9rs v\u00e9r\u00eff\u00ef\u00e9d \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9s. V\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n \u00efs g\u00f6\u00f6d f\u00f6r \u00f6n\u00e9 \u00fd\u00e9\u00e4r. \u00c0ft\u00e9r \u00f6n\u00e9 \u00fd\u00e9\u00e4r, \u00fd\u00f6\u00fc m\u00fcst s\u00fc\u00dfm\u00eft ph\u00f6t\u00f6s f\u00f6r v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454#", "Thank you! We have received your payment for {courseName}.": "Th\u00e4nk \u00fd\u00f6\u00fc! W\u00e9 h\u00e4v\u00e9 r\u00e9\u00e7\u00e9\u00efv\u00e9d \u00fd\u00f6\u00fcr p\u00e4\u00fdm\u00e9nt f\u00f6r {courseName}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -1645,8 +1694,8 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Th\u00e9 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 f\u00f6r th\u00efs l\u00e9\u00e4rn\u00e9r h\u00e4s \u00df\u00e9\u00e9n r\u00e9-v\u00e4l\u00efd\u00e4t\u00e9d \u00e4nd th\u00e9 s\u00fdst\u00e9m \u00efs r\u00e9-r\u00fcnn\u00efng th\u00e9 gr\u00e4d\u00e9 f\u00f6r th\u00efs l\u00e9\u00e4rn\u00e9r. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "The cohort cannot be added": "Th\u00e9 \u00e7\u00f6h\u00f6rt \u00e7\u00e4nn\u00f6t \u00df\u00e9 \u00e4dd\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "The cohort cannot be saved": "Th\u00e9 \u00e7\u00f6h\u00f6rt \u00e7\u00e4nn\u00f6t \u00df\u00e9 s\u00e4v\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "Th\u00e9 \u00e7\u00f6m\u00df\u00efn\u00e9d l\u00e9ngth \u00f6f th\u00e9 \u00f6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n \u00e4nd l\u00ef\u00dfr\u00e4r\u00fd \u00e7\u00f6d\u00e9 f\u00ef\u00e9lds \u00e7\u00e4nn\u00f6t \u00df\u00e9 m\u00f6r\u00e9 th\u00e4n <%=limit%> \u00e7h\u00e4r\u00e4\u00e7t\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "Th\u00e9 \u00e7\u00f6m\u00df\u00efn\u00e9d l\u00e9ngth \u00f6f th\u00e9 \u00f6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n, \u00e7\u00f6\u00fcrs\u00e9 n\u00fcm\u00df\u00e9r, \u00e4nd \u00e7\u00f6\u00fcrs\u00e9 r\u00fcn f\u00ef\u00e9lds \u00e7\u00e4nn\u00f6t \u00df\u00e9 m\u00f6r\u00e9 th\u00e4n <%=limit%> \u00e7h\u00e4r\u00e4\u00e7t\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", + "The combined length of the organization and library code fields cannot be more than <%- limit %> characters.": "Th\u00e9 \u00e7\u00f6m\u00df\u00efn\u00e9d l\u00e9ngth \u00f6f th\u00e9 \u00f6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n \u00e4nd l\u00ef\u00dfr\u00e4r\u00fd \u00e7\u00f6d\u00e9 f\u00ef\u00e9lds \u00e7\u00e4nn\u00f6t \u00df\u00e9 m\u00f6r\u00e9 th\u00e4n <%- limit %> \u00e7h\u00e4r\u00e4\u00e7t\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "The combined length of the organization, course number, and course run fields cannot be more than <%- limit %> characters.": "Th\u00e9 \u00e7\u00f6m\u00df\u00efn\u00e9d l\u00e9ngth \u00f6f th\u00e9 \u00f6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n, \u00e7\u00f6\u00fcrs\u00e9 n\u00fcm\u00df\u00e9r, \u00e4nd \u00e7\u00f6\u00fcrs\u00e9 r\u00fcn f\u00ef\u00e9lds \u00e7\u00e4nn\u00f6t \u00df\u00e9 m\u00f6r\u00e9 th\u00e4n <%- limit %> \u00e7h\u00e4r\u00e4\u00e7t\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "The country or region where you live.": "Th\u00e9 \u00e7\u00f6\u00fcntr\u00fd \u00f6r r\u00e9g\u00ef\u00f6n wh\u00e9r\u00e9 \u00fd\u00f6\u00fc l\u00efv\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "The country that team members primarily identify with.": "Th\u00e9 \u00e7\u00f6\u00fcntr\u00fd th\u00e4t t\u00e9\u00e4m m\u00e9m\u00df\u00e9rs pr\u00efm\u00e4r\u00efl\u00fd \u00efd\u00e9nt\u00eff\u00fd w\u00efth. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The course end date must be later than the course start date.": "Th\u00e9 \u00e7\u00f6\u00fcrs\u00e9 \u00e9nd d\u00e4t\u00e9 m\u00fcst \u00df\u00e9 l\u00e4t\u00e9r th\u00e4n th\u00e9 \u00e7\u00f6\u00fcrs\u00e9 st\u00e4rt d\u00e4t\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -1663,7 +1712,7 @@ "The following email addresses and/or usernames are invalid:": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00e9m\u00e4\u00efl \u00e4ddr\u00e9ss\u00e9s \u00e4nd/\u00f6r \u00fcs\u00e9rn\u00e4m\u00e9s \u00e4r\u00e9 \u00efnv\u00e4l\u00efd: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The following errors were generated:": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00e9rr\u00f6rs w\u00e9r\u00e9 g\u00e9n\u00e9r\u00e4t\u00e9d: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "The following file types are not allowed: ": "Th\u00e9 f\u00f6ll\u00f6w\u00efng f\u00efl\u00e9 t\u00fdp\u00e9s \u00e4r\u00e9 n\u00f6t \u00e4ll\u00f6w\u00e9d: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00efs \u00e4lr\u00e9\u00e4d\u00fd \u00e4 p\u00e4rt \u00f6f \u00fd\u00f6\u00fcr {platform} pr\u00f6f\u00efl\u00e9. W\u00e9\\'v\u00e9 \u00efn\u00e7l\u00fcd\u00e9d \u00eft h\u00e9r\u00e9 f\u00f6r \u00fd\u00f6\u00fcr \u00e4ppl\u00ef\u00e7\u00e4t\u00ef\u00f6n. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", + "The following information is already a part of your {platform} profile. We've included it here for your application.": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00efs \u00e4lr\u00e9\u00e4d\u00fd \u00e4 p\u00e4rt \u00f6f \u00fd\u00f6\u00fcr {platform} pr\u00f6f\u00efl\u00e9. W\u00e9'v\u00e9 \u00efn\u00e7l\u00fcd\u00e9d \u00eft h\u00e9r\u00e9 f\u00f6r \u00fd\u00f6\u00fcr \u00e4ppl\u00ef\u00e7\u00e4t\u00ef\u00f6n. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "The following message will be displayed at the bottom of the courseware pages within your course:": "Th\u00e9 f\u00f6ll\u00f6w\u00efng m\u00e9ss\u00e4g\u00e9 w\u00efll \u00df\u00e9 d\u00efspl\u00e4\u00fd\u00e9d \u00e4t th\u00e9 \u00df\u00f6tt\u00f6m \u00f6f th\u00e9 \u00e7\u00f6\u00fcrs\u00e9w\u00e4r\u00e9 p\u00e4g\u00e9s w\u00efth\u00efn \u00fd\u00f6\u00fcr \u00e7\u00f6\u00fcrs\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "The following options are available for the {license_name} license.": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00f6pt\u00ef\u00f6ns \u00e4r\u00e9 \u00e4v\u00e4\u00efl\u00e4\u00dfl\u00e9 f\u00f6r th\u00e9 {license_name} l\u00ef\u00e7\u00e9ns\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The following users are no longer enrolled in the course:": "Th\u00e9 f\u00f6ll\u00f6w\u00efng \u00fcs\u00e9rs \u00e4r\u00e9 n\u00f6 l\u00f6ng\u00e9r \u00e9nr\u00f6ll\u00e9d \u00efn th\u00e9 \u00e7\u00f6\u00fcrs\u00e9: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -1675,7 +1724,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "Th\u00e9 m\u00efn\u00efm\u00fcm \u00e7\u00f6mpl\u00e9t\u00ef\u00f6n p\u00e9r\u00e7\u00e9nt\u00e4g\u00e9 m\u00fcst \u00df\u00e9 \u00e4 wh\u00f6l\u00e9 n\u00fcm\u00df\u00e9r \u00df\u00e9tw\u00e9\u00e9n 0 \u00e4nd 100. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "The minimum grade for course credit is not set.": "Th\u00e9 m\u00efn\u00efm\u00fcm gr\u00e4d\u00e9 f\u00f6r \u00e7\u00f6\u00fcrs\u00e9 \u00e7r\u00e9d\u00eft \u00efs n\u00f6t s\u00e9t. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The minimum score percentage must be a whole number between 0 and 100.": "Th\u00e9 m\u00efn\u00efm\u00fcm s\u00e7\u00f6r\u00e9 p\u00e9r\u00e7\u00e9nt\u00e4g\u00e9 m\u00fcst \u00df\u00e9 \u00e4 wh\u00f6l\u00e9 n\u00fcm\u00df\u00e9r \u00df\u00e9tw\u00e9\u00e9n 0 \u00e4nd 100. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", - "The more you tell us, the more quickly and helpfully we can respond!": "Th\u00e9 m\u00f6r\u00e9 \u00fd\u00f6\u00fc t\u00e9ll \u00fcs, th\u00e9 m\u00f6r\u00e9 q\u00fc\u00ef\u00e7kl\u00fd \u00e4nd h\u00e9lpf\u00fcll\u00fd w\u00e9 \u00e7\u00e4n r\u00e9sp\u00f6nd! \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "The name of this signatory as it should appear on certificates.": "Th\u00e9 n\u00e4m\u00e9 \u00f6f th\u00efs s\u00efgn\u00e4t\u00f6r\u00fd \u00e4s \u00eft sh\u00f6\u00fcld \u00e4pp\u00e9\u00e4r \u00f6n \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The name that identifies you on {platform_name}. You cannot change your username.": "Th\u00e9 n\u00e4m\u00e9 th\u00e4t \u00efd\u00e9nt\u00eff\u00ef\u00e9s \u00fd\u00f6\u00fc \u00f6n {platform_name}. \u00dd\u00f6\u00fc \u00e7\u00e4nn\u00f6t \u00e7h\u00e4ng\u00e9 \u00fd\u00f6\u00fcr \u00fcs\u00e9rn\u00e4m\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "The name that is used for ID verification and that appears on your certificates.": "Th\u00e9 n\u00e4m\u00e9 th\u00e4t \u00efs \u00fcs\u00e9d f\u00f6r \u00ccD v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n \u00e4nd th\u00e4t \u00e4pp\u00e9\u00e4rs \u00f6n \u00fd\u00f6\u00fcr \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", @@ -1683,7 +1731,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Th\u00e9 n\u00fcm\u00df\u00e9r \u00f6f s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6ns \u00efn th\u00e9 \u00e7\u00f6\u00fcrs\u00e9 th\u00e4t \u00e7\u00f6nt\u00e4\u00efn pr\u00f6\u00dfl\u00e9ms \u00f6f th\u00efs \u00e4ss\u00efgnm\u00e9nt t\u00fdp\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "The organization that this signatory belongs to, as it should appear on certificates.": "Th\u00e9 \u00f6rg\u00e4n\u00efz\u00e4t\u00ef\u00f6n th\u00e4t th\u00efs s\u00efgn\u00e4t\u00f6r\u00fd \u00df\u00e9l\u00f6ngs t\u00f6, \u00e4s \u00eft sh\u00f6\u00fcld \u00e4pp\u00e9\u00e4r \u00f6n \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "The page \"{route}\" could not be found.": "Th\u00e9 p\u00e4g\u00e9 \"{route}\" \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 f\u00f6\u00fcnd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", - "The photo of your face matches the photo on your ID.": "Th\u00e9 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9 m\u00e4t\u00e7h\u00e9s th\u00e9 ph\u00f6t\u00f6 \u00f6n \u00fd\u00f6\u00fcr \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "The post you selected has been deleted.": "Th\u00e9 p\u00f6st \u00fd\u00f6\u00fc s\u00e9l\u00e9\u00e7t\u00e9d h\u00e4s \u00df\u00e9\u00e9n d\u00e9l\u00e9t\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "Th\u00e9 p\u00fc\u00dfl\u00efsh\u00e9d \u00dfr\u00e4n\u00e7h v\u00e9rs\u00ef\u00f6n, {published}, w\u00e4s r\u00e9s\u00e9t t\u00f6 th\u00e9 dr\u00e4ft \u00dfr\u00e4n\u00e7h v\u00e9rs\u00ef\u00f6n, {draft}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "The raw error message is:": "Th\u00e9 r\u00e4w \u00e9rr\u00f6r m\u00e9ss\u00e4g\u00e9 \u00efs: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", @@ -1760,6 +1807,7 @@ "This feature is currently in testing. Course teams can enter highlights, but learners will not receive email messages.": "Th\u00efs f\u00e9\u00e4t\u00fcr\u00e9 \u00efs \u00e7\u00fcrr\u00e9ntl\u00fd \u00efn t\u00e9st\u00efng. \u00c7\u00f6\u00fcrs\u00e9 t\u00e9\u00e4ms \u00e7\u00e4n \u00e9nt\u00e9r h\u00efghl\u00efghts, \u00df\u00fct l\u00e9\u00e4rn\u00e9rs w\u00efll n\u00f6t r\u00e9\u00e7\u00e9\u00efv\u00e9 \u00e9m\u00e4\u00efl m\u00e9ss\u00e4g\u00e9s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "This feedback could not be submitted.": "Th\u00efs f\u00e9\u00e9d\u00df\u00e4\u00e7k \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 s\u00fc\u00dfm\u00eftt\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "This file type is not supported. Supported file type is {supportedFileFormat}.": "Th\u00efs f\u00efl\u00e9 t\u00fdp\u00e9 \u00efs n\u00f6t s\u00fcpp\u00f6rt\u00e9d. S\u00fcpp\u00f6rt\u00e9d f\u00efl\u00e9 t\u00fdp\u00e9 \u00efs {supportedFileFormat}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "This grade will be applied to all members of the team. Do you want to continue?": "Th\u00efs gr\u00e4d\u00e9 w\u00efll \u00df\u00e9 \u00e4ppl\u00ef\u00e9d t\u00f6 \u00e4ll m\u00e9m\u00df\u00e9rs \u00f6f th\u00e9 t\u00e9\u00e4m. D\u00f6 \u00fd\u00f6\u00fc w\u00e4nt t\u00f6 \u00e7\u00f6nt\u00efn\u00fc\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "This group controls access to:": "Th\u00efs gr\u00f6\u00fcp \u00e7\u00f6ntr\u00f6ls \u00e4\u00e7\u00e7\u00e9ss t\u00f6: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", "This group no longer exists. Choose another group or do not restrict access to this unit.": "Th\u00efs gr\u00f6\u00fcp n\u00f6 l\u00f6ng\u00e9r \u00e9x\u00efsts. \u00c7h\u00f6\u00f6s\u00e9 \u00e4n\u00f6th\u00e9r gr\u00f6\u00fcp \u00f6r d\u00f6 n\u00f6t r\u00e9str\u00ef\u00e7t \u00e4\u00e7\u00e7\u00e9ss t\u00f6 th\u00efs \u00fcn\u00eft. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "This image file type is not supported. Supported file types are {supportedFileFormats}.": "Th\u00efs \u00efm\u00e4g\u00e9 f\u00efl\u00e9 t\u00fdp\u00e9 \u00efs n\u00f6t s\u00fcpp\u00f6rt\u00e9d. S\u00fcpp\u00f6rt\u00e9d f\u00efl\u00e9 t\u00fdp\u00e9s \u00e4r\u00e9 {supportedFileFormats}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", @@ -1782,6 +1830,10 @@ "This post could not be reopened. Refresh the page and try again.": "Th\u00efs p\u00f6st \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 r\u00e9\u00f6p\u00e9n\u00e9d. R\u00e9fr\u00e9sh th\u00e9 p\u00e4g\u00e9 \u00e4nd tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "This post could not be unflagged for abuse. Refresh the page and try again.": "Th\u00efs p\u00f6st \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 \u00fcnfl\u00e4gg\u00e9d f\u00f6r \u00e4\u00df\u00fcs\u00e9. R\u00e9fr\u00e9sh th\u00e9 p\u00e4g\u00e9 \u00e4nd tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "This post could not be unpinned. Refresh the page and try again.": "Th\u00efs p\u00f6st \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 \u00fcnp\u00efnn\u00e9d. R\u00e9fr\u00e9sh th\u00e9 p\u00e4g\u00e9 \u00e4nd tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "This post is visible only to %(group_name)s.": "Th\u00efs p\u00f6st \u00efs v\u00efs\u00ef\u00dfl\u00e9 \u00f6nl\u00fd t\u00f6 %(group_name)s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", + "This post is visible to everyone.": "Th\u00efs p\u00f6st \u00efs v\u00efs\u00ef\u00dfl\u00e9 t\u00f6 \u00e9v\u00e9r\u00fd\u00f6n\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", + "This post will be visible only to %(group_name)s.": "Th\u00efs p\u00f6st w\u00efll \u00df\u00e9 v\u00efs\u00ef\u00dfl\u00e9 \u00f6nl\u00fd t\u00f6 %(group_name)s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", + "This post will be visible to everyone.": "Th\u00efs p\u00f6st w\u00efll \u00df\u00e9 v\u00efs\u00ef\u00dfl\u00e9 t\u00f6 \u00e9v\u00e9r\u00fd\u00f6n\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "This problem could not be saved.": "Th\u00efs pr\u00f6\u00dfl\u00e9m \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 s\u00e4v\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "This problem has already been released. Any changes will apply only to future assessments.": "Th\u00efs pr\u00f6\u00dfl\u00e9m h\u00e4s \u00e4lr\u00e9\u00e4d\u00fd \u00df\u00e9\u00e9n r\u00e9l\u00e9\u00e4s\u00e9d. \u00c0n\u00fd \u00e7h\u00e4ng\u00e9s w\u00efll \u00e4ppl\u00fd \u00f6nl\u00fd t\u00f6 f\u00fct\u00fcr\u00e9 \u00e4ss\u00e9ssm\u00e9nts. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "This problem has been reset.": "Th\u00efs pr\u00f6\u00dfl\u00e9m h\u00e4s \u00df\u00e9\u00e9n r\u00e9s\u00e9t. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", @@ -1796,8 +1848,11 @@ "This role requires a divided discussions scheme.": "Th\u00efs r\u00f6l\u00e9 r\u00e9q\u00fc\u00efr\u00e9s \u00e4 d\u00efv\u00efd\u00e9d d\u00efs\u00e7\u00fcss\u00ef\u00f6ns s\u00e7h\u00e9m\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "This section could not be loaded.": "Th\u00efs s\u00e9\u00e7t\u00ef\u00f6n \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 l\u00f6\u00e4d\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.": "Th\u00efs sh\u00f6rt n\u00e4m\u00e9 f\u00f6r th\u00e9 \u00e4ss\u00efgnm\u00e9nt t\u00fdp\u00e9 (f\u00f6r \u00e9x\u00e4mpl\u00e9, HW \u00f6r M\u00efdt\u00e9rm) \u00e4pp\u00e9\u00e4rs n\u00e9xt t\u00f6 \u00e4ss\u00efgnm\u00e9nts \u00f6n \u00e4 l\u00e9\u00e4rn\u00e9r's Pr\u00f6gr\u00e9ss p\u00e4g\u00e9. \u2c60'\u03c3\u044f\u0454\u043c#", + "This special exam has been released to learners. You may not convert it to another type of special exam. You may revert this subsection back to being a basic exam by selecting 'None', but you will NOT be able to configure it as a special exam in the future.": "Th\u00efs sp\u00e9\u00e7\u00ef\u00e4l \u00e9x\u00e4m h\u00e4s \u00df\u00e9\u00e9n r\u00e9l\u00e9\u00e4s\u00e9d t\u00f6 l\u00e9\u00e4rn\u00e9rs. \u00dd\u00f6\u00fc m\u00e4\u00fd n\u00f6t \u00e7\u00f6nv\u00e9rt \u00eft t\u00f6 \u00e4n\u00f6th\u00e9r t\u00fdp\u00e9 \u00f6f sp\u00e9\u00e7\u00ef\u00e4l \u00e9x\u00e4m. \u00dd\u00f6\u00fc m\u00e4\u00fd r\u00e9v\u00e9rt th\u00efs s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6n \u00df\u00e4\u00e7k t\u00f6 \u00df\u00e9\u00efng \u00e4 \u00df\u00e4s\u00ef\u00e7 \u00e9x\u00e4m \u00df\u00fd s\u00e9l\u00e9\u00e7t\u00efng 'N\u00f6n\u00e9', \u00df\u00fct \u00fd\u00f6\u00fc w\u00efll N\u00d6T \u00df\u00e9 \u00e4\u00dfl\u00e9 t\u00f6 \u00e7\u00f6nf\u00efg\u00fcr\u00e9 \u00eft \u00e4s \u00e4 sp\u00e9\u00e7\u00ef\u00e4l \u00e9x\u00e4m \u00efn th\u00e9 f\u00fct\u00fcr\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f#", + "This subsection was released to learners as a special exam, but was reverted back to a basic exam. You may not configure it as a special exam now. Contact edX Support for assistance.": "Th\u00efs s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6n w\u00e4s r\u00e9l\u00e9\u00e4s\u00e9d t\u00f6 l\u00e9\u00e4rn\u00e9rs \u00e4s \u00e4 sp\u00e9\u00e7\u00ef\u00e4l \u00e9x\u00e4m, \u00df\u00fct w\u00e4s r\u00e9v\u00e9rt\u00e9d \u00df\u00e4\u00e7k t\u00f6 \u00e4 \u00df\u00e4s\u00ef\u00e7 \u00e9x\u00e4m. \u00dd\u00f6\u00fc m\u00e4\u00fd n\u00f6t \u00e7\u00f6nf\u00efg\u00fcr\u00e9 \u00eft \u00e4s \u00e4 sp\u00e9\u00e7\u00ef\u00e4l \u00e9x\u00e4m n\u00f6w. \u00c7\u00f6nt\u00e4\u00e7t \u00e9dX S\u00fcpp\u00f6rt f\u00f6r \u00e4ss\u00efst\u00e4n\u00e7\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5#", "This team does not have any members.": "Th\u00efs t\u00e9\u00e4m d\u00f6\u00e9s n\u00f6t h\u00e4v\u00e9 \u00e4n\u00fd m\u00e9m\u00df\u00e9rs. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "This team is full.": "Th\u00efs t\u00e9\u00e4m \u00efs f\u00fcll. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "This thread is closed.": "Th\u00efs thr\u00e9\u00e4d \u00efs \u00e7l\u00f6s\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "This unit has validation issues.": "Th\u00efs \u00fcn\u00eft h\u00e4s v\u00e4l\u00efd\u00e4t\u00ef\u00f6n \u00efss\u00fc\u00e9s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "This vote could not be processed. Refresh the page and try again.": "Th\u00efs v\u00f6t\u00e9 \u00e7\u00f6\u00fcld n\u00f6t \u00df\u00e9 pr\u00f6\u00e7\u00e9ss\u00e9d. R\u00e9fr\u00e9sh th\u00e9 p\u00e4g\u00e9 \u00e4nd tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "This {parentCategory} has no {childCategory}": "Th\u00efs {parentCategory} h\u00e4s n\u00f6 {childCategory} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", @@ -1824,7 +1879,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "T\u00f6 \u00df\u00e9 s\u00fcr\u00e9 \u00e4ll st\u00fcd\u00e9nts \u00e7\u00e4n \u00e4\u00e7\u00e7\u00e9ss th\u00e9 v\u00efd\u00e9\u00f6, w\u00e9 r\u00e9\u00e7\u00f6mm\u00e9nd pr\u00f6v\u00efd\u00efng \u00df\u00f6th \u00e4n .mp4 \u00e4nd \u00e4 .w\u00e9\u00dfm v\u00e9rs\u00ef\u00f6n \u00f6f \u00fd\u00f6\u00fcr v\u00efd\u00e9\u00f6. \u00c7l\u00ef\u00e7k \u00df\u00e9l\u00f6w t\u00f6 \u00e4dd \u00e4 \u00dbRL f\u00f6r \u00e4n\u00f6th\u00e9r v\u00e9rs\u00ef\u00f6n. Th\u00e9s\u00e9 \u00dbRLs \u00e7\u00e4nn\u00f6t \u00df\u00e9 \u00dd\u00f6\u00fcT\u00fc\u00df\u00e9 \u00dbRLs. Th\u00e9 f\u00efrst l\u00efst\u00e9d v\u00efd\u00e9\u00f6 th\u00e4t's \u00e7\u00f6mp\u00e4t\u00ef\u00dfl\u00e9 w\u00efth th\u00e9 st\u00fcd\u00e9nt's \u00e7\u00f6mp\u00fct\u00e9r w\u00efll pl\u00e4\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202#", "To complete the program, you must earn a verified certificate for each course.": "T\u00f6 \u00e7\u00f6mpl\u00e9t\u00e9 th\u00e9 pr\u00f6gr\u00e4m, \u00fd\u00f6\u00fc m\u00fcst \u00e9\u00e4rn \u00e4 v\u00e9r\u00eff\u00ef\u00e9d \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 f\u00f6r \u00e9\u00e4\u00e7h \u00e7\u00f6\u00fcrs\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "To continue learning with this account, sign in below.": "T\u00f6 \u00e7\u00f6nt\u00efn\u00fc\u00e9 l\u00e9\u00e4rn\u00efng w\u00efth th\u00efs \u00e4\u00e7\u00e7\u00f6\u00fcnt, s\u00efgn \u00efn \u00df\u00e9l\u00f6w. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "T\u00f6 f\u00efn\u00e4l\u00efz\u00e9 \u00e7\u00f6\u00fcrs\u00e9 \u00e7r\u00e9d\u00eft, %(display_name)s r\u00e9q\u00fc\u00efr\u00e9s %(platform_name)s l\u00e9\u00e4rn\u00e9rs t\u00f6 s\u00fc\u00dfm\u00eft \u00e4 \u00e7r\u00e9d\u00eft r\u00e9q\u00fc\u00e9st. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", "To invalidate a certificate for a particular learner, add the username or email address below.": "T\u00f6 \u00efnv\u00e4l\u00efd\u00e4t\u00e9 \u00e4 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 f\u00f6r \u00e4 p\u00e4rt\u00ef\u00e7\u00fcl\u00e4r l\u00e9\u00e4rn\u00e9r, \u00e4dd th\u00e9 \u00fcs\u00e9rn\u00e4m\u00e9 \u00f6r \u00e9m\u00e4\u00efl \u00e4ddr\u00e9ss \u00df\u00e9l\u00f6w. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "To receive a certificate, you must also verify your identity before {date}.": "T\u00f6 r\u00e9\u00e7\u00e9\u00efv\u00e9 \u00e4 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9, \u00fd\u00f6\u00fc m\u00fcst \u00e4ls\u00f6 v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd \u00df\u00e9f\u00f6r\u00e9 {date}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "To receive a certificate, you must also verify your identity.": "T\u00f6 r\u00e9\u00e7\u00e9\u00efv\u00e9 \u00e4 \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9, \u00fd\u00f6\u00fc m\u00fcst \u00e4ls\u00f6 v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -1832,7 +1886,7 @@ "To review learner cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on the {link_start}Data Download{link_end} page.": "T\u00f6 r\u00e9v\u00ef\u00e9w l\u00e9\u00e4rn\u00e9r \u00e7\u00f6h\u00f6rt \u00e4ss\u00efgnm\u00e9nts \u00f6r s\u00e9\u00e9 th\u00e9 r\u00e9s\u00fclts \u00f6f \u00fcpl\u00f6\u00e4d\u00efng \u00e4 \u00c7SV f\u00efl\u00e9, d\u00f6wnl\u00f6\u00e4d \u00e7\u00f6\u00fcrs\u00e9 pr\u00f6f\u00efl\u00e9 \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00f6r \u00e7\u00f6h\u00f6rt r\u00e9s\u00fclts \u00f6n th\u00e9 {link_start}D\u00e4t\u00e4 D\u00f6wnl\u00f6\u00e4d{link_end} p\u00e4g\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2#", "To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.": "T\u00f6 sh\u00e4r\u00e9 \u00fd\u00f6\u00fcr \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u00f6n M\u00f6z\u00efll\u00e4 B\u00e4\u00e7kp\u00e4\u00e7k, \u00fd\u00f6\u00fc m\u00fcst f\u00efrst h\u00e4v\u00e9 \u00e4 B\u00e4\u00e7kp\u00e4\u00e7k \u00e4\u00e7\u00e7\u00f6\u00fcnt. \u00c7\u00f6mpl\u00e9t\u00e9 th\u00e9 f\u00f6ll\u00f6w\u00efng st\u00e9ps t\u00f6 \u00e4dd \u00fd\u00f6\u00fcr \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 t\u00f6 B\u00e4\u00e7kp\u00e4\u00e7k. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442#", "To take a successful photo, make sure that:": "T\u00f6 t\u00e4k\u00e9 \u00e4 s\u00fc\u00e7\u00e7\u00e9ssf\u00fcl ph\u00f6t\u00f6, m\u00e4k\u00e9 s\u00fcr\u00e9 th\u00e4t: \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", - "To use the current photo, select the Take Photo button {icon}. To take another photo, select the Retake Photo button {icon}.": "T\u00f6 \u00fcs\u00e9 th\u00e9 \u00e7\u00fcrr\u00e9nt ph\u00f6t\u00f6, s\u00e9l\u00e9\u00e7t th\u00e9 T\u00e4k\u00e9 Ph\u00f6t\u00f6 \u00df\u00fctt\u00f6n {icon}. T\u00f6 t\u00e4k\u00e9 \u00e4n\u00f6th\u00e9r ph\u00f6t\u00f6, s\u00e9l\u00e9\u00e7t th\u00e9 R\u00e9t\u00e4k\u00e9 Ph\u00f6t\u00f6 \u00df\u00fctt\u00f6n {icon}. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", + "To take the photo of your face, click on the camera button {icon}. If you need to try again, click 'Retake Photo'.": "T\u00f6 t\u00e4k\u00e9 th\u00e9 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9, \u00e7l\u00ef\u00e7k \u00f6n th\u00e9 \u00e7\u00e4m\u00e9r\u00e4 \u00df\u00fctt\u00f6n {icon}. \u00ccf \u00fd\u00f6\u00fc n\u00e9\u00e9d t\u00f6 tr\u00fd \u00e4g\u00e4\u00efn, \u00e7l\u00ef\u00e7k 'R\u00e9t\u00e4k\u00e9 Ph\u00f6t\u00f6'. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "To verify your identity, you need a webcam and a government-issued photo ID.": "T\u00f6 v\u00e9r\u00eff\u00fd \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd, \u00fd\u00f6\u00fc n\u00e9\u00e9d \u00e4 w\u00e9\u00df\u00e7\u00e4m \u00e4nd \u00e4 g\u00f6v\u00e9rnm\u00e9nt-\u00efss\u00fc\u00e9d ph\u00f6t\u00f6 \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "Today": "Hodia\u016d", "Toggle Account Password (Usable/Unusable)": "T\u00f6ggl\u00e9 \u00c0\u00e7\u00e7\u00f6\u00fcnt P\u00e4ssw\u00f6rd (\u00dbs\u00e4\u00dfl\u00e9/\u00dbn\u00fcs\u00e4\u00dfl\u00e9) \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", @@ -1841,6 +1895,7 @@ "Tools": "T\u00f6\u00f6ls \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "Top": "T\u00f6p \u2c60'\u03c3\u044f\u0454\u043c#", "Topic": "T\u00f6p\u00ef\u00e7 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", + "Topic area": "T\u00f6p\u00ef\u00e7 \u00e4r\u00e9\u00e4 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Topics": "T\u00f6p\u00ef\u00e7s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Total": "T\u00f6t\u00e4l \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "Total Number": "T\u00f6t\u00e4l N\u00fcm\u00df\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", @@ -1871,7 +1926,9 @@ "Undo Changes": "\u00dbnd\u00f6 \u00c7h\u00e4ng\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Undo move": "\u00dbnd\u00f6 m\u00f6v\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Undo moving": "\u00dbnd\u00f6 m\u00f6v\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", + "Unendorse": "\u00dbn\u00e9nd\u00f6rs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "Unexpected server error.": "\u00dbn\u00e9xp\u00e9\u00e7t\u00e9d s\u00e9rv\u00e9r \u00e9rr\u00f6r. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", + "Unfollow": "\u00dbnf\u00f6ll\u00f6w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Ungraded": "\u00dbngr\u00e4d\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Unit": "\u00dbn\u00eft \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Unit Access": "\u00dbn\u00eft \u00c0\u00e7\u00e7\u00e9ss \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", @@ -1883,14 +1940,20 @@ "Unlink This Account": "\u00dbnl\u00efnk Th\u00efs \u00c0\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Unlink your {accountName} account": "\u00dbnl\u00efnk \u00fd\u00f6\u00fcr {accountName} \u00e4\u00e7\u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "Unlinking": "\u00dbnl\u00efnk\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", + "Unmark as Answer": "\u00dbnm\u00e4rk \u00e4s \u00c0nsw\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Unmute": "\u00dbnm\u00fct\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Unnamed Option": "\u00dbnn\u00e4m\u00e9d \u00d6pt\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", + "Unpin": "\u00dbnp\u00efn \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "Unpublished changes to content that will release in the future": "\u00dbnp\u00fc\u00dfl\u00efsh\u00e9d \u00e7h\u00e4ng\u00e9s t\u00f6 \u00e7\u00f6nt\u00e9nt th\u00e4t w\u00efll r\u00e9l\u00e9\u00e4s\u00e9 \u00efn th\u00e9 f\u00fct\u00fcr\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Unpublished changes to live content": "\u00dbnp\u00fc\u00dfl\u00efsh\u00e9d \u00e7h\u00e4ng\u00e9s t\u00f6 l\u00efv\u00e9 \u00e7\u00f6nt\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442#", "Unpublished units will not be released": "\u00dbnp\u00fc\u00dfl\u00efsh\u00e9d \u00fcn\u00efts w\u00efll n\u00f6t \u00df\u00e9 r\u00e9l\u00e9\u00e4s\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", + "Unreport": "\u00dbnr\u00e9p\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "Unscheduled": "\u00dbns\u00e7h\u00e9d\u00fcl\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Update": "\u00dbpd\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Update Settings": "\u00dbpd\u00e4t\u00e9 S\u00e9tt\u00efngs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", + "Update comment": "\u00dbpd\u00e4t\u00e9 \u00e7\u00f6mm\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", + "Update post": "\u00dbpd\u00e4t\u00e9 p\u00f6st \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", + "Update response": "\u00dbpd\u00e4t\u00e9 r\u00e9sp\u00f6ns\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Update team.": "\u00dbpd\u00e4t\u00e9 t\u00e9\u00e4m. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "Updating Tags": "\u00dbpd\u00e4t\u00efng T\u00e4gs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Updating with latest library content": "\u00dbpd\u00e4t\u00efng w\u00efth l\u00e4t\u00e9st l\u00ef\u00dfr\u00e4r\u00fd \u00e7\u00f6nt\u00e9nt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", @@ -1912,7 +1975,7 @@ "Upload Videos": "\u00dbpl\u00f6\u00e4d V\u00efd\u00e9\u00f6s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Upload a CSV file": "\u00dbpl\u00f6\u00e4d \u00e4 \u00c7SV f\u00efl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u00dbpl\u00f6\u00e4d \u00e4 \u00e7\u00f6mm\u00e4 s\u00e9p\u00e4r\u00e4t\u00e9d v\u00e4l\u00fc\u00e9s (.\u00e7sv) f\u00efl\u00e9 th\u00e4t \u00e7\u00f6nt\u00e4\u00efns th\u00e9 \u00fcs\u00e9rn\u00e4m\u00e9s \u00f6r \u00e9m\u00e4\u00efl \u00e4ddr\u00e9ss\u00e9s \u00f6f l\u00e9\u00e4rn\u00e9rs wh\u00f6 h\u00e4v\u00e9 \u00df\u00e9\u00e9n g\u00efv\u00e9n \u00e9x\u00e7\u00e9pt\u00ef\u00f6ns. \u00ccn\u00e7l\u00fcd\u00e9 th\u00e9 \u00fcs\u00e9rn\u00e4m\u00e9 \u00f6r \u00e9m\u00e4\u00efl \u00e4ddr\u00e9ss \u00efn th\u00e9 f\u00efrst \u00e7\u00f6mm\u00e4 s\u00e9p\u00e4r\u00e4t\u00e9d f\u00ef\u00e9ld. \u00dd\u00f6\u00fc \u00e7\u00e4n \u00efn\u00e7l\u00fcd\u00e9 \u00e4n \u00f6pt\u00ef\u00f6n\u00e4l n\u00f6t\u00e9 d\u00e9s\u00e7r\u00ef\u00df\u00efng th\u00e9 r\u00e9\u00e4s\u00f6n f\u00f6r th\u00e9 \u00e9x\u00e7\u00e9pt\u00ef\u00f6n \u00efn th\u00e9 s\u00e9\u00e7\u00f6nd \u00e7\u00f6mm\u00e4 s\u00e9p\u00e4r\u00e4t\u00e9d f\u00ef\u00e9ld. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9#", - "Upload a new PDF to \u201c<%= name %>\u201d": "\u00dbpl\u00f6\u00e4d \u00e4 n\u00e9w PDF t\u00f6 \u201c<%= name %>\u201d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", + "Upload a new PDF to \u201c<%- name %>\u201d": "\u00dbpl\u00f6\u00e4d \u00e4 n\u00e9w PDF t\u00f6 \u201c<%- name %>\u201d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "Upload an image": "\u00dbpl\u00f6\u00e4d \u00e4n \u00efm\u00e4g\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Upload an image or capture one with your web or phone camera.": "\u00dbpl\u00f6\u00e4d \u00e4n \u00efm\u00e4g\u00e9 \u00f6r \u00e7\u00e4pt\u00fcr\u00e9 \u00f6n\u00e9 w\u00efth \u00fd\u00f6\u00fcr w\u00e9\u00df \u00f6r ph\u00f6n\u00e9 \u00e7\u00e4m\u00e9r\u00e4. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Upload completed": "\u00dbpl\u00f6\u00e4d \u00e7\u00f6mpl\u00e9t\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", @@ -1947,7 +2010,7 @@ "Use my university info": "\u00dbs\u00e9 m\u00fd \u00fcn\u00efv\u00e9rs\u00eft\u00fd \u00efnf\u00f6 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "Use the All Topics menu to find specific topics.": "\u00dbs\u00e9 th\u00e9 \u00c0ll T\u00f6p\u00ef\u00e7s m\u00e9n\u00fc t\u00f6 f\u00efnd sp\u00e9\u00e7\u00eff\u00ef\u00e7 t\u00f6p\u00ef\u00e7s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "Use the Retake Photo button if you are not pleased with your photo": "\u00dbs\u00e9 th\u00e9 R\u00e9t\u00e4k\u00e9 Ph\u00f6t\u00f6 \u00df\u00fctt\u00f6n \u00eff \u00fd\u00f6\u00fc \u00e4r\u00e9 n\u00f6t pl\u00e9\u00e4s\u00e9d w\u00efth \u00fd\u00f6\u00fcr ph\u00f6t\u00f6 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u00dbs\u00e9 \u00fd\u00f6\u00fcr w\u00e9\u00df\u00e7\u00e4m t\u00f6 t\u00e4k\u00e9 \u00e4 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr \u00ccD. W\u00e9 w\u00efll m\u00e4t\u00e7h th\u00efs ph\u00f6t\u00f6 w\u00efth th\u00e9 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9 \u00e4nd th\u00e9 n\u00e4m\u00e9 \u00f6n \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt. \u2c60'\u03c3\u044f\u0454\u043c#", + "Use your webcam to take a photo of your ID.": "\u00dbs\u00e9 \u00fd\u00f6\u00fcr w\u00e9\u00df\u00e7\u00e4m t\u00f6 t\u00e4k\u00e9 \u00e4 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u00dbs\u00e9 \u00fd\u00f6\u00fcr w\u00e9\u00df\u00e7\u00e4m t\u00f6 t\u00e4k\u00e9 \u00e4 ph\u00f6t\u00f6 \u00f6f \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9. W\u00e9 w\u00efll m\u00e4t\u00e7h th\u00efs ph\u00f6t\u00f6 w\u00efth th\u00e9 ph\u00f6t\u00f6 \u00f6n \u00fd\u00f6\u00fcr \u00ccD. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Used": "\u00dbs\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "Used in {count} location": [ @@ -1973,7 +2036,6 @@ "Verified Certificate upgrade": "V\u00e9r\u00eff\u00ef\u00e9d \u00c7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u00fcpgr\u00e4d\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Verified Status": "V\u00e9r\u00eff\u00ef\u00e9d St\u00e4t\u00fcs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "Verified mode price": "V\u00e9r\u00eff\u00ef\u00e9d m\u00f6d\u00e9 pr\u00ef\u00e7\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", - "Verify Now": "V\u00e9r\u00eff\u00fd N\u00f6w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Version": "V\u00e9rs\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "Vertical space": "V\u00e9rt\u00ef\u00e7\u00e4l sp\u00e4\u00e7\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "Very loud": "V\u00e9r\u00fd l\u00f6\u00fcd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", @@ -2000,16 +2062,19 @@ "View Teams in the {topic_name} Topic": "V\u00ef\u00e9w T\u00e9\u00e4ms \u00efn th\u00e9 {topic_name} T\u00f6p\u00ef\u00e7 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "View all errors": "V\u00ef\u00e9w \u00e4ll \u00e9rr\u00f6rs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "View child items": "V\u00ef\u00e9w \u00e7h\u00efld \u00eft\u00e9ms \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "View discussion": "V\u00ef\u00e9w d\u00efs\u00e7\u00fcss\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "View {span_start} {team_name} {span_end}": "V\u00ef\u00e9w {span_start} {team_name} {span_end} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "Viewing %s course": [ "V\u00ef\u00e9w\u00efng %s \u00e7\u00f6\u00fcrs\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "V\u00ef\u00e9w\u00efng %s \u00e7\u00f6\u00fcrs\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#" ], "Visibility": "V\u00efs\u00ef\u00df\u00efl\u00eft\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", + "Visible to": "V\u00efs\u00ef\u00dfl\u00e9 t\u00f6 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "Visible to Staff Only": "V\u00efs\u00ef\u00dfl\u00e9 t\u00f6 St\u00e4ff \u00d6nl\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "Visual aids": "V\u00efs\u00fc\u00e4l \u00e4\u00efds \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Volume": "V\u00f6l\u00fcm\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "Vote for good posts and responses": "V\u00f6t\u00e9 f\u00f6r g\u00f6\u00f6d p\u00f6sts \u00e4nd r\u00e9sp\u00f6ns\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", + "Vote for this post,": "V\u00f6t\u00e9 f\u00f6r th\u00efs p\u00f6st, \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "Waiting": "W\u00e4\u00eft\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "Want to confirm your identity later?": "W\u00e4nt t\u00f6 \u00e7\u00f6nf\u00efrm \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd l\u00e4t\u00e9r? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", "Warning": "W\u00e4rn\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", @@ -2019,9 +2084,11 @@ "We couldn't find any results for \"%s\".": "W\u00e9 \u00e7\u00f6\u00fcldn't f\u00efnd \u00e4n\u00fd r\u00e9s\u00fclts f\u00f6r \"%s\". \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "We couldn't sign you in.": "W\u00e9 \u00e7\u00f6\u00fcldn't s\u00efgn \u00fd\u00f6\u00fc \u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "We have encountered an error. Refresh your browser and then try again.": "W\u00e9 h\u00e4v\u00e9 \u00e9n\u00e7\u00f6\u00fcnt\u00e9r\u00e9d \u00e4n \u00e9rr\u00f6r. R\u00e9fr\u00e9sh \u00fd\u00f6\u00fcr \u00dfr\u00f6ws\u00e9r \u00e4nd th\u00e9n tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "W\u00e9 h\u00e4v\u00e9 r\u00e9\u00e7\u00e9\u00efv\u00e9d \u00fd\u00f6\u00fcr \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00e4nd \u00e4r\u00e9 v\u00e9r\u00eff\u00fd\u00efng \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd. \u00dd\u00f6\u00fc w\u00efll s\u00e9\u00e9 \u00e4 m\u00e9ss\u00e4g\u00e9 \u00f6n \u00fd\u00f6\u00fcr d\u00e4sh\u00df\u00f6\u00e4rd wh\u00e9n th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss \u00efs \u00e7\u00f6mpl\u00e9t\u00e9 (\u00fcs\u00fc\u00e4ll\u00fd w\u00efth\u00efn 1-2 d\u00e4\u00fds). \u00ccn th\u00e9 m\u00e9\u00e4nt\u00efm\u00e9, \u00fd\u00f6\u00fc \u00e7\u00e4n st\u00efll \u00e4\u00e7\u00e7\u00e9ss \u00e4ll \u00e4v\u00e4\u00efl\u00e4\u00dfl\u00e9 \u00e7\u00f6\u00fcrs\u00e9 \u00e7\u00f6nt\u00e9nt. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454#", + "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days). In the meantime, you can still access all available course content.": "W\u00e9 h\u00e4v\u00e9 r\u00e9\u00e7\u00e9\u00efv\u00e9d \u00fd\u00f6\u00fcr \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00e4nd \u00e4r\u00e9 v\u00e9r\u00eff\u00fd\u00efng \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd. \u00dd\u00f6\u00fc w\u00efll s\u00e9\u00e9 \u00e4 m\u00e9ss\u00e4g\u00e9 \u00f6n \u00fd\u00f6\u00fcr d\u00e4sh\u00df\u00f6\u00e4rd wh\u00e9n th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss \u00efs \u00e7\u00f6mpl\u00e9t\u00e9 (\u00fcs\u00fc\u00e4ll\u00fd w\u00efth\u00efn 5-7 d\u00e4\u00fds). \u00ccn th\u00e9 m\u00e9\u00e4nt\u00efm\u00e9, \u00fd\u00f6\u00fc \u00e7\u00e4n st\u00efll \u00e4\u00e7\u00e7\u00e9ss \u00e4ll \u00e4v\u00e4\u00efl\u00e4\u00dfl\u00e9 \u00e7\u00f6\u00fcrs\u00e9 \u00e7\u00f6nt\u00e9nt. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454#", "We just need a little more information before you start learning with %(platformName)s.": "W\u00e9 j\u00fcst n\u00e9\u00e9d \u00e4 l\u00efttl\u00e9 m\u00f6r\u00e9 \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00df\u00e9f\u00f6r\u00e9 \u00fd\u00f6\u00fc st\u00e4rt l\u00e9\u00e4rn\u00efng w\u00efth %(platformName)s. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", + "We securely encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "W\u00e9 s\u00e9\u00e7\u00fcr\u00e9l\u00fd \u00e9n\u00e7r\u00fdpt \u00fd\u00f6\u00fcr ph\u00f6t\u00f6 \u00e4nd s\u00e9nd \u00eft t\u00f6 \u00f6\u00fcr \u00e4\u00fcth\u00f6r\u00efz\u00e4t\u00ef\u00f6n s\u00e9rv\u00ef\u00e7\u00e9 f\u00f6r r\u00e9v\u00ef\u00e9w. \u00dd\u00f6\u00fcr ph\u00f6t\u00f6 \u00e4nd \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00e4r\u00e9 n\u00f6t s\u00e4v\u00e9d \u00f6r v\u00efs\u00ef\u00dfl\u00e9 \u00e4n\u00fdwh\u00e9r\u00e9 \u00f6n %(platformName)s \u00e4ft\u00e9r th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss \u00efs \u00e7\u00f6mpl\u00e9t\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442#", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "W\u00e9 \u00fcs\u00e9 th\u00e9 h\u00efgh\u00e9st l\u00e9v\u00e9ls \u00f6f s\u00e9\u00e7\u00fcr\u00eft\u00fd \u00e4v\u00e4\u00efl\u00e4\u00dfl\u00e9 t\u00f6 \u00e9n\u00e7r\u00fdpt \u00fd\u00f6\u00fcr ph\u00f6t\u00f6 \u00e4nd s\u00e9nd \u00eft t\u00f6 \u00f6\u00fcr \u00e4\u00fcth\u00f6r\u00efz\u00e4t\u00ef\u00f6n s\u00e9rv\u00ef\u00e7\u00e9 f\u00f6r r\u00e9v\u00ef\u00e9w. \u00dd\u00f6\u00fcr ph\u00f6t\u00f6 \u00e4nd \u00efnf\u00f6rm\u00e4t\u00ef\u00f6n \u00e4r\u00e9 n\u00f6t s\u00e4v\u00e9d \u00f6r v\u00efs\u00ef\u00dfl\u00e9 \u00e4n\u00fdwh\u00e9r\u00e9 \u00f6n %(platformName)s \u00e4ft\u00e9r th\u00e9 v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n pr\u00f6\u00e7\u00e9ss \u00efs \u00e7\u00f6mpl\u00e9t\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c#", + "We use your verification photos to confirm your identity and ensure the validity of your certificate.": "W\u00e9 \u00fcs\u00e9 \u00fd\u00f6\u00fcr v\u00e9r\u00eff\u00ef\u00e7\u00e4t\u00ef\u00f6n ph\u00f6t\u00f6s t\u00f6 \u00e7\u00f6nf\u00efrm \u00fd\u00f6\u00fcr \u00efd\u00e9nt\u00eft\u00fd \u00e4nd \u00e9ns\u00fcr\u00e9 th\u00e9 v\u00e4l\u00efd\u00eft\u00fd \u00f6f \u00fd\u00f6\u00fcr \u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "We're sorry to see you go! Your account will be deleted shortly.": "W\u00e9'r\u00e9 s\u00f6rr\u00fd t\u00f6 s\u00e9\u00e9 \u00fd\u00f6\u00fc g\u00f6! \u00dd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt w\u00efll \u00df\u00e9 d\u00e9l\u00e9t\u00e9d sh\u00f6rtl\u00fd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "We're sorry, there was an error": "W\u00e9'r\u00e9 s\u00f6rr\u00fd, th\u00e9r\u00e9 w\u00e4s \u00e4n \u00e9rr\u00f6r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", "We've encountered an error. Refresh your browser and then try again.": "W\u00e9'v\u00e9 \u00e9n\u00e7\u00f6\u00fcnt\u00e9r\u00e9d \u00e4n \u00e9rr\u00f6r. R\u00e9fr\u00e9sh \u00fd\u00f6\u00fcr \u00dfr\u00f6ws\u00e9r \u00e4nd th\u00e9n tr\u00fd \u00e4g\u00e4\u00efn. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", @@ -2044,6 +2111,7 @@ "When learners submit an answer to an assessment, they immediately see whether the answer is correct or incorrect, and the score received.": "Wh\u00e9n l\u00e9\u00e4rn\u00e9rs s\u00fc\u00dfm\u00eft \u00e4n \u00e4nsw\u00e9r t\u00f6 \u00e4n \u00e4ss\u00e9ssm\u00e9nt, th\u00e9\u00fd \u00efmm\u00e9d\u00ef\u00e4t\u00e9l\u00fd s\u00e9\u00e9 wh\u00e9th\u00e9r th\u00e9 \u00e4nsw\u00e9r \u00efs \u00e7\u00f6rr\u00e9\u00e7t \u00f6r \u00efn\u00e7\u00f6rr\u00e9\u00e7t, \u00e4nd th\u00e9 s\u00e7\u00f6r\u00e9 r\u00e9\u00e7\u00e9\u00efv\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442 \u03b1\u03b7\u03b9\u043c \u03b9\u2202 \u0454\u0455\u0442 \u0142\u03b1\u0432\u03c3#", "When your face is in position, use the Take Photo button {icon} below to take your photo.": "Wh\u00e9n \u00fd\u00f6\u00fcr f\u00e4\u00e7\u00e9 \u00efs \u00efn p\u00f6s\u00eft\u00ef\u00f6n, \u00fcs\u00e9 th\u00e9 T\u00e4k\u00e9 Ph\u00f6t\u00f6 \u00df\u00fctt\u00f6n {icon} \u00df\u00e9l\u00f6w t\u00f6 t\u00e4k\u00e9 \u00fd\u00f6\u00fcr ph\u00f6t\u00f6. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "Which timed transcript would you like to use?": "Wh\u00ef\u00e7h t\u00efm\u00e9d tr\u00e4ns\u00e7r\u00efpt w\u00f6\u00fcld \u00fd\u00f6\u00fc l\u00efk\u00e9 t\u00f6 \u00fcs\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", + "While our support team is happy to assist with the edX platform, the course staff has the expertise for specific assignment questions, grading or the proper procedures in each course. Please post all course related questions within the Discussion Forum where the Course Staff can directly respond.": "Wh\u00efl\u00e9 \u00f6\u00fcr s\u00fcpp\u00f6rt t\u00e9\u00e4m \u00efs h\u00e4pp\u00fd t\u00f6 \u00e4ss\u00efst w\u00efth th\u00e9 \u00e9dX pl\u00e4tf\u00f6rm, th\u00e9 \u00e7\u00f6\u00fcrs\u00e9 st\u00e4ff h\u00e4s th\u00e9 \u00e9xp\u00e9rt\u00efs\u00e9 f\u00f6r sp\u00e9\u00e7\u00eff\u00ef\u00e7 \u00e4ss\u00efgnm\u00e9nt q\u00fc\u00e9st\u00ef\u00f6ns, gr\u00e4d\u00efng \u00f6r th\u00e9 pr\u00f6p\u00e9r pr\u00f6\u00e7\u00e9d\u00fcr\u00e9s \u00efn \u00e9\u00e4\u00e7h \u00e7\u00f6\u00fcrs\u00e9. Pl\u00e9\u00e4s\u00e9 p\u00f6st \u00e4ll \u00e7\u00f6\u00fcrs\u00e9 r\u00e9l\u00e4t\u00e9d q\u00fc\u00e9st\u00ef\u00f6ns w\u00efth\u00efn th\u00e9 D\u00efs\u00e7\u00fcss\u00ef\u00f6n F\u00f6r\u00fcm wh\u00e9r\u00e9 th\u00e9 \u00c7\u00f6\u00fcrs\u00e9 St\u00e4ff \u00e7\u00e4n d\u00efr\u00e9\u00e7tl\u00fd r\u00e9sp\u00f6nd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142#", "Whole words": "Wh\u00f6l\u00e9 w\u00f6rds \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "Why activate?": "Wh\u00fd \u00e4\u00e7t\u00efv\u00e4t\u00e9? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "Why does %(platformName)s need my photo?": "Wh\u00fd d\u00f6\u00e9s %(platformName)s n\u00e9\u00e9d m\u00fd ph\u00f6t\u00f6? \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", @@ -2126,14 +2194,13 @@ "You must specify a name": "\u00dd\u00f6\u00fc m\u00fcst sp\u00e9\u00e7\u00eff\u00fd \u00e4 n\u00e4m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3#", "You must specify a name for the cohort": "\u00dd\u00f6\u00fc m\u00fcst sp\u00e9\u00e7\u00eff\u00fd \u00e4 n\u00e4m\u00e9 f\u00f6r th\u00e9 \u00e7\u00f6h\u00f6rt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u00dd\u00f6\u00fc m\u00fcst sp\u00e9\u00e7\u00eff\u00fd \u00fd\u00f6\u00fcr \u00df\u00efrth \u00fd\u00e9\u00e4r \u00df\u00e9f\u00f6r\u00e9 \u00fd\u00f6\u00fc \u00e7\u00e4n sh\u00e4r\u00e9 \u00fd\u00f6\u00fcr f\u00fcll pr\u00f6f\u00efl\u00e9. T\u00f6 sp\u00e9\u00e7\u00eff\u00fd \u00fd\u00f6\u00fcr \u00df\u00efrth \u00fd\u00e9\u00e4r, g\u00f6 t\u00f6 th\u00e9 {account_settings_page_link} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", - "You need a computer or cell phone that has a webcam. When you receive a browser prompt, make sure that you allow access to the camera.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4 \u00e7\u00f6mp\u00fct\u00e9r \u00f6r \u00e7\u00e9ll ph\u00f6n\u00e9 th\u00e4t h\u00e4s \u00e4 w\u00e9\u00df\u00e7\u00e4m. Wh\u00e9n \u00fd\u00f6\u00fc r\u00e9\u00e7\u00e9\u00efv\u00e9 \u00e4 \u00dfr\u00f6ws\u00e9r pr\u00f6mpt, m\u00e4k\u00e9 s\u00fcr\u00e9 th\u00e4t \u00fd\u00f6\u00fc \u00e4ll\u00f6w \u00e4\u00e7\u00e7\u00e9ss t\u00f6 th\u00e9 \u00e7\u00e4m\u00e9r\u00e4. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2\u03c5\u0142\u03c1\u03b1 q\u03c5\u03b9 \u03c3\u0192\u0192\u03b9\u00a2\u03b9\u03b1 \u2202\u0454\u0455\u0454\u044f\u03c5\u03b7\u0442 \u043c\u03c3\u0142\u0142\u03b9\u0442 \u03b1\u03b7\u03b9\u043c \u03b9\u2202 \u0454\u0455\u0442 \u0142\u03b1\u0432\u03c3\u044f\u03c5\u043c#", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4 dr\u00efv\u00e9r's l\u00ef\u00e7\u00e9ns\u00e9, p\u00e4ssp\u00f6rt, \u00f6r \u00f6th\u00e9r g\u00f6v\u00e9rnm\u00e9nt-\u00efss\u00fc\u00e9d \u00ccD th\u00e4t h\u00e4s \u00fd\u00f6\u00fcr n\u00e4m\u00e9 \u00e4nd ph\u00f6t\u00f6. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4n \u00ccD w\u00efth \u00fd\u00f6\u00fcr n\u00e4m\u00e9 \u00e4nd ph\u00f6t\u00f6. \u00c0 dr\u00efv\u00e9r's l\u00ef\u00e7\u00e9ns\u00e9, p\u00e4ssp\u00f6rt, \u00f6r \u00f6th\u00e9r g\u00f6v\u00e9rnm\u00e9nt-\u00efss\u00fc\u00e9d \u00ccDs \u00e4r\u00e9 \u00e4ll \u00e4\u00e7\u00e7\u00e9pt\u00e4\u00dfl\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", + "You need a device that has a webcam. If you receive a browser prompt for access to your camera, please make sure to click 'Allow'.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4 d\u00e9v\u00ef\u00e7\u00e9 th\u00e4t h\u00e4s \u00e4 w\u00e9\u00df\u00e7\u00e4m. \u00ccf \u00fd\u00f6\u00fc r\u00e9\u00e7\u00e9\u00efv\u00e9 \u00e4 \u00dfr\u00f6ws\u00e9r pr\u00f6mpt f\u00f6r \u00e4\u00e7\u00e7\u00e9ss t\u00f6 \u00fd\u00f6\u00fcr \u00e7\u00e4m\u00e9r\u00e4, pl\u00e9\u00e4s\u00e9 m\u00e4k\u00e9 s\u00fcr\u00e9 t\u00f6 \u00e7l\u00ef\u00e7k '\u00c0ll\u00f6w'. \u2c60'#", + "You need a valid ID that contains your full name and photo.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4 v\u00e4l\u00efd \u00ccD th\u00e4t \u00e7\u00f6nt\u00e4\u00efns \u00fd\u00f6\u00fcr f\u00fcll n\u00e4m\u00e9 \u00e4nd ph\u00f6t\u00f6. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", + "You need an ID with your name and photo. A driver's license, passport, or ID are all acceptable.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d \u00e4n \u00ccD w\u00efth \u00fd\u00f6\u00fcr n\u00e4m\u00e9 \u00e4nd ph\u00f6t\u00f6. \u00c0 dr\u00efv\u00e9r's l\u00ef\u00e7\u00e9ns\u00e9, p\u00e4ssp\u00f6rt, \u00f6r \u00ccD \u00e4r\u00e9 \u00e4ll \u00e4\u00e7\u00e7\u00e9pt\u00e4\u00dfl\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d t\u00f6 \u00e4\u00e7t\u00efv\u00e4t\u00e9 \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00df\u00e9f\u00f6r\u00e9 \u00fd\u00f6\u00fc \u00e7\u00e4n \u00e9nr\u00f6ll \u00efn \u00e7\u00f6\u00fcrs\u00e9s. \u00c7h\u00e9\u00e7k \u00fd\u00f6\u00fcr \u00efn\u00df\u00f6x f\u00f6r \u00e4n \u00e4\u00e7t\u00efv\u00e4t\u00ef\u00f6n \u00e9m\u00e4\u00efl. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u00dd\u00f6\u00fc n\u00e9\u00e9d t\u00f6 \u00e4\u00e7t\u00efv\u00e4t\u00e9 \u00fd\u00f6\u00fcr \u00e4\u00e7\u00e7\u00f6\u00fcnt \u00df\u00e9f\u00f6r\u00e9 \u00fd\u00f6\u00fc \u00e7\u00e4n \u00e9nr\u00f6ll \u00efn \u00e7\u00f6\u00fcrs\u00e9s. \u00c7h\u00e9\u00e7k \u00fd\u00f6\u00fcr \u00efn\u00df\u00f6x f\u00f6r \u00e4n \u00e4\u00e7t\u00efv\u00e4t\u00ef\u00f6n \u00e9m\u00e4\u00efl. \u00c0ft\u00e9r \u00fd\u00f6\u00fc \u00e7\u00f6mpl\u00e9t\u00e9 \u00e4\u00e7t\u00efv\u00e4t\u00ef\u00f6n \u00fd\u00f6\u00fc \u00e7\u00e4n r\u00e9t\u00fcrn \u00e4nd r\u00e9fr\u00e9sh th\u00efs p\u00e4g\u00e9. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1\u2202\u03b9\u03c1\u03b9\u0455\u03b9\u00a2\u03b9\u03b7g \u0454\u0142\u03b9\u0442, \u0455\u0454\u2202 \u2202\u03c3 \u0454\u03b9\u03c5\u0455\u043c\u03c3\u2202 \u0442\u0454\u043c\u03c1\u03c3\u044f \u03b9\u03b7\u00a2\u03b9\u2202\u03b9\u2202\u03c5\u03b7\u0442 \u03c5\u0442 \u0142\u03b1\u0432\u03c3\u044f\u0454 \u0454\u0442 \u2202\u03c3\u0142\u03c3\u044f\u0454 \u043c\u03b1g\u03b7\u03b1 \u03b1\u0142\u03b9q\u03c5\u03b1. \u03c5\u0442 \u0454\u03b7\u03b9\u043c \u03b1\u2202 \u043c\u03b9\u03b7\u03b9\u043c \u03bd\u0454\u03b7\u03b9\u03b1\u043c, q\u03c5\u03b9\u0455 \u03b7\u03c3\u0455\u0442\u044f\u03c5\u2202 \u0454\u03c7\u0454\u044f\u00a2\u03b9\u0442\u03b1\u0442\u03b9\u03c3\u03b7 \u03c5\u0142\u0142\u03b1\u043c\u00a2\u03c3 \u0142\u03b1\u0432\u03c3\u044f\u03b9\u0455 \u03b7\u03b9\u0455\u03b9 \u03c5\u0442 \u03b1\u0142\u03b9q\u03c5\u03b9\u03c1 \u0454\u03c7 \u0454\u03b1 \u00a2\u03c3\u043c\u043c\u03c3\u2202\u03c3 \u00a2\u03c3\u03b7\u0455\u0454q\u03c5\u03b1\u0442. \u2202\u03c5\u03b9\u0455 \u03b1\u03c5\u0442\u0454 \u03b9\u044f\u03c5\u044f\u0454 \u2202\u03c3\u0142\u03c3\u044f \u03b9\u03b7 \u044f\u0454\u03c1\u044f\u0454\u043d\u0454\u03b7\u2202\u0454\u044f\u03b9\u0442 \u03b9\u03b7 \u03bd\u03c3\u0142\u03c5\u03c1\u0442\u03b1\u0442\u0454 \u03bd\u0454\u0142\u03b9\u0442 \u0454\u0455\u0455\u0454 \u00a2\u03b9\u0142\u0142\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f\u0454 \u0454\u03c5 \u0192\u03c5g\u03b9\u03b1\u0442 \u03b7\u03c5\u0142\u0142\u03b1 \u03c1\u03b1\u044f\u03b9\u03b1\u0442\u03c5\u044f. \u0454\u03c7\u00a2\u0454\u03c1\u0442\u0454\u03c5\u044f \u0455\u03b9\u03b7\u0442 \u03c3\u00a2\u00a2\u03b1\u0454\u00a2\u03b1\u0442 \u00a2\u03c5\u03c1\u03b9\u2202\u03b1\u0442\u03b1\u0442 \u03b7\u03c3\u03b7 \u03c1\u044f\u03c3\u03b9\u2202\u0454\u03b7\u0442, \u0455\u03c5\u03b7\u0442 \u03b9\u03b7 \u00a2#", "You receive messages from {platform_name} and course teams at this address.": "\u00dd\u00f6\u00fc r\u00e9\u00e7\u00e9\u00efv\u00e9 m\u00e9ss\u00e4g\u00e9s fr\u00f6m {platform_name} \u00e4nd \u00e7\u00f6\u00fcrs\u00e9 t\u00e9\u00e4ms \u00e4t th\u00efs \u00e4ddr\u00e9ss. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "You reserve all rights for your work": "\u00dd\u00f6\u00fc r\u00e9s\u00e9rv\u00e9 \u00e4ll r\u00efghts f\u00f6r \u00fd\u00f6\u00fcr w\u00f6rk \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5#", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u00dd\u00f6\u00fc st\u00efll n\u00e9\u00e9d t\u00f6 v\u00efs\u00eft th\u00e9 %(display_name)s w\u00e9\u00dfs\u00eft\u00e9 t\u00f6 \u00e7\u00f6mpl\u00e9t\u00e9 th\u00e9 \u00e7r\u00e9d\u00eft pr\u00f6\u00e7\u00e9ss. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "You submitted {filename}; only {allowedFiles} are allowed.": "\u00dd\u00f6\u00fc s\u00fc\u00dfm\u00eftt\u00e9d {filename}; \u00f6nl\u00fd {allowedFiles} \u00e4r\u00e9 \u00e4ll\u00f6w\u00e9d. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f#", "You waive some rights for your work, such that others can use it too": "\u00dd\u00f6\u00fc w\u00e4\u00efv\u00e9 s\u00f6m\u00e9 r\u00efghts f\u00f6r \u00fd\u00f6\u00fcr w\u00f6rk, s\u00fc\u00e7h th\u00e4t \u00f6th\u00e9rs \u00e7\u00e4n \u00fcs\u00e9 \u00eft t\u00f6\u00f6 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "You will be refunded the amount you paid.": "\u00dd\u00f6\u00fc w\u00efll \u00df\u00e9 r\u00e9f\u00fcnd\u00e9d th\u00e9 \u00e4m\u00f6\u00fcnt \u00fd\u00f6\u00fc p\u00e4\u00efd. \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", @@ -2202,6 +2269,7 @@ "and others": "\u00e4nd \u00f6th\u00e9rs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "anonymous": "\u00e4n\u00f6n\u00fdm\u00f6\u00fcs \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "answer": "\u00e4nsw\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", + "answered question": "\u00e4nsw\u00e9r\u00e9d q\u00fc\u00e9st\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "asset_path is required": "\u00e4ss\u00e9t_p\u00e4th \u00efs r\u00e9q\u00fc\u00efr\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "bytes": "\u00df\u00fdt\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "certificate": "\u00e7\u00e9rt\u00eff\u00ef\u00e7\u00e4t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", @@ -2213,6 +2281,8 @@ "delete chapter": "d\u00e9l\u00e9t\u00e9 \u00e7h\u00e4pt\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "delete group": "d\u00e9l\u00e9t\u00e9 gr\u00f6\u00fcp \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", "details about the failure": "d\u00e9t\u00e4\u00efls \u00e4\u00df\u00f6\u00fct th\u00e9 f\u00e4\u00efl\u00fcr\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", + "discussion": "d\u00efs\u00e7\u00fcss\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", + "discussion posted %(time_ago)s by %(author)s": "d\u00efs\u00e7\u00fcss\u00ef\u00f6n p\u00f6st\u00e9d %(time_ago)s \u00df\u00fd %(author)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", "dragging": "dr\u00e4gg\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202#", "dragging out of slider": "dr\u00e4gg\u00efng \u00f6\u00fct \u00f6f sl\u00efd\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2#", "dropped in slider": "dr\u00f6pp\u00e9d \u00efn sl\u00efd\u00e9r \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", @@ -2222,15 +2292,19 @@ "e.g. 'http://google.com'": "\u00e9.g. 'http://g\u00f6\u00f6gl\u00e9.\u00e7\u00f6m' \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "e.g. johndoe@example.com, JaneDoe, joeydoe@example.com": "\u00e9.g. j\u00f6hnd\u00f6\u00e9@\u00e9x\u00e4mpl\u00e9.\u00e7\u00f6m, J\u00e4n\u00e9D\u00f6\u00e9, j\u00f6\u00e9\u00fdd\u00f6\u00e9@\u00e9x\u00e4mpl\u00e9.\u00e7\u00f6m \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "emphasized text": "\u00e9mph\u00e4s\u00efz\u00e9d t\u00e9xt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", + "endorsed %(time_ago)s": "\u00e9nd\u00f6rs\u00e9d %(time_ago)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", + "endorsed %(time_ago)s by %(user)s": "\u00e9nd\u00f6rs\u00e9d %(time_ago)s \u00df\u00fd %(user)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "enter code here": "\u00e9nt\u00e9r \u00e7\u00f6d\u00e9 h\u00e9r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "enter link description here": "\u00e9nt\u00e9r l\u00efnk d\u00e9s\u00e7r\u00efpt\u00ef\u00f6n h\u00e9r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", + "follow this post": "f\u00f6ll\u00f6w th\u00efs p\u00f6st \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", "for": "f\u00f6r \u2c60'\u03c3\u044f\u0454\u043c#", - "for {courseName}": "f\u00f6r {courseName} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "group configuration": "gr\u00f6\u00fcp \u00e7\u00f6nf\u00efg\u00fcr\u00e4t\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "image omitted": "\u00efm\u00e4g\u00e9 \u00f6m\u00eftt\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "incorrect": "\u00efn\u00e7\u00f6rr\u00e9\u00e7t \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142#", "last activity": "l\u00e4st \u00e4\u00e7t\u00efv\u00eft\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "less than a minute": "l\u00e9ss th\u00e4n \u00e4 m\u00efn\u00fct\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", + "marked as answer %(time_ago)s": "m\u00e4rk\u00e9d \u00e4s \u00e4nsw\u00e9r %(time_ago)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", + "marked as answer %(time_ago)s by %(user)s": "m\u00e4rk\u00e9d \u00e4s \u00e4nsw\u00e9r %(time_ago)s \u00df\u00fd %(user)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "minute": "m\u00efn\u00fct\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "minutes": "m\u00efn\u00fct\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "name": "n\u00e4m\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", @@ -2248,9 +2322,13 @@ "or create a new one here": "\u00f6r \u00e7r\u00e9\u00e4t\u00e9 \u00e4 n\u00e9w \u00f6n\u00e9 h\u00e9r\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7#", "or sign in with": "\u00f6r s\u00efgn \u00efn w\u00efth \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1#", "path/to/introductionToCookieBaking-CH{order}.pdf": "p\u00e4th/t\u00f6/\u00efntr\u00f6d\u00fc\u00e7t\u00ef\u00f6nT\u00f6\u00c7\u00f6\u00f6k\u00ef\u00e9B\u00e4k\u00efng-\u00c7H{order}.pdf \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", + "post anonymously": "p\u00f6st \u00e4n\u00f6n\u00fdm\u00f6\u00fcsl\u00fd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c#", + "post anonymously to classmates": "p\u00f6st \u00e4n\u00f6n\u00fdm\u00f6\u00fcsl\u00fd t\u00f6 \u00e7l\u00e4ssm\u00e4t\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442#", + "posted %(time_ago)s by %(author)s": "p\u00f6st\u00e9d %(time_ago)s \u00df\u00fd %(author)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454#", "price": "pr\u00ef\u00e7\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455#", "provide the title/name of the chapter that will be used in navigating": "pr\u00f6v\u00efd\u00e9 th\u00e9 t\u00eftl\u00e9/n\u00e4m\u00e9 \u00f6f th\u00e9 \u00e7h\u00e4pt\u00e9r th\u00e4t w\u00efll \u00df\u00e9 \u00fcs\u00e9d \u00efn n\u00e4v\u00efg\u00e4t\u00efng \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f #", "provide the title/name of the text book as you would like your students to see it": "pr\u00f6v\u00efd\u00e9 th\u00e9 t\u00eftl\u00e9/n\u00e4m\u00e9 \u00f6f th\u00e9 t\u00e9xt \u00df\u00f6\u00f6k \u00e4s \u00fd\u00f6\u00fc w\u00f6\u00fcld l\u00efk\u00e9 \u00fd\u00f6\u00fcr st\u00fcd\u00e9nts t\u00f6 s\u00e9\u00e9 \u00eft \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454#", + "question posted %(time_ago)s by %(author)s": "q\u00fc\u00e9st\u00ef\u00f6n p\u00f6st\u00e9d %(time_ago)s \u00df\u00fd %(author)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455#", "remove": "r\u00e9m\u00f6v\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", "remove all": "r\u00e9m\u00f6v\u00e9 \u00e4ll \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "second": "s\u00e9\u00e7\u00f6nd \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5#", @@ -2262,6 +2340,7 @@ "team count": "t\u00e9\u00e4m \u00e7\u00f6\u00fcnt \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3#", "text_word_{uniqueId}": "t\u00e9xt_w\u00f6rd_{uniqueId} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9#", "text_word_{uniqueId} title_word_{uniqueId}": "t\u00e9xt_w\u00f6rd_{uniqueId} t\u00eftl\u00e9_w\u00f6rd_{uniqueId} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#", + "the more quickly and helpfully we can respond!": "th\u00e9 m\u00f6r\u00e9 q\u00fc\u00ef\u00e7kl\u00fd \u00e4nd h\u00e9lpf\u00fcll\u00fd w\u00e9 \u00e7\u00e4n r\u00e9sp\u00f6nd! \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", "there is currently {numVotes} vote": [ "th\u00e9r\u00e9 \u00efs \u00e7\u00fcrr\u00e9ntl\u00fd {numVotes} v\u00f6t\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454#", "th\u00e9r\u00e9 \u00e4r\u00e9 \u00e7\u00fcrr\u00e9ntl\u00fd {numVotes} v\u00f6t\u00e9s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2#" @@ -2269,6 +2348,7 @@ "title_word_{uniqueId}": "t\u00eftl\u00e9_w\u00f6rd_{uniqueId} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442#", "toggle chapter %(displayName)s": "t\u00f6ggl\u00e9 \u00e7h\u00e4pt\u00e9r %(displayName)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442#", "toggle subsection %(displayName)s": "t\u00f6ggl\u00e9 s\u00fc\u00dfs\u00e9\u00e7t\u00ef\u00f6n %(displayName)s \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, #", + "unanswered question": "\u00fcn\u00e4nsw\u00e9r\u00e9d q\u00fc\u00e9st\u00ef\u00f6n \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442,#", "unit": "\u00fcn\u00eft \u2c60'\u03c3\u044f\u0454\u043c \u03b9#", "unsubmitted": "\u00fcns\u00fc\u00dfm\u00eftt\u00e9d \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "upload a PDF file or provide the path to a Studio asset file": "\u00fcpl\u00f6\u00e4d \u00e4 PDF f\u00efl\u00e9 \u00f6r pr\u00f6v\u00efd\u00e9 th\u00e9 p\u00e4th t\u00f6 \u00e4 St\u00fcd\u00ef\u00f6 \u00e4ss\u00e9t f\u00efl\u00e9 \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455\u03b9\u0442 \u03b1\u043c\u0454\u0442, \u00a2\u03c3\u03b7\u0455\u0454\u00a2\u0442\u0454\u0442\u03c5\u044f \u03b1#", @@ -2365,6 +2445,7 @@ ], "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}": "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension} \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f #", "{type} Progress": "{type} Pr\u00f6gr\u00e9ss \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c \u2202\u03c3\u0142\u03c3\u044f \u0455#", + "{unread_comments_count} new": "{unread_comments_count} n\u00e9w \u2c60'\u03c3\u044f\u0454\u043c \u03b9\u03c1\u0455\u03c5\u043c #", "\u2026": "\u2026 \u2c60#" }; for (var key in newcatalog) { @@ -2387,7 +2468,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2449,9 +2530,9 @@ "%d %m %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j\\-\\a \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "Y-m-d H:i", "SHORT_DATE_FORMAT": "Y-m-d", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/es-419/djangojs.js b/lms/static/js/i18n/es-419/djangojs.js index e0708b61b6b15a2fe399db50686b8dc9bab33b85..ef7c05993bdf67c3672eb14e9e8ba3c1ee614ec0 100644 --- a/lms/static/js/i18n/es-419/djangojs.js +++ b/lms/static/js/i18n/es-419/djangojs.js @@ -96,10 +96,15 @@ " ${price} {currency} )": " ${price} {currency} )", " From this point in time, you must follow the <a href=\"%(link_urls.online_proctoring_rules)s\" target=\"_blank\">online proctoring rules</a> to pass the proctoring review for your exam. ": "A partir de este momento, debe seguir las <a href=\"%(link_urls.online_proctoring_rules)s\" target=\"_blank\">reglas de supervisi\u00f3n online</a> para aprobar la revisi\u00f3n de la supervisi\u00f3n para su examen.", " Link": "Enlace", + " Member": [ + "Miembro", + "Miembros" + ], " Your Proctoring Session Has Started ": "Su Sesi\u00f3n Supervisada Ha Comenzado", " and ": "y", " and {num_of_minutes} minute": "y {num_of_minutes} minuto", " and {num_of_minutes} minutes": "y {num_of_minutes} minutos", + " as many questions may have already been answered.": "ya que muchas preguntas comunes pueden ya haber sido respondidas.", " learner does not exist in LMS and not added to the exception list": "estudiante no existe en el LMS y no se a\u00f1adi\u00f3 a la lista de excepciones", " learner is already white listed and not added to the exception list": "el estudiante ya est\u00e1 en la lista blanca y no se a\u00f1adi\u00f3 a las excepciones", " learner is not enrolled in course and not added to the exception list": "el estudiante no est\u00e1 inscrito en el curso y no se a\u00f1adi\u00f3 a la lista de excepciones", @@ -113,6 +118,8 @@ " to complete and submit the exam.": "para completar y enviar el examen.", "${listPrice}": "${listPrice}", "%(cohort_name)s (%(user_count)s)": "%(cohort_name)s (%(user_count)s)", + "%(comments_count)s %(span_sr_open)scomments %(span_close)s": "%(comments_count)s %(span_sr_open)s comentarios %(span_close)s", + "%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s unread comments)%(span_close)s": "%(comments_count)s %(span_sr_open)s comentarios (%(unread_comments_count)s comentarios no le\u00eddos)%(span_close)s", "%(errorCount)s error found in form.": [ "%(errorCount)s error en el formulario.", "%(errorCount)s errores en el formulario." @@ -158,6 +165,7 @@ "%s from now": "%s a partir de ahora", "(Add signatories for a certificate)": "(A\u00f1adir signatarios para el certificado)", "(Caption will be displayed when you start playing the video.)": "(Los subt\u00edtulos ser\u00e1n mostrados al iniciar la reproducci\u00f3n del video.)", + "(Community TA)": "(Profesor ayudante de la comunidad)", "(Optional)": "(Opcional)", "(Read-only)": "(Solo-lectura)", "(Required Field)": "(Campo requerido)", @@ -165,6 +173,7 @@ "(Self-paced) Ends {end}": "(A ritmo propio)Termina{end}", "(Self-paced) Started {start}": "(A ritmo propio) Empezado {start}", "(Self-paced) Starts {start}": "(A su propio ritmo) Empieza {start}", + "(Staff)": "(Equipo del curso)", "(contains %(student_count)s student)": [ "(contiene %(student_count)s estudiante)", "(contiene %(student_count)s estudiantes)" @@ -226,7 +235,12 @@ "Add URLs for additional versions": "A\u00f1ada URLs para las versiones adicionales", "Add a Chapter": "A\u00f1adir cap\u00edtulo", "Add a New Cohort": "A\u00f1adir NuevaCohorte", + "Add a Post": "A\u00f1ade una publicaci\u00f3n", + "Add a Response": "A\u00f1ade una respuesta", + "Add a clear and descriptive title to encourage participation. (Required)": "Agrega un t\u00edtulo claro y descriptivo para fomentar la participaci\u00f3n. (Requerido)", + "Add a comment": "A\u00f1ade un comentario", "Add a learning outcome here": "Agregar Resultado de aprendizaje", + "Add a response:": "A\u00f1ade tu respuesta:", "Add another group": "A\u00f1adir nuevo grupo", "Add language": "A\u00f1adir idioma", "Add learners to this cohort": "Agregar estudiantes a este cohorte", @@ -236,6 +250,7 @@ "Add your first content group": "Agrege su primer grupo de contenido", "Add your first group configuration": "Agregue su primera configuraci\u00f3n de grupo", "Add your first textbook": "A\u00f1ada su primer libro de texto", + "Add your post to a relevant topic to help others find it. (Required)": "A\u00f1ade tu publicaci\u00f3n a un tema relevante para que los dem\u00e1s la puedan encontrar. (Requerido)", "Add {role} Access": "A\u00f1adir permisos de {role}", "Adding": "A\u00f1adiendo", "Adding the selected course to your cart": "A\u00f1adiendo el curso seleccionado a tu carrito de compras", @@ -256,6 +271,7 @@ "Align left": "Alienar a la izquierda", "Align right": "Alinear a la derecha", "Alignment": "Alinear a la", + "All Groups": "Todos los grupos", "All Learners and Staff": "Todos los estudiantes y equipo del curso", "All Posts": "Todas las publicaciones", "All Rights Reserved": "Todos los derechos reservados", @@ -308,6 +324,7 @@ "An error occurred. Please reload the page.": "Ocurri\u00f3 un error. Por favor recargue la p\u00e1gina.", "An error occurred. Please try again.": "Ocurri\u00f3 un error. Por favor, intenta nuevamente.", "An error occurred. Try again.": "Ocurri\u00f3 un error. Intenta nuevamente.", + "An unexpected error has occurred.": "Ha ocurrido un error inesperado.", "An unexpected error occurred. Please try again.": "Se produjo un error inesperado. Por favor, int\u00e9ntalo nuevamente.", "Anchor": "Ancla", "Anchors": "Anclas", @@ -319,6 +336,7 @@ "Are you having trouble finding a team to join?": "\u00bfTiene problemas para encontrar un equipo al cual unirse?", "Are you sure that you want to leave this session?": "\u00bf Est\u00e1 seguro de que quiere salir de esta sesi\u00f3n?", "Are you sure you want to change to a different session?": "\u00bfEst\u00e1 seguro de que quiere cambiar a una sesi\u00f3n diferente?", + "Are you sure you want to delete the following file? It cannot be restored.\nFile: ": "\u00bfEst\u00e1s seguro de que desea eliminar el siguiente archivo? No puede ser restaurado.\nArchivo:", "Are you sure you want to delete this comment?": "\u00bfEst\u00e1s seguro de que deseas borrar este comentario?", "Are you sure you want to delete this page? This action cannot be undone.": "\u00bfEst\u00e1s seguro de que deseas borrar esta p\u00e1gina? Esta acci\u00f3n no se puede deshacer.", "Are you sure you want to delete this post?": "\u00bfEst\u00e1s seguro de que deseas borrar esta publicaci\u00f3n?", @@ -339,10 +357,12 @@ "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "\u00bfEst\u00e1 seguro de que desea borrar este \u00edtem?. \u00a1Esta acci\u00f3n no puede revertirse!\n\nCualquier contenido que haga referencia a este \u00edtem dejar\u00e1 de funcionar (im\u00e1genes o v\u00ednculos)", "Are you sure?": "\u00bfEst\u00e1 seguro?", "As part of the verification process, you take a photo of both your face and a government-issued photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "Como parte del proceso de verificaci\u00f3n, usted debe tomar una foto de su cara y de su documento de identidad. Nuestro servicio de autorizaci\u00f3n confirmar\u00e1 su identidad comparando la foto que usted se toma con la foto en su documento.", + "As part of the verification process, you take a photo of both your face and a photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "Como parte del proceso de verificaci\u00f3n, usted tomar\u00e1 una foto de su cara y de su documento de identificaci\u00f3n con foto. Nuestro servicio de autorizaci\u00f3n confirma su identidad comparando la foto que toma con la foto en su identificaci\u00f3n.", "As you complete courses, you will see them listed here.": "Mientras completas cursos, los ver\u00e1s enumerados aqu\u00ed.", "Assessment": "Evaluaci\u00f3n", "Assessment Results Visibility": "Visibilidad de los resultados de la evaluaci\u00f3n", "Assessments": "Evaluaciones", + "Assign Team Memberships": "Asignar membres\u00edas de equipo", "Assign learners to cohorts by uploading a CSV file": "Asignar estudiantes a cohortes subiendo un archivo CSV", "Assign students to cohorts by uploading a CSV file.": "Asignar estudiantes al cohorte cargando un archivo CSV.", "Assignment Type Name": "Nombre del tipo de tarea", @@ -402,6 +422,7 @@ "Cannot delete when in use by a unit": "No puede borrar cuando esta en uso por una unidad", "Cannot delete when in use by an experiment": "No se puede borrar mientras est\u00e9 en uso por un experimento", "Cannot drop more <%= types %> assignments than are assigned.": "No se pueden borrar m\u00e1s asignaciones de <%= types %> de los que son asignados.", + "Cannot join instructor managed team": "No se puede unir al equipo administrado por el instructor", "Caption": "Leyenda", "Caution: The last published version of this unit is live. By publishing changes you will change the student experience.": "Atenci\u00f3n: La \u00faltima versi\u00f3n publicada de esta unidad est\u00e1 en vivo. Al publicar los cambios, cambiar\u00e1 la experiencia de los estudiantes.", "Cell": "Celda", @@ -481,6 +502,7 @@ "Click to remove all chosen %s at once.": "Haz clic para eliminar todos los %s elegidos", "Close": "Cerrar", "Close Calculator": "Cerrar Calculadora", + "Closed": "Cerrado", "Code": "C\u00f3digo", "Code Sample (Ctrl+K)": "C\u00f3digo (Ctrl+K)", "Code block": "Bloque de c\u00f3digo", @@ -499,6 +521,7 @@ "Coming Soon": "Pr\u00f3ximamente", "Commentary": "Comentario", "Common Problem Types": "Tipos de problemas comunes", + "Community TA": "Profesor asistente de la comunidad", "Complete courses on your schedule to ensure you stand out in your field!": "\u00a1Complete cursos seg\u00fan tu horario para asegurar que sobresalgas en tu disciplina!", "Completed": "Finalizado", "Component": "Componente", @@ -524,6 +547,7 @@ "Continue to my practice exam": "Continuar a mi examen de pr\u00e1ctica", "Continue to my proctored exam. I want to be eligible for credit.": "Continuar a mi examen supervisado. Quiero ser elegible para cr\u00e9dito.", "Copy": "Copiar", + "Copy Component Location": "Copiar la ubicaci\u00f3n del Componente", "Copy Email To Editor": "Copiar el correo al editor", "Copy row": "Copiar la fila", "Correct failed component": "Corregir componente fallido", @@ -534,6 +558,7 @@ "Could not find the specified string.": "No se encontr\u00f3 la cadena especificada.", "Could not find users associated with the following identifiers:": "No se puede encontrar el usuario asociado al siguiente identificador:", "Could not grade your answer. The submission was aborted.": "No se ha podido calificar tu respuesta. El registro fue cancelado.", + "Could not load teams information.": "No se pudo cargar la informaci\u00f3n de los equipos.", "Could not override problem score for {user}.": "No fue posible sobreescribir el puntaje del problema para el usuario {user}.", "Could not retrieve download url.": "No se pudo recuperar la url de descarga.", "Could not retrieve payment information": "No se pudo conseguir la informaci\u00f3n del pago", @@ -551,6 +576,7 @@ ], "Course Content": "Contenidos del curso", "Course Credit Requirements": "Requerimientos de cr\u00e9ditos para el curso", + "Course Discussion Forum": "Foro de discusi\u00f3n del curso", "Course End": "Finalizaci\u00f3n del curso", "Course Handouts": "Materiales del curso", "Course ID": "Id de Curso", @@ -562,6 +588,7 @@ "Course Number Override": "Reemplazo para el n\u00famero de curso", "Course Number:": "N\u00famero del curso:", "Course Outline": "Estructura del curso", + "Course Run:": "Edici\u00f3n del Curso:", "Course Start": "Inicio del Curso", "Course Title": "T\u00edtulo del curso", "Course Title Override": "Reemplazo para el t\u00edtulo del curso", @@ -573,9 +600,11 @@ "Create": "Crear", "Create Account": "Crear cuenta", "Create Re-run": "Crear reapertura", + "Create Support Ticket": "Crear caso de soporte", "Create a New Team": "Crear un nuevo equipo", "Create a content group": "Crear contenido de grupo", "Create a new team if you can't find an existing team to join, or if you would like to learn with friends you know.": "Crea un nuevo equipo si no puedes encontrar uno existente para unirte o si deseas aprender con personas que ya conoces.", + "Create a {link_start}Mozilla Backpack{link_end} account, or log in to your existing account": "Crear una {link_start}cuenta en Mozilla Backpack{link_end} o iniciar sesi\u00f3n en una cuenta existente.", "Create account using %(providerName)s.": "Crear una cuenta usando %(providerName)s", "Create an Account": "Crear una cuenta", "Create an Account.": "Crear una cuenta.", @@ -612,7 +641,6 @@ "Default (Local Time Zone)": "Por defecto (Zona horaria local)", "Default Timed Transcript": "Transcripci\u00f3n con tiempos por defecto", "Delete": "Borrar", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u00bfDesea borrar \"<%= signatoryName %>\" de la lista de signatarios?", "Delete File Confirmation": "Confirmaci\u00f3n de borrado de archivo", "Delete My Account": "Eliminar mi cuenta", "Delete Page Confirmation": "Confirmaci\u00f3n de eliminaci\u00f3n de p\u00e1gina", @@ -627,9 +655,11 @@ "Delete this team?": "\u00bfBorrar este equipo?", "Delete this {xblock_type} (and prerequisite)?": "\u00bfEliminar este {xblock_type} (y prerrequisitos)?", "Delete this {xblock_type}?": "\u00bfEliminar este {xblock_type}?", + "Delete \u201c<%- name %>\u201d?": "Eliminar \u201c<%- name %>\u201d?", "Deleted Content Group": "Contenido de grupo eliminado", "Deleted Group": "Grupo eliminado", "Deleting": "Borrando", + "Deleting a team is permanent and cannot be undone.All members are removed from the team, and team discussions can no longer be accessed.": "Borrar un equipo es una acci\u00f3n permanente y no puede ser revertida. Todos los miembros son removidos del equipo, y las discusiones creadas en el equipo no pueden ser accedidas de nuevo.", "Deleting a textbook cannot be undone and once deleted any reference to it in your courseware's navigation will also be removed.": "El borrado de un libro de texto no se puede deshacer y una vez borrado, cualquier referencia al mismo en la navegaci\u00f3n del curso ser\u00e1 eliminada.", "Deleting this %(item_display_name)s is permanent and cannot be undone.": "Eliminar %(item_display_name)s is permanente y no puede deshacerse", "Deleting this {xblock_type} is permanent and cannot be undone.": "Eliminar este {xblock_type} es una acci\u00f3n permanente y no se puede revertir.", @@ -638,11 +668,14 @@ "Description": "Descripci\u00f3n", "Description of the certificate": "Descripci\u00f3n del certificado", "Details": "Detalles", + "Device with Camera": "Dispositivo con c\u00e1mara", "Dimensions": "Dimensiones", "Disc": "Disco", "Discard Changes": "Descartar cambios", "Discarding Changes": "Descartando cambios", + "Discussion": "Discusi\u00f3n", "Discussion Home": "Inicio de la discusi\u00f3n", + "Discussion admins, moderators, and TAs can make their posts visible to all students or specify a single group.": "Los administradores de la discusi\u00f3n, moderadores, y profesores asociados pueden hacer sus publicaciones visibles a todos los estudiantes o especificar un grupo en particular.", "Discussion topics in the course are not divided.": "Temas de discusi\u00f3n en el curso no son divididos.", "Discussions are unified; all learners interact with posts from other learners, regardless of the group they are in.": "Las discusiones son unificadas; todos los estudiantes interact\u00faan con publicaciones de otros estudiantes, sin considerar su grupo.", "Display Name": "Nombre para mostrar:", @@ -655,13 +688,13 @@ "Do you want to upload your file before submitting?": "Quieres subir tu archivo antes de enviarlo ?", "Document properties": "Propiedades del documento", "Does the name on your ID match your account name: %(fullName)s?": "\u00bfCorresponde el nombre en su identificaci\u00f3n con el nombre es su cuenta: %(fullName)s?", - "Does the photo of you match your ID photo?": "\u00bfSu foto corresponde a la foto en su identificaci\u00f3n?", "Does the photo of you show your whole face?": "\u00bfMuestra la foto su cara completa?", "Doing so means that you are no longer eligible for academic credit.": "Hacer esto significa que ya no ser\u00e1 elegible para cr\u00e9dito acad\u00e9mico.", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u00bfNo puede ver su foto? Aseg\u00farese de permitir a su navegador que utilice la c\u00e1mara web cuando este le solicite tal autorizaci\u00f3n.", "Donate": "Donar", "Double-check that your webcam is connected and working to continue.": "Verifica que tu c\u00e1mara web est\u00e9 conectada y funcionando para continuar.", "Download": "Descargar", + "Download Memberships": "Descargar membres\u00edas", "Download Software Clicked": "'Descargar aplicaci\u00f3n' seleccionado", "Download Transcript for Editing": "Descargar Transcripci\u00f3n para editar", "Download URL": "URL de descarga", @@ -677,6 +710,7 @@ "Due Date:": "Fecha l\u00edmite:", "Due Time in UTC:": "Hora l\u00edmite en UTC:", "Due date cannot be before start date.": "Fecha l\u00edmite no puede ser menor al a fecha de inicio.", + "Due to the recent increase in interest in online education and edX, we are currently experiencing an unusually high volume of support requests. We appreciate your patience as we work to review each request. Please check the ": "Debido al reciente aumento en el inter\u00e9s en la educaci\u00f3n en l\u00ednea y en edX, actualmente estamos experimentando un volumen inusualmente alto de solicitudes de soporte. Agradecemos su paciencia mientras trabajamos para revisar cada solicitud. Por favor, consulte el", "Due:": "Fecha de entrega:", "Duplicate": "Duplicar", "Duplicating": "Duplicando", @@ -693,9 +727,15 @@ "Edit Membership": "Editar membres\u00eda", "Edit Team": "Editar Equipo", "Edit Thumbnail": "Editar imagen miniatura", + "Edit Title": "Editar t\u00edtulo", "Edit Your Name": "Edite su nombre", "Edit this certificate?": "\u00bfEditar este certificado?", + "Edit your post below.": "Edita tu publicaci\u00f3n a continuaci\u00f3n.", "Editable": "Editable", + "Editing access for: {title}": "Editando acceso para: {title}", + "Editing comment": "Editando comentario", + "Editing post": "Editando publicaci\u00f3n", + "Editing response": "Editando respuesta", "Editing: {title}": "Edici\u00f3n: {title}", "Editor": "Editor", "Education Completed": "Educaci\u00f3n completada", @@ -713,6 +753,7 @@ "Encoding": "Codificaci\u00f3n", "End My Exam": "Finalizar mi examen", "End of transcript. Skip to the start.": "Fin de la transcripci\u00f3n. Saltar al inicio.", + "Endorse": "Validar", "Ends {end}": "Termina {end}", "Engage with posts": "Trabajar con las publicaciones", "Enroll Now": "Incr\u00edbase ahora", @@ -747,6 +788,7 @@ "Error adding learners.": "Error para agregar estudiantes.", "Error adding user": "Error al a\u00f1adir el usuario.", "Error adding/removing users as beta testers.": "Error a\u00f1adiendo o eliminando usuarios de pruebas.", + "Error assigning team memberships": "Error al asignar membres\u00edas de equipo", "Error changing user's permissions.": "Error al cambiar los permisos del usuario.", "Error deleting entrance exam state for student '{student_id}'. Make sure student identifier is correct.": "Error borrando el estado del examen de ingreso para el estudiante '{student_id}'. Aseg\u00farate que el identificador del estudiante es correcto.", "Error deleting student '<%- student_id %>'s state on problem '<%- problem_id %>'. Make sure that the problem and student identifiers are complete and correct.": "Error al borrar el estado del estudiante '<%- student_id %>' para el problema '<%- problem_id %>'. Verifica que el problema y el estudiante est\u00e9n identificados correctamente.", @@ -767,6 +809,7 @@ "Error getting the number of ungraded responses": "Error al obtener el n\u00famero de respuestas no calificadas.", "Error importing course": "Error al importar el curso", "Error listing task history for this student and problem.": "Error listando el historial de tareas para este estudiante y problema.", + "Error posting your message.": "Error al publicar tu mensaje.", "Error removing user": "Error al remover el usuario.", "Error resetting entrance exam attempts for student '{student_id}'. Make sure student identifier is correct.": "Error reiniciando los intentos de examen de ingreso para el estudiante '{student_id}'. Aseg\u00farate que el identificador es correcto.", "Error resetting problem attempts for problem '<%= problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "Error al reiniciar los env\u00edos para el problema '<%= problem_id %>' y estudiante '<%- student_id %>'. Aseg\u00farate de que los identificadores del problema y el estudiante est\u00e9n completos y correctos.", @@ -777,6 +820,7 @@ "Error starting a task to rescore problem '<%- problem_id %>' for student '<%- student_id %>'. Make sure that the the problem and student identifiers are complete and correct.": "Error al iniciar el proceso de re puntuaci\u00f3n del problema '<%- problem_id %>' para el estudiante '<%- student_id %>'. Verifica que el problema y el estudiante est\u00e9n identificados correctamente.", "Error starting a task to rescore problem '<%- problem_id %>'. Make sure that the problem identifier is complete and correct.": "Error al iniciar la tarea para re puntuar el problema '<%- problem_id %>'. Verifica que el problema est\u00e9 identificado correctamente.", "Error starting a task to reset attempts for all students on problem '<%- problem_id %>'. Make sure that the problem identifier is complete and correct.": "Error en el proceso de reinicio de env\u00edos para todos los estudiantes para el problema '<%- problem_id %>'. Verifica que el problema est\u00e9 identificado correctamente.", + "Error when looking up username": "Error al buscar el nombre de usuario", "Error while generating certificates. Please try again.": "Error al generar los certificados. Por favor intenta nuevamente.", "Error while regenerating certificates. Please try again.": "Error al regenerar los certificados. Por favor int\u00e9ntalo nuevamente.", "Error.": "Error.", @@ -824,7 +868,6 @@ "Fill browser": "Ir a pantalla completa", "Filter": "Filtro", "Filter and sort topics": "Filtrar y ordenar los temas", - "Final Grade": "Calificaci\u00f3n Final", "Final Grade Received": "Calificaci\u00f3n final recibida", "Financial Aid": "Ayuda financiera", "Financial Assistance": "Asistencia financiera", @@ -838,7 +881,9 @@ "Find previous": "Encontrar el anterior", "Finish": "Finalizar", "First time here?": "Primera vez aqu\u00ed?", + "Follow": "Seguir", "Follow or unfollow posts": "Seguir o dejar de seguir publicaciones", + "Following": "Siguiendo", "Font Family": "Tipo de fuente", "Font Sizes": "Tama\u00f1o de fuente", "Footer": "Pie de p\u00e1gina", @@ -858,7 +903,6 @@ "Generate": "Generar", "Generate Exception Certificates": "Generar excepciones de certificados", "Generate the user's certificate": "Generar el certificado del usuario", - "Get Credit": "Obtenga cr\u00e9ditos", "Go Back": "Volver Atr\u00e1s", "Go to Dashboard": "Ir al panel de control", "Go to my Dashboard": "Ir a mi Panel De Control", @@ -935,21 +979,23 @@ "ID-Verification is not required for this Professional Education course.": "La verification de ID no se requiere para este curso de Educaci\u00f3n Profesional", "Identity Verification In Progress": "Verificaci\u00f3n de identidad en progreso", "If the course does not have an end date, learners always see their scores when they submit answers to assessments.": "Si el curso no tiene fecha de caducidad, los estudiantes siempre ven sus puntajes cuando env\u00edan las respuestas de las evaluaciones.", + "If the photos you submit are rejected, try moving the computer or camera orientation to change the lighting angle. The most common reason for rejection is inability to read the text on the ID card.": "Si las fotos que env\u00eda son rechazadas, intente mover la computadora o la orientaci\u00f3n de la c\u00e1mara para cambiar el \u00e1ngulo de iluminaci\u00f3n. La raz\u00f3n m\u00e1s com\u00fan para el rechazo es la imposibilidad de leer el texto en la tarjeta de identificaci\u00f3n.", "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "Si la subsecci\u00f3n no tiene fecha de caducidad, los estudiantes siempre pueden ver sus puntajes cuando env\u00edan las respuestas a la evaluaci\u00f3n.", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "Si la unidad fue publicada anteriormente y liberada a los estudiantes, cualquier cambio que haya realizado cuando estaba oculta ser\u00e1 ahora visible para los estudiantes.", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "Si la unidad fue publicada anteriormente y liberada a los estudiantes, cualquier cambio realizado cuando estaba oculta ser\u00e1 ahora visible para los estudiantes. \u00bfDeseas proceder?", - "If you are unable to access your account contact us via email using {email}.": "Si no puedes acceder a tu cuenta, cont\u00e1ctanos por correo electr\u00f3nico a {email}.", "If you do not yet have an account, use the button below to register.": "Si todav\u00eda no tienes una cuenta, puedes utilizar el bot\u00f3n abajo para registrarte ", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "Si no verifica su identidad ahora, de todas formas podr\u00e1 explorar el curso desde su Panel de Control. Recibir\u00e1 recordatorios peri\u00f3dicos de %(platformName)s para realizar la verificaci\u00f3n de identidad.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "Si no verifica su identidad ahora, de todas formas podr\u00e1 explorar el curso desde su Panel de Control. Recibir\u00e1 recordatorios peri\u00f3dicos de {platformName} para realizar la verificaci\u00f3n de identidad.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "Si abandona esta p\u00e1gina sin guardar o enviar su respuesta, perder\u00e1 todo el trabajo realizado en la respuesta.", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "Si abandona esta p\u00e1gina sin enviar su trabajo, perder\u00e1 todos los cambios realizados.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "Si abandona esta p\u00e1gina sin enviar su auto evaluaci\u00f3n, perder\u00e1 todos los cambios realizados.", "If you leave this page without submitting your staff assessment, you will lose any work you have done.": "Si abandona esta p\u00e1gina sin enviar su evaluaci\u00f3n, se perder\u00e1n todos los cambios realizados.", + "If you leave, you can no longer post in this team's discussions.Your place will be available to another learner.": "Si deja el equipo, no puede volver a publicar discusiones dentro del equipo. Su lugar en el quipo estar\u00e1 disponible para otro estudiante.", "If you make significant changes, make sure you notify members of the team before making these changes.": "Si haces cambios significativos, aseg\u00farate de avisarle a los miembros del equipos antes de realizar estos cambios.", "If you make this %(xblockType)s visible to learners, learners will be able to see its content after the release date has passed and you have published the unit. Only units that are explicitly hidden from learners will remain hidden after you clear this option for the %(xblockType)s.": "Si hace este %(xblockType)s visible a los estudiantes, podr\u00e1n ver su contenido a partir de la fecha de liberaci\u00f3n siempre que haya publicado la unidad. S\u00f3lo las unidades que est\u00e1n ocultos expl\u00edcitamente permanecer\u00e1n ocultas despu\u00e9s de quitar esta opci\u00f3n para %(xblockType)s.", + "If you proceed, you will be unable to use this account to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "Si procedes, no podr\u00e1s usarla ni tomar cursos en la app {platformName}, {siteName}, ni en cualquier otro sitio de {platformName}.", "If you remove this transcript, the transcript will not be available for any components that use this video.": "Si elimina esta transcripci\u00f3n, la transcripci\u00f3n no estar\u00e1 disponible para ning\u00fan componente que use este v\u00eddeo.", "If you remove this transcript, the transcript will not be available for this component.": "Si elimina esta transcripci\u00f3n, la transcripci\u00f3n no estar\u00e1 disponible para este componente.", + "If you require assistance with taking either photo for submission, contact %(platformName)s support for additional suggestions.": "Si requiere asistencia tomando cualquiera de las fotos para enviarlas, contacte soporte%(platformName)s para sugerencias adicionales.", "If you select an option other than \"%(hide_label)s\", published units in this subsection become available to learners unless they are explicitly hidden.": "Si selecciona esta opci\u00f3n distinta a \"%(hide_label)s\", \nlas unidades publicadas en este subsecci\u00f3n pasar\u00e1n a estar disponible para los estudiantes a menos que est\u00e1n expl\u00edcitamente ocultas.", "If you still wish to continue and delete your account, please enter your account password:": "Si deseas continuar y eliminar tu cuenta, por favor introduce la contrase\u00f1a de tu cuenta:", "If you use the Advanced Editor, this problem will be converted to XML and you will not be able to return to the Simple Editor Interface.\n\nProceed to the Advanced Editor and convert this problem to XML?": "Si utiliza el Editor Avanzado, este problema ser\u00e1 convertido a formato XML y no podr\u00e1 volver a la pantalla del Editor Simple.\n\n\u00bfPasar al Editor avanzado y convertir este problema al formato XML?", @@ -970,6 +1016,7 @@ "Incorrect url format.": "Formato incorrecto de URL.", "Increase indent": "Aumentar Sangr\u00eda", "Individual Exceptions": "Excepciones individuales", + "Individual file size must be {max_files_mb}MB or less.": "El tama\u00f1o del archivo debe ser de aproximadamente {max_files_mb}MB o menos.", "Inheriting Student Visibility": "Heredando la Visibilidad a estudiantes.", "Inline": "Dentro de la l\u00ednea", "Insert": "Insertar", @@ -1025,6 +1072,7 @@ "Last Activity %(date)s": "\u00daltima Actividad %(date)s", "Last Edited:": "\u00daltima modificaci\u00f3n:", "Last Updated": "\u00daltima Actualizaci\u00f3n", + "Last activity {date}": "\u00daltima actividad {date}", "Last modified by": "\u00daltima modificaci\u00f3n por", "Last published %(last_published_date)s by %(publish_username)s": "Publicado por \u00faltima vez el %(last_published_date)s por %(publish_username)s", "Last published {lastPublishedStart}{publishedOn}{lastPublishedEnd} by {publishedByStart}{publishedBy}{publishedByEnd}": "Last published {lastPublishedStart}{publishedOn}{lastPublishedEnd} por {publishedByStart}{publishedBy}{publishedByEnd}", @@ -1068,6 +1116,7 @@ "Live view of webcam": "Se\u00f1al en vivo de la webcam", "Load Another File": "Cargar otro archivo", "Load all responses": "Cargando todas las respuestas", + "Load more": "Cargar m\u00e1s", "Load next {numResponses} responses": "Cargar las siguientes {numResponses} respuestas", "Load next {num_items} result": [ "Cargar el siguiente {num_items} resultado", @@ -1096,10 +1145,12 @@ "Make sure your face is well-lit": "Asegurese de que su rostro est\u00e9 bien iluminado", "Make this subsection available as a prerequisite to other content": "Deje disponible esta secci\u00f3n como prerrequisito de otro contenido", "Making Visible to Students": "Haciendo visible a los estudiantes", + "Manage": "Administrar", "Manage Learners": "Manejar Estudiantes", "Manual": "Manual", "March": "Marzo", "Mark Exam As Completed": "Marcar el examen como completado", + "Mark as Answer": "Marcar como respuesta", "Mark enrollment code as unused": "Marcar c\u00f3digo de inscripci\u00f3n como no utilizado", "Markdown Editing Help": "Ayuda para la edici\u00f3n con marcadores Markdown", "Masters": "Maestr\u00edas", @@ -1111,6 +1162,8 @@ "Membership": "Afiliaci\u00f3n", "Merge cells": "Fusionar celdas", "Message:": "Mensaje:", + "MicroBachelors": "MicroBachelors", + "MicroMasters": "MicroMasters", "Middle": "Educaci\u00f3n media", "Midnight": "Medianoche", "Minimum Completion:": "Valor m\u00ednimo a completar:", @@ -1123,11 +1176,13 @@ "Move cancelled. \"{sourceDisplayName}\" has been moved back to its original location.": "Movimiento cancelado. \"{sourceDisplayName}\" ha sido movido a su ubicaci\u00f3n original.", "Move: {displayName}": "Mover: {displayName}", "Moving": "Moviendo", + "Multiple teams returned for course": "Varios equipos encontrados para el curso", "Must be a Staff User to Perform this request.": "Hay que ser un usuario del equipo para cumplir esta petici\u00f3n.", "Must complete verification checkpoint": "Debe completar el punto de verificaci\u00f3n", "Mute": "Silenciar", "Muted": "En silencio", "My Orders": "Mis Pedidos", + "My Teams": "Mis equipos", "N/A": "N/D", "Name": "Nombre", "Name ": "Nombre", @@ -1212,11 +1267,16 @@ "Ok": "Aceptar", "Onboarding": "Integraci\u00f3n", "Onboarding Exam": "Examen de Integraci\u00f3n", + "Once in position, use the Take Photo button {icon} to capture your ID": "Una vez en posici\u00f3n, use el bot\u00f3n Tomar foto {icon} para captura su ID", + "Once in position, use the Take Photo button {icon} to capture your photo": "Una vez en posici\u00f3n, use el bot\u00f3n Tomar foto {icon} para captura su foto", "Once you complete one of the program requirements you have a program record. This record is marked complete once you meet all program requirements. A program record can be used to continue your learning journey and demonstrate your learning to others.": "Una vez complete uno de los requisitos de programa, usted tendr\u00e1 un registro de programa. Este registro es marcado como completo una vez cumpla con todos los requisitos del programa. Un registro del programa puede ser usado para continuar su registro diario de aprendizaje y demostrar su aprendizaje a otros.", + "Once your account is deleted, you cannot use it to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "Una vez tu cuenta es borrada, no podr\u00e1s usarla ni tomar cursos en la app {platformName}, {siteName}, ni en cualquier otro sitio de {platformName}.", "One or more rescheduling tasks failed.": "Una o m\u00e1s tareas de re-programaci\u00f3n fall\u00f3.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "S\u00f3lo pueden cargarse archivos de tipo <%= fileTypes %>. Por favor selecciona un archivo que termine en <%= fileExtensions %> para ser cargado.", + "Only ": "Solo", + "Only <%- fileTypes %> files can be uploaded. Please select a file ending in <%- (fileExtensions) %> to upload.": "Solo archivos <%- fileTypes %> pueden ser cargados. Por favor seleccione un archivo que finalice en <%- (fileExtensions) %> para cargarlo.", "Only properly formatted .csv files will be accepted.": "Solo archivos .csv correctamente formateados pueden ser utilizados.", "Only the parent course staff of a CCX can create content groups.": "S\u00f3lo el personal del curso principal de un CCX puede crear grupos de contenido.", + "Open": "Abrir", "Open Calculator": "Abrir Calculadora", "Open language menu": "Abrir men\u00fa de idioma", "Open the certificate you earned for the %(title)s program.": "Abrir el certificado que ganaste en el programa %(title)s.", @@ -1235,6 +1295,7 @@ "Organization ": "Organizaci\u00f3n", "Organization Name": "Nombre de la organizaci\u00f3n", "Organization of the signatory": "Organizaci\u00f3n del signatario", + "Organization:": "Organizaci\u00f3n:", "Other": "Otro", "Overall Score": "Puntaje general", "PDF Chapters": "Cap\u00edtulos de PDF", @@ -1267,6 +1328,8 @@ "Photo of %(fullName)s's ID": "Foto de la identificaci\u00f3n de %(fullName)s", "Photo requirements:": "Requerimientos para las fotos:", "Photos don't meet the requirements?": "\u00bfSus fotos no cumplen los requerimientos?", + "Pin": "Marcar", + "Pinned": "Marcado", "Placeholder": "Marcador de posici\u00f3n", "Play": "Reproducir", "Play video": "Reproducir video", @@ -1298,6 +1361,7 @@ "Please enter your log-in or recovery email address below and we will send you an email with instructions.": "Por favor ingrese su direcci\u00f3n de correo electr\u00f3nico de inicio de sesi\u00f3n o de recuperaci\u00f3n a continuaci\u00f3n , y le enviaremos un correo electr\u00f3nico con instrucciones.", "Please fix the following errors:": "Por favor corrija los siguientes errores:", "Please follow the instructions here to upload a file elsewhere and link to it: {maxFileSizeRedirectUrl}": "Por favor siga las instrucciones aqui para cargar un archivo en otro parte y enlazelo: {maxFileSizeRedirectUrl}", + "Please note: Deletion of your account and personal data is permanent and cannot be undone. {platformName} will not be able to recover your account or the data that is deleted.": "Cuidado: la eliminaci\u00f3n de su cuenta y datos personales es permanente e irreversible. {platformName} no podr\u00e1 recuperar ni su cuenta ni los datos eliminados.", "Please print this page for your records; it serves as your receipt. You will also receive an email with the same information.": "Por favor imprima esta p\u00e1gina para sus registros; la misma es v\u00e1lida como su recibo. Tambi\u00e9n recibir\u00e1 un correo electr\u00f3nico con la esta informaci\u00f3n.", "Please provide a description of the link destination.": "Por favor, provee una descripci\u00f3n de la destinaci\u00f3n del v\u00ednculo.", "Please provide a valid URL.": "Por favor, provee un URL v\u00e1lido.", @@ -1310,6 +1374,7 @@ "Please wait": "Por favor espere", "Plugins": "Plug-ins", "Post": "Publicaci\u00f3n", + "Post type": "Tipo de publicaci\u00f3n", "Poster": "Poster", "Practice Exam Completed": "Examen de pr\u00e1ctica completado", "Practice Exam Failed": "Examen de pr\u00e1ctica no aprobado", @@ -1369,8 +1434,11 @@ "Published and Live": "Publicado y en vivo", "Publishing": "Publicando", "Publishing Status": "Estado de publicaci\u00f3n", + "Question": "Pregunta", + "Questions raise issues that need answers. Discussions share ideas and start conversations. (Required)": "Utiliza Pregunta para plantear temas que necesitan respuestas. Utiliza Discusi\u00f3n para compartir tus ideas y comenzar conversaciones. (Requerido)", "Queued": "En cola", "REMAINING COURSES": "CURSOS RESTANTES", + "Re-run Course": "Relanzar Curso", "Read More": "Leer mas", "Read more": "Leer m\u00e1s", "Ready To Start": "Listo para comenzar", @@ -1390,6 +1458,7 @@ "Regenerate the user's certificate": "Regenerar el certificado del usuario", "Register with Institution/Campus Credentials": "Registrarse con las credenciales de la instituci\u00f3n o el Campus", "Rejected": "Rechazado", + "Related to: %(courseware_title_linked)s": "Relacionado con: %(courseware_title_linked)s", "Release Date and Time": "Fecha y hora de liberaci\u00f3n", "Release Date:": "Fecha de liberaci\u00f3n:", "Release Status:": "Estado de liberaci\u00f3n:", @@ -1418,7 +1487,10 @@ "Replace all": "Reemplazar todo", "Replace with": "Reemplazar con", "Reply to Annotation": "Responder a la anotaci\u00f3n", + "Report": "Denunciar", + "Report abuse": "Denunciar un abuso", "Report abuse, topics, and responses": "Denunciar abusos, temas, y respuestas", + "Reported": "Denunciado", "Requester": "Solicitante", "Required": "Requerido", "Required field.": "Campo requerido.", @@ -1438,6 +1510,7 @@ "Return and add email address": "Volver y introduir un correo electr\u00f3nico. ", "Return to Export": "Regresar a exportar", "Return to Your Dashboard": "Volver al panel principal", + "Return to all posts": "Volver a todas las publicaciones", "Return to team listing": "Volver a la lista del equipo", "Review Policy Exception": "Revisar excepci\u00f3n a la pol\u00edtica", "Review Rules": "Revisar las reglas", @@ -1473,6 +1546,10 @@ "Section Highlights": "Destacados de la secci\u00f3n", "Section Visibility": "Visibilidad de la secci\u00f3n", "Sections": "Secciones", + "Security": "Seguridad", + "See all teams you belong to and all public teams in your course, organized by topic.": "Vea todos los equipos a los que pertenece y todos los equipos p\u00fablicos en su curso, organizados por tema.", + "See all teams you belong to and all public teams in your course, organized by topic. Join an open public team to collaborate with other learners who are interested in the same topic as you are.": "Vea todos los equipos a los que pertenece y todos los equipos p\u00fablicos en su curso, organizados por tema. \u00danase a un equipo p\u00fablico abierto para colaborar con otros estudiantes interesados en el mismo tema que usted.", + "See all teams you belong to.": "Ver todos los equipos a los que usted pertenece.", "Select": "Seleccionar", "Select Session": "Seleccione la sesi\u00f3n.", "Select a Content Group": "seleccionar contenido de grupo", @@ -1518,6 +1595,10 @@ "Show": "Mostrar", "Show All": "Mostrar todo", "Show Annotations": "Mostrar anotaciones", + "Show Comment (%(num_comments)s)": [ + "Mostrar comentario (%(num_comments)s)", + "Mostrar comentarios (%(num_comments)s)" + ], "Show Deprecated Settings": "Mostrar configuraciones descartadas", "Show Discussion": "Mostrar Discusi\u00f3n", "Show Less": "Mostrar menos", @@ -1686,9 +1767,8 @@ "Textbook Name": "Nombre", "Textbook information": "Informaci\u00f3n del libro de texto", "Textbook name is required": "Se requiere el nombre del libro de texto", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Gracias %(full_name)s! Hemos recibido su pago para el curso %(course_name)s.", "Thank you for setting your course goal to {goal}!": "\u00a1 Gracias por establecer su objetivo para este curso en {goal}!", - "Thank you for submitting a request! We will contact you within 24 hours.": "Gracias por mandarnos un mensaje. Te contactaremos dentro de las siguientes 24 horas.", + "Thank you for submitting a request! We appreciate your patience while we work to review your request.": "\u00a1Gracias por su env\u00edo! Agradecemos su paciencia mientras trabajamos para revisar su solicitud.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Gracias por enviar tu aplicaci\u00f3n de financiamiento para {course_name}!. Espera una respuesta de 2-4 dias h\u00e1biles.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Gracias por enviar sus fotos. Las revisaremos pronto. Ahora puede registrarse para cualquier curso de %(platformName)s que ofrezca Certficados Verificados. La verificaci\u00f3n es v\u00e1lida por un a\u00f1o. Despu\u00e9s de este periodo, deber\u00e1 volver a enviar fotograf\u00edas para una nueva verificaci\u00f3n.", "Thank you! We have received your payment for {courseName}.": "\u00a1Gracias! Hemos recibido tu pago para {courseName}.", @@ -1700,8 +1780,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "El certificado para este estudiante ha sido revalidado y el sistema est\u00e1 computando nuevamente la calificaci\u00f3n.", "The cohort cannot be added": "El cohorte no puede ser a\u00f1adido", "The cohort cannot be saved": "El cohorte debe ser grabado", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "La longitud combinada de los campos para la organizaci\u00f3n y c\u00f3digo de la librer\u00eda no puede superar los <%=limit%> caracteres.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "La longitud combinada de los campos para la organizaci\u00f3n, n\u00famero de curso y grupo no puede superar los <%=limit%> caracteres.", "The country or region where you live.": "El pa\u00eds o la regi\u00f3n donde t\u00fa vives. ", "The country that team members primarily identify with.": "El pa\u00eds que identifica de forma primaria a los miembros del equipo.", "The course end date must be later than the course start date.": "La fecha de finalizaci\u00f3n del curso debe ser posterior a la fecha de inicio.", @@ -1717,7 +1795,7 @@ "The following email addresses and/or usernames are invalid:": "El correo electr\u00f3nico y/o el nombre de usuario no son v\u00e1lidos:", "The following errors were generated:": "Se generaron los siguientes errores:", "The following file types are not allowed: ": "Los siguientes tipos de archivos son soportados:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "La siguiente informaci\u00f3n ya es parte de su perfil en {platform} . La hemos incluido aqu\u00ed para su aplicaci\u00f3n.", + "The following information is already a part of your {platform} profile. We've included it here for your application.": "La siguiente informaci\u00f3n ya es parte de su perfil en {platform} . La hemos incluido aqu\u00ed para su aplicaci\u00f3n", "The following message will be displayed at the bottom of the courseware pages within your course:": "El siguiente mensaje ser\u00e1 mostrado al final de las p\u00e1ginas de los cursos. ", "The following options are available for the {license_name} license.": "Las siguientes opciones est\u00e1n disponibles para {license_name} licencia", "The following users are no longer enrolled in the course:": "Los siguientes usuarios ya no est\u00e1n inscritos en el curso:", @@ -1729,7 +1807,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "El porcentaje m\u00ednimo a completar debe ser un n\u00famero entero entre 0 y 100. ", "The minimum grade for course credit is not set.": "La calificaci\u00f3n m\u00ednima para obtener cr\u00e9ditos por el curso no est\u00e1 definida.", "The minimum score percentage must be a whole number between 0 and 100.": "La nota m\u00ednima para aprobar debe ser un n\u00famero entero entre 0 y 100.", - "The more you tell us, the more quickly and helpfully we can respond!": "Cuanto m\u00e1s nos digas, antes y mejor podremos ayudarte.", "The name of this signatory as it should appear on certificates.": "El nombre de este signatario como debe aparecer en los certificados.", "The name that identifies you on {platform_name}. You cannot change your username.": "El nombre que lo identifica en {platform_name}. No puede cambiar el nombre de usuario.", "The name that is used for ID verification and that appears on your certificates.": "El nombre que es usado para la verificaci\u00f3n de identidad y aparece en sus certificados.", @@ -1737,7 +1814,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "El n\u00famero de subdivisiones del curso que contiene problemas de este tipo de asignaci\u00f3n.", "The organization that this signatory belongs to, as it should appear on certificates.": "La organizaci\u00f3n a la que pertenece el firmante, como debe aparecer en los certificados. ", "The page \"{route}\" could not be found.": "La p\u00e1gina \"{route}\" no pudo ser encontrada.", - "The photo of your face matches the photo on your ID.": "La foto de su documento coincide con la foto de su cara.", "The post you selected has been deleted.": "La publicaci\u00f3n que seleccion\u00f3 ha sido borrada.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "La versi\u00f3n publicada, {published}, fue restablecida a la versi\u00f3n borrador, {draft}.", "The raw error message is:": "El error crudo es:", @@ -1814,16 +1890,19 @@ "This feature is currently in testing. Course teams can enter highlights, but learners will not receive email messages.": "Esta caracter\u00edstica est\u00e1 en prueba actualmente. Equipos del curso pueden ingresar destacados, pero los estudiantes no recibir\u00e1n mensajes de correo electr\u00f3nico.", "This feedback could not be submitted.": "Este comentario no pudo ser enviado.", "This file type is not supported. Supported file type is {supportedFileFormat}.": "Este tipo de archivo no es soportado. El tipo de archivo soportado es {supportedFileFormat}.", + "This grade will be applied to all members of the team. Do you want to continue?": "Esta calificaci\u00f3n se aplicar\u00e1 a todos los miembros del equipo. \u00bfDesea continuar?", "This group controls access to:": "Este grupo controla el acceso a:", "This group no longer exists. Choose another group or do not restrict access to this unit.": "Este grupo ya no existe. Seleccione otro grupo o no restrinja el acceso a esta unidad.", "This image file type is not supported. Supported file types are {supportedFileFormats}.": "El tipo de archivo no es soportado. Los tipos de archivo soportados son {supportedFileFormats}.", "This image is for decorative purposes only and does not require a description.": "Esta imagen es decorativa solamente y no requiere descripci\u00f3n.", + "This includes access to {siteName} from your employer\u2019s or university\u2019s system{additionalSiteSpecificDeletionText}.": "Esto incluye acceso a {siteName} desde el sistema de tu empleador o universidad{additionalSiteSpecificDeletionText}.", "This is the Description of the Group Configuration": "Esta es la descripci\u00f3n de configuraci\u00f3n del grupo", "This is the Name of the Group Configuration": "Este es el nombre de la Configuraci\u00f3n del Grupo", "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "Esta es la lista de %s disponibles. Puede elegir algunos seleccion\u00e1ndolos en la caja inferior y luego haciendo clic en la flecha \"Elegir\" que hay entre las dos cajas.", "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "Esta es la lista de los %s elegidos. Puede elmininar algunos seleccion\u00e1ndolos en la caja inferior y luego haciendo click en la flecha \"Eliminar\" que hay entre las dos cajas.", "This is the name of the group": "Este es el nombre del grupo", "This learner is currently sharing a limited profile.": "Este usuario est\u00e1 compartiendo un perfil limitado.", + "This learner will be removed from the team,allowing another learner to take the available spot.": "Este estudiante ser\u00e1 removido del equipo, permitiendo a otro estudiante tomar su lugar.", "This link will open in a modal window": "Este enlace se abrir\u00e1 en una ventana modal", "This link will open in a new browser window/tab": "Este enlace se abrir\u00e1 en una nueva ventana o pesta\u00f1a del navegador", "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.": "Esto puede estar sucediendo debido a un error con nuestros servidores o con tu conexi\u00f3n a Internet. Intenta refrescar la p\u00e1gina o verifica tu acceso a Internet.", @@ -1834,6 +1913,10 @@ "This post could not be reopened. Refresh the page and try again.": "No se pudo abrir esta publicaci\u00f3n de nuevo. Recarga la p\u00e1gina e intenta nuevamente.", "This post could not be unflagged for abuse. Refresh the page and try again.": "No se pudo desmarcar esta publicaci\u00f3n como abusiva. Recarga la p\u00e1gina e intenta nuevamente.", "This post could not be unpinned. Refresh the page and try again.": "No se pudo desmarcar esta publicaci\u00f3n. Recarga la p\u00e1gina e intente nuevamente.", + "This post is visible only to %(group_name)s.": "Este post es visible solo para %(group_name)s.", + "This post is visible to everyone.": "Esta publicaci\u00f3n es visible para todos.", + "This post will be visible only to %(group_name)s.": "Esta publicaci\u00f3n ser\u00e1 visible solo para %(group_name)s.", + "This post will be visible to everyone.": "Esta publicaci\u00f3n ser\u00e1 visible para todos.", "This problem could not be saved.": "Este problema no pudo ser guardado.", "This problem has already been released. Any changes will apply only to future assessments.": "Este problema ya ha sido liberado. Cualquier cambio en el mismo se aplicar\u00e1 solo a los env\u00edo futuros.", "This problem has been reset.": "Este problema ha sido restablecido.", @@ -1850,6 +1933,7 @@ "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.": "Estos nombres para los tipos de asignaciones (por ejemplo, Tareas o Examen trimestral) aparecen al lado de las asignaciones en la p\u00e1gina de Progreso del estudiante.", "This team does not have any members.": "Este equipo no tiene todav\u00eda ning\u00fan miembro.", "This team is full.": "Este equipo est\u00e1 lleno.", + "This thread is closed.": "Este hilo est\u00e1 cerrado.", "This unit has validation issues.": "Esta unidad tiene errores de validaci\u00f3n", "This vote could not be processed. Refresh the page and try again.": "Este voto no se pudo procesar. Recarga la p\u00e1gina e intenta nuevamente.", "This {parentCategory} has no {childCategory}": "Esta {parentCategory} no tiene {childCategory}", @@ -1876,7 +1960,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "Para asegurar que todos los estudiantes puedan ver el video, recomendamos suministrar tanto una versi\u00f3n .mp4 como una versi\u00f3n .webm del recurso. Haga clic a continuaci\u00f3n para a\u00f1adir la URL de una nueva versi\u00f3n. Estas URLs no pueden ser de Youtube. El primer video listado que sea compatible con la terminal del usuario ser\u00e1 el que se reproducir\u00e1.", "To complete the program, you must earn a verified certificate for each course.": "Para completar el programa, deber\u00e1s ganar un certificado verificado en cada curso.", "To continue learning with this account, sign in below.": "Para continuar aprendiendo con esta cuenta, reg\u00edstrese a continuaci\u00f3n.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "Para finalizar un cr\u00e9dito de curso, %(display_name)s requieres %(platform_name)s profesores para postular una solicitud de cr\u00e9dito.", "To invalidate a certificate for a particular learner, add the username or email address below.": "Para invalidar el certificado de un estudiante particular, a\u00f1ada el nombre de usuario o correo electr\u00f3nico a continuaci\u00f3n.", "To pass this exam, you must complete the problems in the time allowed.": "Para aprobar este examen, hay que completar los problemas durante el tiempo permitido.", "To receive a certificate, you must also verify your identity before {date}.": "Para recibir un certificado, tambi\u00e9n debe verificar su identidad antes del {date}.", @@ -1885,6 +1968,7 @@ "To review learner cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on the {link_start}Data Download{link_end} page.": "Para revisar asiginaciones de cohortes de los estudiantes o ver los resultados del archivo CVS que est\u00e1 subiendo, descargue la informaci\u00f3n del perfil del curso o los resultados del cohorte en la p\u00e1gina {link_start}Data Download{link_end}.", "To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.": "Para compartir tu certificado en Mozilla Backpack, debes tener una cuenta de Backpack primero. Completa los siguientes pasos para agregar tu certificado a Backpack.", "To take a successful photo, make sure that:": "Para tomar la foto correctamente, aseg\u00farese de: ", + "To take the photo of your face, click on the camera button {icon}. If you need to try again, click 'Retake Photo'.": "Para tomar la foto de su cara, haga clic en el bot\u00f3n de la c\u00e1mara {icon}. Si necesita volver a intentarlo, haga clic en 'Retomar foto'.", "To verify your identity, you need a webcam and a government-issued photo ID.": "Para verificar su identidad, necesitar\u00e1 una c\u00e1mara web, y un documento de identificaci\u00f3n oficial con foto.", "Today": "Hoy", "Toggle Account Password (Usable/Unusable)": "Cambiar Contrase\u00f1a de Cuenta (Usable/No-usable)", @@ -1893,6 +1977,7 @@ "Tools": "Herramientas", "Top": "Superior", "Topic": "Tema", + "Topic area": "\u00c1rea tem\u00e1tica", "Topics": "Temas", "Total": "Total", "Total Number": "N\u00famero total", @@ -1924,7 +2009,9 @@ "Undo Changes": "Deshacer Cambios", "Undo move": "Deshacer movimiento", "Undo moving": "Deshacer movimiento", + "Unendorse": "Invalidar", "Unexpected server error.": "Ocurri\u00f3 un error inesperado en el servidor.", + "Unfollow": "Dejar de seguir", "Ungraded": "No calificado", "Ungraded Practice Exam": "Examen de pr\u00e1ctica no calificado", "Unit": "Unidad", @@ -1937,14 +2024,20 @@ "Unlink This Account": "Desvincular esta cuenta", "Unlink your {accountName} account": "Desvincular tu cuenta de {accountName} ", "Unlinking": "Desvinculando", + "Unmark as Answer": "Desmarcar como respuesta", "Unmute": "Restablecer sonido", "Unnamed Option": "Opci\u00f3n sin nombre", + "Unpin": "Desmarcar", "Unpublished changes to content that will release in the future": "Cambios no publicados del contenido que ser\u00e1 liberado en el futuro", "Unpublished changes to live content": "Cambios no publicados en el contenido en vivo", "Unpublished units will not be released": "Las unidades no publicadas no ser\u00e1n liberadas", + "Unreport": "Dejar de denunciar", "Unscheduled": "No programado", "Update": "Actualizar", "Update Settings": "Actualizar ajustes", + "Update comment": "Actualizar comentario", + "Update post": "Actualiza publicaci\u00f3n", + "Update response": "Actualiza respuesta", "Update team.": "Actualizar el equipo.", "Updating Tags": "Actualizando Etiquetas", "Updating with latest library content": "Actualizando con el m\u00e1s reciente contenido de la librer\u00eda", @@ -1955,6 +2048,7 @@ "Upload": "Subir", "Upload File": "Subir archivo", "Upload File and Assign Students": "Cargar archivo y asignar estudiantes", + "Upload Memberships": "Subir membres\u00edas", "Upload New .srt Transcript": "Cargar nuevo archivo de transcripci\u00f3n .srt", "Upload New File": "Subir nuevo archivo", "Upload New Transcript": "Cargar nueva transcripci\u00f3n", @@ -1964,7 +2058,7 @@ "Upload Videos": "Cargar Videos", "Upload a CSV file": "Cargar un archivo CSV", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "Cargue un archivo separado por comas (.csv) que contenga los nombres de usuario o correos electr\u00f3nicos de los estudiantes a los que se le han otorgado excepciones. Incluya el nombre de usuario o correo electr\u00f3nico en el primer campo. Puede incluir adem\u00e1s en un segundo campo, una nota opcional describiendo la raz\u00f3n para otorgar la excepci\u00f3n.", - "Upload a new PDF to \u201c<%= name %>\u201d": "Subir un nuevo PDF a \u201c<%= name %>\u201d", + "Upload a new PDF to \u201c<%- name %>\u201d": "cargar un nuevo PDF a \u201c<%- name %>\u201d", "Upload an image": "Subir una imagen", "Upload an image or capture one with your web or phone camera.": "Subir una imagen o captura con tu camara web o del tel\u00e9fono", "Upload completed": "Carga terminada", @@ -1994,8 +2088,10 @@ "Use cohorts as the basis for dividing discussions. All learners, regardless of cohort, see the same discussion topics, but within divided topics, only members of the same cohort see and respond to each others\u2019 posts. ": "Usar cohortes como base de dividir las discusiones. Todos los estudiantes, sin considerar su cohorte, ven los mismos temas de discusi\u00f3n, pero dentro de temas divididos, los estudiantes solamente ven y responden a las publicaciones de otros estudiantes en el mismo cohorte como ellos.", "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "Usar rutas de inscripci\u00f3n como base de dividir las discusiones. Todos los estudiantes, sin considerar su ruta de inscripci\u00f3n, ven los mismos temas de discusi\u00f3n, pero dentro de temas divididos, los estudiantes solamente ven y responden a las publicaciones de otros estudiantes en la misma ruta de inscripci\u00f3n como ellos.", "Use my institution/campus credentials": "Usar mis credenciales de la instituci\u00f3n o el Campus", + "Use my university info": "Usar informaci\u00f3n de mi universidad", "Use the All Topics menu to find specific topics.": "Use el men\u00fa de todos los temas para encontrar temas espec\u00edficos.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Use su c\u00e1mara web para tomar una fotograf\u00eda de su documento de identidad. Usaremos esta foto para verificarla contra la fotograf\u00eda de su cara y el nombre de su cuenta.", + "Use the Retake Photo button if you are not pleased with your photo": "Use el bot\u00f3n Retomar foto si no est\u00e1 satisfecho con su foto", + "Use your webcam to take a photo of your ID.": "Use su c\u00e1mara web para tomar una fotograf\u00eda de su documento de identificaci\u00f3n.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Use su c\u00e1mara web para tomar una fotograf\u00eda de su cara. Usaremos esta foto para verificarla contra la fotograf\u00eda de su documento de identificaci\u00f3n.", "Used": "Utilizado", "Used in {count} location": [ @@ -2003,6 +2099,7 @@ "Usado en {count} ubicaciones" ], "User Email": "Correo electr\u00f3nico del usuario", + "User lookup failed": "Fall\u00f3 b\u00fasqueda del usuario", "Username": "Nombre de usuario", "Username or email address": "Nombre de usuario o correo electr\u00f3nico", "Users must create and activate their account before they can be promoted to beta tester.": "Los usuarios deben crear y activar su cuenta antes de que puedan ser promovidos a usuarios de prueba.", @@ -2019,7 +2116,6 @@ "Verified Certificate upgrade": "Optar por el Certificado Verificado", "Verified Status": "Verificaci\u00f3n", "Verified mode price": "Precio del modo verificado", - "Verify Now": "Verificar ahora", "Version": "Versi\u00f3n", "Vertical space": "Espacio vertical", "Very loud": "Muy alto", @@ -2040,32 +2136,40 @@ "View Archived Course": "Ver curso archivado", "View Cohort": "Ver Cohorte", "View Course": "Ver curso", + "View Current Team Memberships": "Ver las membres\u00edas actuales del equipo", "View Live": "Ver en vivo", "View Program Record": "Ver registros del programa", + "View Teams in the {topic_name} Topic": "Ver equipos en el tema {topic_name}", "View all errors": "Ver todos los errores", "View child items": "Ver items hijos", + "View discussion": "Ver discusi\u00f3n", "View my exam": "Ver mi examen", + "View {span_start} {team_name} {span_end}": "Ver {span_start} {team_name} {span_end}", "Viewing %s course": [ "Mostrando %s curso", "Mostrando %s cursos" ], "Visibility": "Visibilidad", + "Visible to": "Visible para", "Visible to Staff Only": "Visible solo para el equipo del curso", "Visual aids": "Ayudas visuales", "Volume": "Volumen", "Vote for good posts and responses": "Votar por las mejores publicaciones y respuestas", + "Vote for this post,": "Votar esta publicaci\u00f3n", "Waiting": "Esperando", "Want to confirm your identity later?": "\u00bfDesea confirmar su identidad despu\u00e9s?", - "Warning": "Atenci\u00f3n:", + "Warning": "Advertencia", "Warnings": "Advertencias", "We ask you to activate your account to ensure it is really you creating the account and to prevent fraud.": "Necesitamos que active su cuenta para asegurarnos que es usted realmente el que est\u00e1 creando la cuenta y para prevenir fraude.", "We couldn't create your account.": "No pudimos crear tu cuenta.", "We couldn't find any results for \"%s\".": "No se ha encontrado ninguna coincidencia para \"%s\".", "We couldn't sign you in.": "No se ha podido iniciar tu sesi\u00f3n.", "We have encountered an error. Refresh your browser and then try again.": "Hemos detectado un error. Por favor recarga la p\u00e1gina en el navegador e intenta nuevamente.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Hemos recibido la informaci\u00f3n enviada y estamos verificando su identidad. Recibir un mensaje en su Panel principal cuando el proceso de verificaci\u00f3n est\u00e9 completado (usualmente entre 1-2 d\u00edas). Durante este tiempo, igualmente tendr\u00e1 acceso a todo el contenido de su curso.", + "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days). In the meantime, you can still access all available course content.": "Hemos recibido su informaci\u00f3n y estamos verificando su identidad. Ver\u00e1 un mensaje en su tablero cuando se complete el proceso de verificaci\u00f3n (generalmente dentro de 5-7 d\u00edas). Mientras tanto, a\u00fan puede acceder a todo el contenido del curso disponible.", "We just need a little more information before you start learning with %(platformName)s.": "Necesitamos un poco mas de informaci\u00f3n antes de que comiences a aprender con %(platformName)s.", + "We securely encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Ciframos su foto de forma segura y la enviamos a nuestro servicio de autorizaci\u00f3n para su revisi\u00f3n. Su foto e informaci\u00f3n no se guardan ni son visibles en ning\u00fan lugar de %(platformName)s despu\u00e9s de que se complete el proceso de verificaci\u00f3n.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Usamos los m\u00e1s altos niveles de seguridad disponibles para encriptar su foto y enviarla a nuestro servicio de autorizaci\u00f3n para revisi\u00f3n. Su foto y su informaci\u00f3n no son guardadas ni quedan visibles en ninguna parte de %(platformName)s desp\u00faes de que el proceso de verificaci\u00f3n haya sido completado.", + "We use your verification photos to confirm your identity and ensure the validity of your certificate.": "Utilizamos sus fotos de verificaci\u00f3n para confirmar su identidad y garantizar la validez de su certificado.", "We're sorry to see you go! Your account will be deleted shortly.": "\u00a1Sentimos que te vayas! Tu cuenta ser\u00e1 eliminada en breve.", "We're sorry, there was an error": "Lo sentimos, ha habido un error", "We've encountered an error. Refresh your browser and then try again.": "Hemos detectado un error. Por favor recarga la p\u00e1gina en el navegador e intenta nuevamente.", @@ -2081,9 +2185,14 @@ "What can we help you with, {username}?": "\u00bfEn qu\u00e9 podemos ayudarte, {username}?", "What does %(platformName)s do with this photo?": "\u00bfQu\u00e9 hace %(platformName)s con esta imagen?", "What does this mean?": "\u00bfQu\u00e9 significa esto?", + "What if I can't see the camera image, or if I can't see my photo do determine which side is visible?": "\u00bfQu\u00e9 sucede si no puedo ver la imagen de la c\u00e1mara, o si no puedo ver mi foto para determinar qu\u00e9 lado es visible?", + "What if I have difficulty holding my ID in position relative to the camera?": "\u00bfQu\u00e9 sucede si tengo dificultades para mantener mi identificaci\u00f3n en posici\u00f3n con respecto a la c\u00e1mara?", + "What if I have difficulty holding my head in position relative to the camera?": "\u00bfQu\u00e9 sucede si tengo dificultades para mantener la cabeza en posici\u00f3n con respecto a la c\u00e1mara?", "What's Your Next Accomplishment?": "\u00bfQu\u00e9 ser\u00e1 tu pr\u00f3ximo logro?", "When learners submit an answer to an assessment, they immediately see whether the answer is correct or incorrect, and the score received.": "Cuando los estudiantes env\u00edan una respuesta para evaluaci\u00f3n, ven inmediatamente si la respuesta es correcta o incorrecta, y la calificaci\u00f3n recibida.", + "When your face is in position, use the Take Photo button {icon} below to take your photo.": "Cuando su cara est\u00e9 en posici\u00f3n, use el bot\u00f3n Tomar foto {icon} a continuaci\u00f3n para tomar su foto.", "Which timed transcript would you like to use?": "\u00bfCu\u00e1l de las transcripciones desea utilizar?", + "While our support team is happy to assist with the edX platform, the course staff has the expertise for specific assignment questions, grading or the proper procedures in each course. Please post all course related questions within the Discussion Forum where the Course Staff can directly respond.": "Si bien nuestro equipo de soporte est\u00e1 encantado de ayudar con la plataforma edX, el personal del curso tiene la experiencia para preguntas espec\u00edficas del curso, calificaci\u00f3n o los procedimientos adecuados en cada curso. Publique todas las preguntas relacionadas con el curso en el Foro de discusi\u00f3n donde el personal del curso pueda responder directamente.", "Whole words": "Palabras completas", "Why activate?": "Por qu\u00e9 activar?", "Why does %(platformName)s need my photo?": "Por qu\u00e9 %(platformName)s necesita mi foto ?", @@ -2097,6 +2206,7 @@ "Yes, delete this {xblock_type}": "Si, eliminar este {xblock_type}", "Yes, replace the edX transcript with the YouTube transcript": "Si, reemplazar la transcripci\u00f3n de edX con la de YouTube", "Yesterday": "Ayer", + "You already belong to another team in this team set.": "Usted ya pertenece a otro equipo en este conjunto.", "You already have an edX account with your {enterprise_name} email address.": "Ya tiene una cuenta edX con su direcci\u00f3n de correo electr\u00f3nico de {enterprise_name}", "You are a member of this team.": "Usted ya es miembro de este equipo.", "You are currently sharing a limited profile.": "Actualmente est\u00e1 compartiendo un perfil limitado.", @@ -2105,6 +2215,7 @@ "You are not enrolled in any programs yet.": "No se encuentra inscrito en ning\u00fan programa a\u00fan.", "You are now enrolled as a verified student for:": "Ahora estas inscrito como estudiante verificado para:", "You are sending an email message with the subject {subject} to the following recipients.": "Tu est\u00e1s enviando un correo electr\u00f3nico con asunto {subject} a los siguientes destinatarios.", + "You are taking \"{exam_link}\" as {exam_type}. ": "Est\u00e1s tomando \"{exam_link}\" como {exam_type}. ", "You are upgrading your enrollment for: {courseName}": "Est\u00e1s cambiando a la modalidad verificada para: {courseName}", "You can also retry this practice exam": "Tambi\u00e9n puede comenzar este examen de pr\u00e1ctica nuevamente", "You can change sessions until {expiration_date}.": "Puede cambiar ediciones hasta {expiration_date}.", @@ -2142,6 +2253,7 @@ "You have not created any group configurations yet.": "No ha creado ninguna configuraci\u00f3n de grupo.", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "Ha seleccionado una acci\u00f3n y no hs hecho ning\u00fan cambio en campos individuales. Probablemente est\u00e9 buscando el bot\u00f3n Ejecutar en lugar del bot\u00f3n Guardar.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "Ha seleccionado una acci\u00f3n, pero no ha guardado los cambios en los campos individuales todav\u00eda. Pulse OK para guardar. Tendr\u00e1 que volver a ejecutar la acci\u00f3n.", + "You have selected \u201cDelete my account.\u201d Deletion of your account and personal data is permanent and cannot be undone. {platformName} will not be able to recover your account or the data that is deleted.": "Ha seleccionado \u201cEliminar mi cuenta\u201d. La eliminaci\u00f3n de su cuenta y datos personales es permanente e irreversible. {platformName} no podr\u00e1 recuperar su cuenta o los datos que se hayan borrado.", "You have set your language to {beta_language}, which is currently not fully translated. You can help us translate this language fully by joining the Transifex community and adding translations from English for learners that speak {beta_language}.": "Ha establecido su idioma en {beta_language}, el cual no est\u00e1 traducido completamente. Puede ayudarnos a traducir este idioma totalmente uni\u00e9ndose la comunidad Transifex y adicionando traducciones desde el Ingl\u00e9s para los estudiantes que hablan {beta_language}.", "You have successfully signed into %(currentProvider)s, but your %(currentProvider)s account does not have a linked %(platformName)s account. To link your accounts, sign in now using your %(platformName)s password.": "Has iniciado sesi\u00f3n exitosamente en %(currentProvider)s, pero tu cuenta de %(currentProvider)s no est\u00e1 vinculada con una cuenta en %(platformName)s. Para vincular tus cuentas, ingresa con tu usuario y contrase\u00f1a de %(platformName)s.", "You have successfully updated your goal.": "Ha actualizado exitosamente su objetivo.", @@ -2153,6 +2265,8 @@ "You haven't added any textbooks to this course yet.": "No ha a\u00f1adido a\u00fan ning\u00fan libro de texto a este curso.", "You may access your account with this address if single-sign on or access to your primary email is not available.": "Puede acceder a su cuenta con esta direcci\u00f3n si no est\u00e1n disponibles el inicio de sesi\u00f3n \u00fanico -SSO- o el acceso a su correo electr\u00f3nico principal.", "You may also lose access to verified certificates and other program credentials like MicroMasters certificates. If you want to make a copy of these for your records before proceeding with deletion, follow the instructions for {htmlStart}printing or downloading a certificate{htmlEnd}.": "Puede que tambi\u00e9n pierdas el acceso a los certificados verificados y otros certificados de programas como los de los MicroMasters. Si quieres hacer una copia de dichos certificados para tus archivos antes de proceder a la eliminaci\u00f3n, sigue las instrucciones para {htmlStart}imprimir o descargar un certificado{htmlEnd}.", + "You may be able to complete the image capture procedure without assistance, but it may take a couple of submission attempts to get the camera positioning right. Optimal camera positioning varies with each computer, but generally the best position for a headshot is approximately 12-18 inches (30-45 centimeters) from the camera, with your head centered relative to the computer screen. ": "Es posible que pueda completar el procedimiento de captura de im\u00e1genes sin ayuda, pero puede tomar un par de intentos de env\u00edo para obtener la posici\u00f3n correcta de la c\u00e1mara. El posicionamiento \u00f3ptimo de la c\u00e1mara var\u00eda con cada computadora, pero generalmente la mejor posici\u00f3n para la doma de la cabeza es de aproximadamente 12-18 pulgadas (30-45 cent\u00edmetros) de la c\u00e1mara, con la cabeza centrada en relaci\u00f3n con la pantalla de la computadora.", + "You may be able to complete the image capture procedure without assistance, but it may take a couple of submission attempts to get the camera positioning right. Optimal camera positioning varies with each computer, but generally, the best position for a photo of an ID card is 8-12 inches (20-30 centimeters) from the camera, with the ID card centered relative to the camera. ": "Es posible que pueda completar el procedimiento de captura de im\u00e1genes sin ayuda, pero puede tomar un par de intentos de env\u00edo para obtener la posici\u00f3n correcta de la c\u00e1mara. El posicionamiento \u00f3ptimo de la c\u00e1mara var\u00eda con cada computadora, pero en general, la mejor posici\u00f3n para una foto de una tarjeta de identificaci\u00f3n es de 8 a 12 pulgadas (20-30 cent\u00edmetros) de la c\u00e1mara, con la tarjeta de identificaci\u00f3n centrada en relaci\u00f3n con la c\u00e1mara.", "You must be over 13 to share a full profile. If you are over 13, make sure that you have specified a birth year on the {account_settings_page_link}": "Debes tener 13 a\u00f1os o m\u00e1s para compartir un perfil completo. Si tienes m\u00e1s de esta edad, aseg\u00farate que has especificado un a\u00f1o de nacimiento en {account_settings_page_link}", "You must enter a valid email address in order to add a new team member": "Se debe introducir un email valido para adicionar un nuevo miembro en el equipo. ", "You must provide a learner name.": "Debe ingresar un nombre.", @@ -2162,13 +2276,13 @@ "You must specify a name": "Debes especificar un nombre", "You must specify a name for the cohort": "Debes especificar un nombre para el cohorte", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "Debes especificar un a\u00f1o de nacimiento antes de poder compartir tu perfil completo. Para definir un a\u00f1o de nacimiento, visita {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Necesita el documento de identidad, licencia de conducir, pasaporte u otra identificaci\u00f3n certificada por el gobierno, que contenga su foto y nombre.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Necesitas un ID con tu nombre y foto. Licencia, pasaporte, c\u00e9dula todos son aceptados.", + "You need a device that has a webcam. If you receive a browser prompt for access to your camera, please make sure to click 'Allow'.": "Necesita un dispositivo que tenga una c\u00e1mara web. Si recibe un mensaje del navegador para acceder a su c\u00e1mara, aseg\u00farese de hacer clic en \"Permitir\".", + "You need a valid ID that contains your full name and photo.": "Necesita un ID v\u00e1lida que contenga su nombre completo y foto.", + "You need an ID with your name and photo. A driver's license, passport, or ID are all acceptable.": "Necesita un documento de identificaci\u00f3n con su nombre y foto. Licencia de conducir, pasaporte o c\u00e9dula son aceptados.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Necesita activar la cuenta antes de que pueda registrarse para el curso. Revise su bandeja de entrada que un correo electr\u00f3nico de activaci\u00f3n fue enviado.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Necesita activar la cuenta antes de que pueda registrarse para el curso. Revise su bandeja de entrada que un correo electr\u00f3nico de activaci\u00f3n fue enviado. Una vez haya completado la activaci\u00f3n puede regresar y recargar esta p\u00e1gina.", "You receive messages from {platform_name} and course teams at this address.": "Recibe mensajes de {platform_name} y equipos del curso en esta direcci\u00f3n.", "You reserve all rights for your work": "Te reservas todos los derechos por tu trabajo", - "You still need to visit the %(display_name)s website to complete the credit process.": "Todav\u00eda debe visitar el sitio web de %(display_name)s para completar el proceso de cr\u00e9dito.", "You submitted {filename}; only {allowedFiles} are allowed.": "Tu enviaste {filename}; solamente se permiten {allowedFiles}.", "You waive some rights for your work, such that others can use it too": "Renuncias a algunos derechos de tu trabajo para que otros puedan usarlo tambi\u00e9n. ", "You will be refunded the amount you paid.": "Se le devolver\u00e1 el valor pagado.", @@ -2238,6 +2352,7 @@ "and others": "y otros", "anonymous": "an\u00f3nimo", "answer": "pregunta", + "answered question": "pregunta respondida", "asset_path is required": "Se requiere la ruta_del_recurso", "bytes": "bytes", "certificate": "certificado", @@ -2251,6 +2366,8 @@ "delete chapter": "borrar cap\u00edtulo", "delete group": "borrar grupo", "details about the failure": "detalles sobre la falla", + "discussion": "discusi\u00f3n", + "discussion posted %(time_ago)s by %(author)s": "discusi\u00f3n publicada hace %(time_ago)s por %(author)s", "dragging": "arrastrando", "dragging out of slider": "arrastrando fuera del carrusel", "dropped in slider": "soltada en el carrusel", @@ -2260,16 +2377,20 @@ "e.g. 'http://google.com'": "p.ej. 'https://google.com'", "e.g. johndoe@example.com, JaneDoe, joeydoe@example.com": "ej. johndoe@example.com, JaneDoe, joeydoe@example.com", "emphasized text": "texto enfatizado", + "endorsed %(time_ago)s": "Validado hace %(time_ago)s", + "endorsed %(time_ago)s by %(user)s": "Validado hace %(time_ago)s por %(user)s", "enter code here": "ingresa el c\u00f3digo aqu\u00ed", "enter link description here": "Ingresa la descripci\u00f3n del v\u00ednculo aqu\u00ed", + "follow this post": "sigue esta publicaci\u00f3n", "for": "para", - "for {courseName}": "Para {courseName}", "group configuration": "Configuraci\u00f3n de Grupo", "image omitted": "imagen omitida", "incorrect": "incorrecto", "internally reviewed": "revisado internamente", "last activity": "\u00faltima actividad", "less than a minute": "menos de un minuto", + "marked as answer %(time_ago)s": "marcado como respuesta hace %(time_ago)s", + "marked as answer %(time_ago)s by %(user)s": "marcado como respuesta hace %(time_ago)s por %(user)s", "minute": "minuto", "minutes": "minutos", "name": "nombre", @@ -2288,11 +2409,15 @@ "or sign in with": "o inicie sesi\u00f3n con", "path/to/introductionToCookieBaking-CH{order}.pdf": "path/to/introductionToCookieBaking-CH{order}.pdf", "pending": "pendiente", + "post anonymously": "Escribe una publicaci\u00f3n de forma an\u00f3nima", + "post anonymously to classmates": "publica an\u00f3nimamente a tus compa\u00f1eros de curso", + "posted %(time_ago)s by %(author)s": "publicado hace %(time_ago)s por %(author)s", "practice": "pr\u00e1ctica", "price": "precio", "proctored": "supervisado", "provide the title/name of the chapter that will be used in navigating": "Ingrese el t\u00edtulo / nombre del cap\u00edtulo que se usar\u00e1", "provide the title/name of the text book as you would like your students to see it": "ingrese el t\u00edtulo / nombre del libro de texto como ser\u00e1 visto por los estudiantes", + "question posted %(time_ago)s by %(author)s": "pregunta publicada hace %(time_ago)s por %(author)s", "remove": "eliminar", "remove all": "eliminar todo", "satisfactory": "adecuado", @@ -2305,6 +2430,7 @@ "team count": "Cantidad de equipos", "text_word_{uniqueId}": "text_word_{uniqueId}", "text_word_{uniqueId} title_word_{uniqueId}": "text_word_{uniqueId} title_word_{uniqueId}", + "the more quickly and helpfully we can respond!": "\u00a1lo m\u00e1s r\u00e1pido y servicial que podemos responder!", "there is currently {numVotes} vote": [ "actualmente hay {numVotes} voto", "actualmente hay {numVotes} votos" @@ -2313,6 +2439,7 @@ "title_word_{uniqueId}": "title_word_{uniqueId}", "toggle chapter %(displayName)s": "cambiar cap\u00edtulo %(displayName)s", "toggle subsection %(displayName)s": "cambiar subsecci\u00f3n %(displayName)s", + "unanswered question": "pregunta sin responder", "unit": "unidad", "unsatisfactory": "inadecuado", "unsubmitted": "No enviado", @@ -2330,6 +2457,15 @@ "{categoryText} in {parentDisplayname}": "{categoryText} en {parentDisplayname}", "{currentCountOpeningTag}{currentCharacterCount}{currentCountClosingTag} of {maxCharacters}": "{currentCountOpeningTag}{currentCharacterCount}{currentCountClosingTag} de {maxCharacters}", "{display_name} Settings": "Ajustes de configuraci\u00f3n para {display_name} ", + "{download_link_start}Download this image (right-click or option-click, save as){link_end} and then {upload_link_start}upload{link_end} it to your backpack.": "{download_link_start}descargar esta imagen (clic derecho, guardar como){link_end} y luego {upload_link_start} carguela {link_end} a su bolsa en Mozilla Backpack.", + "{earned}/{possible} point (graded)": [ + "{earned}/{possible} punto (calificado)", + "{earned}/{possible} puntos (calificado)" + ], + "{earned}/{possible} point (ungraded)": [ + "{earned}/{possible} punto (no calificado)", + "{earned}/{possible} puntos (no calificado)" + ], "{email}": "{email}", "{email} is already on the {container} team. Recheck the email address if you want to add a new member.": "{email} ya est\u00e1 en el equipo de {container}. Verifique nuevamente la direcic\u00f3n de correo si desea a\u00f1adir un nuevo miembro.", "{filename} exceeds maximum size of {maxFileSizeInGB} GB.": "El archivo {filename} excede el tama\u00f1o m\u00e1ximo de {maxFileSizeInGB} GB.", @@ -2371,8 +2507,25 @@ "{num_of_hours} hours": "{num_of_hours} horas", "{num_of_minutes} minute": "{num_of_minutes} minuto", "{num_of_minutes} minutes": "{num_of_minutes} minutos", + "{num_points} point possible (graded)": [ + "{num_points} punto posible (calificable)", + "{num_points} puntos posibles (calificables)" + ], + "{num_points} point possible (graded, results hidden)": [ + "{num_points} punto posible (calificable, resultado oculto)", + "{num_points} puntos posibles (calificables, resultados ocultos)" + ], + "{num_points} point possible (ungraded)": [ + "{num_points} punto posible (no calificable)", + "{num_points} puntos posibles (no calificables)" + ], + "{num_points} point possible (ungraded, results hidden)": [ + "{num_points} punto posible (no calificable, resultado oculto)", + "{num_points} puntos posibles (no calificables, resultados ocultos)" + ], "{organization}\\'s logo": "Logo de la {organization}", "{paragraphStart}You entered {boldStart}{email}{boldEnd}. If this email address is associated with your {platform_name} account, we will send a message with password recovery instructions to this email address.{paragraphEnd}{paragraphStart}If you do not receive a password reset message after 1 minute, verify that you entered the correct email address, or check your spam folder.{paragraphEnd}{paragraphStart}If you need further assistance, {anchorStart}contact technical support{anchorEnd}.{paragraphEnd}": "{paragraphStart}Has escrito {boldStart}{email}{boldEnd}. Si este correo electr\u00f3nico est\u00e1 asociado a tu cuenta {platform_name}, te enviaremos un correo con las instrucciones para recuperar tu contrase\u00f1a a este correo electr\u00f3nico. {paragraphEnd}{paragraphStart}Si no recibes el correo de restablecimiento de contrase\u00f1a despu\u00e9s de 1 minuto, verifica que escribiste la direcci\u00f3n de correo correcta o mira en tu carpeta de correo no deseado.{paragraphEnd}{paragraphStart}Si necesitas m\u00e1s ayuda, {anchorStart}contacta con soporte t\u00e9cnico{anchorEnd}.{paragraphEnd}", + "{paragraph}=p;{preformatted}=pre;{heading3}=h3;{heading4}=h4;{heading5}=h5;{heading6}=h6": "{paragraph}=p;{preformatted}=pre;{heading3}=h3;{heading4}=h4;{heading5}=h5;{heading6}=h6", "{screen_reader_start}Warning:{screen_reader_end} No content groups exist.": "{screen_reader_start}Advertencia:{screen_reader_end} No existe ning\u00fan grupo de contenido.", "{screen_reader_start}Warning:{screen_reader_end} The previously selected content group was deleted. Select another content group.": "{screen_reader_start}Advertencia:{screen_reader_end} El grupo de contenido previamente seleccionado ha sido borrado. Seleccione otro grupo de contenido.", "{seconds} {unit}": "{seconds} {unit}", @@ -2380,6 +2533,11 @@ "{sessionDates} (Open until {enrollmentEnd})": "{sessionDates} (Abierto hasta {enrollmentEnd})", "{sessionDates} - Currently Selected": "{sessionDates} - seleccionado actualmente", "{start_strong}{total}{end_strong} words submitted in total.": "{start_strong}{total}{end_strong} palabras enviadas en total.", + "{strongStart}Warning: Account deletion is permanent.{strongEnd} Please read the above carefully before proceeding. This is an irreversible action, and {strongStart}you will no longer be able to use the same email on {platformName}.{strongEnd}": "{strongStart}Advertencia: La eliminaci\u00f3n de la cuenta es permanente.{strongEnd} Por favor lea cuidadosamente la informaci\u00f3n en la parte superior antes de proceder. Esta es una acci\u00f3n irreversible, y {strongStart}no podr\u00e1 volver a usar el mismo correo electr\u00f3nico en {platformName}.{strongEnd}", + "{team_count} Team": [ + "{team_count} equipo", + "{team_count} Equipos" + ], "{totalItems} total": "{totalItems} total", "{total_results} result": [ "{total_results} resultado", @@ -2387,6 +2545,7 @@ ], "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}": "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}", "{type} Progress": "{type} Progreso", + "{unread_comments_count} new": "{unread_comments_count} nuevos", "\u2026": "..." }; for (var key in newcatalog) { @@ -2409,7 +2568,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2463,9 +2622,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/es-ar/djangojs.js b/lms/static/js/i18n/es-ar/djangojs.js index 9ebf997a285108aba512555183ed36b3a3c2d8b7..e10b8e4e89f4766582cc736ca4c419c4f313e7d3 100644 --- a/lms/static/js/i18n/es-ar/djangojs.js +++ b/lms/static/js/i18n/es-ar/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -155,9 +155,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/es-ec/djangojs.js b/lms/static/js/i18n/es-ec/djangojs.js index f8aa7d47094c0dce17243a2d17b7257bdfda827c..19d80dd5152e1887111e369d78a0eb31a2dc6e84 100644 --- a/lms/static/js/i18n/es-ec/djangojs.js +++ b/lms/static/js/i18n/es-ec/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -155,9 +155,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/es-es/djangojs.js b/lms/static/js/i18n/es-es/djangojs.js index ce63c1eab48eeeb03a266518a04d99080d74efcd..5bf397cb7ebabf587369b32f4c90dfb2e0a442a2 100644 --- a/lms/static/js/i18n/es-es/djangojs.js +++ b/lms/static/js/i18n/es-es/djangojs.js @@ -128,7 +128,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -182,9 +182,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/es-mx/djangojs.js b/lms/static/js/i18n/es-mx/djangojs.js index 89713b7e3b46201854ec85d2b137a832a09c8d5b..175107bba148f3d96f15c2df2f481be8838b5a04 100644 --- a/lms/static/js/i18n/es-mx/djangojs.js +++ b/lms/static/js/i18n/es-mx/djangojs.js @@ -25,21 +25,44 @@ "%(sel)s de %(cnt)s seleccionados/as" ], "6 a.m.": "6 a.m.", + "6 p.m.": "6 p.m.", + "April": "Abril", + "August": "Agosto", "Available %s": "Disponible %s", "Cancel": "Cancelar", "Choose": "Seleccionar", + "Choose a Date": "Elija una fecha", + "Choose a Time": "Elija una hora", "Choose a time": "Elija una hora", "Choose all": "Seleccionar todos", "Chosen %s": "%s seleccionados", "Click to choose all %s at once.": "Da click para seleccionar todos los %s de una vez.", "Click to remove all chosen %s at once.": "Da click para eliminar todos los %s seleccionados de una vez.", + "December": "Diciembre", + "February": "Febrero", "Filter": "Filtro", "Hide": "Ocultar", + "January": "Enero", + "July": "Julio", + "June": "Junio", + "March": "Marzo", + "May": "Mayo", "Midnight": "Medianoche", "Noon": "Mediod\u00eda", + "Note: You are %s hour ahead of server time.": [ + "Nota: Usted esta a %s horas por delante de la hora del servidor.", + "Nota: Usted va %s horas por delante de la hora del servidor." + ], + "Note: You are %s hour behind server time.": [ + "Nota: Usted esta a %s hora de retraso de tiempo de servidor.", + "Nota: Usted va %s horas por detr\u00e1s de la hora del servidor." + ], + "November": "Noviembre", "Now": "Ahora", + "October": "Octubre", "Remove": "Quitar", "Remove all": "Eliminar todos", + "September": "Septiembre", "Show": "Mostrar", "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "Esta es la lista de los %s disponibles. Usted puede elegir algunos seleccion\u00e1ndolos en el cuadro de abajo y haciendo click en la flecha \"Seleccionar\" entre las dos cajas.", "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "Esta es la lista de los %s elegidos. Usted puede eliminar algunos seleccion\u00e1ndolos en el cuadro de abajo y haciendo click en la flecha \"Eliminar\" entre las dos cajas.", @@ -49,7 +72,14 @@ "Yesterday": "Ayer", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "Ha seleccionado una acci\u00f3n pero no ha realizado ninguna modificaci\u00f3n en campos individuales. Es probable que lo que necesite usar en realidad sea el bot\u00f3n Ejecutar y no el bot\u00f3n Guardar.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "Ha seleccionado una acci\u00f3n, pero todav\u00eda no ha grabado las modificaciones que ha realizado en campos individuales. Por favor haga click en Aceptar para grabarlas. Necesitar\u00e1 ejecutar la acci\u00f3n nuevamente.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Tiene modificaciones sin guardar en campos modificables individuales. Si ejecuta una acci\u00f3n las mismas se perder\u00e1n." + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Tiene modificaciones sin guardar en campos modificables individuales. Si ejecuta una acci\u00f3n las mismas se perder\u00e1n.", + "one letter Friday\u0004F": "V", + "one letter Monday\u0004M": "L", + "one letter Saturday\u0004S": "S", + "one letter Sunday\u0004S": "D", + "one letter Thursday\u0004T": "J", + "one letter Tuesday\u0004T": "M", + "one letter Wednesday\u0004W": "M" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -71,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -126,12 +156,12 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", - "THOUSAND_SEPARATOR": "\u00a0", + "THOUSAND_SEPARATOR": ",", "TIME_FORMAT": "H:i", "TIME_INPUT_FORMATS": [ "%H:%M:%S", diff --git a/lms/static/js/i18n/es-pe/djangojs.js b/lms/static/js/i18n/es-pe/djangojs.js index f8aa7d47094c0dce17243a2d17b7257bdfda827c..19d80dd5152e1887111e369d78a0eb31a2dc6e84 100644 --- a/lms/static/js/i18n/es-pe/djangojs.js +++ b/lms/static/js/i18n/es-pe/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -155,9 +155,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/et-ee/djangojs.js b/lms/static/js/i18n/et-ee/djangojs.js index 00a1e6c73dd5d6f1780d13d38afc0140ff335b1f..04605d36fbd88aa7905b689f0f6724c52ea23444 100644 --- a/lms/static/js/i18n/et-ee/djangojs.js +++ b/lms/static/js/i18n/et-ee/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -165,9 +165,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/eu-es/djangojs.js b/lms/static/js/i18n/eu-es/djangojs.js index fb4b07de30088ea3ef1551fad65f629664c15b41..a981097ecd5ba507942499b239581de86af7b19e 100644 --- a/lms/static/js/i18n/eu-es/djangojs.js +++ b/lms/static/js/i18n/eu-es/djangojs.js @@ -377,7 +377,6 @@ "Default": "Berezkoa", "Default (Local Time Zone)": "Berezko (tokian tokiko ordu-eremua)", "Delete": "Ezabatu", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\"<%= signatoryName %>\" ezabatu nahi duzu sinatzaileen zerrendatik?", "Delete File Confirmation": "Fitxategia ezabatzeko konfirmazioa", "Delete My Account": "Ezabatu nire kontua", "Delete Page Confirmation": "Orria ezabatzeko konfirmazioa", @@ -505,7 +504,6 @@ "Fill browser": "Zabaldu nabigatzailea", "Filter": "Filtroa", "Filter and sort topics": "Iragazi eta ordenatu gaiak", - "Final Grade": "Azken kalifikazioa", "Financial Assistance Application": "Finantza-laguntzarako eskaria", "Find": "Bilatu", "Find a course": "Bilatu ikastaroa", @@ -529,7 +527,6 @@ "General": "Orokorra", "Generate": "Sortu", "Generate the user's certificate": "Sortu erabiltzailearen ziurtagiria", - "Get Credit": "Lortu kreditua", "Go Back": "Itzuli", "Go to Dashboard": "Joan aginte-panelera", "Go to my Dashboard": "Joan aginte-panelera", @@ -936,7 +933,6 @@ "Select a group type": "Aukeratu talde-mota", "Select a section or problem": "Aukeratu atala edo ariketa", "Select a session:": "Aukeratu saioa:", - "Select a subject for your support request.": "Aukeratu laguntza-eskaeraren gaia.", "Select all": "Aukeratu guztiak", "Select language": "Aukeratu hizkuntza", "Select one or more groups:": "Aukera talde bat edo gehiago:", @@ -1055,7 +1051,6 @@ "Textbook Name": "Testu-liburuaren izena", "Textbook information": "Testu-liburuaren informazioa", "Textbook name is required": "Testu-liburuaren izena beharrezkoa da", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Eskerrik asko %(full_name)s! Zure ordainketa jaso dugu %(course_name)s dela-eta.", "Thank you! We have received your payment for {courseName}.": "Eskerrik asko! Zure ordainketa jaso dugu {courseName} ikastarorako.", "The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "Badirudi sartu duzun URL-a e-posta helbidea dela. Nahi al duzu beharrrezko den mailto: aurrizkia gehitzea?", "The URL you entered seems to be an external link. Do you want to add the required http:// prefix?": "Badirudi sartu duzun URL-a kanporako esteka dela. Nahi al duzu beharrezko den http:// aurrizkia gehitzea?", @@ -1076,7 +1071,6 @@ "The grading process is still running. Refresh the page to see updates.": "Kalifikazio-prozesua abian da. Eguneratu orria azken emaitzak ikusteko.", "The language that team members primarily use to communicate with each other.": "Elkarrekin komunikatzeko taldeko partaideek erabiltzen duten hizkuntza nagusia.", "The language used throughout this site. This site is currently available in a limited number of languages. Changing the value of this field will cause the page to refresh.": "Gunean zehar erabilitako hizkuntza. Gune honetan hizkuntza kopuru mugatua dago eskura eskura. Eremu honetan balorea aldatzeak orria freskatuko du.", - "The more you tell us, the more quickly and helpfully we can respond!": "Zenbat eta gehiago esan, orduan eta azkarrago eta hobeto erantzungo dizugu!", "The name that identifies you on {platform_name}. You cannot change your username.": "{platform_name} plataforman identifikatzen zaituen izena. Ezin duzu erabiltzaile-izena aldatu.", "The selected content group does not exist": "Aukeratutako eduki-taldea ez da existitzen", "The server could not be contacted.": "Ezin izan da zerbitzariarekin konektatu.", @@ -1214,7 +1208,6 @@ "Verification Deadline": "Egiaztatzeko azken data", "Verified": "Egiaztatuta", "Verified Certificate": "Egiaztatutako ziurtagiria", - "Verify Now": "Egiaztatu orain!", "Version": "Bertsioa", "Vertical space": "Espazio bertikala", "Very loud": "Oso altu", @@ -1465,7 +1458,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1499,7 +1492,7 @@ /* formatting library */ django.formats = { - "DATETIME_FORMAT": "N j, Y, P", + "DATETIME_FORMAT": "Y\\k\\o N j\\a, H:i", "DATETIME_INPUT_FORMATS": [ "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", @@ -1529,11 +1522,11 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", - "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", - "SHORT_DATETIME_FORMAT": "m/d/Y P", - "SHORT_DATE_FORMAT": "Y M j", + "FIRST_DAY_OF_WEEK": 1, + "MONTH_DAY_FORMAT": "F\\r\\e\\n j\\a", + "NUMBER_GROUPING": 3, + "SHORT_DATETIME_FORMAT": "Y-m-d H:i", + "SHORT_DATE_FORMAT": "Y-m-d", "THOUSAND_SEPARATOR": ".", "TIME_FORMAT": "H:i", "TIME_INPUT_FORMATS": [ @@ -1541,7 +1534,7 @@ "%H:%M:%S.%f", "%H:%M" ], - "YEAR_MONTH_FORMAT": "F Y" + "YEAR_MONTH_FORMAT": "Y\\k\\o F" }; django.get_format = function(format_type) { diff --git a/lms/static/js/i18n/fa-ir/djangojs.js b/lms/static/js/i18n/fa-ir/djangojs.js index 34ca6f67a61fc264dfa84c62ee2e65c43158c74f..17e5f1e50af3a87bef785ebdc4f8329ec855287b 100644 --- a/lms/static/js/i18n/fa-ir/djangojs.js +++ b/lms/static/js/i18n/fa-ir/djangojs.js @@ -6,7 +6,7 @@ django.pluralidx = function(n) { - var v=0; + var v=(n > 1); if (typeof(v) == 'boolean') { return v ? 1 : 0; } else { @@ -21,6 +21,7 @@ var newcatalog = { "%(sel)s of %(cnt)s selected": [ + " %(sel)s \u0627\u0632 %(cnt)s \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647\u200c\u0627\u0646\u062f", " %(sel)s \u0627\u0632 %(cnt)s \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647\u200c\u0627\u0646\u062f" ], "6 a.m.": "\u06f6 \u0635\u0628\u062d", @@ -49,9 +50,11 @@ "Midnight": "\u0646\u06cc\u0645\u0647\u200c\u0634\u0628", "Noon": "\u0638\u0647\u0631", "Note: You are %s hour ahead of server time.": [ + "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u062c\u0644\u0648 \u0647\u0633\u062a\u06cc\u062f.", "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u062c\u0644\u0648 \u0647\u0633\u062a\u06cc\u062f." ], "Note: You are %s hour behind server time.": [ + "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u0639\u0642\u0628 \u0647\u0633\u062a\u06cc\u062f.", "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u0639\u0642\u0628 \u0647\u0633\u062a\u06cc\u062f." ], "November": "\u0646\u0648\u0627\u0645\u0628\u0631", @@ -98,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -162,9 +165,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "6", + "FIRST_DAY_OF_WEEK": 6, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "Y/n/j\u060c\u200f G:i", "SHORT_DATE_FORMAT": "Y/n/j", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/fa/djangojs.js b/lms/static/js/i18n/fa/djangojs.js index 34ca6f67a61fc264dfa84c62ee2e65c43158c74f..17e5f1e50af3a87bef785ebdc4f8329ec855287b 100644 --- a/lms/static/js/i18n/fa/djangojs.js +++ b/lms/static/js/i18n/fa/djangojs.js @@ -6,7 +6,7 @@ django.pluralidx = function(n) { - var v=0; + var v=(n > 1); if (typeof(v) == 'boolean') { return v ? 1 : 0; } else { @@ -21,6 +21,7 @@ var newcatalog = { "%(sel)s of %(cnt)s selected": [ + " %(sel)s \u0627\u0632 %(cnt)s \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647\u200c\u0627\u0646\u062f", " %(sel)s \u0627\u0632 %(cnt)s \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647\u200c\u0627\u0646\u062f" ], "6 a.m.": "\u06f6 \u0635\u0628\u062d", @@ -49,9 +50,11 @@ "Midnight": "\u0646\u06cc\u0645\u0647\u200c\u0634\u0628", "Noon": "\u0638\u0647\u0631", "Note: You are %s hour ahead of server time.": [ + "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u062c\u0644\u0648 \u0647\u0633\u062a\u06cc\u062f.", "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u062c\u0644\u0648 \u0647\u0633\u062a\u06cc\u062f." ], "Note: You are %s hour behind server time.": [ + "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u0639\u0642\u0628 \u0647\u0633\u062a\u06cc\u062f.", "\u062a\u0648\u062c\u0647: \u0634\u0645\u0627 %s \u0633\u0627\u0639\u062a \u0627\u0632 \u0632\u0645\u0627\u0646 \u0633\u0631\u0648\u0631 \u0639\u0642\u0628 \u0647\u0633\u062a\u06cc\u062f." ], "November": "\u0646\u0648\u0627\u0645\u0628\u0631", @@ -98,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -162,9 +165,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "6", + "FIRST_DAY_OF_WEEK": 6, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "Y/n/j\u060c\u200f G:i", "SHORT_DATE_FORMAT": "Y/n/j", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/fake2/djangojs.js b/lms/static/js/i18n/fake2/djangojs.js index 0c2c86c25ab39e2ff087090c02f66ce2a7989bbc..30a4c73c2bef614dc4d7f138ffd260fce01859be 100644 --- a/lms/static/js/i18n/fake2/djangojs.js +++ b/lms/static/js/i18n/fake2/djangojs.js @@ -27,6 +27,7 @@ " M\u01dd\u026fb\u01dd\u0279s" ], " and ": " \u0250nd ", + " as many questions may have already been answered.": " \u0250s \u026f\u0250n\u028e bn\u01dds\u0287\u1d09\u00f8ns \u026f\u0250\u028e \u0265\u0250\u028c\u01dd \u0250l\u0279\u01dd\u0250d\u028e b\u01dd\u01ddn \u0250ns\u028d\u01dd\u0279\u01ddd.", " learner does not exist in LMS and not added to the exception list": " l\u01dd\u0250\u0279n\u01dd\u0279 d\u00f8\u01dds n\u00f8\u0287 \u01ddx\u1d09s\u0287 \u1d09n \u0141MS \u0250nd n\u00f8\u0287 \u0250dd\u01ddd \u0287\u00f8 \u0287\u0265\u01dd \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8n l\u1d09s\u0287", " learner is already white listed and not added to the exception list": " l\u01dd\u0250\u0279n\u01dd\u0279 \u1d09s \u0250l\u0279\u01dd\u0250d\u028e \u028d\u0265\u1d09\u0287\u01dd l\u1d09s\u0287\u01ddd \u0250nd n\u00f8\u0287 \u0250dd\u01ddd \u0287\u00f8 \u0287\u0265\u01dd \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8n l\u1d09s\u0287", " learner is not enrolled in course and not added to the exception list": " l\u01dd\u0250\u0279n\u01dd\u0279 \u1d09s n\u00f8\u0287 \u01ddn\u0279\u00f8ll\u01ddd \u1d09n \u0254\u00f8n\u0279s\u01dd \u0250nd n\u00f8\u0287 \u0250dd\u01ddd \u0287\u00f8 \u0287\u0265\u01dd \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8n l\u1d09s\u0287", @@ -39,6 +40,8 @@ " records are not in correct format and not added to the exception list": " \u0279\u01dd\u0254\u00f8\u0279ds \u0250\u0279\u01dd n\u00f8\u0287 \u1d09n \u0254\u00f8\u0279\u0279\u01dd\u0254\u0287 \u025f\u00f8\u0279\u026f\u0250\u0287 \u0250nd n\u00f8\u0287 \u0250dd\u01ddd \u0287\u00f8 \u0287\u0265\u01dd \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8n l\u1d09s\u0287", "${listPrice}": "${listPrice}", "%(cohort_name)s (%(user_count)s)": "%(cohort_name)s (%(user_count)s)", + "%(comments_count)s %(span_sr_open)scomments %(span_close)s": "%(comments_count)s %(span_sr_open)s\u0254\u00f8\u026f\u026f\u01ddn\u0287s %(span_close)s", + "%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s unread comments)%(span_close)s": "%(comments_count)s %(span_sr_open)s\u0254\u00f8\u026f\u026f\u01ddn\u0287s (%(unread_comments_count)s nn\u0279\u01dd\u0250d \u0254\u00f8\u026f\u026f\u01ddn\u0287s)%(span_close)s", "%(errorCount)s error found in form.": [ "%(errorCount)s \u01dd\u0279\u0279\u00f8\u0279 \u025f\u00f8nnd \u1d09n \u025f\u00f8\u0279\u026f.", "%(errorCount)s \u01dd\u0279\u0279\u00f8\u0279s \u025f\u00f8nnd \u1d09n \u025f\u00f8\u0279\u026f." @@ -80,6 +83,7 @@ "%s from now": "%s \u025f\u0279\u00f8\u026f n\u00f8\u028d", "(Add signatories for a certificate)": "(\u023add s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u1d09\u01dds \u025f\u00f8\u0279 \u0250 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd)", "(Caption will be displayed when you start playing the video.)": "(\u023b\u0250d\u0287\u1d09\u00f8n \u028d\u1d09ll b\u01dd d\u1d09sdl\u0250\u028e\u01ddd \u028d\u0265\u01ddn \u028e\u00f8n s\u0287\u0250\u0279\u0287 dl\u0250\u028e\u1d09n\u0183 \u0287\u0265\u01dd \u028c\u1d09d\u01dd\u00f8.)", + "(Community TA)": "(\u023b\u00f8\u026f\u026fnn\u1d09\u0287\u028e \u0166\u023a)", "(Optional)": "(\u00d8d\u0287\u1d09\u00f8n\u0250l)", "(Read-only)": "(\u024c\u01dd\u0250d-\u00f8nl\u028e)", "(Required Field)": "(\u024c\u01ddbn\u1d09\u0279\u01ddd F\u1d09\u01ddld)", @@ -87,6 +91,7 @@ "(Self-paced) Ends {end}": "(S\u01ddl\u025f-d\u0250\u0254\u01ddd) \u0246nds {end}", "(Self-paced) Started {start}": "(S\u01ddl\u025f-d\u0250\u0254\u01ddd) S\u0287\u0250\u0279\u0287\u01ddd {start}", "(Self-paced) Starts {start}": "(S\u01ddl\u025f-d\u0250\u0254\u01ddd) S\u0287\u0250\u0279\u0287s {start}", + "(Staff)": "(S\u0287\u0250\u025f\u025f)", "(contains %(student_count)s student)": [ "(\u0254\u00f8n\u0287\u0250\u1d09ns %(student_count)s s\u0287nd\u01ddn\u0287)", "(\u0254\u00f8n\u0287\u0250\u1d09ns %(student_count)s s\u0287nd\u01ddn\u0287s)" @@ -145,7 +150,12 @@ "Add URLs for additional versions": "\u023add \u0244\u024c\u0141s \u025f\u00f8\u0279 \u0250dd\u1d09\u0287\u1d09\u00f8n\u0250l \u028c\u01dd\u0279s\u1d09\u00f8ns", "Add a Chapter": "\u023add \u0250 \u023b\u0265\u0250d\u0287\u01dd\u0279", "Add a New Cohort": "\u023add \u0250 N\u01dd\u028d \u023b\u00f8\u0265\u00f8\u0279\u0287", + "Add a Post": "\u023add \u0250 \u2c63\u00f8s\u0287", + "Add a Response": "\u023add \u0250 \u024c\u01ddsd\u00f8ns\u01dd", + "Add a clear and descriptive title to encourage participation. (Required)": "\u023add \u0250 \u0254l\u01dd\u0250\u0279 \u0250nd d\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u028c\u01dd \u0287\u1d09\u0287l\u01dd \u0287\u00f8 \u01ddn\u0254\u00f8n\u0279\u0250\u0183\u01dd d\u0250\u0279\u0287\u1d09\u0254\u1d09d\u0250\u0287\u1d09\u00f8n. (\u024c\u01ddbn\u1d09\u0279\u01ddd)", + "Add a comment": "\u023add \u0250 \u0254\u00f8\u026f\u026f\u01ddn\u0287", "Add a learning outcome here": "\u023add \u0250 l\u01dd\u0250\u0279n\u1d09n\u0183 \u00f8n\u0287\u0254\u00f8\u026f\u01dd \u0265\u01dd\u0279\u01dd", + "Add a response:": "\u023add \u0250 \u0279\u01ddsd\u00f8ns\u01dd:", "Add another group": "\u023add \u0250n\u00f8\u0287\u0265\u01dd\u0279 \u0183\u0279\u00f8nd", "Add language": "\u023add l\u0250n\u0183n\u0250\u0183\u01dd", "Add learners to this cohort": "\u023add l\u01dd\u0250\u0279n\u01dd\u0279s \u0287\u00f8 \u0287\u0265\u1d09s \u0254\u00f8\u0265\u00f8\u0279\u0287", @@ -155,6 +165,7 @@ "Add your first content group": "\u023add \u028e\u00f8n\u0279 \u025f\u1d09\u0279s\u0287 \u0254\u00f8n\u0287\u01ddn\u0287 \u0183\u0279\u00f8nd", "Add your first group configuration": "\u023add \u028e\u00f8n\u0279 \u025f\u1d09\u0279s\u0287 \u0183\u0279\u00f8nd \u0254\u00f8n\u025f\u1d09\u0183n\u0279\u0250\u0287\u1d09\u00f8n", "Add your first textbook": "\u023add \u028e\u00f8n\u0279 \u025f\u1d09\u0279s\u0287 \u0287\u01ddx\u0287b\u00f8\u00f8\u029e", + "Add your post to a relevant topic to help others find it. (Required)": "\u023add \u028e\u00f8n\u0279 d\u00f8s\u0287 \u0287\u00f8 \u0250 \u0279\u01ddl\u01dd\u028c\u0250n\u0287 \u0287\u00f8d\u1d09\u0254 \u0287\u00f8 \u0265\u01ddld \u00f8\u0287\u0265\u01dd\u0279s \u025f\u1d09nd \u1d09\u0287. (\u024c\u01ddbn\u1d09\u0279\u01ddd)", "Add {role} Access": "\u023add {role} \u023a\u0254\u0254\u01ddss", "Adding": "\u023add\u1d09n\u0183", "Adding the selected course to your cart": "\u023add\u1d09n\u0183 \u0287\u0265\u01dd s\u01ddl\u01dd\u0254\u0287\u01ddd \u0254\u00f8n\u0279s\u01dd \u0287\u00f8 \u028e\u00f8n\u0279 \u0254\u0250\u0279\u0287", @@ -173,6 +184,7 @@ "Align left": "\u023al\u1d09\u0183n l\u01dd\u025f\u0287", "Align right": "\u023al\u1d09\u0183n \u0279\u1d09\u0183\u0265\u0287", "Alignment": "\u023al\u1d09\u0183n\u026f\u01ddn\u0287", + "All Groups": "\u023all \u01e4\u0279\u00f8nds", "All Learners and Staff": "\u023all \u0141\u01dd\u0250\u0279n\u01dd\u0279s \u0250nd S\u0287\u0250\u025f\u025f", "All Posts": "\u023all \u2c63\u00f8s\u0287s", "All Rights Reserved": "\u023all \u024c\u1d09\u0183\u0265\u0287s \u024c\u01dds\u01dd\u0279\u028c\u01ddd", @@ -254,6 +266,7 @@ "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "\u023a\u0279\u01dd \u028e\u00f8n sn\u0279\u01dd \u028e\u00f8n \u028d\u1d09s\u0265 \u0287\u00f8 d\u01ddl\u01dd\u0287\u01dd \u0287\u0265\u1d09s \u1d09\u0287\u01dd\u026f. \u0197\u0287 \u0254\u0250nn\u00f8\u0287 b\u01dd \u0279\u01dd\u028c\u01dd\u0279s\u01ddd!\n\n\u023als\u00f8 \u0250n\u028e \u0254\u00f8n\u0287\u01ddn\u0287 \u0287\u0265\u0250\u0287 l\u1d09n\u029es/\u0279\u01dd\u025f\u01dd\u0279s \u0287\u00f8 \u0287\u0265\u1d09s \u1d09\u0287\u01dd\u026f \u028d\u1d09ll n\u00f8 l\u00f8n\u0183\u01dd\u0279 \u028d\u00f8\u0279\u029e (\u01dd.\u0183. b\u0279\u00f8\u029e\u01ddn \u1d09\u026f\u0250\u0183\u01dds \u0250nd/\u00f8\u0279 l\u1d09n\u029es)", "Are you sure?": "\u023a\u0279\u01dd \u028e\u00f8n sn\u0279\u01dd?", "As part of the verification process, you take a photo of both your face and a government-issued photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u023as d\u0250\u0279\u0287 \u00f8\u025f \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss, \u028e\u00f8n \u0287\u0250\u029e\u01dd \u0250 d\u0265\u00f8\u0287\u00f8 \u00f8\u025f b\u00f8\u0287\u0265 \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd \u0250nd \u0250 \u0183\u00f8\u028c\u01dd\u0279n\u026f\u01ddn\u0287-\u1d09ssn\u01ddd d\u0265\u00f8\u0287\u00f8 \u0197\u0110. \u00d8n\u0279 \u0250n\u0287\u0265\u00f8\u0279\u1d09z\u0250\u0287\u1d09\u00f8n s\u01dd\u0279\u028c\u1d09\u0254\u01dd \u0254\u00f8n\u025f\u1d09\u0279\u026fs \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e b\u028e \u0254\u00f8\u026fd\u0250\u0279\u1d09n\u0183 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u028e\u00f8n \u0287\u0250\u029e\u01dd \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8n \u028e\u00f8n\u0279 \u0197\u0110.", + "As part of the verification process, you take a photo of both your face and a photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u023as d\u0250\u0279\u0287 \u00f8\u025f \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss, \u028e\u00f8n \u0287\u0250\u029e\u01dd \u0250 d\u0265\u00f8\u0287\u00f8 \u00f8\u025f b\u00f8\u0287\u0265 \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd \u0250nd \u0250 d\u0265\u00f8\u0287\u00f8 \u0197\u0110. \u00d8n\u0279 \u0250n\u0287\u0265\u00f8\u0279\u1d09z\u0250\u0287\u1d09\u00f8n s\u01dd\u0279\u028c\u1d09\u0254\u01dd \u0254\u00f8n\u025f\u1d09\u0279\u026fs \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e b\u028e \u0254\u00f8\u026fd\u0250\u0279\u1d09n\u0183 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u028e\u00f8n \u0287\u0250\u029e\u01dd \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8n \u028e\u00f8n\u0279 \u0197\u0110.", "As you complete courses, you will see them listed here.": "\u023as \u028e\u00f8n \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0254\u00f8n\u0279s\u01dds, \u028e\u00f8n \u028d\u1d09ll s\u01dd\u01dd \u0287\u0265\u01dd\u026f l\u1d09s\u0287\u01ddd \u0265\u01dd\u0279\u01dd.", "Assessment Results Visibility": "\u023ass\u01ddss\u026f\u01ddn\u0287 \u024c\u01ddsnl\u0287s V\u1d09s\u1d09b\u1d09l\u1d09\u0287\u028e", "Assign Team Memberships": "\u023ass\u1d09\u0183n \u0166\u01dd\u0250\u026f M\u01dd\u026fb\u01dd\u0279s\u0265\u1d09ds", @@ -381,6 +394,7 @@ "Click to edit": "\u023bl\u1d09\u0254\u029e \u0287\u00f8 \u01ddd\u1d09\u0287", "Close": "\u023bl\u00f8s\u01dd", "Close Calculator": "\u023bl\u00f8s\u01dd \u023b\u0250l\u0254nl\u0250\u0287\u00f8\u0279", + "Closed": "\u023bl\u00f8s\u01ddd", "Code": "\u023b\u00f8d\u01dd", "Code Sample (Ctrl+K)": "\u023b\u00f8d\u01dd S\u0250\u026fdl\u01dd (\u023b\u0287\u0279l+\ua740)", "Code block": "\u023b\u00f8d\u01dd bl\u00f8\u0254\u029e", @@ -399,6 +413,7 @@ "Coming Soon": "\u023b\u00f8\u026f\u1d09n\u0183 S\u00f8\u00f8n", "Commentary": "\u023b\u00f8\u026f\u026f\u01ddn\u0287\u0250\u0279\u028e", "Common Problem Types": "\u023b\u00f8\u026f\u026f\u00f8n \u2c63\u0279\u00f8bl\u01dd\u026f \u0166\u028ed\u01dds", + "Community TA": "\u023b\u00f8\u026f\u026fnn\u1d09\u0287\u028e \u0166\u023a", "Complete courses on your schedule to ensure you stand out in your field!": "\u023b\u00f8\u026fdl\u01dd\u0287\u01dd \u0254\u00f8n\u0279s\u01dds \u00f8n \u028e\u00f8n\u0279 s\u0254\u0265\u01dddnl\u01dd \u0287\u00f8 \u01ddnsn\u0279\u01dd \u028e\u00f8n s\u0287\u0250nd \u00f8n\u0287 \u1d09n \u028e\u00f8n\u0279 \u025f\u1d09\u01ddld!", "Completed": "\u023b\u00f8\u026fdl\u01dd\u0287\u01ddd", "Component": "\u023b\u00f8\u026fd\u00f8n\u01ddn\u0287", @@ -445,6 +460,7 @@ ], "Course Content": "\u023b\u00f8n\u0279s\u01dd \u023b\u00f8n\u0287\u01ddn\u0287", "Course Credit Requirements": "\u023b\u00f8n\u0279s\u01dd \u023b\u0279\u01ddd\u1d09\u0287 \u024c\u01ddbn\u1d09\u0279\u01dd\u026f\u01ddn\u0287s", + "Course Discussion Forum": "\u023b\u00f8n\u0279s\u01dd \u0110\u1d09s\u0254nss\u1d09\u00f8n F\u00f8\u0279n\u026f", "Course End": "\u023b\u00f8n\u0279s\u01dd \u0246nd", "Course Handouts": "\u023b\u00f8n\u0279s\u01dd \u0126\u0250nd\u00f8n\u0287s", "Course ID": "\u023b\u00f8n\u0279s\u01dd \u0197\u0110", @@ -467,6 +483,7 @@ "Create": "\u023b\u0279\u01dd\u0250\u0287\u01dd", "Create Account": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u023a\u0254\u0254\u00f8nn\u0287", "Create Re-run": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u024c\u01dd-\u0279nn", + "Create Support Ticket": "\u023b\u0279\u01dd\u0250\u0287\u01dd Sndd\u00f8\u0279\u0287 \u0166\u1d09\u0254\u029e\u01dd\u0287", "Create a New Team": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250 N\u01dd\u028d \u0166\u01dd\u0250\u026f", "Create a content group": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250 \u0254\u00f8n\u0287\u01ddn\u0287 \u0183\u0279\u00f8nd", "Create a new team if you can't find an existing team to join, or if you would like to learn with friends you know.": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250 n\u01dd\u028d \u0287\u01dd\u0250\u026f \u1d09\u025f \u028e\u00f8n \u0254\u0250n'\u0287 \u025f\u1d09nd \u0250n \u01ddx\u1d09s\u0287\u1d09n\u0183 \u0287\u01dd\u0250\u026f \u0287\u00f8 \u027e\u00f8\u1d09n, \u00f8\u0279 \u1d09\u025f \u028e\u00f8n \u028d\u00f8nld l\u1d09\u029e\u01dd \u0287\u00f8 l\u01dd\u0250\u0279n \u028d\u1d09\u0287\u0265 \u025f\u0279\u1d09\u01ddnds \u028e\u00f8n \u029en\u00f8\u028d.", @@ -474,6 +491,7 @@ "Create account using %(providerName)s.": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250\u0254\u0254\u00f8nn\u0287 ns\u1d09n\u0183 %(providerName)s.", "Create an Account": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250n \u023a\u0254\u0254\u00f8nn\u0287", "Create an Account.": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250n \u023a\u0254\u0254\u00f8nn\u0287.", + "Create an account": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250n \u0250\u0254\u0254\u00f8nn\u0287", "Create an account using": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0250n \u0250\u0254\u0254\u00f8nn\u0287 ns\u1d09n\u0183", "Create team.": "\u023b\u0279\u01dd\u0250\u0287\u01dd \u0287\u01dd\u0250\u026f.", "Creating missing groups": "\u023b\u0279\u01dd\u0250\u0287\u1d09n\u0183 \u026f\u1d09ss\u1d09n\u0183 \u0183\u0279\u00f8nds", @@ -496,13 +514,14 @@ "Date Placed": "\u0110\u0250\u0287\u01dd \u2c63l\u0250\u0254\u01ddd", "Date added": "\u0110\u0250\u0287\u01dd \u0250dd\u01ddd", "Deactivate": "\u0110\u01dd\u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u01dd", + "Deactivating": "\u0110\u01dd\u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u1d09n\u0183", "Deadlines": "\u0110\u01dd\u0250dl\u1d09n\u01dds", "Decrease indent": "\u0110\u01dd\u0254\u0279\u01dd\u0250s\u01dd \u1d09nd\u01ddn\u0287", "Default": "\u0110\u01dd\u025f\u0250nl\u0287", "Default (Local Time Zone)": "\u0110\u01dd\u025f\u0250nl\u0287 (\u0141\u00f8\u0254\u0250l \u0166\u1d09\u026f\u01dd \u01b5\u00f8n\u01dd)", "Default Timed Transcript": "\u0110\u01dd\u025f\u0250nl\u0287 \u0166\u1d09\u026f\u01ddd \u0166\u0279\u0250ns\u0254\u0279\u1d09d\u0287", "Delete": "\u0110\u01ddl\u01dd\u0287\u01dd", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u0110\u01ddl\u01dd\u0287\u01dd \"<%= signatoryName %>\" \u025f\u0279\u00f8\u026f \u0287\u0265\u01dd l\u1d09s\u0287 \u00f8\u025f s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u1d09\u01dds?", + "Delete \"<%- signatoryName %>\" from the list of signatories?": "\u0110\u01ddl\u01dd\u0287\u01dd \"<%- signatoryName %>\" \u025f\u0279\u00f8\u026f \u0287\u0265\u01dd l\u1d09s\u0287 \u00f8\u025f s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u1d09\u01dds?", "Delete File Confirmation": "\u0110\u01ddl\u01dd\u0287\u01dd F\u1d09l\u01dd \u023b\u00f8n\u025f\u1d09\u0279\u026f\u0250\u0287\u1d09\u00f8n", "Delete My Account": "\u0110\u01ddl\u01dd\u0287\u01dd M\u028e \u023a\u0254\u0254\u00f8nn\u0287", "Delete Page Confirmation": "\u0110\u01ddl\u01dd\u0287\u01dd \u2c63\u0250\u0183\u01dd \u023b\u00f8n\u025f\u1d09\u0279\u026f\u0250\u0287\u1d09\u00f8n", @@ -529,11 +548,14 @@ "Description": "\u0110\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n", "Description of the certificate": "\u0110\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n \u00f8\u025f \u0287\u0265\u01dd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd", "Details": "\u0110\u01dd\u0287\u0250\u1d09ls", + "Device with Camera": "\u0110\u01dd\u028c\u1d09\u0254\u01dd \u028d\u1d09\u0287\u0265 \u023b\u0250\u026f\u01dd\u0279\u0250", "Dimensions": "\u0110\u1d09\u026f\u01ddns\u1d09\u00f8ns", "Disc": "\u0110\u1d09s\u0254", "Discard Changes": "\u0110\u1d09s\u0254\u0250\u0279d \u023b\u0265\u0250n\u0183\u01dds", "Discarding Changes": "\u0110\u1d09s\u0254\u0250\u0279d\u1d09n\u0183 \u023b\u0265\u0250n\u0183\u01dds", + "Discussion": "\u0110\u1d09s\u0254nss\u1d09\u00f8n", "Discussion Home": "\u0110\u1d09s\u0254nss\u1d09\u00f8n \u0126\u00f8\u026f\u01dd", + "Discussion admins, moderators, and TAs can make their posts visible to all students or specify a single group.": "\u0110\u1d09s\u0254nss\u1d09\u00f8n \u0250d\u026f\u1d09ns, \u026f\u00f8d\u01dd\u0279\u0250\u0287\u00f8\u0279s, \u0250nd \u0166\u023as \u0254\u0250n \u026f\u0250\u029e\u01dd \u0287\u0265\u01dd\u1d09\u0279 d\u00f8s\u0287s \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 \u0250ll s\u0287nd\u01ddn\u0287s \u00f8\u0279 sd\u01dd\u0254\u1d09\u025f\u028e \u0250 s\u1d09n\u0183l\u01dd \u0183\u0279\u00f8nd.", "Discussion topics in the course are not divided.": "\u0110\u1d09s\u0254nss\u1d09\u00f8n \u0287\u00f8d\u1d09\u0254s \u1d09n \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd \u0250\u0279\u01dd n\u00f8\u0287 d\u1d09\u028c\u1d09d\u01ddd.", "Discussions are unified; all learners interact with posts from other learners, regardless of the group they are in.": "\u0110\u1d09s\u0254nss\u1d09\u00f8ns \u0250\u0279\u01dd nn\u1d09\u025f\u1d09\u01ddd; \u0250ll l\u01dd\u0250\u0279n\u01dd\u0279s \u1d09n\u0287\u01dd\u0279\u0250\u0254\u0287 \u028d\u1d09\u0287\u0265 d\u00f8s\u0287s \u025f\u0279\u00f8\u026f \u00f8\u0287\u0265\u01dd\u0279 l\u01dd\u0250\u0279n\u01dd\u0279s, \u0279\u01dd\u0183\u0250\u0279dl\u01ddss \u00f8\u025f \u0287\u0265\u01dd \u0183\u0279\u00f8nd \u0287\u0265\u01dd\u028e \u0250\u0279\u01dd \u1d09n.", "Display Name": "\u0110\u1d09sdl\u0250\u028e N\u0250\u026f\u01dd", @@ -545,7 +567,6 @@ "Do you want to replace the edX transcript with the YouTube transcript?": "\u0110\u00f8 \u028e\u00f8n \u028d\u0250n\u0287 \u0287\u00f8 \u0279\u01dddl\u0250\u0254\u01dd \u0287\u0265\u01dd \u01dddX \u0287\u0279\u0250ns\u0254\u0279\u1d09d\u0287 \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd \u024e\u00f8n\u0166nb\u01dd \u0287\u0279\u0250ns\u0254\u0279\u1d09d\u0287?", "Document properties": "\u0110\u00f8\u0254n\u026f\u01ddn\u0287 d\u0279\u00f8d\u01dd\u0279\u0287\u1d09\u01dds", "Does the name on your ID match your account name: %(fullName)s?": "\u0110\u00f8\u01dds \u0287\u0265\u01dd n\u0250\u026f\u01dd \u00f8n \u028e\u00f8n\u0279 \u0197\u0110 \u026f\u0250\u0287\u0254\u0265 \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 n\u0250\u026f\u01dd: %(fullName)s?", - "Does the photo of you match your ID photo?": "\u0110\u00f8\u01dds \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n \u026f\u0250\u0287\u0254\u0265 \u028e\u00f8n\u0279 \u0197\u0110 d\u0265\u00f8\u0287\u00f8?", "Does the photo of you show your whole face?": "\u0110\u00f8\u01dds \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n s\u0265\u00f8\u028d \u028e\u00f8n\u0279 \u028d\u0265\u00f8l\u01dd \u025f\u0250\u0254\u01dd?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u0110\u00f8n'\u0287 s\u01dd\u01dd \u028e\u00f8n\u0279 d\u1d09\u0254\u0287n\u0279\u01dd? M\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u00f8 \u0250ll\u00f8\u028d \u028e\u00f8n\u0279 b\u0279\u00f8\u028ds\u01dd\u0279 \u0287\u00f8 ns\u01dd \u028e\u00f8n\u0279 \u0254\u0250\u026f\u01dd\u0279\u0250 \u028d\u0265\u01ddn \u1d09\u0287 \u0250s\u029es \u025f\u00f8\u0279 d\u01dd\u0279\u026f\u1d09ss\u1d09\u00f8n.", "Donate": "\u0110\u00f8n\u0250\u0287\u01dd", @@ -566,6 +587,7 @@ "Due Date:": "\u0110n\u01dd \u0110\u0250\u0287\u01dd:", "Due Time in UTC:": "\u0110n\u01dd \u0166\u1d09\u026f\u01dd \u1d09n \u0244\u0166\u023b:", "Due date cannot be before start date.": "\u0110n\u01dd d\u0250\u0287\u01dd \u0254\u0250nn\u00f8\u0287 b\u01dd b\u01dd\u025f\u00f8\u0279\u01dd s\u0287\u0250\u0279\u0287 d\u0250\u0287\u01dd.", + "Due to the recent increase in interest in online education and edX, we are currently experiencing an unusually high volume of support requests. We appreciate your patience as we work to review each request. Please check the ": "\u0110n\u01dd \u0287\u00f8 \u0287\u0265\u01dd \u0279\u01dd\u0254\u01ddn\u0287 \u1d09n\u0254\u0279\u01dd\u0250s\u01dd \u1d09n \u1d09n\u0287\u01dd\u0279\u01dds\u0287 \u1d09n \u00f8nl\u1d09n\u01dd \u01dddn\u0254\u0250\u0287\u1d09\u00f8n \u0250nd \u01dddX, \u028d\u01dd \u0250\u0279\u01dd \u0254n\u0279\u0279\u01ddn\u0287l\u028e \u01ddxd\u01dd\u0279\u1d09\u01ddn\u0254\u1d09n\u0183 \u0250n nnnsn\u0250ll\u028e \u0265\u1d09\u0183\u0265 \u028c\u00f8ln\u026f\u01dd \u00f8\u025f sndd\u00f8\u0279\u0287 \u0279\u01ddbn\u01dds\u0287s. W\u01dd \u0250dd\u0279\u01dd\u0254\u1d09\u0250\u0287\u01dd \u028e\u00f8n\u0279 d\u0250\u0287\u1d09\u01ddn\u0254\u01dd \u0250s \u028d\u01dd \u028d\u00f8\u0279\u029e \u0287\u00f8 \u0279\u01dd\u028c\u1d09\u01dd\u028d \u01dd\u0250\u0254\u0265 \u0279\u01ddbn\u01dds\u0287. \u2c63l\u01dd\u0250s\u01dd \u0254\u0265\u01dd\u0254\u029e \u0287\u0265\u01dd ", "Due:": "\u0110n\u01dd:", "Duplicate": "\u0110ndl\u1d09\u0254\u0250\u0287\u01dd", "Duplicating": "\u0110ndl\u1d09\u0254\u0250\u0287\u1d09n\u0183", @@ -585,8 +607,12 @@ "Edit Title": "\u0246d\u1d09\u0287 \u0166\u1d09\u0287l\u01dd", "Edit Your Name": "\u0246d\u1d09\u0287 \u024e\u00f8n\u0279 N\u0250\u026f\u01dd", "Edit this certificate?": "\u0246d\u1d09\u0287 \u0287\u0265\u1d09s \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd?", + "Edit your post below.": "\u0246d\u1d09\u0287 \u028e\u00f8n\u0279 d\u00f8s\u0287 b\u01ddl\u00f8\u028d.", "Editable": "\u0246d\u1d09\u0287\u0250bl\u01dd", "Editing access for: {title}": "\u0246d\u1d09\u0287\u1d09n\u0183 \u0250\u0254\u0254\u01ddss \u025f\u00f8\u0279: {title}", + "Editing comment": "\u0246d\u1d09\u0287\u1d09n\u0183 \u0254\u00f8\u026f\u026f\u01ddn\u0287", + "Editing post": "\u0246d\u1d09\u0287\u1d09n\u0183 d\u00f8s\u0287", + "Editing response": "\u0246d\u1d09\u0287\u1d09n\u0183 \u0279\u01ddsd\u00f8ns\u01dd", "Editing: {title}": "\u0246d\u1d09\u0287\u1d09n\u0183: {title}", "Editor": "\u0246d\u1d09\u0287\u00f8\u0279", "Education Completed": "\u0246dn\u0254\u0250\u0287\u1d09\u00f8n \u023b\u00f8\u026fdl\u01dd\u0287\u01ddd", @@ -604,6 +630,7 @@ "Encoding": "\u0246n\u0254\u00f8d\u1d09n\u0183", "End My Exam": "\u0246nd M\u028e \u0246x\u0250\u026f", "End of transcript. Skip to the start.": "\u0246nd \u00f8\u025f \u0287\u0279\u0250ns\u0254\u0279\u1d09d\u0287. S\u029e\u1d09d \u0287\u00f8 \u0287\u0265\u01dd s\u0287\u0250\u0279\u0287.", + "Endorse": "\u0246nd\u00f8\u0279s\u01dd", "Ends {end}": "\u0246nds {end}", "Engage with posts": "\u0246n\u0183\u0250\u0183\u01dd \u028d\u1d09\u0287\u0265 d\u00f8s\u0287s", "Enroll Now": "\u0246n\u0279\u00f8ll N\u00f8\u028d", @@ -658,6 +685,7 @@ "Error getting task history for problem '<%- problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "\u0246\u0279\u0279\u00f8\u0279 \u0183\u01dd\u0287\u0287\u1d09n\u0183 \u0287\u0250s\u029e \u0265\u1d09s\u0287\u00f8\u0279\u028e \u025f\u00f8\u0279 d\u0279\u00f8bl\u01dd\u026f '<%- problem_id %>' \u0250nd s\u0287nd\u01ddn\u0287 '<%- student_id %>'. M\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u0265\u0250\u0287 \u0287\u0265\u01dd d\u0279\u00f8bl\u01dd\u026f \u0250nd s\u0287nd\u01ddn\u0287 \u1d09d\u01ddn\u0287\u1d09\u025f\u1d09\u01dd\u0279s \u0250\u0279\u01dd \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0250nd \u0254\u00f8\u0279\u0279\u01dd\u0254\u0287.", "Error importing course": "\u0246\u0279\u0279\u00f8\u0279 \u1d09\u026fd\u00f8\u0279\u0287\u1d09n\u0183 \u0254\u00f8n\u0279s\u01dd", "Error listing task history for this student and problem.": "\u0246\u0279\u0279\u00f8\u0279 l\u1d09s\u0287\u1d09n\u0183 \u0287\u0250s\u029e \u0265\u1d09s\u0287\u00f8\u0279\u028e \u025f\u00f8\u0279 \u0287\u0265\u1d09s s\u0287nd\u01ddn\u0287 \u0250nd d\u0279\u00f8bl\u01dd\u026f.", + "Error posting your message.": "\u0246\u0279\u0279\u00f8\u0279 d\u00f8s\u0287\u1d09n\u0183 \u028e\u00f8n\u0279 \u026f\u01ddss\u0250\u0183\u01dd.", "Error removing user": "\u0246\u0279\u0279\u00f8\u0279 \u0279\u01dd\u026f\u00f8\u028c\u1d09n\u0183 ns\u01dd\u0279", "Error resetting entrance exam attempts for student '{student_id}'. Make sure student identifier is correct.": "\u0246\u0279\u0279\u00f8\u0279 \u0279\u01dds\u01dd\u0287\u0287\u1d09n\u0183 \u01ddn\u0287\u0279\u0250n\u0254\u01dd \u01ddx\u0250\u026f \u0250\u0287\u0287\u01dd\u026fd\u0287s \u025f\u00f8\u0279 s\u0287nd\u01ddn\u0287 '{student_id}'. M\u0250\u029e\u01dd sn\u0279\u01dd s\u0287nd\u01ddn\u0287 \u1d09d\u01ddn\u0287\u1d09\u025f\u1d09\u01dd\u0279 \u1d09s \u0254\u00f8\u0279\u0279\u01dd\u0254\u0287.", "Error resetting problem attempts for problem '<%= problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "\u0246\u0279\u0279\u00f8\u0279 \u0279\u01dds\u01dd\u0287\u0287\u1d09n\u0183 d\u0279\u00f8bl\u01dd\u026f \u0250\u0287\u0287\u01dd\u026fd\u0287s \u025f\u00f8\u0279 d\u0279\u00f8bl\u01dd\u026f '<%= problem_id %>' \u0250nd s\u0287nd\u01ddn\u0287 '<%- student_id %>'. M\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u0265\u0250\u0287 \u0287\u0265\u01dd d\u0279\u00f8bl\u01dd\u026f \u0250nd s\u0287nd\u01ddn\u0287 \u1d09d\u01ddn\u0287\u1d09\u025f\u1d09\u01dd\u0279s \u0250\u0279\u01dd \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0250nd \u0254\u00f8\u0279\u0279\u01dd\u0254\u0287.", @@ -709,7 +737,6 @@ "Files that you upload must be smaller than 5MB in size.": "F\u1d09l\u01dds \u0287\u0265\u0250\u0287 \u028e\u00f8n ndl\u00f8\u0250d \u026fns\u0287 b\u01dd s\u026f\u0250ll\u01dd\u0279 \u0287\u0265\u0250n 5M\u0243 \u1d09n s\u1d09z\u01dd.", "Fill browser": "F\u1d09ll b\u0279\u00f8\u028ds\u01dd\u0279", "Filter and sort topics": "F\u1d09l\u0287\u01dd\u0279 \u0250nd s\u00f8\u0279\u0287 \u0287\u00f8d\u1d09\u0254s", - "Final Grade": "F\u1d09n\u0250l \u01e4\u0279\u0250d\u01dd", "Financial Aid": "F\u1d09n\u0250n\u0254\u1d09\u0250l \u023a\u1d09d", "Financial Assistance": "F\u1d09n\u0250n\u0254\u1d09\u0250l \u023ass\u1d09s\u0287\u0250n\u0254\u01dd", "Financial Assistance Application": "F\u1d09n\u0250n\u0254\u1d09\u0250l \u023ass\u1d09s\u0287\u0250n\u0254\u01dd \u023addl\u1d09\u0254\u0250\u0287\u1d09\u00f8n", @@ -722,12 +749,15 @@ "Find previous": "F\u1d09nd d\u0279\u01dd\u028c\u1d09\u00f8ns", "Finish": "F\u1d09n\u1d09s\u0265", "First time here?": "F\u1d09\u0279s\u0287 \u0287\u1d09\u026f\u01dd \u0265\u01dd\u0279\u01dd?", + "Follow": "F\u00f8ll\u00f8\u028d", "Follow or unfollow posts": "F\u00f8ll\u00f8\u028d \u00f8\u0279 nn\u025f\u00f8ll\u00f8\u028d d\u00f8s\u0287s", + "Following": "F\u00f8ll\u00f8\u028d\u1d09n\u0183", "Font Family": "F\u00f8n\u0287 F\u0250\u026f\u1d09l\u028e", "Font Sizes": "F\u00f8n\u0287 S\u1d09z\u01dds", "Footer": "F\u00f8\u00f8\u0287\u01dd\u0279", "For grading to work, you must change all {oldName} subsections to {newName}.": "F\u00f8\u0279 \u0183\u0279\u0250d\u1d09n\u0183 \u0287\u00f8 \u028d\u00f8\u0279\u029e, \u028e\u00f8n \u026fns\u0287 \u0254\u0265\u0250n\u0183\u01dd \u0250ll {oldName} snbs\u01dd\u0254\u0287\u1d09\u00f8ns \u0287\u00f8 {newName}.", "For inquiries regarding assignments, grades, or structure of a specific course, please post in the discussion forums for that course directly.": "F\u00f8\u0279 \u1d09nbn\u1d09\u0279\u1d09\u01dds \u0279\u01dd\u0183\u0250\u0279d\u1d09n\u0183 \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287s, \u0183\u0279\u0250d\u01dds, \u00f8\u0279 s\u0287\u0279n\u0254\u0287n\u0279\u01dd \u00f8\u025f \u0250 sd\u01dd\u0254\u1d09\u025f\u1d09\u0254 \u0254\u00f8n\u0279s\u01dd, dl\u01dd\u0250s\u01dd d\u00f8s\u0287 \u1d09n \u0287\u0265\u01dd d\u1d09s\u0254nss\u1d09\u00f8n \u025f\u00f8\u0279n\u026fs \u025f\u00f8\u0279 \u0287\u0265\u0250\u0287 \u0254\u00f8n\u0279s\u01dd d\u1d09\u0279\u01dd\u0254\u0287l\u028e.", + "Forgot my password": "F\u00f8\u0279\u0183\u00f8\u0287 \u026f\u028e d\u0250ss\u028d\u00f8\u0279d", "Format": "F\u00f8\u0279\u026f\u0250\u0287", "Formats": "F\u00f8\u0279\u026f\u0250\u0287s", "Free text notes": "F\u0279\u01dd\u01dd \u0287\u01ddx\u0287 n\u00f8\u0287\u01dds", @@ -742,7 +772,6 @@ "Generate": "\u01e4\u01ddn\u01dd\u0279\u0250\u0287\u01dd", "Generate Exception Certificates": "\u01e4\u01ddn\u01dd\u0279\u0250\u0287\u01dd \u0246x\u0254\u01ddd\u0287\u1d09\u00f8n \u023b\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dds", "Generate the user's certificate": "\u01e4\u01ddn\u01dd\u0279\u0250\u0287\u01dd \u0287\u0265\u01dd ns\u01dd\u0279's \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd", - "Get Credit": "\u01e4\u01dd\u0287 \u023b\u0279\u01ddd\u1d09\u0287", "Go to Dashboard": "\u01e4\u00f8 \u0287\u00f8 \u0110\u0250s\u0265b\u00f8\u0250\u0279d", "Go to my Dashboard": "\u01e4\u00f8 \u0287\u00f8 \u026f\u028e \u0110\u0250s\u0265b\u00f8\u0250\u0279d", "Go to your Dashboard": "\u01e4\u00f8 \u0287\u00f8 \u028e\u00f8n\u0279 \u0110\u0250s\u0265b\u00f8\u0250\u0279d", @@ -823,10 +852,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "\u0197\u025f \u0287\u0265\u01dd snbs\u01dd\u0254\u0287\u1d09\u00f8n d\u00f8\u01dds n\u00f8\u0287 \u0265\u0250\u028c\u01dd \u0250 dn\u01dd d\u0250\u0287\u01dd, l\u01dd\u0250\u0279n\u01dd\u0279s \u0250l\u028d\u0250\u028es s\u01dd\u01dd \u0287\u0265\u01dd\u1d09\u0279 s\u0254\u00f8\u0279\u01dds \u028d\u0265\u01ddn \u0287\u0265\u01dd\u028e snb\u026f\u1d09\u0287 \u0250ns\u028d\u01dd\u0279s \u0287\u00f8 \u0250ss\u01ddss\u026f\u01ddn\u0287s.", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u0197\u025f \u0287\u0265\u01dd nn\u1d09\u0287 \u028d\u0250s d\u0279\u01dd\u028c\u1d09\u00f8nsl\u028e dnbl\u1d09s\u0265\u01ddd \u0250nd \u0279\u01ddl\u01dd\u0250s\u01ddd \u0287\u00f8 l\u01dd\u0250\u0279n\u01dd\u0279s, \u0250n\u028e \u0254\u0265\u0250n\u0183\u01dds \u028e\u00f8n \u026f\u0250d\u01dd \u0287\u00f8 \u0287\u0265\u01dd nn\u1d09\u0287 \u028d\u0265\u01ddn \u1d09\u0287 \u028d\u0250s \u0265\u1d09dd\u01ddn \u028d\u1d09ll n\u00f8\u028d b\u01dd \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 l\u01dd\u0250\u0279n\u01dd\u0279s.", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "\u0197\u025f \u0287\u0265\u01dd nn\u1d09\u0287 \u028d\u0250s d\u0279\u01dd\u028c\u1d09\u00f8nsl\u028e dnbl\u1d09s\u0265\u01ddd \u0250nd \u0279\u01ddl\u01dd\u0250s\u01ddd \u0287\u00f8 s\u0287nd\u01ddn\u0287s, \u0250n\u028e \u0254\u0265\u0250n\u0183\u01dds \u028e\u00f8n \u026f\u0250d\u01dd \u0287\u00f8 \u0287\u0265\u01dd nn\u1d09\u0287 \u028d\u0265\u01ddn \u1d09\u0287 \u028d\u0250s \u0265\u1d09dd\u01ddn \u028d\u1d09ll n\u00f8\u028d b\u01dd \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 s\u0287nd\u01ddn\u0287s. \u0110\u00f8 \u028e\u00f8n \u028d\u0250n\u0287 \u0287\u00f8 d\u0279\u00f8\u0254\u01dd\u01ddd?", - "If you are unable to access your account contact us via email using {email}.": "\u0197\u025f \u028e\u00f8n \u0250\u0279\u01dd nn\u0250bl\u01dd \u0287\u00f8 \u0250\u0254\u0254\u01ddss \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 \u0254\u00f8n\u0287\u0250\u0254\u0287 ns \u028c\u1d09\u0250 \u01dd\u026f\u0250\u1d09l ns\u1d09n\u0183 {email}.", "If you do not yet have an account, use the button below to register.": "\u0197\u025f \u028e\u00f8n d\u00f8 n\u00f8\u0287 \u028e\u01dd\u0287 \u0265\u0250\u028c\u01dd \u0250n \u0250\u0254\u0254\u00f8nn\u0287, ns\u01dd \u0287\u0265\u01dd bn\u0287\u0287\u00f8n b\u01ddl\u00f8\u028d \u0287\u00f8 \u0279\u01dd\u0183\u1d09s\u0287\u01dd\u0279.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u0197\u025f \u028e\u00f8n d\u00f8n'\u0287 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e n\u00f8\u028d, \u028e\u00f8n \u0254\u0250n s\u0287\u1d09ll \u01ddxdl\u00f8\u0279\u01dd \u028e\u00f8n\u0279 \u0254\u00f8n\u0279s\u01dd \u025f\u0279\u00f8\u026f \u028e\u00f8n\u0279 d\u0250s\u0265b\u00f8\u0250\u0279d. \u024e\u00f8n \u028d\u1d09ll \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd d\u01dd\u0279\u1d09\u00f8d\u1d09\u0254 \u0279\u01dd\u026f\u1d09nd\u01dd\u0279s \u025f\u0279\u00f8\u026f %(platformName)s \u0287\u00f8 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u0197\u025f \u028e\u00f8n d\u00f8n'\u0287 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e n\u00f8\u028d, \u028e\u00f8n \u0254\u0250n s\u0287\u1d09ll \u01ddxdl\u00f8\u0279\u01dd \u028e\u00f8n\u0279 \u0254\u00f8n\u0279s\u01dd \u025f\u0279\u00f8\u026f \u028e\u00f8n\u0279 d\u0250s\u0265b\u00f8\u0250\u0279d. \u024e\u00f8n \u028d\u1d09ll \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd d\u01dd\u0279\u1d09\u00f8d\u1d09\u0254 \u0279\u01dd\u026f\u1d09nd\u01dd\u0279s \u025f\u0279\u00f8\u026f {platformName} \u0287\u00f8 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e.", "If you leave, you can no longer post in this team's discussions.Your place will be available to another learner.": "\u0197\u025f \u028e\u00f8n l\u01dd\u0250\u028c\u01dd, \u028e\u00f8n \u0254\u0250n n\u00f8 l\u00f8n\u0183\u01dd\u0279 d\u00f8s\u0287 \u1d09n \u0287\u0265\u1d09s \u0287\u01dd\u0250\u026f's d\u1d09s\u0254nss\u1d09\u00f8ns.\u024e\u00f8n\u0279 dl\u0250\u0254\u01dd \u028d\u1d09ll b\u01dd \u0250\u028c\u0250\u1d09l\u0250bl\u01dd \u0287\u00f8 \u0250n\u00f8\u0287\u0265\u01dd\u0279 l\u01dd\u0250\u0279n\u01dd\u0279.", "If you make significant changes, make sure you notify members of the team before making these changes.": "\u0197\u025f \u028e\u00f8n \u026f\u0250\u029e\u01dd s\u1d09\u0183n\u1d09\u025f\u1d09\u0254\u0250n\u0287 \u0254\u0265\u0250n\u0183\u01dds, \u026f\u0250\u029e\u01dd sn\u0279\u01dd \u028e\u00f8n n\u00f8\u0287\u1d09\u025f\u028e \u026f\u01dd\u026fb\u01dd\u0279s \u00f8\u025f \u0287\u0265\u01dd \u0287\u01dd\u0250\u026f b\u01dd\u025f\u00f8\u0279\u01dd \u026f\u0250\u029e\u1d09n\u0183 \u0287\u0265\u01dds\u01dd \u0254\u0265\u0250n\u0183\u01dds.", "If you make this %(xblockType)s visible to learners, learners will be able to see its content after the release date has passed and you have published the unit. Only units that are explicitly hidden from learners will remain hidden after you clear this option for the %(xblockType)s.": "\u0197\u025f \u028e\u00f8n \u026f\u0250\u029e\u01dd \u0287\u0265\u1d09s %(xblockType)s \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 l\u01dd\u0250\u0279n\u01dd\u0279s, l\u01dd\u0250\u0279n\u01dd\u0279s \u028d\u1d09ll b\u01dd \u0250bl\u01dd \u0287\u00f8 s\u01dd\u01dd \u1d09\u0287s \u0254\u00f8n\u0287\u01ddn\u0287 \u0250\u025f\u0287\u01dd\u0279 \u0287\u0265\u01dd \u0279\u01ddl\u01dd\u0250s\u01dd d\u0250\u0287\u01dd \u0265\u0250s d\u0250ss\u01ddd \u0250nd \u028e\u00f8n \u0265\u0250\u028c\u01dd dnbl\u1d09s\u0265\u01ddd \u0287\u0265\u01dd nn\u1d09\u0287. \u00d8nl\u028e nn\u1d09\u0287s \u0287\u0265\u0250\u0287 \u0250\u0279\u01dd \u01ddxdl\u1d09\u0254\u1d09\u0287l\u028e \u0265\u1d09dd\u01ddn \u025f\u0279\u00f8\u026f l\u01dd\u0250\u0279n\u01dd\u0279s \u028d\u1d09ll \u0279\u01dd\u026f\u0250\u1d09n \u0265\u1d09dd\u01ddn \u0250\u025f\u0287\u01dd\u0279 \u028e\u00f8n \u0254l\u01dd\u0250\u0279 \u0287\u0265\u1d09s \u00f8d\u0287\u1d09\u00f8n \u025f\u00f8\u0279 \u0287\u0265\u01dd %(xblockType)s.", @@ -948,6 +975,7 @@ "Live view of webcam": "\u0141\u1d09\u028c\u01dd \u028c\u1d09\u01dd\u028d \u00f8\u025f \u028d\u01ddb\u0254\u0250\u026f", "Load Another File": "\u0141\u00f8\u0250d \u023an\u00f8\u0287\u0265\u01dd\u0279 F\u1d09l\u01dd", "Load all responses": "\u0141\u00f8\u0250d \u0250ll \u0279\u01ddsd\u00f8ns\u01dds", + "Load more": "\u0141\u00f8\u0250d \u026f\u00f8\u0279\u01dd", "Load next {numResponses} responses": "\u0141\u00f8\u0250d n\u01ddx\u0287 {numResponses} \u0279\u01ddsd\u00f8ns\u01dds", "Load next {num_items} result": [ "\u0141\u00f8\u0250d n\u01ddx\u0287 {num_items} \u0279\u01ddsnl\u0287", @@ -980,6 +1008,7 @@ "Manage Learners": "M\u0250n\u0250\u0183\u01dd \u0141\u01dd\u0250\u0279n\u01dd\u0279s", "Manual": "M\u0250nn\u0250l", "Mark Exam As Completed": "M\u0250\u0279\u029e \u0246x\u0250\u026f \u023as \u023b\u00f8\u026fdl\u01dd\u0287\u01ddd", + "Mark as Answer": "M\u0250\u0279\u029e \u0250s \u023ans\u028d\u01dd\u0279", "Mark enrollment code as unused": "M\u0250\u0279\u029e \u01ddn\u0279\u00f8ll\u026f\u01ddn\u0287 \u0254\u00f8d\u01dd \u0250s nnns\u01ddd", "Markdown Editing Help": "M\u0250\u0279\u029ed\u00f8\u028dn \u0246d\u1d09\u0287\u1d09n\u0183 \u0126\u01ddld", "Masters": "M\u0250s\u0287\u01dd\u0279s", @@ -1018,6 +1047,8 @@ "Name or short description of the configuration": "N\u0250\u026f\u01dd \u00f8\u0279 s\u0265\u00f8\u0279\u0287 d\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n \u00f8\u025f \u0287\u0265\u01dd \u0254\u00f8n\u025f\u1d09\u0183n\u0279\u0250\u0287\u1d09\u00f8n", "Navigate up": "N\u0250\u028c\u1d09\u0183\u0250\u0287\u01dd nd", "Need help logging in?": "N\u01dd\u01ddd \u0265\u01ddld l\u00f8\u0183\u0183\u1d09n\u0183 \u1d09n?", + "Need help signing in?": "N\u01dd\u01ddd \u0265\u01ddld s\u1d09\u0183n\u1d09n\u0183 \u1d09n?", + "Need other help signing in?": "N\u01dd\u01ddd \u00f8\u0287\u0265\u01dd\u0279 \u0265\u01ddld s\u1d09\u0183n\u1d09n\u0183 \u1d09n?", "Needs verified certificate ": "N\u01dd\u01ddds \u028c\u01dd\u0279\u1d09\u025f\u1d09\u01ddd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd ", "Never published": "N\u01dd\u028c\u01dd\u0279 dnbl\u1d09s\u0265\u01ddd", "Never show assessment results": "N\u01dd\u028c\u01dd\u0279 s\u0265\u00f8\u028d \u0250ss\u01ddss\u026f\u01ddn\u0287 \u0279\u01ddsnl\u0287s", @@ -1037,6 +1068,7 @@ "No Flash Detected": "N\u00f8 Fl\u0250s\u0265 \u0110\u01dd\u0287\u01dd\u0254\u0287\u01ddd", "No Timed Transcript": "N\u00f8 \u0166\u1d09\u026f\u01ddd \u0166\u0279\u0250ns\u0254\u0279\u1d09d\u0287", "No Webcam Detected": "N\u00f8 W\u01ddb\u0254\u0250\u026f \u0110\u01dd\u0287\u01dd\u0254\u0287\u01ddd", + "No assignments for team": "N\u00f8 \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287s \u025f\u00f8\u0279 \u0287\u01dd\u0250\u026f", "No color": "N\u00f8 \u0254\u00f8l\u00f8\u0279", "No content-specific discussion topics exist.": "N\u00f8 \u0254\u00f8n\u0287\u01ddn\u0287-sd\u01dd\u0254\u1d09\u025f\u1d09\u0254 d\u1d09s\u0254nss\u1d09\u00f8n \u0287\u00f8d\u1d09\u0254s \u01ddx\u1d09s\u0287.", "No description available": "N\u00f8 d\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n \u0250\u028c\u0250\u1d09l\u0250bl\u01dd", @@ -1085,9 +1117,10 @@ "Once in position, use the Take Photo button {icon} to capture your photo": "\u00d8n\u0254\u01dd \u1d09n d\u00f8s\u1d09\u0287\u1d09\u00f8n, ns\u01dd \u0287\u0265\u01dd \u0166\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8 bn\u0287\u0287\u00f8n {icon} \u0287\u00f8 \u0254\u0250d\u0287n\u0279\u01dd \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8", "Once you complete one of the program requirements you have a program record. This record is marked complete once you meet all program requirements. A program record can be used to continue your learning journey and demonstrate your learning to others.": "\u00d8n\u0254\u01dd \u028e\u00f8n \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u00f8n\u01dd \u00f8\u025f \u0287\u0265\u01dd d\u0279\u00f8\u0183\u0279\u0250\u026f \u0279\u01ddbn\u1d09\u0279\u01dd\u026f\u01ddn\u0287s \u028e\u00f8n \u0265\u0250\u028c\u01dd \u0250 d\u0279\u00f8\u0183\u0279\u0250\u026f \u0279\u01dd\u0254\u00f8\u0279d. \u0166\u0265\u1d09s \u0279\u01dd\u0254\u00f8\u0279d \u1d09s \u026f\u0250\u0279\u029e\u01ddd \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u00f8n\u0254\u01dd \u028e\u00f8n \u026f\u01dd\u01dd\u0287 \u0250ll d\u0279\u00f8\u0183\u0279\u0250\u026f \u0279\u01ddbn\u1d09\u0279\u01dd\u026f\u01ddn\u0287s. \u023a d\u0279\u00f8\u0183\u0279\u0250\u026f \u0279\u01dd\u0254\u00f8\u0279d \u0254\u0250n b\u01dd ns\u01ddd \u0287\u00f8 \u0254\u00f8n\u0287\u1d09nn\u01dd \u028e\u00f8n\u0279 l\u01dd\u0250\u0279n\u1d09n\u0183 \u027e\u00f8n\u0279n\u01dd\u028e \u0250nd d\u01dd\u026f\u00f8ns\u0287\u0279\u0250\u0287\u01dd \u028e\u00f8n\u0279 l\u01dd\u0250\u0279n\u1d09n\u0183 \u0287\u00f8 \u00f8\u0287\u0265\u01dd\u0279s.", "Once your account is deleted, you cannot use it to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "\u00d8n\u0254\u01dd \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 \u1d09s d\u01ddl\u01dd\u0287\u01ddd, \u028e\u00f8n \u0254\u0250nn\u00f8\u0287 ns\u01dd \u1d09\u0287 \u0287\u00f8 \u0287\u0250\u029e\u01dd \u0254\u00f8n\u0279s\u01dds \u00f8n \u0287\u0265\u01dd {platformName} \u0250dd, {siteName}, \u00f8\u0279 \u0250n\u028e \u00f8\u0287\u0265\u01dd\u0279 s\u1d09\u0287\u01dd \u0265\u00f8s\u0287\u01ddd b\u028e {platformName}.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u00d8nl\u028e <%= fileTypes %> \u025f\u1d09l\u01dds \u0254\u0250n b\u01dd ndl\u00f8\u0250d\u01ddd. \u2c63l\u01dd\u0250s\u01dd s\u01ddl\u01dd\u0254\u0287 \u0250 \u025f\u1d09l\u01dd \u01ddnd\u1d09n\u0183 \u1d09n <%= fileExtensions %> \u0287\u00f8 ndl\u00f8\u0250d.", + "Only <%- fileTypes %> files can be uploaded. Please select a file ending in <%- (fileExtensions) %> to upload.": "\u00d8nl\u028e <%- fileTypes %> \u025f\u1d09l\u01dds \u0254\u0250n b\u01dd ndl\u00f8\u0250d\u01ddd. \u2c63l\u01dd\u0250s\u01dd s\u01ddl\u01dd\u0254\u0287 \u0250 \u025f\u1d09l\u01dd \u01ddnd\u1d09n\u0183 \u1d09n <%- (fileExtensions) %> \u0287\u00f8 ndl\u00f8\u0250d.", "Only properly formatted .csv files will be accepted.": "\u00d8nl\u028e d\u0279\u00f8d\u01dd\u0279l\u028e \u025f\u00f8\u0279\u026f\u0250\u0287\u0287\u01ddd .\u0254s\u028c \u025f\u1d09l\u01dds \u028d\u1d09ll b\u01dd \u0250\u0254\u0254\u01ddd\u0287\u01ddd.", "Only the parent course staff of a CCX can create content groups.": "\u00d8nl\u028e \u0287\u0265\u01dd d\u0250\u0279\u01ddn\u0287 \u0254\u00f8n\u0279s\u01dd s\u0287\u0250\u025f\u025f \u00f8\u025f \u0250 \u023b\u023bX \u0254\u0250n \u0254\u0279\u01dd\u0250\u0287\u01dd \u0254\u00f8n\u0287\u01ddn\u0287 \u0183\u0279\u00f8nds.", + "Open": "\u00d8d\u01ddn", "Open Calculator": "\u00d8d\u01ddn \u023b\u0250l\u0254nl\u0250\u0287\u00f8\u0279", "Open language menu": "\u00d8d\u01ddn l\u0250n\u0183n\u0250\u0183\u01dd \u026f\u01ddnn", "Open the certificate you earned for the %(title)s program.": "\u00d8d\u01ddn \u0287\u0265\u01dd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u028e\u00f8n \u01dd\u0250\u0279n\u01ddd \u025f\u00f8\u0279 \u0287\u0265\u01dd %(title)s d\u0279\u00f8\u0183\u0279\u0250\u026f.", @@ -1107,6 +1140,7 @@ "Organization of the signatory": "\u00d8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n \u00f8\u025f \u0287\u0265\u01dd s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u028e", "Organization:": "\u00d8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n:", "Other": "\u00d8\u0287\u0265\u01dd\u0279", + "Other sign-in issues": "\u00d8\u0287\u0265\u01dd\u0279 s\u1d09\u0183n-\u1d09n \u1d09ssn\u01dds", "Overall Score": "\u00d8\u028c\u01dd\u0279\u0250ll S\u0254\u00f8\u0279\u01dd", "PDF Chapters": "\u2c63\u0110F \u023b\u0265\u0250d\u0287\u01dd\u0279s", "Page break": "\u2c63\u0250\u0183\u01dd b\u0279\u01dd\u0250\u029e", @@ -1135,6 +1169,8 @@ "Photo of %(fullName)s's ID": "\u2c63\u0265\u00f8\u0287\u00f8 \u00f8\u025f %(fullName)s's \u0197\u0110", "Photo requirements:": "\u2c63\u0265\u00f8\u0287\u00f8 \u0279\u01ddbn\u1d09\u0279\u01dd\u026f\u01ddn\u0287s:", "Photos don't meet the requirements?": "\u2c63\u0265\u00f8\u0287\u00f8s d\u00f8n'\u0287 \u026f\u01dd\u01dd\u0287 \u0287\u0265\u01dd \u0279\u01ddbn\u1d09\u0279\u01dd\u026f\u01ddn\u0287s?", + "Pin": "\u2c63\u1d09n", + "Pinned": "\u2c63\u1d09nn\u01ddd", "Placeholder": "\u2c63l\u0250\u0254\u01dd\u0265\u00f8ld\u01dd\u0279", "Play": "\u2c63l\u0250\u028e", "Play video": "\u2c63l\u0250\u028e \u028c\u1d09d\u01dd\u00f8", @@ -1177,6 +1213,7 @@ "Please verify that your webcam is connected and that you have allowed your browser to access it.": "\u2c63l\u01dd\u0250s\u01dd \u028c\u01dd\u0279\u1d09\u025f\u028e \u0287\u0265\u0250\u0287 \u028e\u00f8n\u0279 \u028d\u01ddb\u0254\u0250\u026f \u1d09s \u0254\u00f8nn\u01dd\u0254\u0287\u01ddd \u0250nd \u0287\u0265\u0250\u0287 \u028e\u00f8n \u0265\u0250\u028c\u01dd \u0250ll\u00f8\u028d\u01ddd \u028e\u00f8n\u0279 b\u0279\u00f8\u028ds\u01dd\u0279 \u0287\u00f8 \u0250\u0254\u0254\u01ddss \u1d09\u0287.", "Plugins": "\u2c63ln\u0183\u1d09ns", "Post": "\u2c63\u00f8s\u0287", + "Post type": "\u2c63\u00f8s\u0287 \u0287\u028ed\u01dd", "Poster": "\u2c63\u00f8s\u0287\u01dd\u0279", "Practice Proctored": "\u2c63\u0279\u0250\u0254\u0287\u1d09\u0254\u01dd \u2c63\u0279\u00f8\u0254\u0287\u00f8\u0279\u01ddd", "Practice proctored Exam": "\u2c63\u0279\u0250\u0254\u0287\u1d09\u0254\u01dd d\u0279\u00f8\u0254\u0287\u00f8\u0279\u01ddd \u0246x\u0250\u026f", @@ -1231,6 +1268,8 @@ "Published and Live": "\u2c63nbl\u1d09s\u0265\u01ddd \u0250nd \u0141\u1d09\u028c\u01dd", "Publishing": "\u2c63nbl\u1d09s\u0265\u1d09n\u0183", "Publishing Status": "\u2c63nbl\u1d09s\u0265\u1d09n\u0183 S\u0287\u0250\u0287ns", + "Question": "Qn\u01dds\u0287\u1d09\u00f8n", + "Questions raise issues that need answers. Discussions share ideas and start conversations. (Required)": "Qn\u01dds\u0287\u1d09\u00f8ns \u0279\u0250\u1d09s\u01dd \u1d09ssn\u01dds \u0287\u0265\u0250\u0287 n\u01dd\u01ddd \u0250ns\u028d\u01dd\u0279s. \u0110\u1d09s\u0254nss\u1d09\u00f8ns s\u0265\u0250\u0279\u01dd \u1d09d\u01dd\u0250s \u0250nd s\u0287\u0250\u0279\u0287 \u0254\u00f8n\u028c\u01dd\u0279s\u0250\u0287\u1d09\u00f8ns. (\u024c\u01ddbn\u1d09\u0279\u01ddd)", "Queued": "Qn\u01ddn\u01ddd", "REMAINING COURSES": "\u024c\u0246M\u023a\u0197N\u0197N\u01e4 \u023b\u00d8\u0244\u024cS\u0246S", "Re-run Course": "\u024c\u01dd-\u0279nn \u023b\u00f8n\u0279s\u01dd", @@ -1250,6 +1289,7 @@ "Regenerate": "\u024c\u01dd\u0183\u01ddn\u01dd\u0279\u0250\u0287\u01dd", "Regenerate the user's certificate": "\u024c\u01dd\u0183\u01ddn\u01dd\u0279\u0250\u0287\u01dd \u0287\u0265\u01dd ns\u01dd\u0279's \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd", "Register with Institution/Campus Credentials": "\u024c\u01dd\u0183\u1d09s\u0287\u01dd\u0279 \u028d\u1d09\u0287\u0265 \u0197ns\u0287\u1d09\u0287n\u0287\u1d09\u00f8n/\u023b\u0250\u026fdns \u023b\u0279\u01ddd\u01ddn\u0287\u1d09\u0250ls", + "Related to: %(courseware_title_linked)s": "\u024c\u01ddl\u0250\u0287\u01ddd \u0287\u00f8: %(courseware_title_linked)s", "Release Date and Time": "\u024c\u01ddl\u01dd\u0250s\u01dd \u0110\u0250\u0287\u01dd \u0250nd \u0166\u1d09\u026f\u01dd", "Release Date:": "\u024c\u01ddl\u01dd\u0250s\u01dd \u0110\u0250\u0287\u01dd:", "Release Status:": "\u024c\u01ddl\u01dd\u0250s\u01dd S\u0287\u0250\u0287ns:", @@ -1277,7 +1317,10 @@ "Replace all": "\u024c\u01dddl\u0250\u0254\u01dd \u0250ll", "Replace with": "\u024c\u01dddl\u0250\u0254\u01dd \u028d\u1d09\u0287\u0265", "Reply to Annotation": "\u024c\u01dddl\u028e \u0287\u00f8 \u023ann\u00f8\u0287\u0250\u0287\u1d09\u00f8n", + "Report": "\u024c\u01ddd\u00f8\u0279\u0287", + "Report abuse": "\u024c\u01ddd\u00f8\u0279\u0287 \u0250bns\u01dd", "Report abuse, topics, and responses": "\u024c\u01ddd\u00f8\u0279\u0287 \u0250bns\u01dd, \u0287\u00f8d\u1d09\u0254s, \u0250nd \u0279\u01ddsd\u00f8ns\u01dds", + "Reported": "\u024c\u01ddd\u00f8\u0279\u0287\u01ddd", "Requester": "\u024c\u01ddbn\u01dds\u0287\u01dd\u0279", "Required": "\u024c\u01ddbn\u1d09\u0279\u01ddd", "Required field.": "\u024c\u01ddbn\u1d09\u0279\u01ddd \u025f\u1d09\u01ddld.", @@ -1296,6 +1339,7 @@ "Return and add email address": "\u024c\u01dd\u0287n\u0279n \u0250nd \u0250dd \u01dd\u026f\u0250\u1d09l \u0250dd\u0279\u01ddss", "Return to Export": "\u024c\u01dd\u0287n\u0279n \u0287\u00f8 \u0246xd\u00f8\u0279\u0287", "Return to Your Dashboard": "\u024c\u01dd\u0287n\u0279n \u0287\u00f8 \u024e\u00f8n\u0279 \u0110\u0250s\u0265b\u00f8\u0250\u0279d", + "Return to all posts": "\u024c\u01dd\u0287n\u0279n \u0287\u00f8 \u0250ll d\u00f8s\u0287s", "Return to team listing": "\u024c\u01dd\u0287n\u0279n \u0287\u00f8 \u0287\u01dd\u0250\u026f l\u1d09s\u0287\u1d09n\u0183", "Review Rules": "\u024c\u01dd\u028c\u1d09\u01dd\u028d \u024cnl\u01dds", "Review Your Photos": "\u024c\u01dd\u028c\u1d09\u01dd\u028d \u024e\u00f8n\u0279 \u2c63\u0265\u00f8\u0287\u00f8s", @@ -1373,6 +1417,10 @@ "Short explanation": "S\u0265\u00f8\u0279\u0287 \u01ddxdl\u0250n\u0250\u0287\u1d09\u00f8n", "Show All": "S\u0265\u00f8\u028d \u023all", "Show Annotations": "S\u0265\u00f8\u028d \u023ann\u00f8\u0287\u0250\u0287\u1d09\u00f8ns", + "Show Comment (%(num_comments)s)": [ + "S\u0265\u00f8\u028d \u023b\u00f8\u026f\u026f\u01ddn\u0287 (%(num_comments)s)", + "S\u0265\u00f8\u028d \u023b\u00f8\u026f\u026f\u01ddn\u0287s (%(num_comments)s)" + ], "Show Deprecated Settings": "S\u0265\u00f8\u028d \u0110\u01ddd\u0279\u01dd\u0254\u0250\u0287\u01ddd S\u01dd\u0287\u0287\u1d09n\u0183s", "Show Discussion": "S\u0265\u00f8\u028d \u0110\u1d09s\u0254nss\u1d09\u00f8n", "Show Less": "S\u0265\u00f8\u028d \u0141\u01ddss", @@ -1409,6 +1457,7 @@ "Sign in using %(providerName)s": "S\u1d09\u0183n \u1d09n ns\u1d09n\u0183 %(providerName)s", "Sign in with %(providerName)s": "S\u1d09\u0183n \u1d09n \u028d\u1d09\u0287\u0265 %(providerName)s", "Sign in with Institution/Campus Credentials": "S\u1d09\u0183n \u1d09n \u028d\u1d09\u0287\u0265 \u0197ns\u0287\u1d09\u0287n\u0287\u1d09\u00f8n/\u023b\u0250\u026fdns \u023b\u0279\u01ddd\u01ddn\u0287\u1d09\u0250ls", + "Sign in with your company or school": "S\u1d09\u0183n \u1d09n \u028d\u1d09\u0287\u0265 \u028e\u00f8n\u0279 \u0254\u00f8\u026fd\u0250n\u028e \u00f8\u0279 s\u0254\u0265\u00f8\u00f8l", "Sign in.": "S\u1d09\u0183n \u1d09n.", "Signatory": "S\u1d09\u0183n\u0250\u0287\u00f8\u0279\u028e", "Signatory field(s) has invalid data.": "S\u1d09\u0183n\u0250\u0287\u00f8\u0279\u028e \u025f\u1d09\u01ddld(s) \u0265\u0250s \u1d09n\u028c\u0250l\u1d09d d\u0250\u0287\u0250.", @@ -1515,6 +1564,7 @@ "Task inputs": "\u0166\u0250s\u029e \u1d09ndn\u0287s", "Teaching Assistant": "\u0166\u01dd\u0250\u0254\u0265\u1d09n\u0183 \u023ass\u1d09s\u0287\u0250n\u0287", "Team \"{team}\" successfully deleted.": "\u0166\u01dd\u0250\u026f \"{team}\" sn\u0254\u0254\u01ddss\u025fnll\u028e d\u01ddl\u01dd\u0287\u01ddd.", + "Team Assignments": "\u0166\u01dd\u0250\u026f \u023ass\u1d09\u0183n\u026f\u01ddn\u0287s", "Team Description (Required) *": "\u0166\u01dd\u0250\u026f \u0110\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n (\u024c\u01ddbn\u1d09\u0279\u01ddd) *", "Team Details": "\u0166\u01dd\u0250\u026f \u0110\u01dd\u0287\u0250\u1d09ls", "Team Name (Required) *": "\u0166\u01dd\u0250\u026f N\u0250\u026f\u01dd (\u024c\u01ddbn\u1d09\u0279\u01ddd) *", @@ -1533,9 +1583,8 @@ "Textbook Name": "\u0166\u01ddx\u0287b\u00f8\u00f8\u029e N\u0250\u026f\u01dd", "Textbook information": "\u0166\u01ddx\u0287b\u00f8\u00f8\u029e \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n", "Textbook name is required": "\u0166\u01ddx\u0287b\u00f8\u00f8\u029e n\u0250\u026f\u01dd \u1d09s \u0279\u01ddbn\u1d09\u0279\u01ddd", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n %(full_name)s! W\u01dd \u0265\u0250\u028c\u01dd \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01ddd \u028e\u00f8n\u0279 d\u0250\u028e\u026f\u01ddn\u0287 \u025f\u00f8\u0279 %(course_name)s.", "Thank you for setting your course goal to {goal}!": "\u0166\u0265\u0250n\u029e \u028e\u00f8n \u025f\u00f8\u0279 s\u01dd\u0287\u0287\u1d09n\u0183 \u028e\u00f8n\u0279 \u0254\u00f8n\u0279s\u01dd \u0183\u00f8\u0250l \u0287\u00f8 {goal}!", - "Thank you for submitting a request! We will contact you within 24 hours.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n \u025f\u00f8\u0279 snb\u026f\u1d09\u0287\u0287\u1d09n\u0183 \u0250 \u0279\u01ddbn\u01dds\u0287! W\u01dd \u028d\u1d09ll \u0254\u00f8n\u0287\u0250\u0254\u0287 \u028e\u00f8n \u028d\u1d09\u0287\u0265\u1d09n 24 \u0265\u00f8n\u0279s.", + "Thank you for submitting a request! We appreciate your patience while we work to review your request.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n \u025f\u00f8\u0279 snb\u026f\u1d09\u0287\u0287\u1d09n\u0183 \u0250 \u0279\u01ddbn\u01dds\u0287! W\u01dd \u0250dd\u0279\u01dd\u0254\u1d09\u0250\u0287\u01dd \u028e\u00f8n\u0279 d\u0250\u0287\u1d09\u01ddn\u0254\u01dd \u028d\u0265\u1d09l\u01dd \u028d\u01dd \u028d\u00f8\u0279\u029e \u0287\u00f8 \u0279\u01dd\u028c\u1d09\u01dd\u028d \u028e\u00f8n\u0279 \u0279\u01ddbn\u01dds\u0287.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n \u025f\u00f8\u0279 snb\u026f\u1d09\u0287\u0287\u1d09n\u0183 \u028e\u00f8n\u0279 \u025f\u1d09n\u0250n\u0254\u1d09\u0250l \u0250ss\u1d09s\u0287\u0250n\u0254\u01dd \u0250ddl\u1d09\u0254\u0250\u0287\u1d09\u00f8n \u025f\u00f8\u0279 {course_name}! \u024e\u00f8n \u0254\u0250n \u01ddxd\u01dd\u0254\u0287 \u0250 \u0279\u01ddsd\u00f8ns\u01dd \u1d09n 2-4 bns\u1d09n\u01ddss d\u0250\u028es.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n \u025f\u00f8\u0279 snb\u026f\u1d09\u0287\u0287\u1d09n\u0183 \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8s. W\u01dd \u028d\u1d09ll \u0279\u01dd\u028c\u1d09\u01dd\u028d \u0287\u0265\u01dd\u026f s\u0265\u00f8\u0279\u0287l\u028e. \u024e\u00f8n \u0254\u0250n n\u00f8\u028d s\u1d09\u0183n nd \u025f\u00f8\u0279 \u0250n\u028e %(platformName)s \u0254\u00f8n\u0279s\u01dd \u0287\u0265\u0250\u0287 \u00f8\u025f\u025f\u01dd\u0279s \u028c\u01dd\u0279\u1d09\u025f\u1d09\u01ddd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dds. V\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n \u1d09s \u0183\u00f8\u00f8d \u025f\u00f8\u0279 \u00f8n\u01dd \u028e\u01dd\u0250\u0279. \u023a\u025f\u0287\u01dd\u0279 \u00f8n\u01dd \u028e\u01dd\u0250\u0279, \u028e\u00f8n \u026fns\u0287 snb\u026f\u1d09\u0287 d\u0265\u00f8\u0287\u00f8s \u025f\u00f8\u0279 \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n \u0250\u0183\u0250\u1d09n.", "Thank you! We have received your payment for {courseName}.": "\u0166\u0265\u0250n\u029e \u028e\u00f8n! W\u01dd \u0265\u0250\u028c\u01dd \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01ddd \u028e\u00f8n\u0279 d\u0250\u028e\u026f\u01ddn\u0287 \u025f\u00f8\u0279 {courseName}.", @@ -1547,8 +1596,8 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u0166\u0265\u01dd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u025f\u00f8\u0279 \u0287\u0265\u1d09s l\u01dd\u0250\u0279n\u01dd\u0279 \u0265\u0250s b\u01dd\u01ddn \u0279\u01dd-\u028c\u0250l\u1d09d\u0250\u0287\u01ddd \u0250nd \u0287\u0265\u01dd s\u028es\u0287\u01dd\u026f \u1d09s \u0279\u01dd-\u0279nnn\u1d09n\u0183 \u0287\u0265\u01dd \u0183\u0279\u0250d\u01dd \u025f\u00f8\u0279 \u0287\u0265\u1d09s l\u01dd\u0250\u0279n\u01dd\u0279.", "The cohort cannot be added": "\u0166\u0265\u01dd \u0254\u00f8\u0265\u00f8\u0279\u0287 \u0254\u0250nn\u00f8\u0287 b\u01dd \u0250dd\u01ddd", "The cohort cannot be saved": "\u0166\u0265\u01dd \u0254\u00f8\u0265\u00f8\u0279\u0287 \u0254\u0250nn\u00f8\u0287 b\u01dd s\u0250\u028c\u01ddd", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u0166\u0265\u01dd \u0254\u00f8\u026fb\u1d09n\u01ddd l\u01ddn\u0183\u0287\u0265 \u00f8\u025f \u0287\u0265\u01dd \u00f8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n \u0250nd l\u1d09b\u0279\u0250\u0279\u028e \u0254\u00f8d\u01dd \u025f\u1d09\u01ddlds \u0254\u0250nn\u00f8\u0287 b\u01dd \u026f\u00f8\u0279\u01dd \u0287\u0265\u0250n <%=limit%> \u0254\u0265\u0250\u0279\u0250\u0254\u0287\u01dd\u0279s.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u0166\u0265\u01dd \u0254\u00f8\u026fb\u1d09n\u01ddd l\u01ddn\u0183\u0287\u0265 \u00f8\u025f \u0287\u0265\u01dd \u00f8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n, \u0254\u00f8n\u0279s\u01dd nn\u026fb\u01dd\u0279, \u0250nd \u0254\u00f8n\u0279s\u01dd \u0279nn \u025f\u1d09\u01ddlds \u0254\u0250nn\u00f8\u0287 b\u01dd \u026f\u00f8\u0279\u01dd \u0287\u0265\u0250n <%=limit%> \u0254\u0265\u0250\u0279\u0250\u0254\u0287\u01dd\u0279s.", + "The combined length of the organization and library code fields cannot be more than <%- limit %> characters.": "\u0166\u0265\u01dd \u0254\u00f8\u026fb\u1d09n\u01ddd l\u01ddn\u0183\u0287\u0265 \u00f8\u025f \u0287\u0265\u01dd \u00f8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n \u0250nd l\u1d09b\u0279\u0250\u0279\u028e \u0254\u00f8d\u01dd \u025f\u1d09\u01ddlds \u0254\u0250nn\u00f8\u0287 b\u01dd \u026f\u00f8\u0279\u01dd \u0287\u0265\u0250n <%- limit %> \u0254\u0265\u0250\u0279\u0250\u0254\u0287\u01dd\u0279s.", + "The combined length of the organization, course number, and course run fields cannot be more than <%- limit %> characters.": "\u0166\u0265\u01dd \u0254\u00f8\u026fb\u1d09n\u01ddd l\u01ddn\u0183\u0287\u0265 \u00f8\u025f \u0287\u0265\u01dd \u00f8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n, \u0254\u00f8n\u0279s\u01dd nn\u026fb\u01dd\u0279, \u0250nd \u0254\u00f8n\u0279s\u01dd \u0279nn \u025f\u1d09\u01ddlds \u0254\u0250nn\u00f8\u0287 b\u01dd \u026f\u00f8\u0279\u01dd \u0287\u0265\u0250n <%- limit %> \u0254\u0265\u0250\u0279\u0250\u0254\u0287\u01dd\u0279s.", "The country or region where you live.": "\u0166\u0265\u01dd \u0254\u00f8nn\u0287\u0279\u028e \u00f8\u0279 \u0279\u01dd\u0183\u1d09\u00f8n \u028d\u0265\u01dd\u0279\u01dd \u028e\u00f8n l\u1d09\u028c\u01dd.", "The country that team members primarily identify with.": "\u0166\u0265\u01dd \u0254\u00f8nn\u0287\u0279\u028e \u0287\u0265\u0250\u0287 \u0287\u01dd\u0250\u026f \u026f\u01dd\u026fb\u01dd\u0279s d\u0279\u1d09\u026f\u0250\u0279\u1d09l\u028e \u1d09d\u01ddn\u0287\u1d09\u025f\u028e \u028d\u1d09\u0287\u0265.", "The course end date must be later than the course start date.": "\u0166\u0265\u01dd \u0254\u00f8n\u0279s\u01dd \u01ddnd d\u0250\u0287\u01dd \u026fns\u0287 b\u01dd l\u0250\u0287\u01dd\u0279 \u0287\u0265\u0250n \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd s\u0287\u0250\u0279\u0287 d\u0250\u0287\u01dd.", @@ -1563,7 +1612,7 @@ "The file you are trying to upload is too large.": "\u0166\u0265\u01dd \u025f\u1d09l\u01dd \u028e\u00f8n \u0250\u0279\u01dd \u0287\u0279\u028e\u1d09n\u0183 \u0287\u00f8 ndl\u00f8\u0250d \u1d09s \u0287\u00f8\u00f8 l\u0250\u0279\u0183\u01dd.", "The following email addresses and/or usernames are invalid:": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u01dd\u026f\u0250\u1d09l \u0250dd\u0279\u01ddss\u01dds \u0250nd/\u00f8\u0279 ns\u01dd\u0279n\u0250\u026f\u01dds \u0250\u0279\u01dd \u1d09n\u028c\u0250l\u1d09d:", "The following errors were generated:": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u01dd\u0279\u0279\u00f8\u0279s \u028d\u01dd\u0279\u01dd \u0183\u01ddn\u01dd\u0279\u0250\u0287\u01ddd:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u1d09s \u0250l\u0279\u01dd\u0250d\u028e \u0250 d\u0250\u0279\u0287 \u00f8\u025f \u028e\u00f8n\u0279 {platform} d\u0279\u00f8\u025f\u1d09l\u01dd. W\u01dd\\'\u028c\u01dd \u1d09n\u0254lnd\u01ddd \u1d09\u0287 \u0265\u01dd\u0279\u01dd \u025f\u00f8\u0279 \u028e\u00f8n\u0279 \u0250ddl\u1d09\u0254\u0250\u0287\u1d09\u00f8n.", + "The following information is already a part of your {platform} profile. We've included it here for your application.": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u1d09s \u0250l\u0279\u01dd\u0250d\u028e \u0250 d\u0250\u0279\u0287 \u00f8\u025f \u028e\u00f8n\u0279 {platform} d\u0279\u00f8\u025f\u1d09l\u01dd. W\u01dd'\u028c\u01dd \u1d09n\u0254lnd\u01ddd \u1d09\u0287 \u0265\u01dd\u0279\u01dd \u025f\u00f8\u0279 \u028e\u00f8n\u0279 \u0250ddl\u1d09\u0254\u0250\u0287\u1d09\u00f8n.", "The following message will be displayed at the bottom of the courseware pages within your course:": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u026f\u01ddss\u0250\u0183\u01dd \u028d\u1d09ll b\u01dd d\u1d09sdl\u0250\u028e\u01ddd \u0250\u0287 \u0287\u0265\u01dd b\u00f8\u0287\u0287\u00f8\u026f \u00f8\u025f \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd\u028d\u0250\u0279\u01dd d\u0250\u0183\u01dds \u028d\u1d09\u0287\u0265\u1d09n \u028e\u00f8n\u0279 \u0254\u00f8n\u0279s\u01dd:", "The following options are available for the {license_name} license.": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 \u00f8d\u0287\u1d09\u00f8ns \u0250\u0279\u01dd \u0250\u028c\u0250\u1d09l\u0250bl\u01dd \u025f\u00f8\u0279 \u0287\u0265\u01dd {license_name} l\u1d09\u0254\u01ddns\u01dd.", "The following users are no longer enrolled in the course:": "\u0166\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 ns\u01dd\u0279s \u0250\u0279\u01dd n\u00f8 l\u00f8n\u0183\u01dd\u0279 \u01ddn\u0279\u00f8ll\u01ddd \u1d09n \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd:", @@ -1575,7 +1624,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "\u0166\u0265\u01dd \u026f\u1d09n\u1d09\u026fn\u026f \u0254\u00f8\u026fdl\u01dd\u0287\u1d09\u00f8n d\u01dd\u0279\u0254\u01ddn\u0287\u0250\u0183\u01dd \u026fns\u0287 b\u01dd \u0250 \u028d\u0265\u00f8l\u01dd nn\u026fb\u01dd\u0279 b\u01dd\u0287\u028d\u01dd\u01ddn 0 \u0250nd 100.", "The minimum grade for course credit is not set.": "\u0166\u0265\u01dd \u026f\u1d09n\u1d09\u026fn\u026f \u0183\u0279\u0250d\u01dd \u025f\u00f8\u0279 \u0254\u00f8n\u0279s\u01dd \u0254\u0279\u01ddd\u1d09\u0287 \u1d09s n\u00f8\u0287 s\u01dd\u0287.", "The minimum score percentage must be a whole number between 0 and 100.": "\u0166\u0265\u01dd \u026f\u1d09n\u1d09\u026fn\u026f s\u0254\u00f8\u0279\u01dd d\u01dd\u0279\u0254\u01ddn\u0287\u0250\u0183\u01dd \u026fns\u0287 b\u01dd \u0250 \u028d\u0265\u00f8l\u01dd nn\u026fb\u01dd\u0279 b\u01dd\u0287\u028d\u01dd\u01ddn 0 \u0250nd 100.", - "The more you tell us, the more quickly and helpfully we can respond!": "\u0166\u0265\u01dd \u026f\u00f8\u0279\u01dd \u028e\u00f8n \u0287\u01ddll ns, \u0287\u0265\u01dd \u026f\u00f8\u0279\u01dd bn\u1d09\u0254\u029el\u028e \u0250nd \u0265\u01ddld\u025fnll\u028e \u028d\u01dd \u0254\u0250n \u0279\u01ddsd\u00f8nd!", "The name of this signatory as it should appear on certificates.": "\u0166\u0265\u01dd n\u0250\u026f\u01dd \u00f8\u025f \u0287\u0265\u1d09s s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u028e \u0250s \u1d09\u0287 s\u0265\u00f8nld \u0250dd\u01dd\u0250\u0279 \u00f8n \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dds.", "The name that identifies you on {platform_name}. You cannot change your username.": "\u0166\u0265\u01dd n\u0250\u026f\u01dd \u0287\u0265\u0250\u0287 \u1d09d\u01ddn\u0287\u1d09\u025f\u1d09\u01dds \u028e\u00f8n \u00f8n {platform_name}. \u024e\u00f8n \u0254\u0250nn\u00f8\u0287 \u0254\u0265\u0250n\u0183\u01dd \u028e\u00f8n\u0279 ns\u01dd\u0279n\u0250\u026f\u01dd.", "The name that is used for ID verification and that appears on your certificates.": "\u0166\u0265\u01dd n\u0250\u026f\u01dd \u0287\u0265\u0250\u0287 \u1d09s ns\u01ddd \u025f\u00f8\u0279 \u0197\u0110 \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n \u0250nd \u0287\u0265\u0250\u0287 \u0250dd\u01dd\u0250\u0279s \u00f8n \u028e\u00f8n\u0279 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dds.", @@ -1583,7 +1631,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "\u0166\u0265\u01dd nn\u026fb\u01dd\u0279 \u00f8\u025f snbs\u01dd\u0254\u0287\u1d09\u00f8ns \u1d09n \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd \u0287\u0265\u0250\u0287 \u0254\u00f8n\u0287\u0250\u1d09n d\u0279\u00f8bl\u01dd\u026fs \u00f8\u025f \u0287\u0265\u1d09s \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287 \u0287\u028ed\u01dd.", "The organization that this signatory belongs to, as it should appear on certificates.": "\u0166\u0265\u01dd \u00f8\u0279\u0183\u0250n\u1d09z\u0250\u0287\u1d09\u00f8n \u0287\u0265\u0250\u0287 \u0287\u0265\u1d09s s\u1d09\u0183n\u0250\u0287\u00f8\u0279\u028e b\u01ddl\u00f8n\u0183s \u0287\u00f8, \u0250s \u1d09\u0287 s\u0265\u00f8nld \u0250dd\u01dd\u0250\u0279 \u00f8n \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dds.", "The page \"{route}\" could not be found.": "\u0166\u0265\u01dd d\u0250\u0183\u01dd \"{route}\" \u0254\u00f8nld n\u00f8\u0287 b\u01dd \u025f\u00f8nnd.", - "The photo of your face matches the photo on your ID.": "\u0166\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd \u026f\u0250\u0287\u0254\u0265\u01dds \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8n \u028e\u00f8n\u0279 \u0197\u0110.", "The post you selected has been deleted.": "\u0166\u0265\u01dd d\u00f8s\u0287 \u028e\u00f8n s\u01ddl\u01dd\u0254\u0287\u01ddd \u0265\u0250s b\u01dd\u01ddn d\u01ddl\u01dd\u0287\u01ddd.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "\u0166\u0265\u01dd dnbl\u1d09s\u0265\u01ddd b\u0279\u0250n\u0254\u0265 \u028c\u01dd\u0279s\u1d09\u00f8n, {published}, \u028d\u0250s \u0279\u01dds\u01dd\u0287 \u0287\u00f8 \u0287\u0265\u01dd d\u0279\u0250\u025f\u0287 b\u0279\u0250n\u0254\u0265 \u028c\u01dd\u0279s\u1d09\u00f8n, {draft}.", "The raw error message is:": "\u0166\u0265\u01dd \u0279\u0250\u028d \u01dd\u0279\u0279\u00f8\u0279 \u026f\u01ddss\u0250\u0183\u01dd \u1d09s:", @@ -1675,6 +1722,10 @@ "This post could not be reopened. Refresh the page and try again.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u0254\u00f8nld n\u00f8\u0287 b\u01dd \u0279\u01dd\u00f8d\u01ddn\u01ddd. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", "This post could not be unflagged for abuse. Refresh the page and try again.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u0254\u00f8nld n\u00f8\u0287 b\u01dd nn\u025fl\u0250\u0183\u0183\u01ddd \u025f\u00f8\u0279 \u0250bns\u01dd. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", "This post could not be unpinned. Refresh the page and try again.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u0254\u00f8nld n\u00f8\u0287 b\u01dd nnd\u1d09nn\u01ddd. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", + "This post is visible only to %(group_name)s.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u1d09s \u028c\u1d09s\u1d09bl\u01dd \u00f8nl\u028e \u0287\u00f8 %(group_name)s.", + "This post is visible to everyone.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u1d09s \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 \u01dd\u028c\u01dd\u0279\u028e\u00f8n\u01dd.", + "This post will be visible only to %(group_name)s.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u028d\u1d09ll b\u01dd \u028c\u1d09s\u1d09bl\u01dd \u00f8nl\u028e \u0287\u00f8 %(group_name)s.", + "This post will be visible to everyone.": "\u0166\u0265\u1d09s d\u00f8s\u0287 \u028d\u1d09ll b\u01dd \u028c\u1d09s\u1d09bl\u01dd \u0287\u00f8 \u01dd\u028c\u01dd\u0279\u028e\u00f8n\u01dd.", "This problem has been reset.": "\u0166\u0265\u1d09s d\u0279\u00f8bl\u01dd\u026f \u0265\u0250s b\u01dd\u01ddn \u0279\u01dds\u01dd\u0287.", "This response could not be marked as an answer. Refresh the page and try again.": "\u0166\u0265\u1d09s \u0279\u01ddsd\u00f8ns\u01dd \u0254\u00f8nld n\u00f8\u0287 b\u01dd \u026f\u0250\u0279\u029e\u01ddd \u0250s \u0250n \u0250ns\u028d\u01dd\u0279. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", "This response could not be marked as endorsed. Refresh the page and try again.": "\u0166\u0265\u1d09s \u0279\u01ddsd\u00f8ns\u01dd \u0254\u00f8nld n\u00f8\u0287 b\u01dd \u026f\u0250\u0279\u029e\u01ddd \u0250s \u01ddnd\u00f8\u0279s\u01ddd. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", @@ -1682,8 +1733,11 @@ "This response could not be unmarked as an answer. Refresh the page and try again.": "\u0166\u0265\u1d09s \u0279\u01ddsd\u00f8ns\u01dd \u0254\u00f8nld n\u00f8\u0287 b\u01dd nn\u026f\u0250\u0279\u029e\u01ddd \u0250s \u0250n \u0250ns\u028d\u01dd\u0279. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", "This role requires a divided discussions scheme.": "\u0166\u0265\u1d09s \u0279\u00f8l\u01dd \u0279\u01ddbn\u1d09\u0279\u01dds \u0250 d\u1d09\u028c\u1d09d\u01ddd d\u1d09s\u0254nss\u1d09\u00f8ns s\u0254\u0265\u01dd\u026f\u01dd.", "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.": "\u0166\u0265\u1d09s s\u0265\u00f8\u0279\u0287 n\u0250\u026f\u01dd \u025f\u00f8\u0279 \u0287\u0265\u01dd \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287 \u0287\u028ed\u01dd (\u025f\u00f8\u0279 \u01ddx\u0250\u026fdl\u01dd, \u0126W \u00f8\u0279 M\u1d09d\u0287\u01dd\u0279\u026f) \u0250dd\u01dd\u0250\u0279s n\u01ddx\u0287 \u0287\u00f8 \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287s \u00f8n \u0250 l\u01dd\u0250\u0279n\u01dd\u0279's \u2c63\u0279\u00f8\u0183\u0279\u01ddss d\u0250\u0183\u01dd.", + "This special exam has been released to learners. You may not convert it to another type of special exam. You may revert this subsection back to being a basic exam by selecting 'None', but you will NOT be able to configure it as a special exam in the future.": "\u0166\u0265\u1d09s sd\u01dd\u0254\u1d09\u0250l \u01ddx\u0250\u026f \u0265\u0250s b\u01dd\u01ddn \u0279\u01ddl\u01dd\u0250s\u01ddd \u0287\u00f8 l\u01dd\u0250\u0279n\u01dd\u0279s. \u024e\u00f8n \u026f\u0250\u028e n\u00f8\u0287 \u0254\u00f8n\u028c\u01dd\u0279\u0287 \u1d09\u0287 \u0287\u00f8 \u0250n\u00f8\u0287\u0265\u01dd\u0279 \u0287\u028ed\u01dd \u00f8\u025f sd\u01dd\u0254\u1d09\u0250l \u01ddx\u0250\u026f. \u024e\u00f8n \u026f\u0250\u028e \u0279\u01dd\u028c\u01dd\u0279\u0287 \u0287\u0265\u1d09s snbs\u01dd\u0254\u0287\u1d09\u00f8n b\u0250\u0254\u029e \u0287\u00f8 b\u01dd\u1d09n\u0183 \u0250 b\u0250s\u1d09\u0254 \u01ddx\u0250\u026f b\u028e s\u01ddl\u01dd\u0254\u0287\u1d09n\u0183 'N\u00f8n\u01dd', bn\u0287 \u028e\u00f8n \u028d\u1d09ll N\u00d8\u0166 b\u01dd \u0250bl\u01dd \u0287\u00f8 \u0254\u00f8n\u025f\u1d09\u0183n\u0279\u01dd \u1d09\u0287 \u0250s \u0250 sd\u01dd\u0254\u1d09\u0250l \u01ddx\u0250\u026f \u1d09n \u0287\u0265\u01dd \u025fn\u0287n\u0279\u01dd.", + "This subsection was released to learners as a special exam, but was reverted back to a basic exam. You may not configure it as a special exam now. Contact edX Support for assistance.": "\u0166\u0265\u1d09s snbs\u01dd\u0254\u0287\u1d09\u00f8n \u028d\u0250s \u0279\u01ddl\u01dd\u0250s\u01ddd \u0287\u00f8 l\u01dd\u0250\u0279n\u01dd\u0279s \u0250s \u0250 sd\u01dd\u0254\u1d09\u0250l \u01ddx\u0250\u026f, bn\u0287 \u028d\u0250s \u0279\u01dd\u028c\u01dd\u0279\u0287\u01ddd b\u0250\u0254\u029e \u0287\u00f8 \u0250 b\u0250s\u1d09\u0254 \u01ddx\u0250\u026f. \u024e\u00f8n \u026f\u0250\u028e n\u00f8\u0287 \u0254\u00f8n\u025f\u1d09\u0183n\u0279\u01dd \u1d09\u0287 \u0250s \u0250 sd\u01dd\u0254\u1d09\u0250l \u01ddx\u0250\u026f n\u00f8\u028d. \u023b\u00f8n\u0287\u0250\u0254\u0287 \u01dddX Sndd\u00f8\u0279\u0287 \u025f\u00f8\u0279 \u0250ss\u1d09s\u0287\u0250n\u0254\u01dd.", "This team does not have any members.": "\u0166\u0265\u1d09s \u0287\u01dd\u0250\u026f d\u00f8\u01dds n\u00f8\u0287 \u0265\u0250\u028c\u01dd \u0250n\u028e \u026f\u01dd\u026fb\u01dd\u0279s.", "This team is full.": "\u0166\u0265\u1d09s \u0287\u01dd\u0250\u026f \u1d09s \u025fnll.", + "This thread is closed.": "\u0166\u0265\u1d09s \u0287\u0265\u0279\u01dd\u0250d \u1d09s \u0254l\u00f8s\u01ddd.", "This unit has validation issues.": "\u0166\u0265\u1d09s nn\u1d09\u0287 \u0265\u0250s \u028c\u0250l\u1d09d\u0250\u0287\u1d09\u00f8n \u1d09ssn\u01dds.", "This vote could not be processed. Refresh the page and try again.": "\u0166\u0265\u1d09s \u028c\u00f8\u0287\u01dd \u0254\u00f8nld n\u00f8\u0287 b\u01dd d\u0279\u00f8\u0254\u01ddss\u01ddd. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u01dd d\u0250\u0183\u01dd \u0250nd \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", "This {parentCategory} has no {childCategory}": "\u0166\u0265\u1d09s {parentCategory} \u0265\u0250s n\u00f8 {childCategory}", @@ -1708,7 +1762,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "\u0166\u00f8 b\u01dd sn\u0279\u01dd \u0250ll s\u0287nd\u01ddn\u0287s \u0254\u0250n \u0250\u0254\u0254\u01ddss \u0287\u0265\u01dd \u028c\u1d09d\u01dd\u00f8, \u028d\u01dd \u0279\u01dd\u0254\u00f8\u026f\u026f\u01ddnd d\u0279\u00f8\u028c\u1d09d\u1d09n\u0183 b\u00f8\u0287\u0265 \u0250n .\u026fd4 \u0250nd \u0250 .\u028d\u01ddb\u026f \u028c\u01dd\u0279s\u1d09\u00f8n \u00f8\u025f \u028e\u00f8n\u0279 \u028c\u1d09d\u01dd\u00f8. \u023bl\u1d09\u0254\u029e b\u01ddl\u00f8\u028d \u0287\u00f8 \u0250dd \u0250 \u0244\u024c\u0141 \u025f\u00f8\u0279 \u0250n\u00f8\u0287\u0265\u01dd\u0279 \u028c\u01dd\u0279s\u1d09\u00f8n. \u0166\u0265\u01dds\u01dd \u0244\u024c\u0141s \u0254\u0250nn\u00f8\u0287 b\u01dd \u024e\u00f8n\u0166nb\u01dd \u0244\u024c\u0141s. \u0166\u0265\u01dd \u025f\u1d09\u0279s\u0287 l\u1d09s\u0287\u01ddd \u028c\u1d09d\u01dd\u00f8 \u0287\u0265\u0250\u0287's \u0254\u00f8\u026fd\u0250\u0287\u1d09bl\u01dd \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd s\u0287nd\u01ddn\u0287's \u0254\u00f8\u026fdn\u0287\u01dd\u0279 \u028d\u1d09ll dl\u0250\u028e.", "To complete the program, you must earn a verified certificate for each course.": "\u0166\u00f8 \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0287\u0265\u01dd d\u0279\u00f8\u0183\u0279\u0250\u026f, \u028e\u00f8n \u026fns\u0287 \u01dd\u0250\u0279n \u0250 \u028c\u01dd\u0279\u1d09\u025f\u1d09\u01ddd \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u025f\u00f8\u0279 \u01dd\u0250\u0254\u0265 \u0254\u00f8n\u0279s\u01dd.", "To continue learning with this account, sign in below.": "\u0166\u00f8 \u0254\u00f8n\u0287\u1d09nn\u01dd l\u01dd\u0250\u0279n\u1d09n\u0183 \u028d\u1d09\u0287\u0265 \u0287\u0265\u1d09s \u0250\u0254\u0254\u00f8nn\u0287, s\u1d09\u0183n \u1d09n b\u01ddl\u00f8\u028d.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "\u0166\u00f8 \u025f\u1d09n\u0250l\u1d09z\u01dd \u0254\u00f8n\u0279s\u01dd \u0254\u0279\u01ddd\u1d09\u0287, %(display_name)s \u0279\u01ddbn\u1d09\u0279\u01dds %(platform_name)s l\u01dd\u0250\u0279n\u01dd\u0279s \u0287\u00f8 snb\u026f\u1d09\u0287 \u0250 \u0254\u0279\u01ddd\u1d09\u0287 \u0279\u01ddbn\u01dds\u0287.", "To invalidate a certificate for a particular learner, add the username or email address below.": "\u0166\u00f8 \u1d09n\u028c\u0250l\u1d09d\u0250\u0287\u01dd \u0250 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u025f\u00f8\u0279 \u0250 d\u0250\u0279\u0287\u1d09\u0254nl\u0250\u0279 l\u01dd\u0250\u0279n\u01dd\u0279, \u0250dd \u0287\u0265\u01dd ns\u01dd\u0279n\u0250\u026f\u01dd \u00f8\u0279 \u01dd\u026f\u0250\u1d09l \u0250dd\u0279\u01ddss b\u01ddl\u00f8\u028d.", "To receive a certificate, you must also verify your identity before {date}.": "\u0166\u00f8 \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd \u0250 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd, \u028e\u00f8n \u026fns\u0287 \u0250ls\u00f8 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e b\u01dd\u025f\u00f8\u0279\u01dd {date}.", "To receive a certificate, you must also verify your identity.": "\u0166\u00f8 \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd \u0250 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd, \u028e\u00f8n \u026fns\u0287 \u0250ls\u00f8 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e.", @@ -1716,13 +1769,14 @@ "To review learner cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on the {link_start}Data Download{link_end} page.": "\u0166\u00f8 \u0279\u01dd\u028c\u1d09\u01dd\u028d l\u01dd\u0250\u0279n\u01dd\u0279 \u0254\u00f8\u0265\u00f8\u0279\u0287 \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287s \u00f8\u0279 s\u01dd\u01dd \u0287\u0265\u01dd \u0279\u01ddsnl\u0287s \u00f8\u025f ndl\u00f8\u0250d\u1d09n\u0183 \u0250 \u023bSV \u025f\u1d09l\u01dd, d\u00f8\u028dnl\u00f8\u0250d \u0254\u00f8n\u0279s\u01dd d\u0279\u00f8\u025f\u1d09l\u01dd \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u00f8\u0279 \u0254\u00f8\u0265\u00f8\u0279\u0287 \u0279\u01ddsnl\u0287s \u00f8n \u0287\u0265\u01dd {link_start}\u0110\u0250\u0287\u0250 \u0110\u00f8\u028dnl\u00f8\u0250d{link_end} d\u0250\u0183\u01dd.", "To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.": "\u0166\u00f8 s\u0265\u0250\u0279\u01dd \u028e\u00f8n\u0279 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u00f8n M\u00f8z\u1d09ll\u0250 \u0243\u0250\u0254\u029ed\u0250\u0254\u029e, \u028e\u00f8n \u026fns\u0287 \u025f\u1d09\u0279s\u0287 \u0265\u0250\u028c\u01dd \u0250 \u0243\u0250\u0254\u029ed\u0250\u0254\u029e \u0250\u0254\u0254\u00f8nn\u0287. \u023b\u00f8\u026fdl\u01dd\u0287\u01dd \u0287\u0265\u01dd \u025f\u00f8ll\u00f8\u028d\u1d09n\u0183 s\u0287\u01ddds \u0287\u00f8 \u0250dd \u028e\u00f8n\u0279 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd \u0287\u00f8 \u0243\u0250\u0254\u029ed\u0250\u0254\u029e.", "To take a successful photo, make sure that:": "\u0166\u00f8 \u0287\u0250\u029e\u01dd \u0250 sn\u0254\u0254\u01ddss\u025fnl d\u0265\u00f8\u0287\u00f8, \u026f\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u0265\u0250\u0287:", - "To use the current photo, select the Take Photo button {icon}. To take another photo, select the Retake Photo button {icon}.": "\u0166\u00f8 ns\u01dd \u0287\u0265\u01dd \u0254n\u0279\u0279\u01ddn\u0287 d\u0265\u00f8\u0287\u00f8, s\u01ddl\u01dd\u0254\u0287 \u0287\u0265\u01dd \u0166\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8 bn\u0287\u0287\u00f8n {icon}. \u0166\u00f8 \u0287\u0250\u029e\u01dd \u0250n\u00f8\u0287\u0265\u01dd\u0279 d\u0265\u00f8\u0287\u00f8, s\u01ddl\u01dd\u0254\u0287 \u0287\u0265\u01dd \u024c\u01dd\u0287\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8 bn\u0287\u0287\u00f8n {icon}.", + "To take the photo of your face, click on the camera button {icon}. If you need to try again, click 'Retake Photo'.": "\u0166\u00f8 \u0287\u0250\u029e\u01dd \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd, \u0254l\u1d09\u0254\u029e \u00f8n \u0287\u0265\u01dd \u0254\u0250\u026f\u01dd\u0279\u0250 bn\u0287\u0287\u00f8n {icon}. \u0197\u025f \u028e\u00f8n n\u01dd\u01ddd \u0287\u00f8 \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n, \u0254l\u1d09\u0254\u029e '\u024c\u01dd\u0287\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8'.", "To verify your identity, you need a webcam and a government-issued photo ID.": "\u0166\u00f8 \u028c\u01dd\u0279\u1d09\u025f\u028e \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e, \u028e\u00f8n n\u01dd\u01ddd \u0250 \u028d\u01ddb\u0254\u0250\u026f \u0250nd \u0250 \u0183\u00f8\u028c\u01dd\u0279n\u026f\u01ddn\u0287-\u1d09ssn\u01ddd d\u0265\u00f8\u0287\u00f8 \u0197\u0110.", "Toggle Account Password (Usable/Unusable)": "\u0166\u00f8\u0183\u0183l\u01dd \u023a\u0254\u0254\u00f8nn\u0287 \u2c63\u0250ss\u028d\u00f8\u0279d (\u0244s\u0250bl\u01dd/\u0244nns\u0250bl\u01dd)", "Toggle Notifications Setting": "\u0166\u00f8\u0183\u0183l\u01dd N\u00f8\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8ns S\u01dd\u0287\u0287\u1d09n\u0183", "Tools": "\u0166\u00f8\u00f8ls", "Top": "\u0166\u00f8d", "Topic": "\u0166\u00f8d\u1d09\u0254", + "Topic area": "\u0166\u00f8d\u1d09\u0254 \u0250\u0279\u01dd\u0250", "Topics": "\u0166\u00f8d\u1d09\u0254s", "Total": "\u0166\u00f8\u0287\u0250l", "Total Number": "\u0166\u00f8\u0287\u0250l Nn\u026fb\u01dd\u0279", @@ -1749,6 +1803,8 @@ "Undo Changes": "\u0244nd\u00f8 \u023b\u0265\u0250n\u0183\u01dds", "Undo move": "\u0244nd\u00f8 \u026f\u00f8\u028c\u01dd", "Undo moving": "\u0244nd\u00f8 \u026f\u00f8\u028c\u1d09n\u0183", + "Unendorse": "\u0244n\u01ddnd\u00f8\u0279s\u01dd", + "Unfollow": "\u0244n\u025f\u00f8ll\u00f8\u028d", "Ungraded": "\u0244n\u0183\u0279\u0250d\u01ddd", "Unit": "\u0244n\u1d09\u0287", "Unit Access": "\u0244n\u1d09\u0287 \u023a\u0254\u0254\u01ddss", @@ -1759,13 +1815,19 @@ "Unlink This Account": "\u0244nl\u1d09n\u029e \u0166\u0265\u1d09s \u023a\u0254\u0254\u00f8nn\u0287", "Unlink your {accountName} account": "\u0244nl\u1d09n\u029e \u028e\u00f8n\u0279 {accountName} \u0250\u0254\u0254\u00f8nn\u0287", "Unlinking": "\u0244nl\u1d09n\u029e\u1d09n\u0183", + "Unmark as Answer": "\u0244n\u026f\u0250\u0279\u029e \u0250s \u023ans\u028d\u01dd\u0279", "Unmute": "\u0244n\u026fn\u0287\u01dd", + "Unpin": "\u0244nd\u1d09n", "Unpublished changes to content that will release in the future": "\u0244ndnbl\u1d09s\u0265\u01ddd \u0254\u0265\u0250n\u0183\u01dds \u0287\u00f8 \u0254\u00f8n\u0287\u01ddn\u0287 \u0287\u0265\u0250\u0287 \u028d\u1d09ll \u0279\u01ddl\u01dd\u0250s\u01dd \u1d09n \u0287\u0265\u01dd \u025fn\u0287n\u0279\u01dd", "Unpublished changes to live content": "\u0244ndnbl\u1d09s\u0265\u01ddd \u0254\u0265\u0250n\u0183\u01dds \u0287\u00f8 l\u1d09\u028c\u01dd \u0254\u00f8n\u0287\u01ddn\u0287", "Unpublished units will not be released": "\u0244ndnbl\u1d09s\u0265\u01ddd nn\u1d09\u0287s \u028d\u1d09ll n\u00f8\u0287 b\u01dd \u0279\u01ddl\u01dd\u0250s\u01ddd", + "Unreport": "\u0244n\u0279\u01ddd\u00f8\u0279\u0287", "Unscheduled": "\u0244ns\u0254\u0265\u01dddnl\u01ddd", "Update": "\u0244dd\u0250\u0287\u01dd", "Update Settings": "\u0244dd\u0250\u0287\u01dd S\u01dd\u0287\u0287\u1d09n\u0183s", + "Update comment": "\u0244dd\u0250\u0287\u01dd \u0254\u00f8\u026f\u026f\u01ddn\u0287", + "Update post": "\u0244dd\u0250\u0287\u01dd d\u00f8s\u0287", + "Update response": "\u0244dd\u0250\u0287\u01dd \u0279\u01ddsd\u00f8ns\u01dd", "Update team.": "\u0244dd\u0250\u0287\u01dd \u0287\u01dd\u0250\u026f.", "Updating Tags": "\u0244dd\u0250\u0287\u1d09n\u0183 \u0166\u0250\u0183s", "Updating with latest library content": "\u0244dd\u0250\u0287\u1d09n\u0183 \u028d\u1d09\u0287\u0265 l\u0250\u0287\u01dds\u0287 l\u1d09b\u0279\u0250\u0279\u028e \u0254\u00f8n\u0287\u01ddn\u0287", @@ -1787,7 +1849,7 @@ "Upload Videos": "\u0244dl\u00f8\u0250d V\u1d09d\u01dd\u00f8s", "Upload a CSV file": "\u0244dl\u00f8\u0250d \u0250 \u023bSV \u025f\u1d09l\u01dd", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u0244dl\u00f8\u0250d \u0250 \u0254\u00f8\u026f\u026f\u0250 s\u01ddd\u0250\u0279\u0250\u0287\u01ddd \u028c\u0250ln\u01dds (.\u0254s\u028c) \u025f\u1d09l\u01dd \u0287\u0265\u0250\u0287 \u0254\u00f8n\u0287\u0250\u1d09ns \u0287\u0265\u01dd ns\u01dd\u0279n\u0250\u026f\u01dds \u00f8\u0279 \u01dd\u026f\u0250\u1d09l \u0250dd\u0279\u01ddss\u01dds \u00f8\u025f l\u01dd\u0250\u0279n\u01dd\u0279s \u028d\u0265\u00f8 \u0265\u0250\u028c\u01dd b\u01dd\u01ddn \u0183\u1d09\u028c\u01ddn \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8ns. \u0197n\u0254lnd\u01dd \u0287\u0265\u01dd ns\u01dd\u0279n\u0250\u026f\u01dd \u00f8\u0279 \u01dd\u026f\u0250\u1d09l \u0250dd\u0279\u01ddss \u1d09n \u0287\u0265\u01dd \u025f\u1d09\u0279s\u0287 \u0254\u00f8\u026f\u026f\u0250 s\u01ddd\u0250\u0279\u0250\u0287\u01ddd \u025f\u1d09\u01ddld. \u024e\u00f8n \u0254\u0250n \u1d09n\u0254lnd\u01dd \u0250n \u00f8d\u0287\u1d09\u00f8n\u0250l n\u00f8\u0287\u01dd d\u01dds\u0254\u0279\u1d09b\u1d09n\u0183 \u0287\u0265\u01dd \u0279\u01dd\u0250s\u00f8n \u025f\u00f8\u0279 \u0287\u0265\u01dd \u01ddx\u0254\u01ddd\u0287\u1d09\u00f8n \u1d09n \u0287\u0265\u01dd s\u01dd\u0254\u00f8nd \u0254\u00f8\u026f\u026f\u0250 s\u01ddd\u0250\u0279\u0250\u0287\u01ddd \u025f\u1d09\u01ddld.", - "Upload a new PDF to \u201c<%= name %>\u201d": "\u0244dl\u00f8\u0250d \u0250 n\u01dd\u028d \u2c63\u0110F \u0287\u00f8 \u201c<%= name %>\u201d", + "Upload a new PDF to \u201c<%- name %>\u201d": "\u0244dl\u00f8\u0250d \u0250 n\u01dd\u028d \u2c63\u0110F \u0287\u00f8 \u201c<%- name %>\u201d", "Upload an image": "\u0244dl\u00f8\u0250d \u0250n \u1d09\u026f\u0250\u0183\u01dd", "Upload an image or capture one with your web or phone camera.": "\u0244dl\u00f8\u0250d \u0250n \u1d09\u026f\u0250\u0183\u01dd \u00f8\u0279 \u0254\u0250d\u0287n\u0279\u01dd \u00f8n\u01dd \u028d\u1d09\u0287\u0265 \u028e\u00f8n\u0279 \u028d\u01ddb \u00f8\u0279 d\u0265\u00f8n\u01dd \u0254\u0250\u026f\u01dd\u0279\u0250.", "Upload completed": "\u0244dl\u00f8\u0250d \u0254\u00f8\u026fdl\u01dd\u0287\u01ddd", @@ -1822,7 +1884,7 @@ "Use my university info": "\u0244s\u01dd \u026f\u028e nn\u1d09\u028c\u01dd\u0279s\u1d09\u0287\u028e \u1d09n\u025f\u00f8", "Use the All Topics menu to find specific topics.": "\u0244s\u01dd \u0287\u0265\u01dd \u023all \u0166\u00f8d\u1d09\u0254s \u026f\u01ddnn \u0287\u00f8 \u025f\u1d09nd sd\u01dd\u0254\u1d09\u025f\u1d09\u0254 \u0287\u00f8d\u1d09\u0254s.", "Use the Retake Photo button if you are not pleased with your photo": "\u0244s\u01dd \u0287\u0265\u01dd \u024c\u01dd\u0287\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8 bn\u0287\u0287\u00f8n \u1d09\u025f \u028e\u00f8n \u0250\u0279\u01dd n\u00f8\u0287 dl\u01dd\u0250s\u01ddd \u028d\u1d09\u0287\u0265 \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u0244s\u01dd \u028e\u00f8n\u0279 \u028d\u01ddb\u0254\u0250\u026f \u0287\u00f8 \u0287\u0250\u029e\u01dd \u0250 d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u0197\u0110. W\u01dd \u028d\u1d09ll \u026f\u0250\u0287\u0254\u0265 \u0287\u0265\u1d09s d\u0265\u00f8\u0287\u00f8 \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd \u0250nd \u0287\u0265\u01dd n\u0250\u026f\u01dd \u00f8n \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287.", + "Use your webcam to take a photo of your ID.": "\u0244s\u01dd \u028e\u00f8n\u0279 \u028d\u01ddb\u0254\u0250\u026f \u0287\u00f8 \u0287\u0250\u029e\u01dd \u0250 d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u0197\u0110.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u0244s\u01dd \u028e\u00f8n\u0279 \u028d\u01ddb\u0254\u0250\u026f \u0287\u00f8 \u0287\u0250\u029e\u01dd \u0250 d\u0265\u00f8\u0287\u00f8 \u00f8\u025f \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd. W\u01dd \u028d\u1d09ll \u026f\u0250\u0287\u0254\u0265 \u0287\u0265\u1d09s d\u0265\u00f8\u0287\u00f8 \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd d\u0265\u00f8\u0287\u00f8 \u00f8n \u028e\u00f8n\u0279 \u0197\u0110.", "Used": "\u0244s\u01ddd", "Used in {count} location": [ @@ -1845,7 +1907,6 @@ "Verified Certificate upgrade": "V\u01dd\u0279\u1d09\u025f\u1d09\u01ddd \u023b\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd nd\u0183\u0279\u0250d\u01dd", "Verified Status": "V\u01dd\u0279\u1d09\u025f\u1d09\u01ddd S\u0287\u0250\u0287ns", "Verified mode price": "V\u01dd\u0279\u1d09\u025f\u1d09\u01ddd \u026f\u00f8d\u01dd d\u0279\u1d09\u0254\u01dd", - "Verify Now": "V\u01dd\u0279\u1d09\u025f\u028e N\u00f8\u028d", "Version": "V\u01dd\u0279s\u1d09\u00f8n", "Vertical space": "V\u01dd\u0279\u0287\u1d09\u0254\u0250l sd\u0250\u0254\u01dd", "Very loud": "V\u01dd\u0279\u028e l\u00f8nd", @@ -1872,16 +1933,19 @@ "View Teams in the {topic_name} Topic": "V\u1d09\u01dd\u028d \u0166\u01dd\u0250\u026fs \u1d09n \u0287\u0265\u01dd {topic_name} \u0166\u00f8d\u1d09\u0254", "View all errors": "V\u1d09\u01dd\u028d \u0250ll \u01dd\u0279\u0279\u00f8\u0279s", "View child items": "V\u1d09\u01dd\u028d \u0254\u0265\u1d09ld \u1d09\u0287\u01dd\u026fs", + "View discussion": "V\u1d09\u01dd\u028d d\u1d09s\u0254nss\u1d09\u00f8n", "View {span_start} {team_name} {span_end}": "V\u1d09\u01dd\u028d {span_start} {team_name} {span_end}", "Viewing %s course": [ "V\u1d09\u01dd\u028d\u1d09n\u0183 %s \u0254\u00f8n\u0279s\u01dd", "V\u1d09\u01dd\u028d\u1d09n\u0183 %s \u0254\u00f8n\u0279s\u01dds" ], "Visibility": "V\u1d09s\u1d09b\u1d09l\u1d09\u0287\u028e", + "Visible to": "V\u1d09s\u1d09bl\u01dd \u0287\u00f8", "Visible to Staff Only": "V\u1d09s\u1d09bl\u01dd \u0287\u00f8 S\u0287\u0250\u025f\u025f \u00d8nl\u028e", "Visual aids": "V\u1d09sn\u0250l \u0250\u1d09ds", "Volume": "V\u00f8ln\u026f\u01dd", "Vote for good posts and responses": "V\u00f8\u0287\u01dd \u025f\u00f8\u0279 \u0183\u00f8\u00f8d d\u00f8s\u0287s \u0250nd \u0279\u01ddsd\u00f8ns\u01dds", + "Vote for this post,": "V\u00f8\u0287\u01dd \u025f\u00f8\u0279 \u0287\u0265\u1d09s d\u00f8s\u0287,", "Want to confirm your identity later?": "W\u0250n\u0287 \u0287\u00f8 \u0254\u00f8n\u025f\u1d09\u0279\u026f \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e l\u0250\u0287\u01dd\u0279?", "Warning": "W\u0250\u0279n\u1d09n\u0183", "Warnings": "W\u0250\u0279n\u1d09n\u0183s", @@ -1890,9 +1954,11 @@ "We couldn't find any results for \"%s\".": "W\u01dd \u0254\u00f8nldn'\u0287 \u025f\u1d09nd \u0250n\u028e \u0279\u01ddsnl\u0287s \u025f\u00f8\u0279 \"%s\".", "We couldn't sign you in.": "W\u01dd \u0254\u00f8nldn'\u0287 s\u1d09\u0183n \u028e\u00f8n \u1d09n.", "We have encountered an error. Refresh your browser and then try again.": "W\u01dd \u0265\u0250\u028c\u01dd \u01ddn\u0254\u00f8nn\u0287\u01dd\u0279\u01ddd \u0250n \u01dd\u0279\u0279\u00f8\u0279. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u028e\u00f8n\u0279 b\u0279\u00f8\u028ds\u01dd\u0279 \u0250nd \u0287\u0265\u01ddn \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "W\u01dd \u0265\u0250\u028c\u01dd \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01ddd \u028e\u00f8n\u0279 \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u0250nd \u0250\u0279\u01dd \u028c\u01dd\u0279\u1d09\u025f\u028e\u1d09n\u0183 \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e. \u024e\u00f8n \u028d\u1d09ll s\u01dd\u01dd \u0250 \u026f\u01ddss\u0250\u0183\u01dd \u00f8n \u028e\u00f8n\u0279 d\u0250s\u0265b\u00f8\u0250\u0279d \u028d\u0265\u01ddn \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss \u1d09s \u0254\u00f8\u026fdl\u01dd\u0287\u01dd (nsn\u0250ll\u028e \u028d\u1d09\u0287\u0265\u1d09n 1-2 d\u0250\u028es). \u0197n \u0287\u0265\u01dd \u026f\u01dd\u0250n\u0287\u1d09\u026f\u01dd, \u028e\u00f8n \u0254\u0250n s\u0287\u1d09ll \u0250\u0254\u0254\u01ddss \u0250ll \u0250\u028c\u0250\u1d09l\u0250bl\u01dd \u0254\u00f8n\u0279s\u01dd \u0254\u00f8n\u0287\u01ddn\u0287.", + "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days). In the meantime, you can still access all available course content.": "W\u01dd \u0265\u0250\u028c\u01dd \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01ddd \u028e\u00f8n\u0279 \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u0250nd \u0250\u0279\u01dd \u028c\u01dd\u0279\u1d09\u025f\u028e\u1d09n\u0183 \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e. \u024e\u00f8n \u028d\u1d09ll s\u01dd\u01dd \u0250 \u026f\u01ddss\u0250\u0183\u01dd \u00f8n \u028e\u00f8n\u0279 d\u0250s\u0265b\u00f8\u0250\u0279d \u028d\u0265\u01ddn \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss \u1d09s \u0254\u00f8\u026fdl\u01dd\u0287\u01dd (nsn\u0250ll\u028e \u028d\u1d09\u0287\u0265\u1d09n 5-7 d\u0250\u028es). \u0197n \u0287\u0265\u01dd \u026f\u01dd\u0250n\u0287\u1d09\u026f\u01dd, \u028e\u00f8n \u0254\u0250n s\u0287\u1d09ll \u0250\u0254\u0254\u01ddss \u0250ll \u0250\u028c\u0250\u1d09l\u0250bl\u01dd \u0254\u00f8n\u0279s\u01dd \u0254\u00f8n\u0287\u01ddn\u0287.", "We just need a little more information before you start learning with %(platformName)s.": "W\u01dd \u027ens\u0287 n\u01dd\u01ddd \u0250 l\u1d09\u0287\u0287l\u01dd \u026f\u00f8\u0279\u01dd \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n b\u01dd\u025f\u00f8\u0279\u01dd \u028e\u00f8n s\u0287\u0250\u0279\u0287 l\u01dd\u0250\u0279n\u1d09n\u0183 \u028d\u1d09\u0287\u0265 %(platformName)s.", + "We securely encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "W\u01dd s\u01dd\u0254n\u0279\u01ddl\u028e \u01ddn\u0254\u0279\u028ed\u0287 \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8 \u0250nd s\u01ddnd \u1d09\u0287 \u0287\u00f8 \u00f8n\u0279 \u0250n\u0287\u0265\u00f8\u0279\u1d09z\u0250\u0287\u1d09\u00f8n s\u01dd\u0279\u028c\u1d09\u0254\u01dd \u025f\u00f8\u0279 \u0279\u01dd\u028c\u1d09\u01dd\u028d. \u024e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8 \u0250nd \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u0250\u0279\u01dd n\u00f8\u0287 s\u0250\u028c\u01ddd \u00f8\u0279 \u028c\u1d09s\u1d09bl\u01dd \u0250n\u028e\u028d\u0265\u01dd\u0279\u01dd \u00f8n %(platformName)s \u0250\u025f\u0287\u01dd\u0279 \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss \u1d09s \u0254\u00f8\u026fdl\u01dd\u0287\u01dd.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "W\u01dd ns\u01dd \u0287\u0265\u01dd \u0265\u1d09\u0183\u0265\u01dds\u0287 l\u01dd\u028c\u01ddls \u00f8\u025f s\u01dd\u0254n\u0279\u1d09\u0287\u028e \u0250\u028c\u0250\u1d09l\u0250bl\u01dd \u0287\u00f8 \u01ddn\u0254\u0279\u028ed\u0287 \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8 \u0250nd s\u01ddnd \u1d09\u0287 \u0287\u00f8 \u00f8n\u0279 \u0250n\u0287\u0265\u00f8\u0279\u1d09z\u0250\u0287\u1d09\u00f8n s\u01dd\u0279\u028c\u1d09\u0254\u01dd \u025f\u00f8\u0279 \u0279\u01dd\u028c\u1d09\u01dd\u028d. \u024e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8 \u0250nd \u1d09n\u025f\u00f8\u0279\u026f\u0250\u0287\u1d09\u00f8n \u0250\u0279\u01dd n\u00f8\u0287 s\u0250\u028c\u01ddd \u00f8\u0279 \u028c\u1d09s\u1d09bl\u01dd \u0250n\u028e\u028d\u0265\u01dd\u0279\u01dd \u00f8n %(platformName)s \u0250\u025f\u0287\u01dd\u0279 \u0287\u0265\u01dd \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0279\u00f8\u0254\u01ddss \u1d09s \u0254\u00f8\u026fdl\u01dd\u0287\u01dd.", + "We use your verification photos to confirm your identity and ensure the validity of your certificate.": "W\u01dd ns\u01dd \u028e\u00f8n\u0279 \u028c\u01dd\u0279\u1d09\u025f\u1d09\u0254\u0250\u0287\u1d09\u00f8n d\u0265\u00f8\u0287\u00f8s \u0287\u00f8 \u0254\u00f8n\u025f\u1d09\u0279\u026f \u028e\u00f8n\u0279 \u1d09d\u01ddn\u0287\u1d09\u0287\u028e \u0250nd \u01ddnsn\u0279\u01dd \u0287\u0265\u01dd \u028c\u0250l\u1d09d\u1d09\u0287\u028e \u00f8\u025f \u028e\u00f8n\u0279 \u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd.", "We're sorry to see you go! Your account will be deleted shortly.": "W\u01dd'\u0279\u01dd s\u00f8\u0279\u0279\u028e \u0287\u00f8 s\u01dd\u01dd \u028e\u00f8n \u0183\u00f8! \u024e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 \u028d\u1d09ll b\u01dd d\u01ddl\u01dd\u0287\u01ddd s\u0265\u00f8\u0279\u0287l\u028e.", "We're sorry, there was an error": "W\u01dd'\u0279\u01dd s\u00f8\u0279\u0279\u028e, \u0287\u0265\u01dd\u0279\u01dd \u028d\u0250s \u0250n \u01dd\u0279\u0279\u00f8\u0279", "We've encountered an error. Refresh your browser and then try again.": "W\u01dd'\u028c\u01dd \u01ddn\u0254\u00f8nn\u0287\u01dd\u0279\u01ddd \u0250n \u01dd\u0279\u0279\u00f8\u0279. \u024c\u01dd\u025f\u0279\u01dds\u0265 \u028e\u00f8n\u0279 b\u0279\u00f8\u028ds\u01dd\u0279 \u0250nd \u0287\u0265\u01ddn \u0287\u0279\u028e \u0250\u0183\u0250\u1d09n.", @@ -1915,6 +1981,7 @@ "When learners submit an answer to an assessment, they immediately see whether the answer is correct or incorrect, and the score received.": "W\u0265\u01ddn l\u01dd\u0250\u0279n\u01dd\u0279s snb\u026f\u1d09\u0287 \u0250n \u0250ns\u028d\u01dd\u0279 \u0287\u00f8 \u0250n \u0250ss\u01ddss\u026f\u01ddn\u0287, \u0287\u0265\u01dd\u028e \u1d09\u026f\u026f\u01ddd\u1d09\u0250\u0287\u01ddl\u028e s\u01dd\u01dd \u028d\u0265\u01dd\u0287\u0265\u01dd\u0279 \u0287\u0265\u01dd \u0250ns\u028d\u01dd\u0279 \u1d09s \u0254\u00f8\u0279\u0279\u01dd\u0254\u0287 \u00f8\u0279 \u1d09n\u0254\u00f8\u0279\u0279\u01dd\u0254\u0287, \u0250nd \u0287\u0265\u01dd s\u0254\u00f8\u0279\u01dd \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01ddd.", "When your face is in position, use the Take Photo button {icon} below to take your photo.": "W\u0265\u01ddn \u028e\u00f8n\u0279 \u025f\u0250\u0254\u01dd \u1d09s \u1d09n d\u00f8s\u1d09\u0287\u1d09\u00f8n, ns\u01dd \u0287\u0265\u01dd \u0166\u0250\u029e\u01dd \u2c63\u0265\u00f8\u0287\u00f8 bn\u0287\u0287\u00f8n {icon} b\u01ddl\u00f8\u028d \u0287\u00f8 \u0287\u0250\u029e\u01dd \u028e\u00f8n\u0279 d\u0265\u00f8\u0287\u00f8.", "Which timed transcript would you like to use?": "W\u0265\u1d09\u0254\u0265 \u0287\u1d09\u026f\u01ddd \u0287\u0279\u0250ns\u0254\u0279\u1d09d\u0287 \u028d\u00f8nld \u028e\u00f8n l\u1d09\u029e\u01dd \u0287\u00f8 ns\u01dd?", + "While our support team is happy to assist with the edX platform, the course staff has the expertise for specific assignment questions, grading or the proper procedures in each course. Please post all course related questions within the Discussion Forum where the Course Staff can directly respond.": "W\u0265\u1d09l\u01dd \u00f8n\u0279 sndd\u00f8\u0279\u0287 \u0287\u01dd\u0250\u026f \u1d09s \u0265\u0250dd\u028e \u0287\u00f8 \u0250ss\u1d09s\u0287 \u028d\u1d09\u0287\u0265 \u0287\u0265\u01dd \u01dddX dl\u0250\u0287\u025f\u00f8\u0279\u026f, \u0287\u0265\u01dd \u0254\u00f8n\u0279s\u01dd s\u0287\u0250\u025f\u025f \u0265\u0250s \u0287\u0265\u01dd \u01ddxd\u01dd\u0279\u0287\u1d09s\u01dd \u025f\u00f8\u0279 sd\u01dd\u0254\u1d09\u025f\u1d09\u0254 \u0250ss\u1d09\u0183n\u026f\u01ddn\u0287 bn\u01dds\u0287\u1d09\u00f8ns, \u0183\u0279\u0250d\u1d09n\u0183 \u00f8\u0279 \u0287\u0265\u01dd d\u0279\u00f8d\u01dd\u0279 d\u0279\u00f8\u0254\u01dddn\u0279\u01dds \u1d09n \u01dd\u0250\u0254\u0265 \u0254\u00f8n\u0279s\u01dd. \u2c63l\u01dd\u0250s\u01dd d\u00f8s\u0287 \u0250ll \u0254\u00f8n\u0279s\u01dd \u0279\u01ddl\u0250\u0287\u01ddd bn\u01dds\u0287\u1d09\u00f8ns \u028d\u1d09\u0287\u0265\u1d09n \u0287\u0265\u01dd \u0110\u1d09s\u0254nss\u1d09\u00f8n F\u00f8\u0279n\u026f \u028d\u0265\u01dd\u0279\u01dd \u0287\u0265\u01dd \u023b\u00f8n\u0279s\u01dd S\u0287\u0250\u025f\u025f \u0254\u0250n d\u1d09\u0279\u01dd\u0254\u0287l\u028e \u0279\u01ddsd\u00f8nd.", "Whole words": "W\u0265\u00f8l\u01dd \u028d\u00f8\u0279ds", "Why activate?": "W\u0265\u028e \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u01dd?", "Why does %(platformName)s need my photo?": "W\u0265\u028e d\u00f8\u01dds %(platformName)s n\u01dd\u01ddd \u026f\u028e d\u0265\u00f8\u0287\u00f8?", @@ -1987,14 +2054,13 @@ "You must specify a name": "\u024e\u00f8n \u026fns\u0287 sd\u01dd\u0254\u1d09\u025f\u028e \u0250 n\u0250\u026f\u01dd", "You must specify a name for the cohort": "\u024e\u00f8n \u026fns\u0287 sd\u01dd\u0254\u1d09\u025f\u028e \u0250 n\u0250\u026f\u01dd \u025f\u00f8\u0279 \u0287\u0265\u01dd \u0254\u00f8\u0265\u00f8\u0279\u0287", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u024e\u00f8n \u026fns\u0287 sd\u01dd\u0254\u1d09\u025f\u028e \u028e\u00f8n\u0279 b\u1d09\u0279\u0287\u0265 \u028e\u01dd\u0250\u0279 b\u01dd\u025f\u00f8\u0279\u01dd \u028e\u00f8n \u0254\u0250n s\u0265\u0250\u0279\u01dd \u028e\u00f8n\u0279 \u025fnll d\u0279\u00f8\u025f\u1d09l\u01dd. \u0166\u00f8 sd\u01dd\u0254\u1d09\u025f\u028e \u028e\u00f8n\u0279 b\u1d09\u0279\u0287\u0265 \u028e\u01dd\u0250\u0279, \u0183\u00f8 \u0287\u00f8 \u0287\u0265\u01dd {account_settings_page_link}", - "You need a computer or cell phone that has a webcam. When you receive a browser prompt, make sure that you allow access to the camera.": "\u024e\u00f8n n\u01dd\u01ddd \u0250 \u0254\u00f8\u026fdn\u0287\u01dd\u0279 \u00f8\u0279 \u0254\u01ddll d\u0265\u00f8n\u01dd \u0287\u0265\u0250\u0287 \u0265\u0250s \u0250 \u028d\u01ddb\u0254\u0250\u026f. W\u0265\u01ddn \u028e\u00f8n \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd \u0250 b\u0279\u00f8\u028ds\u01dd\u0279 d\u0279\u00f8\u026fd\u0287, \u026f\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u0265\u0250\u0287 \u028e\u00f8n \u0250ll\u00f8\u028d \u0250\u0254\u0254\u01ddss \u0287\u00f8 \u0287\u0265\u01dd \u0254\u0250\u026f\u01dd\u0279\u0250.", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u024e\u00f8n n\u01dd\u01ddd \u0250 d\u0279\u1d09\u028c\u01dd\u0279's l\u1d09\u0254\u01ddns\u01dd, d\u0250ssd\u00f8\u0279\u0287, \u00f8\u0279 \u00f8\u0287\u0265\u01dd\u0279 \u0183\u00f8\u028c\u01dd\u0279n\u026f\u01ddn\u0287-\u1d09ssn\u01ddd \u0197\u0110 \u0287\u0265\u0250\u0287 \u0265\u0250s \u028e\u00f8n\u0279 n\u0250\u026f\u01dd \u0250nd d\u0265\u00f8\u0287\u00f8.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u024e\u00f8n n\u01dd\u01ddd \u0250n \u0197\u0110 \u028d\u1d09\u0287\u0265 \u028e\u00f8n\u0279 n\u0250\u026f\u01dd \u0250nd d\u0265\u00f8\u0287\u00f8. \u023a d\u0279\u1d09\u028c\u01dd\u0279's l\u1d09\u0254\u01ddns\u01dd, d\u0250ssd\u00f8\u0279\u0287, \u00f8\u0279 \u00f8\u0287\u0265\u01dd\u0279 \u0183\u00f8\u028c\u01dd\u0279n\u026f\u01ddn\u0287-\u1d09ssn\u01ddd \u0197\u0110s \u0250\u0279\u01dd \u0250ll \u0250\u0254\u0254\u01ddd\u0287\u0250bl\u01dd.", + "You need a device that has a webcam. If you receive a browser prompt for access to your camera, please make sure to click 'Allow'.": "\u024e\u00f8n n\u01dd\u01ddd \u0250 d\u01dd\u028c\u1d09\u0254\u01dd \u0287\u0265\u0250\u0287 \u0265\u0250s \u0250 \u028d\u01ddb\u0254\u0250\u026f. \u0197\u025f \u028e\u00f8n \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd \u0250 b\u0279\u00f8\u028ds\u01dd\u0279 d\u0279\u00f8\u026fd\u0287 \u025f\u00f8\u0279 \u0250\u0254\u0254\u01ddss \u0287\u00f8 \u028e\u00f8n\u0279 \u0254\u0250\u026f\u01dd\u0279\u0250, dl\u01dd\u0250s\u01dd \u026f\u0250\u029e\u01dd sn\u0279\u01dd \u0287\u00f8 \u0254l\u1d09\u0254\u029e '\u023all\u00f8\u028d'.", + "You need a valid ID that contains your full name and photo.": "\u024e\u00f8n n\u01dd\u01ddd \u0250 \u028c\u0250l\u1d09d \u0197\u0110 \u0287\u0265\u0250\u0287 \u0254\u00f8n\u0287\u0250\u1d09ns \u028e\u00f8n\u0279 \u025fnll n\u0250\u026f\u01dd \u0250nd d\u0265\u00f8\u0287\u00f8.", + "You need an ID with your name and photo. A driver's license, passport, or ID are all acceptable.": "\u024e\u00f8n n\u01dd\u01ddd \u0250n \u0197\u0110 \u028d\u1d09\u0287\u0265 \u028e\u00f8n\u0279 n\u0250\u026f\u01dd \u0250nd d\u0265\u00f8\u0287\u00f8. \u023a d\u0279\u1d09\u028c\u01dd\u0279's l\u1d09\u0254\u01ddns\u01dd, d\u0250ssd\u00f8\u0279\u0287, \u00f8\u0279 \u0197\u0110 \u0250\u0279\u01dd \u0250ll \u0250\u0254\u0254\u01ddd\u0287\u0250bl\u01dd.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u024e\u00f8n n\u01dd\u01ddd \u0287\u00f8 \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u01dd \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 b\u01dd\u025f\u00f8\u0279\u01dd \u028e\u00f8n \u0254\u0250n \u01ddn\u0279\u00f8ll \u1d09n \u0254\u00f8n\u0279s\u01dds. \u023b\u0265\u01dd\u0254\u029e \u028e\u00f8n\u0279 \u1d09nb\u00f8x \u025f\u00f8\u0279 \u0250n \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u1d09\u00f8n \u01dd\u026f\u0250\u1d09l.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u024e\u00f8n n\u01dd\u01ddd \u0287\u00f8 \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u01dd \u028e\u00f8n\u0279 \u0250\u0254\u0254\u00f8nn\u0287 b\u01dd\u025f\u00f8\u0279\u01dd \u028e\u00f8n \u0254\u0250n \u01ddn\u0279\u00f8ll \u1d09n \u0254\u00f8n\u0279s\u01dds. \u023b\u0265\u01dd\u0254\u029e \u028e\u00f8n\u0279 \u1d09nb\u00f8x \u025f\u00f8\u0279 \u0250n \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u1d09\u00f8n \u01dd\u026f\u0250\u1d09l. \u023a\u025f\u0287\u01dd\u0279 \u028e\u00f8n \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0250\u0254\u0287\u1d09\u028c\u0250\u0287\u1d09\u00f8n \u028e\u00f8n \u0254\u0250n \u0279\u01dd\u0287n\u0279n \u0250nd \u0279\u01dd\u025f\u0279\u01dds\u0265 \u0287\u0265\u1d09s d\u0250\u0183\u01dd.", "You receive messages from {platform_name} and course teams at this address.": "\u024e\u00f8n \u0279\u01dd\u0254\u01dd\u1d09\u028c\u01dd \u026f\u01ddss\u0250\u0183\u01dds \u025f\u0279\u00f8\u026f {platform_name} \u0250nd \u0254\u00f8n\u0279s\u01dd \u0287\u01dd\u0250\u026fs \u0250\u0287 \u0287\u0265\u1d09s \u0250dd\u0279\u01ddss.", "You reserve all rights for your work": "\u024e\u00f8n \u0279\u01dds\u01dd\u0279\u028c\u01dd \u0250ll \u0279\u1d09\u0183\u0265\u0287s \u025f\u00f8\u0279 \u028e\u00f8n\u0279 \u028d\u00f8\u0279\u029e", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u024e\u00f8n s\u0287\u1d09ll n\u01dd\u01ddd \u0287\u00f8 \u028c\u1d09s\u1d09\u0287 \u0287\u0265\u01dd %(display_name)s \u028d\u01ddbs\u1d09\u0287\u01dd \u0287\u00f8 \u0254\u00f8\u026fdl\u01dd\u0287\u01dd \u0287\u0265\u01dd \u0254\u0279\u01ddd\u1d09\u0287 d\u0279\u00f8\u0254\u01ddss.", "You submitted {filename}; only {allowedFiles} are allowed.": "\u024e\u00f8n snb\u026f\u1d09\u0287\u0287\u01ddd {filename}; \u00f8nl\u028e {allowedFiles} \u0250\u0279\u01dd \u0250ll\u00f8\u028d\u01ddd.", "You waive some rights for your work, such that others can use it too": "\u024e\u00f8n \u028d\u0250\u1d09\u028c\u01dd s\u00f8\u026f\u01dd \u0279\u1d09\u0183\u0265\u0287s \u025f\u00f8\u0279 \u028e\u00f8n\u0279 \u028d\u00f8\u0279\u029e, sn\u0254\u0265 \u0287\u0265\u0250\u0287 \u00f8\u0287\u0265\u01dd\u0279s \u0254\u0250n ns\u01dd \u1d09\u0287 \u0287\u00f8\u00f8", "You will be refunded the amount you paid.": "\u024e\u00f8n \u028d\u1d09ll b\u01dd \u0279\u01dd\u025fnnd\u01ddd \u0287\u0265\u01dd \u0250\u026f\u00f8nn\u0287 \u028e\u00f8n d\u0250\u1d09d.", @@ -2061,6 +2127,7 @@ "and others": "\u0250nd \u00f8\u0287\u0265\u01dd\u0279s", "anonymous": "\u0250n\u00f8n\u028e\u026f\u00f8ns", "answer": "\u0250ns\u028d\u01dd\u0279", + "answered question": "\u0250ns\u028d\u01dd\u0279\u01ddd bn\u01dds\u0287\u1d09\u00f8n", "asset_path is required": "\u0250ss\u01dd\u0287_d\u0250\u0287\u0265 \u1d09s \u0279\u01ddbn\u1d09\u0279\u01ddd", "bytes": "b\u028e\u0287\u01dds", "certificate": "\u0254\u01dd\u0279\u0287\u1d09\u025f\u1d09\u0254\u0250\u0287\u01dd", @@ -2072,6 +2139,8 @@ "delete chapter": "d\u01ddl\u01dd\u0287\u01dd \u0254\u0265\u0250d\u0287\u01dd\u0279", "delete group": "d\u01ddl\u01dd\u0287\u01dd \u0183\u0279\u00f8nd", "details about the failure": "d\u01dd\u0287\u0250\u1d09ls \u0250b\u00f8n\u0287 \u0287\u0265\u01dd \u025f\u0250\u1d09ln\u0279\u01dd", + "discussion": "d\u1d09s\u0254nss\u1d09\u00f8n", + "discussion posted %(time_ago)s by %(author)s": "d\u1d09s\u0254nss\u1d09\u00f8n d\u00f8s\u0287\u01ddd %(time_ago)s b\u028e %(author)s", "dragging": "d\u0279\u0250\u0183\u0183\u1d09n\u0183", "dragging out of slider": "d\u0279\u0250\u0183\u0183\u1d09n\u0183 \u00f8n\u0287 \u00f8\u025f sl\u1d09d\u01dd\u0279", "dropped in slider": "d\u0279\u00f8dd\u01ddd \u1d09n sl\u1d09d\u01dd\u0279", @@ -2081,15 +2150,19 @@ "e.g. 'http://google.com'": "\u01dd.\u0183. '\u0265\u0287\u0287d://\u0183\u00f8\u00f8\u0183l\u01dd.\u0254\u00f8\u026f'", "e.g. johndoe@example.com, JaneDoe, joeydoe@example.com": "\u01dd.\u0183. \u027e\u00f8\u0265nd\u00f8\u01dd@\u01ddx\u0250\u026fdl\u01dd.\u0254\u00f8\u026f, \u0248\u0250n\u01dd\u0110\u00f8\u01dd, \u027e\u00f8\u01dd\u028ed\u00f8\u01dd@\u01ddx\u0250\u026fdl\u01dd.\u0254\u00f8\u026f", "emphasized text": "\u01dd\u026fd\u0265\u0250s\u1d09z\u01ddd \u0287\u01ddx\u0287", + "endorsed %(time_ago)s": "\u01ddnd\u00f8\u0279s\u01ddd %(time_ago)s", + "endorsed %(time_ago)s by %(user)s": "\u01ddnd\u00f8\u0279s\u01ddd %(time_ago)s b\u028e %(user)s", "enter code here": "\u01ddn\u0287\u01dd\u0279 \u0254\u00f8d\u01dd \u0265\u01dd\u0279\u01dd", "enter link description here": "\u01ddn\u0287\u01dd\u0279 l\u1d09n\u029e d\u01dds\u0254\u0279\u1d09d\u0287\u1d09\u00f8n \u0265\u01dd\u0279\u01dd", + "follow this post": "\u025f\u00f8ll\u00f8\u028d \u0287\u0265\u1d09s d\u00f8s\u0287", "for": "\u025f\u00f8\u0279", - "for {courseName}": "\u025f\u00f8\u0279 {courseName}", "group configuration": "\u0183\u0279\u00f8nd \u0254\u00f8n\u025f\u1d09\u0183n\u0279\u0250\u0287\u1d09\u00f8n", "image omitted": "\u1d09\u026f\u0250\u0183\u01dd \u00f8\u026f\u1d09\u0287\u0287\u01ddd", "incorrect": "\u1d09n\u0254\u00f8\u0279\u0279\u01dd\u0254\u0287", "last activity": "l\u0250s\u0287 \u0250\u0254\u0287\u1d09\u028c\u1d09\u0287\u028e", "less than a minute": "l\u01ddss \u0287\u0265\u0250n \u0250 \u026f\u1d09nn\u0287\u01dd", + "marked as answer %(time_ago)s": "\u026f\u0250\u0279\u029e\u01ddd \u0250s \u0250ns\u028d\u01dd\u0279 %(time_ago)s", + "marked as answer %(time_ago)s by %(user)s": "\u026f\u0250\u0279\u029e\u01ddd \u0250s \u0250ns\u028d\u01dd\u0279 %(time_ago)s b\u028e %(user)s", "minute": "\u026f\u1d09nn\u0287\u01dd", "minutes": "\u026f\u1d09nn\u0287\u01dds", "name": "n\u0250\u026f\u01dd", @@ -2100,9 +2173,13 @@ "or create a new one here": "\u00f8\u0279 \u0254\u0279\u01dd\u0250\u0287\u01dd \u0250 n\u01dd\u028d \u00f8n\u01dd \u0265\u01dd\u0279\u01dd", "or sign in with": "\u00f8\u0279 s\u1d09\u0183n \u1d09n \u028d\u1d09\u0287\u0265", "path/to/introductionToCookieBaking-CH{order}.pdf": "d\u0250\u0287\u0265/\u0287\u00f8/\u1d09n\u0287\u0279\u00f8dn\u0254\u0287\u1d09\u00f8n\u0166\u00f8\u023b\u00f8\u00f8\u029e\u1d09\u01dd\u0243\u0250\u029e\u1d09n\u0183-\u023b\u0126{order}.dd\u025f", + "post anonymously": "d\u00f8s\u0287 \u0250n\u00f8n\u028e\u026f\u00f8nsl\u028e", + "post anonymously to classmates": "d\u00f8s\u0287 \u0250n\u00f8n\u028e\u026f\u00f8nsl\u028e \u0287\u00f8 \u0254l\u0250ss\u026f\u0250\u0287\u01dds", + "posted %(time_ago)s by %(author)s": "d\u00f8s\u0287\u01ddd %(time_ago)s b\u028e %(author)s", "price": "d\u0279\u1d09\u0254\u01dd", "provide the title/name of the chapter that will be used in navigating": "d\u0279\u00f8\u028c\u1d09d\u01dd \u0287\u0265\u01dd \u0287\u1d09\u0287l\u01dd/n\u0250\u026f\u01dd \u00f8\u025f \u0287\u0265\u01dd \u0254\u0265\u0250d\u0287\u01dd\u0279 \u0287\u0265\u0250\u0287 \u028d\u1d09ll b\u01dd ns\u01ddd \u1d09n n\u0250\u028c\u1d09\u0183\u0250\u0287\u1d09n\u0183", "provide the title/name of the text book as you would like your students to see it": "d\u0279\u00f8\u028c\u1d09d\u01dd \u0287\u0265\u01dd \u0287\u1d09\u0287l\u01dd/n\u0250\u026f\u01dd \u00f8\u025f \u0287\u0265\u01dd \u0287\u01ddx\u0287 b\u00f8\u00f8\u029e \u0250s \u028e\u00f8n \u028d\u00f8nld l\u1d09\u029e\u01dd \u028e\u00f8n\u0279 s\u0287nd\u01ddn\u0287s \u0287\u00f8 s\u01dd\u01dd \u1d09\u0287", + "question posted %(time_ago)s by %(author)s": "bn\u01dds\u0287\u1d09\u00f8n d\u00f8s\u0287\u01ddd %(time_ago)s b\u028e %(author)s", "remove": "\u0279\u01dd\u026f\u00f8\u028c\u01dd", "remove all": "\u0279\u01dd\u026f\u00f8\u028c\u01dd \u0250ll", "second": "s\u01dd\u0254\u00f8nd", @@ -2114,6 +2191,7 @@ "team count": "\u0287\u01dd\u0250\u026f \u0254\u00f8nn\u0287", "text_word_{uniqueId}": "\u0287\u01ddx\u0287_\u028d\u00f8\u0279d_{uniqueId}", "text_word_{uniqueId} title_word_{uniqueId}": "\u0287\u01ddx\u0287_\u028d\u00f8\u0279d_{uniqueId} \u0287\u1d09\u0287l\u01dd_\u028d\u00f8\u0279d_{uniqueId}", + "the more quickly and helpfully we can respond!": "\u0287\u0265\u01dd \u026f\u00f8\u0279\u01dd bn\u1d09\u0254\u029el\u028e \u0250nd \u0265\u01ddld\u025fnll\u028e \u028d\u01dd \u0254\u0250n \u0279\u01ddsd\u00f8nd!", "there is currently {numVotes} vote": [ "\u0287\u0265\u01dd\u0279\u01dd \u1d09s \u0254n\u0279\u0279\u01ddn\u0287l\u028e {numVotes} \u028c\u00f8\u0287\u01dd", "\u0287\u0265\u01dd\u0279\u01dd \u0250\u0279\u01dd \u0254n\u0279\u0279\u01ddn\u0287l\u028e {numVotes} \u028c\u00f8\u0287\u01dds" @@ -2121,6 +2199,7 @@ "title_word_{uniqueId}": "\u0287\u1d09\u0287l\u01dd_\u028d\u00f8\u0279d_{uniqueId}", "toggle chapter %(displayName)s": "\u0287\u00f8\u0183\u0183l\u01dd \u0254\u0265\u0250d\u0287\u01dd\u0279 %(displayName)s", "toggle subsection %(displayName)s": "\u0287\u00f8\u0183\u0183l\u01dd snbs\u01dd\u0254\u0287\u1d09\u00f8n %(displayName)s", + "unanswered question": "nn\u0250ns\u028d\u01dd\u0279\u01ddd bn\u01dds\u0287\u1d09\u00f8n", "unit": "nn\u1d09\u0287", "unsubmitted": "nnsnb\u026f\u1d09\u0287\u0287\u01ddd", "upload a PDF file or provide the path to a Studio asset file": "ndl\u00f8\u0250d \u0250 \u2c63\u0110F \u025f\u1d09l\u01dd \u00f8\u0279 d\u0279\u00f8\u028c\u1d09d\u01dd \u0287\u0265\u01dd d\u0250\u0287\u0265 \u0287\u00f8 \u0250 S\u0287nd\u1d09\u00f8 \u0250ss\u01dd\u0287 \u025f\u1d09l\u01dd", @@ -2217,6 +2296,7 @@ ], "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}": "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}", "{type} Progress": "{type} \u2c63\u0279\u00f8\u0183\u0279\u01ddss", + "{unread_comments_count} new": "{unread_comments_count} n\u01dd\u028d", "\u2026": "\u2026" }; for (var key in newcatalog) { @@ -2239,7 +2319,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2303,9 +2383,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/fi-fi/djangojs.js b/lms/static/js/i18n/fi-fi/djangojs.js index 916c14585ca114ed3cdc42705299b014ed22c5b5..aa650929ca0bb5519e9677bb08ed857bc36e5699 100644 --- a/lms/static/js/i18n/fi-fi/djangojs.js +++ b/lms/static/js/i18n/fi-fi/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -157,9 +157,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j.n.Y G.i", "SHORT_DATE_FORMAT": "j.n.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/fil/djangojs.js b/lms/static/js/i18n/fil/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/lms/static/js/i18n/fil/djangojs.js +++ b/lms/static/js/i18n/fil/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/fr/djangojs.js b/lms/static/js/i18n/fr/djangojs.js index 9eb5f638662f9400a6b60a9db179558c39cbe27a..906bf743c693fcab6afd470c7689cf7ec6e7d0a1 100644 --- a/lms/static/js/i18n/fr/djangojs.js +++ b/lms/static/js/i18n/fr/djangojs.js @@ -505,7 +505,6 @@ "Default (Local Time Zone)": "D\u00e9faut (fuseau horaire local)", "Default Timed Transcript": "Transcription synchronis\u00e9e par d\u00e9faut", "Delete": "Supprimer", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "Supprimer \"<%= signatoryName %>\" de la liste de signataires.", "Delete File Confirmation": "Confirmation de la suppression du fichier", "Delete My Account": "Supprimer mon compte", "Delete Team": "Supprimer l'\u00e9quipe", @@ -544,7 +543,6 @@ "Do you want to upload your file before submitting?": "Charger le fichier avant l'envoi?", "Document properties": "Propri\u00e9t\u00e9s du document", "Does the name on your ID match your account name: %(fullName)s?": "Le nom sur votre ID correspond-il \u00e0 votre nom de compte: %(fullName)s?", - "Does the photo of you match your ID photo?": "Votre photo correspond-elle \u00e0 celle de votre document d'identit\u00e9 ?", "Does the photo of you show your whole face?": "Votre photo montre-t-elle votre visage en entier ?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Vous ne voyez pas votre photo ? Assurez-vous que votre navigateur est autoris\u00e9 \u00e0 utiliser votre webcam quand il le demande.", "Donate": "Faire un don", @@ -720,7 +718,6 @@ "Generate": "G\u00e9n\u00e9r\u00e9", "Generate Exception Certificates": "G\u00e9n\u00e9rer les attestations de d\u00e9rogation", "Generate the user's certificate": "G\u00e9n\u00e9rer le certificat de l'utilisateur", - "Get Credit": "Obtenir un cr\u00e9dit", "Go Back": "Retour", "Go to Dashboard": "Aller au tableau de bord", "Go to your Dashboard": "Aller \u00e0 votre tableau de bord", @@ -1438,7 +1435,6 @@ "Text to display": "Texte \u00e0 afficher", "Textbook Name": "Nom du manuel", "Textbook information": "information sur le manuel", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Merci %(full_name)s! Nous avons re\u00e7u votre paiement pour %(course_name)s.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Merci d'avoir soumis votre demande d'aide financi\u00e8re pour {course_name}! Vous aurez une r\u00e9ponse dans 2-4 jours ouvrables.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Merci d'avoir envoyer vos photos. Nous allons les valider rapidement. Vous pouvez maintenant vous inscrire \u00e0 tous les cours %(platformName)s offrants un certificat v\u00e9rifi\u00e9. La v\u00e9rification est valide un an. Apr\u00e8s un an, vous devrez renvoyer vos photos pour v\u00e9rification.", "Thank you! We have received your payment for {courseName}.": "Merci. Nous avons re\u00e7u votre paiement pour {courseName}.", @@ -1448,8 +1444,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Le certificat de cet apprenant a \u00e9t\u00e9 re-valid\u00e9 et le syst\u00e8me est en train de re-\u00e9valuer les notes de cet apprenant. ", "The cohort cannot be added": "La cohorte ne peut pas \u00eatre ajout\u00e9e", "The cohort cannot be saved": "La cohorte ne peut pas \u00eatre enregistr\u00e9e", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "La longueur totale des champs organisation et codes de biblioth\u00e8que ne doit pas d\u00e9passer <%=limit%> caract\u00e8res.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "La longueur totale des champs organisation, num\u00e9ro du cours et session du cours ne peut d\u00e9passer <%=limit%> caract\u00e8res.", "The country or region where you live.": "Votre pays ou r\u00e9gion de r\u00e9sidence.", "The country that team members primarily identify with.": "Le pays avec lequel les membres de l'\u00e9quipe sont le plus proche.", "The course end date must be later than the course start date.": "La date de fin du cours doit \u00eatre post\u00e9rieure \u00e0 la date de d\u00e9but du cours.", @@ -1464,7 +1458,6 @@ "The following email addresses and/or usernames are invalid:": "Les adresses email et/ou noms d'utilisateurs suivants sont invalides :", "The following errors were generated:": "Les erreurs suivantes ont \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9es:", "The following file types are not allowed: ": "Les types de fichiers suivants ne sont pas support\u00e9s :", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "L'information suivante fait d\u00e9j\u00e0 partie de votre profil {platform}. Nous l\\'avons inclus ici pour votre demander.", "The following message will be displayed at the bottom of the courseware pages within your course:": "Le message suivant sera affich\u00e9 au bas des pages du cours :", "The following options are available for the {license_name} license.": "Les options suivantes sont disponibles pour la licence {license_name}", "The following users are no longer enrolled in the course:": "Les utilisateurs suivants ont \u00e9t\u00e9 d\u00e9sinscrits du cours\u00a0:", @@ -1482,7 +1475,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Le nombre de sous-sections de ce cours qui contiennent des probl\u00e8mes de ce type de devoir.", "The organization that this signatory belongs to, as it should appear on certificates.": "L'organisation \u00e0 laquelle ce signataire appartient, telle qu'elle devrait apparaitre sur les attestations.", "The page \"{route}\" could not be found.": "Page \"{route}\" non trouv\u00e9e.", - "The photo of your face matches the photo on your ID.": "La photo de votre visage concorde avec la photo sur votre pi\u00e8ce d'identit\u00e9.", "The post you selected has been deleted.": "Le message que vous avez s\u00e9lectionn\u00e9 a \u00e9t\u00e9 effac\u00e9.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "La version de la branche publi\u00e9e, {published}, a \u00e9t\u00e9 r\u00e9initialis\u00e9e \u00e0 la branche de la version du brouillon, {draft}.", "The raw error message is:": "Le message d'erreur est:", @@ -1597,7 +1589,6 @@ "Titles more than 100 characters may prevent students from printing their certificate on a single page.": "Les titres de plus de 100 caract\u00e8res peuvent emp\u00eacher les \u00e9tudiants d'imprimer leur certificat sur une seule page.", "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "Afin que tous les \u00e9tudiants puisse acc\u00e9der \u00e0 la vid\u00e9o, nous vous recommandons de fournir une version .mp4 ainsi qu'une version .webm de la vid\u00e9o. Cliquer ci-dessous pour ajouter une URL pour une autre version. Les URLs youtube ne sont pas support\u00e9es. La premi\u00e8re vid\u00e9o de la liste compatible avec l'ordinateur de l'\u00e9tudiant sera vue.", "To complete the program, you must earn a verified certificate for each course.": "Afin de compl\u00e9ter ce programme, vous devez obtenir un certificat v\u00e9rifi\u00e9 pour chacun de ces cours.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "Pour finaliser l'obtention de cr\u00e9dit de cours, %(display_name)s demande aux apprenants de %(platform_name)s de soumettre une demande de cr\u00e9dit.", "To invalidate a certificate for a particular learner, add the username or email address below.": "Pour invalider une attestation pour un apprenant, ajouter le nom d'usager ou l'adresse courriel ci-dessous.", "To pass this exam, you must complete the problems in the time allowed.": "Pour r\u00e9ussir l'examen, vous devez r\u00e9pondre aux questions dans le temps imparti.", "To receive a certificate, you must also verify your identity before {date}.": "Pour recevoir un certificat, vous devez aussi valider votre identit\u00e9 avant le {date}.", @@ -1699,7 +1690,6 @@ "Use as a Prerequisite": "Utilis\u00e9 comme Pr\u00e9-requis", "Use my institution/campus credentials": "Utiliser mes informations institution/campus", "Use the All Topics menu to find specific topics.": "Utilisez le menu 'Tous les sujets' pour trouver un sujet sp\u00e9cific", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Utilisez votre webcam pour prendre une photo de votre pi\u00e8ce d'identit\u00e9. Nous allons v\u00e9rifier sa concordance avec la photo de votre visage et le nom de votre compte.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Utiliser votre webcam pour prendre une photo de votre visage, afin que nous puissions la comparer avec celle de votre pi\u00e8ce d'identit\u00e9.", "Used": "Utilis\u00e9", "Used in {count} location": [ @@ -1723,7 +1713,6 @@ "Verified Certificate upgrade": "Passer \u00e0 un certificat v\u00e9rifi\u00e9", "Verified Status": "Statut v\u00e9rifi\u00e9", "Verified mode price": "Prix du mode v\u00e9rifi\u00e9", - "Verify Now": "V\u00e9rifier Maintenant", "Vertical space": "Espace Vertical", "Very loud": "Tr\u00e8s fort", "Very low": "Tr\u00e8s faible", @@ -1760,7 +1749,6 @@ "We couldn't create your account.": "Nous n'avons pas pu cr\u00e9er votre compte.", "We couldn't find any results for \"%s\".": "Nous ne trouvons pas de r\u00e9sultat pour \"%s\".", "We couldn't sign you in.": "Nous n'avons pas pu vous connecter.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Nous avons re\u00e7us vos informations et nous v\u00e9rifions votre identit\u00e9. Un message sera visible sur votre tableau de bord (1-2 jours de d\u00e9lai). Entre temps, vous avez toujours acc\u00e8s \u00e0 l'ensemble du cours.", "We just need a little more information before you start learning with %(platformName)s.": "Nous avons juste besoin d'un peu plus d'informations avant que vous commenciez votre apprentissage avec %(platformName)s.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Nous utilisons le niveau de s\u00e9curit\u00e9 le plus \u00e9lev\u00e9 pour chiffrer votre photo et l'envoyer \u00e0 notre service d\u2019autorisation afin d'y \u00eatre examin\u00e9e. Votre photo et vos informations ne sont pas enregistr\u00e9es, et ils ne sont pas visible nulle part sur %(platformName)s apr\u00e8s l'accomplissement de processus de v\u00e9rification.", "We've encountered an error. Refresh your browser and then try again.": "Nous avons rencontr\u00e9 une erreur. Rafra\u00eechissez votre navigateur puis r\u00e9essayer.", @@ -1826,7 +1814,7 @@ "You have not created any certificates yet.": "Vous n'avez pas encore cr\u00e9e de certificat.", "You have not created any content groups yet.": "Vous n'avez pas encore cr\u00e9\u00e9 de groupes de contenu.", "You have not created any group configurations yet.": "Vous n'avez pas encore cr\u00e9\u00e9 de configuration des groupes.", - "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "Vous avez s\u00e9lectionn\u00e9 une action, et vous n'avez fait aucune modification sur des champs. Vous cherchez probablement le bouton Envoyer et non le bouton Sauvegarder.", + "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "Vous avez s\u00e9lectionn\u00e9 une action, et vous n'avez fait aucune modification sur des champs. Vous cherchez probablement le bouton Envoyer et non le bouton Enregistrer.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "Vous avez s\u00e9lectionn\u00e9 une action, mais vous n'avez pas encore sauvegard\u00e9 certains champs modifi\u00e9s. Cliquez sur OK pour sauver. Vous devrez r\u00e9appliquer l'action.", "You have successfully signed into %(currentProvider)s, but your %(currentProvider)s account does not have a linked %(platformName)s account. To link your accounts, sign in now using your %(platformName)s password.": "Vous \u00eates connect\u00e9 \u00e0 %(currentProvider)s avec succ\u00e8s,mais votre compte %(currentProvider)s n'est pas reli\u00e9 \u00e0 votre compte %(platformName)s. Pour lier vos comptes, connectez-vous en utilisant votre mot de passe %(platformName)s.", "You have unsaved changes are you sure you want to navigate away?": "Vous avez des modifications non enregistr\u00e9es, \u00eates-vous s\u00fbr de vouloir quitter cette page ?", @@ -1842,12 +1830,9 @@ "You must sign out and sign back in before your language changes take effect.": "Vous devez vous d\u00e9connecter puis vous connecter \u00e0 nouveau afin que les param\u00e8tres de langue prennent effet.", "You must specify a name for the cohort": "Vous devez indiquer un nom pour la cohorte", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "Vous devez renseigner votre ann\u00e9e de naissance avant de pouvoir partager votre profil complet. Pour renseigner votre ann\u00e9e de naissance, allez sur {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Vous avez besoin d'un permis de conduire, d'un passeport ou d'une pi\u00e8ce d'identit\u00e9 avec votre nom et photo.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Vous avez besoin d'un permis de conduire, un passeport ou toute pi\u00e8ce d'identit\u00e9 avec votre nom et photo.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Vous devez activer votre compte avant de vous inscrire \u00e0 des cours. V\u00e9rifier votre bo\u00eete de r\u00e9ception.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Vous devez activer votre compte avant de pouvoir vous inscrire aux cours. V\u00e9rifier votre bo\u00eete de r\u00e9ception pour un email d'activation. Apr\u00e8s l'activation vous pouvez revenir et rafraichir cette page.", "You receive messages from {platform_name} and course teams at this address.": "Les messages que vous recevrez de la part de la plateforme {platform_name} et des \u00e9quipes p\u00e9dagogiques seront envoy\u00e9s \u00e0 cette adresse.", - "You still need to visit the %(display_name)s website to complete the credit process.": "Vous devez encore visiter le site web de %(display_name)s afinn de compl\u00e9ter le processus de cr\u00e9dit.", "You submitted {filename}; only {allowedFiles} are allowed.": "Vous avez envoy\u00e9 {filename}; seul les {allowedFiles} sont autoris\u00e9s.", "You will be refunded the amount you paid.": "Le montant pay\u00e9 vous sera rembours\u00e9.", "You will not be refunded the amount you paid.": "Le montant pay\u00e9 ne vous sera pas rembours\u00e9.", @@ -1932,7 +1917,6 @@ "enter code here": "saisir du code ici", "enter link description here": "saisir une description du lien ici", "for": "pour", - "for {courseName}": "pour {courseName}", "group configuration": "configuration des groupes", "image omitted": "image manquante", "incorrect": "incorrect", @@ -2051,7 +2035,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2109,9 +2093,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j N Y H:i", "SHORT_DATE_FORMAT": "j N Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/gl/djangojs.js b/lms/static/js/i18n/gl/djangojs.js index 4421a34d0a48ee66fb9e16e9e57f966211017ddb..57ea29c47b406403c0a91f9e9aa6f5f88abe442d 100644 --- a/lms/static/js/i18n/gl/djangojs.js +++ b/lms/static/js/i18n/gl/djangojs.js @@ -71,7 +71,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -135,9 +135,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "d-m-Y, H:i", "SHORT_DATE_FORMAT": "d-m-Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/gu/djangojs.js b/lms/static/js/i18n/gu/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/lms/static/js/i18n/gu/djangojs.js +++ b/lms/static/js/i18n/gu/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/he/djangojs.js b/lms/static/js/i18n/he/djangojs.js index d619f772630476b8229f144a8470af682929f53c..1e710d2403eef3bfe5bf20f63cada82bf0bf8e24 100644 --- a/lms/static/js/i18n/he/djangojs.js +++ b/lms/static/js/i18n/he/djangojs.js @@ -146,6 +146,8 @@ ], "%(programName)s Home Page.": "\u05e2\u05de\u05d5\u05d3 \u05d4\u05d1\u05d9\u05ea \u05e9\u05dc %(programName)s", "%(sel)s of %(cnt)s selected": [ + "%(sel)s \u05de %(cnt)s \u05e0\u05d1\u05d7\u05e8\u05d5\u05ea", + "%(sel)s \u05de %(cnt)s \u05e0\u05d1\u05d7\u05e8\u05d5\u05ea", "%(sel)s \u05de %(cnt)s \u05e0\u05d1\u05d7\u05e8\u05d5\u05ea", "%(sel)s \u05de %(cnt)s \u05e0\u05d1\u05d7\u05e8\u05d5\u05ea" ], @@ -840,10 +842,14 @@ "Note: Do not hide graded assignments after they have been released.": "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05dc \u05ea\u05e1\u05ea\u05d9\u05e8 \u05d0\u05ea \u05d4\u05de\u05d8\u05dc\u05d5\u05ea \u05e9\u05e7\u05d9\u05d1\u05dc\u05d5 \u05e6\u05d9\u05d5\u05df \u05dc\u05d0\u05d7\u05e8 \u05d4\u05e4\u05e6\u05ea\u05df.", "Note: You are %s hour ahead of server time.": [ "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d4 \u05dc\u05e4\u05e0\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", + "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05dc\u05e4\u05e0\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", + "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05dc\u05e4\u05e0\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05dc\u05e4\u05e0\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea." ], "Note: You are %s hour behind server time.": [ "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d4 \u05d0\u05d7\u05e8\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", + "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05d0\u05d7\u05e8\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", + "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05d0\u05d7\u05e8\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea.", "\u05d4\u05e2\u05e8\u05d4: \u05d0\u05ea/\u05d4 %s \u05e9\u05e2\u05d5\u05ea \u05d0\u05d7\u05e8\u05d9 \u05d6\u05de\u05df \u05d4\u05e9\u05e8\u05ea." ], "Noted in:": "\u05e6\u05d5\u05d9\u05d9\u05df \u05d1:", @@ -1731,7 +1737,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1795,9 +1801,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j \u05d1F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/hi/djangojs.js b/lms/static/js/i18n/hi/djangojs.js index e12f673e539f6974834027cc771fa0c6bef2190c..8b99dacc4131ede5daea764dfde3900f0ddd0ae9 100644 --- a/lms/static/js/i18n/hi/djangojs.js +++ b/lms/static/js/i18n/hi/djangojs.js @@ -197,7 +197,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -261,9 +261,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "d-m-Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/hr/djangojs.js b/lms/static/js/i18n/hr/djangojs.js index 2d753e19fe9a9fcc4d331111cff9641142ca462c..d749529db5a7a717d8ca915e44ad4e8683992ecb 100644 --- a/lms/static/js/i18n/hr/djangojs.js +++ b/lms/static/js/i18n/hr/djangojs.js @@ -75,7 +75,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -141,9 +141,9 @@ "%d. %m. %y." ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j.m.Y. H:i", "SHORT_DATE_FORMAT": "j.m.Y.", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/hu/djangojs.js b/lms/static/js/i18n/hu/djangojs.js index 0fa2a87315db5be43c08802b6ec87b3be02d0050..ec606e6c8cfd5c8a45d2141ec8069430be39b27f 100644 --- a/lms/static/js/i18n/hu/djangojs.js +++ b/lms/static/js/i18n/hu/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -135,11 +135,11 @@ /* formatting library */ django.formats = { - "DATETIME_FORMAT": "Y. F j. G.i", + "DATETIME_FORMAT": "Y. F j. H:i", "DATETIME_INPUT_FORMATS": [ - "%Y.%m.%d. %H.%M.%S", - "%Y.%m.%d. %H.%M.%S.%f", - "%Y.%m.%d. %H.%M", + "%Y.%m.%d. %H:%M:%S", + "%Y.%m.%d. %H:%M:%S.%f", + "%Y.%m.%d. %H:%M", "%Y.%m.%d.", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", @@ -152,19 +152,17 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "F j.", - "NUMBER_GROUPING": "3", - "SHORT_DATETIME_FORMAT": "Y.m.d. G.i", + "NUMBER_GROUPING": 3, + "SHORT_DATETIME_FORMAT": "Y.m.d. H:i", "SHORT_DATE_FORMAT": "Y.m.d.", "THOUSAND_SEPARATOR": "\u00a0", - "TIME_FORMAT": "G.i", + "TIME_FORMAT": "H:i", "TIME_INPUT_FORMATS": [ - "%H.%M.%S", - "%H.%M", "%H:%M:%S", - "%H:%M:%S.%f", - "%H:%M" + "%H:%M", + "%H:%M:%S.%f" ], "YEAR_MONTH_FORMAT": "Y. F" }; diff --git a/lms/static/js/i18n/hy-am/djangojs.js b/lms/static/js/i18n/hy-am/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..0bf5a1827911bc293256d5bcd7e73fec757e0eb9 100644 --- a/lms/static/js/i18n/hy-am/djangojs.js +++ b/lms/static/js/i18n/hy-am/djangojs.js @@ -5,13 +5,86 @@ var django = globals.django || (globals.django = {}); - django.pluralidx = function(count) { return (count == 1) ? 0 : 1; }; + django.pluralidx = function(n) { + var v=(n != 1); + if (typeof(v) == 'boolean') { + return v ? 1 : 0; + } else { + return v; + } + }; /* gettext library */ django.catalog = django.catalog || {}; + var newcatalog = { + "%(sel)s of %(cnt)s selected": [ + "\u0538\u0576\u057f\u0580\u057e\u0561\u056e \u0567 %(cnt)s-\u056b\u0581 %(sel)s-\u0568", + "\u0538\u0576\u057f\u0580\u057e\u0561\u056e \u0567 %(cnt)s-\u056b\u0581 %(sel)s-\u0568" + ], + "6 a.m.": "6 a.m.", + "6 p.m.": "6 p.m.", + "April": "\u0531\u057a\u0580\u056b\u056c", + "August": "\u0555\u0563\u0578\u057d\u057f\u0578\u057d", + "Available %s": "\u0540\u0561\u057d\u0561\u0576\u0565\u056c\u056b %s", + "Cancel": "\u0549\u0565\u0572\u0561\u0580\u056f\u0565\u056c", + "Choose": "\u0538\u0576\u057f\u0580\u0565\u056c", + "Choose a Date": "\u0538\u0576\u057f\u0580\u0565\u0584 \u0561\u0574\u057d\u0561\u0569\u056b\u057e", + "Choose a Time": "\u0538\u0576\u057f\u0580\u0565\u0584 \u056a\u0561\u0574\u0561\u0576\u0561\u056f", + "Choose a time": "\u0538\u0576\u057f\u0580\u0565\u0584 \u056a\u0561\u0574\u0561\u0576\u0561\u056f", + "Choose all": "\u0538\u0576\u057f\u0580\u0565\u056c \u0562\u0578\u056c\u0578\u0580\u0568", + "Chosen %s": "\u0538\u0576\u057f\u0580\u057e\u0561\u056e %s", + "Click to choose all %s at once.": "\u054d\u0565\u0572\u0574\u0565\u0584 \u0562\u0578\u056c\u0578\u0580 %s\u0568 \u0568\u0576\u057f\u0580\u0565\u056c\u0578\u0582 \u0570\u0561\u0574\u0561\u0580\u0589", + "Click to remove all chosen %s at once.": "\u054d\u0565\u0572\u0574\u0565\u0584 \u0562\u0578\u056c\u0578\u0580 %s\u0568 \u0570\u0565\u057c\u0561\u0581\u0576\u0565\u056c\u0578\u0582 \u0570\u0561\u0574\u0561\u0580\u0589", + "December": "\u0534\u0565\u056f\u057f\u0565\u0574\u0562\u0565\u0580", + "February": "\u0553\u0565\u057f\u0580\u057e\u0561\u0580", + "Filter": "\u0556\u056b\u056c\u057f\u0580\u0565\u056c", + "Hide": "\u0539\u0561\u0584\u0581\u0576\u0565\u056c", + "January": "\u0540\u0578\u0582\u0576\u057e\u0561\u0580", + "July": "\u0540\u0578\u0582\u056c\u056b\u057d", + "June": "\u0540\u0578\u0582\u0576\u056b\u057d", + "March": "\u0544\u0561\u0580\u057f", + "May": "\u0544\u0561\u0575\u056b\u057d", + "Midnight": "\u053f\u0565\u057d\u0563\u056b\u0577\u0565\u0580", + "Noon": "\u053f\u0565\u057d\u0585\u0580", + "Note: You are %s hour ahead of server time.": [ + "\u0541\u0565\u0580 \u056a\u0561\u0574\u0568 \u0561\u057c\u0561\u057b \u0567 \u057d\u0565\u0580\u057e\u0565\u0580\u056b \u056a\u0561\u0574\u0561\u0576\u0561\u056f\u056b\u0581 %s \u056a\u0561\u0574\u0578\u057e", + "\u0541\u0565\u0580 \u056a\u0561\u0574\u0568 \u0561\u057c\u0561\u057b \u0567 \u057d\u0565\u0580\u057e\u0565\u0580\u056b \u056a\u0561\u0574\u0561\u0576\u0561\u056f\u056b\u0581 %s \u056a\u0561\u0574\u0578\u057e" + ], + "Note: You are %s hour behind server time.": [ + "\u0541\u0565\u0580 \u056a\u0561\u0574\u0568 \u0570\u0565\u057f \u0567 \u057d\u0565\u0580\u057e\u0565\u0580\u056b \u056a\u0561\u0574\u0561\u0576\u0561\u056f\u056b\u0581 %s \u056a\u0561\u0574\u0578\u057e", + "\u0541\u0565\u0580 \u056a\u0561\u0574\u0568 \u0570\u0565\u057f \u0567 \u057d\u0565\u0580\u057e\u0565\u0580\u056b \u056a\u0561\u0574\u0561\u0576\u0561\u056f\u056b\u0581 %s \u056a\u0561\u0574\u0578\u057e" + ], + "November": "\u0546\u0578\u0575\u0565\u0574\u0562\u0565\u0580", + "Now": "\u0540\u056b\u0574\u0561", + "October": "\u0540\u0578\u056f\u057f\u0565\u0574\u0562\u0565\u0580", + "Remove": "\u0540\u0565\u057c\u0561\u0581\u0576\u0565\u056c", + "Remove all": "\u0540\u0565\u057c\u0561\u0581\u0576\u0565\u056c \u0562\u0578\u056c\u0578\u0580\u0568", + "September": "\u054d\u0565\u057a\u057f\u0565\u0574\u0562\u0565\u0580", + "Show": "\u0551\u0578\u0582\u0575\u0581 \u057f\u0561\u056c", + "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "\u054d\u0561 \u0570\u0561\u057d\u0561\u0576\u0565\u056c\u056b %s \u0581\u0578\u0582\u0581\u0561\u056f \u0567\u0589 \u0534\u0578\u0582\u0584 \u056f\u0561\u0580\u0578\u0572 \u0565\u0584 \u0568\u0576\u057f\u0580\u0565\u056c \u0576\u0580\u0561\u0576\u0581\u056b\u0581 \u0578\u0580\u0578\u0577\u0576\u0565\u0580\u0568 \u0568\u0576\u057f\u0580\u0565\u056c\u0578\u057e \u0564\u0580\u0561\u0576\u0584 \u057d\u057f\u0578\u0580\u0587 \u0563\u057f\u0576\u057e\u0578\u0572 \u057e\u0561\u0576\u0564\u0561\u056f\u0578\u0582\u0574 \u0587 \u057d\u0565\u0572\u0574\u0565\u056c\u0578\u057e \u0565\u0580\u056f\u0578\u0582 \u057e\u0561\u0576\u0564\u0561\u056f\u0576\u0565\u0580\u056b \u0574\u056b\u057b\u0587 \u0563\u057f\u0576\u057e\u0578\u0572 \"\u0538\u0576\u057f\u0580\u0565\u056c\" \u057d\u056c\u0561\u0584\u0568\u0589", + "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "\u054d\u0561 \u0570\u0561\u057d\u0561\u0576\u0565\u056c\u056b %s\u056b \u0581\u0578\u0582\u0581\u0561\u056f \u0567\u0589 \u0534\u0578\u0582\u0584 \u056f\u0561\u0580\u0578\u0572 \u0565\u0584 \u0570\u0565\u057c\u0561\u0581\u0576\u0565\u056c \u0576\u0580\u0561\u0576\u0581\u056b\u0581 \u0578\u0580\u0578\u0577\u0576\u0565\u0580\u0568 \u0568\u0576\u057f\u0580\u0565\u056c\u0578\u057e \u0564\u0580\u0561\u0576\u0584 \u057d\u057f\u0578\u0580\u0587 \u0563\u057f\u0576\u057e\u0578\u0572 \u057e\u0561\u0576\u0564\u0561\u056f\u0578\u0582\u0574 \u0587 \u057d\u0565\u0572\u0574\u0565\u056c\u0578\u057e \u0565\u0580\u056f\u0578\u0582 \u057e\u0561\u0576\u0564\u0561\u056f\u0576\u0565\u0580\u056b \u0574\u056b\u057b\u0587 \u0563\u057f\u0576\u057e\u0578\u0572 \"\u0540\u0565\u057c\u0561\u0581\u0576\u0565\u056c\" \u057d\u056c\u0561\u0584\u0568\u0589", + "Today": "\u0531\u0575\u057d\u0585\u0580", + "Tomorrow": "\u054e\u0561\u0572\u0568", + "Type into this box to filter down the list of available %s.": "\u0544\u0578\u0582\u057f\u0584\u0561\u0563\u0580\u0565\u0584 \u0561\u0575\u057d \u0564\u0561\u0577\u057f\u0578\u0582\u0574 \u0570\u0561\u057d\u0561\u0576\u0565\u056c\u056b %s \u0581\u0578\u0582\u0581\u0561\u056f\u0568 \u0586\u056b\u056c\u057f\u0580\u0565\u056c\u0578\u0582 \u0570\u0561\u0574\u0561\u0580\u0589", + "Yesterday": "\u0535\u0580\u0565\u056f", + "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "\u0534\u0578\u0582\u0584 \u0568\u0576\u057f\u0580\u0565\u056c \u0565\u0584 \u0563\u0578\u0580\u056e\u0578\u0572\u0578\u0582\u0569\u0575\u0578\u0582\u0576, \u0562\u0561\u0575\u0581 \u0564\u0565\u057c \u0579\u0565\u0584 \u056f\u0561\u057f\u0561\u0580\u0565\u056c \u0578\u0580\u0587\u0567 \u0561\u0576\u0570\u0561\u057f\u0561\u056f\u0561\u0576 \u056d\u0574\u0562\u0561\u0563\u0580\u0565\u056c\u056b \u0564\u0561\u0577\u057f\u0565\u0580\u056b \u0583\u0578\u0583\u0578\u056d\u0578\u0582\u0569\u0575\u0578\u0582\u0576 \u0541\u0565\u0566 \u0570\u0561\u057e\u0561\u0576\u0561\u0562\u0561\u0580 \u057a\u0565\u057f\u0584 \u0567 \u053f\u0561\u057f\u0561\u0580\u0565\u056c \u056f\u0578\u0573\u0561\u056f\u0568, \u054a\u0561\u0570\u057a\u0561\u0576\u0565\u056c \u056f\u0578\u0573\u0561\u056f\u056b \u0583\u0578\u056d\u0561\u0580\u0565\u0576", + "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "\u0534\u0578\u0582\u0584 \u0568\u0576\u057f\u0580\u0565\u056c \u0565\u0584 \u0563\u0578\u0580\u056e\u0578\u0572\u0578\u0582\u0569\u0575\u0578\u0582\u0576, \u0562\u0561\u0575\u0581 \u0564\u0565\u057c \u0579\u0565\u0584 \u057a\u0561\u0570\u057a\u0561\u0576\u0565\u056c \u0561\u0576\u0570\u0561\u057f\u0561\u056f\u0561\u0576 \u056d\u0574\u0562\u0561\u0563\u0580\u0565\u056c\u056b \u0564\u0561\u0577\u057f\u0565\u0580\u056b \u0583\u0578\u0583\u0578\u056d\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0576\u0565\u0580\u0568 \u054d\u0565\u0572\u0574\u0565\u0584 OK \u057a\u0561\u0570\u057a\u0561\u0576\u0565\u056c\u0578\u0582 \u0570\u0561\u0574\u0561\u0580\u0589 \u0531\u0576\u0570\u0580\u0561\u056a\u0565\u0577\u057f \u056f\u056c\u056b\u0576\u056b \u057e\u0565\u0580\u0561\u0563\u0578\u0580\u056e\u0561\u0580\u056f\u0565\u056c \u0563\u0578\u0580\u056e\u0578\u0572\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568", + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "\u0534\u0578\u0582\u0584 \u0578\u0582\u0576\u0565\u0584 \u0579\u057a\u0561\u0570\u057a\u0561\u0576\u057e\u0561\u056e \u0561\u0576\u0570\u0561\u057f\u0561\u056f\u0561\u0576 \u056d\u0574\u0562\u0561\u0563\u0580\u0565\u056c\u056b \u0564\u0561\u0577\u057f\u0565\u0580\u0589 \u0535\u0569\u0565 \u0564\u0578\u0582\u0584 \u056f\u0561\u057f\u0561\u0580\u0565\u0584 \u0563\u0578\u0580\u056e\u0578\u0572\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0568, \u0571\u0565\u0580 \u0579\u057a\u0561\u0570\u057a\u0561\u0576\u057e\u0561\u056e \u0583\u0578\u0583\u0578\u056d\u0578\u0582\u0569\u0575\u0578\u0582\u0576\u0576\u0565\u0580\u0568 \u056f\u056f\u0578\u0580\u0565\u0576\u0589", + "one letter Friday\u0004F": "\u0548\u0552", + "one letter Monday\u0004M": "\u0535", + "one letter Saturday\u0004S": "\u0547", + "one letter Sunday\u0004S": "\u053f", + "one letter Thursday\u0004T": "\u0540", + "one letter Tuesday\u0004T": "\u0535", + "one letter Wednesday\u0004W": "\u0549" + }; + for (var key in newcatalog) { + django.catalog[key] = newcatalog[key]; + } + if (!django.jsi18n_initialized) { django.gettext = function(msgid) { @@ -28,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +165,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/id/djangojs.js b/lms/static/js/i18n/id/djangojs.js index 41bad306e3e7de0ee35b2a3f206aa543a7f34bad..9dc978e064c5929ec710d0dd2d7c6580f0e98ba9 100644 --- a/lms/static/js/i18n/id/djangojs.js +++ b/lms/static/js/i18n/id/djangojs.js @@ -465,7 +465,6 @@ "Do you want to upload your file before submitting?": "Apakah Anda ingin mengunggah berkas Anda sebelum mengirimkan?", "Document properties": "Properti dokumen", "Does the name on your ID match your account name: %(fullName)s?": "Apakah nama pada ID anda sesuai dengan nama account anda: %(fullName)s?", - "Does the photo of you match your ID photo?": "Apakah photo anda sesuai dengan photo ID?", "Does the photo of you show your whole face?": "Apakah photo anda menunjukkan seluruh wajah?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Tidakmelihat gambar anda? pastikan membolehkan browser anda untuk menggunakan kamera jika dia meminta izin ", "Donate": "Donasi", @@ -607,7 +606,6 @@ "Fill browser": "Peramban penuh", "Filter": "Filter", "Filter and sort topics": "Saring dan urutkan topik", - "Final Grade": "Nilai Akhir", "Final Grade Received": "Nilai Akhir Diterima", "Financial Aid": "Bantuan Finansial", "Financial Assistance": "Bantuan Finansial", @@ -638,7 +636,6 @@ "General": "Umum", "Generate": "Generate", "Generate Exception Certificates": "Buat Sertifikat Pengecualian", - "Get Credit": "Dapatkan kredit", "Go Back": "Kembali", "Go to Dashboard": "Menuju dashboard", "Go to my Dashboard": "Menuju Dashboard", @@ -701,7 +698,6 @@ "Hyperlink (Ctrl+L)": "Hyperlink (Ctrl+L)", "ID": "ID", "ID-Verification is not required for this Professional Education course.": "Verifikasi ID tidak dibutuhkan untuk kursus pendidikan profesional", - "If you are unable to access your account contact us via email using {email}.": "Jika Anda tidak dapat masuk, hubungi kami melalui email ke {email}.", "If you do not yet have an account, use the button below to register.": "Jika Anda belum memiliki akun, gunakan tombol di bawah untuk registrasi.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "Jika Anda tidak memverifikasi identitas Anda sekarang, Anda masih dapat melihat kursus Anda dari dashboard Anda. Anda akan menerima pengingat dari %(platformName)s secara periodik untuk memverifikasi identitas Anda.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "Jika Anda meninggalkan halaman ini tanpa menyimpan atau mengirim tanggapan Anda, Anda akan kehilangan semua pekerjaan yang Anda buat pada tanggapan Anda.", @@ -860,7 +856,6 @@ "Name of the signatory": "Nama Penandatangan", "Name or short description of the configuration": "Nama atau gambaran singkat dari konfigurasi", "Navigate up": "Navigasi naik", - "Need help logging in?": "Butuh bantuan untuk masuk?", "Needs verified certificate ": "Memerlukan sertifikat terverifikasi", "Never published": "Tidak pernah dipublikasikan", "Never show assessment results": "Jangan tampilkan hasil penilaian", @@ -927,7 +922,6 @@ "Ok": "Ok", "Once you complete one of the program requirements you have a program record. This record is marked complete once you meet all program requirements. A program record can be used to continue your learning journey and demonstrate your learning to others.": "Setelah Anda melengkapi salah satu persyaratan program Anda akan memiliki record program. Record ini ditandai lengkap setelah Anda memenuhi semua persyaratan program. Record program dapat digunakan untuk melanjutkan perjalanan pembelajaran Anda dan menunjukkan pembelajaran Anda kepada orang lain.", "One or more rescheduling tasks failed.": "Salah satu tugas penjadwalan telah gagal.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "Hanya berkas <%= fileTypes %> yang dapat diunggah. Harap pilih berkas dengan ekstensi <%= fileExtensions %> untuk diunggah.", "Only properly formatted .csv files will be accepted.": "Hanya berkas-berkas .csv yang diformat dengan tepat dapat diterima.", "Open Calculator": "Buka Kalkulator", "Open language menu": "Buka menu bahasa", @@ -1158,7 +1152,6 @@ "Select a course or select \"Not specific to a course\" for your support request.": "Pilih satu kursus atau pilih \"Tidak spesifik untuk kursus tertentu\" untuk permintaan Anda.", "Select a section or problem": "Pilih bagian atau masalah", "Select a session:": "Pilih sesi:", - "Select a subject for your support request.": "Berikan judul untuk permintaan dukungan Anda.", "Select a time allotment for the exam. If it is over 24 hours, type in the amount of time. You can grant individual learners extra time to complete the exam through the Instructor Dashboard.": "Pilih penjatahan waktu untuk ujian. Jika lebih dari 24 jam, ketik jumlah waktu. Anda dapat memberikan peserta didik waktu tambahan untuk menyelesaikan ujian melalui Dashboard Instruktur.", "Select all": "pilih semua", "Select fidelity": "Pilih fidelity", @@ -1320,7 +1313,6 @@ "Textbook Name": "Nama textbook", "Textbook information": "Informasi textbook", "Thank you for setting your course goal to {goal}!": "Terima kasih sudah membuat {goal} sebagai tujuan kursus Anda!", - "Thank you for submitting a request! We will contact you within 24 hours.": "Terima kasih atas permintaan Anda! Kami akan menghubungi Anda dalam 24 jam.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Terimakasih sudah mengirimkan aplikasi bantuan finansial untuk {course_name}. Anda dapat mengharapkan balasan dalam 2-4 hari kerja.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Terimakasih sudah mengirimkan foto Anda. Kami akan meninjaunya segera. Anda dapat mengikuti kursus %(platformName)s apapun yang menawarkan sertifikat terverifikasi. Verifikasi berlaku selamat satu tahun. Setelah itu, Anda harus mengirimkan foto untuk verifikasi lagi.", "The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "URL anda tampak seperti alamat email. Apakah anda ingin menambahkan prefiks mailto:?", @@ -1340,7 +1332,6 @@ "The following email addresses and/or usernames are invalid:": "Alamat email dan atau nama pengguna berikut tidak valid:", "The following errors were generated:": "Kesalahan berikut terjadi:", "The following file types are not allowed: ": "Jenis berkas berikut tidak diperkenankan:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "Informasi berikut merupakan bagian dari profil {platform}. Kami memasukkannya untuk aplikasi Anda.", "The following message will be displayed at the bottom of the courseware pages within your course:": "Pesan berikut akan ditunjukkan pada bagian bawah dari halaman courseware dengan kursus anda", "The following options are available for the {license_name} license.": "Opsi berikut tersedia untuk {license_name} license.", "The following users are no longer enrolled in the course:": "Pengguna berikut sudah tidak terdaftar pada pembelajaran:", @@ -1350,7 +1341,6 @@ "The language that team members primarily use to communicate with each other.": "Bahasa yang terutama digunakan oleh anggota tim untuk berkomunikasi.", "The language used throughout this site. This site is currently available in a limited number of languages. Changing the value of this field will cause the page to refresh.": "Bahasa yang digunakan di seluruh situs. Situs ini saat ini tersedia dalam sejumlah bahasa. Mengubah nilai isian ini akan merefresh halaman ini.", "The minimum score percentage must be a whole number between 0 and 100.": "Persentase skor minimum mesti angka diantara 0 dan 100.", - "The more you tell us, the more quickly and helpfully we can respond!": "Semakin lengkap informasimu, semakin cepat dan tepat respon kami!", "The name of this signatory as it should appear on certificates.": "Nama penandatangan yang harus tercetak di sertifikat", "The name that identifies you on {platform_name}. You cannot change your username.": "Nama yang digunakan untuk mengenali Anda pada {platform_name}. Anda tidak dapat mengubah nama pengguna Anda.", "The name that is used for ID verification and that appears on your certificates.": "Nama yang digunakan untuk verifikasi ID dan ditampilkan di sertifikat Anda.", @@ -1358,7 +1348,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Jumlah subbagian dalam kursus yang berisi masalah dari jenis tugas ini.", "The organization that this signatory belongs to, as it should appear on certificates.": "Organisasi penandatangan yang harus tercetak di sertifikat", "The page \"{route}\" could not be found.": "Halaman \"{route}\" tidak dapat ditemukan.", - "The photo of your face matches the photo on your ID.": "Photo wajah anda sesuai dengan photo pada ID anda", "The post you selected has been deleted.": "Post yang Anda pilih telah dihapus.", "The refund deadline for this course has passed,so you will not receive a refund.": "Batas waktu refund untuk kursus ini telah berakhir, sehingga Anda tidak dapat menerima refund.", "The selected content group does not exist": "Grup isi yang dipilih tidak ada", @@ -1537,7 +1526,6 @@ "Upload PDF": "Unggah PDF", "Upload Photo": "Unggah Foto", "Upload Signature Image": "Unggah Gambar Tandatangan", - "Upload a new PDF to \u201c<%= name %>\u201d": "Unggah berkas PDF baru ke \u201c<%= name %>\u201d", "Upload an image": "Unggah gambar", "Upload completed": "Unggah selesai", "Upload is in progress. To avoid errors, stay on this page until the process is complete.": "Proses unggah sedang berlangsung. Untuk menghindari kesalahan, tetap berada di halaman ini sampai proses selesai.", @@ -1559,7 +1547,6 @@ "Use my institution/campus credentials": "Gunakan Kredensial Kampus/Institusi", "Use my university info": "Gunakan informasi universitas saya", "Use the All Topics menu to find specific topics.": "Gunakan menu Semua Topik untuk menemukan topik tertentu.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Gunakan webcan untuk mengambil foto ID Anda. Kami akan mencocokkan foto ini dengan foto wajah Anda dan nama di akun Anda.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Gunakan webcan untuk mengambil foto ID Anda. Kami akan mencocokkan foto ini dengan foto wajah di kartu identitas Anda.", "Used": "Terpakai", "Username": "Pengguna", @@ -1576,7 +1563,6 @@ "Verified Certificate for {courseName}": "Sertifikat Terverifikasi untuk {courseName}", "Verified Certificate upgrade": "Tingkatkan Sertifikat Terverifikasi", "Verified Status": "Status terverifikasi", - "Verify Now": "Verifikasi sekarang", "Vertical space": "Ruang vertikal", "Very loud": "Sangat Keras", "Very low": "Sangat rendah", @@ -1696,8 +1682,6 @@ "You must specify a name": "Anda harus berikan nama", "You must specify a name for the cohort": "Anda harus menentukan nama untuk kohort ini", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "Anda harus menentukan tahun lahir sebelum Anda dapat membagikan profil lengkap Anda. Untuk memilih tahun lahir, klik {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Anda memerlukan surat izin mengemudi, paspor, atau kartu identitas lain yang diterbitkan pemerintah yang memiliki nama dan foto Anda.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Anda membutuhkan kartu identitas dengan nama dan foto Anda. Surat izin mengemudi, paspor, atau kartu identitas lain yang diterbitkan oleh pemerintah dapat digunakan.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Anda memerlukan untuk aktifasi account anda sebelum anda dapat mendaftar kursus. Periksa inbok anda pada aktifasi email", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Anda harus mengaktifkan akun sebelum Anda dapat mendaftar kursus. Periksa kotak masuk email Anda untuk email aktivasi. Setelah Anda menyelesaikan aktivasi Anda dapat memuat kembali halaman ini.", "You receive messages from {platform_name} and course teams at this address.": "Anda menerima pesan dari {platform_name} dan tim kursus di alamat ini.", @@ -1778,7 +1762,6 @@ "enter code here": "masukan kode disini", "enter link description here": "masukan keterangan tautan di sini", "for": "untuk", - "for {courseName}": "untuk {courseName}", "image omitted": "gambar dihilangkan", "incorrect": "Salah", "internally reviewed": "Telah diulas secara internal", @@ -1890,7 +1873,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1958,9 +1941,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d-m-Y G.i", "SHORT_DATE_FORMAT": "d-m-Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/it-it/djangojs.js b/lms/static/js/i18n/it-it/djangojs.js index 98e7f832b1ccd2aa9438b91aa786469294477587..e508d178a06a491ba713296c0d8b0ef0a009c42a 100644 --- a/lms/static/js/i18n/it-it/djangojs.js +++ b/lms/static/js/i18n/it-it/djangojs.js @@ -886,7 +886,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -953,9 +953,9 @@ "%d/%m/%y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", - "MONTH_DAY_FORMAT": "j/F", - "NUMBER_GROUPING": "3", + "FIRST_DAY_OF_WEEK": 1, + "MONTH_DAY_FORMAT": "j F", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/ja-jp/djangojs.js b/lms/static/js/i18n/ja-jp/djangojs.js index ca0bf55248e1c345c3179820d6290706d3519470..e96ac07c645716caa20c4f1e5e279da33eb05ea8 100644 --- a/lms/static/js/i18n/ja-jp/djangojs.js +++ b/lms/static/js/i18n/ja-jp/djangojs.js @@ -365,7 +365,6 @@ "Default (Local Time Zone)": "\u65e2\u5b9a\u5024 (\u5730\u57df\u5225\u30bf\u30a4\u30e0\u30be\u30fc\u30f3)", "Default Timed Transcript": "\u65e2\u5b9a\u306e\u6642\u9593\u4ed8\u304d\u306e\u5b57\u5e55", "Delete": "\u524a\u9664", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u7f72\u540d\u4e00\u89a7\u304b\u3089 \"<%= signatoryName %>\" \u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f", "Delete File Confirmation": "\u30d5\u30a1\u30a4\u30eb\u524a\u9664\u78ba\u8a8d", "Delete Team": "\u30c1\u30fc\u30e0\u3092\u524a\u9664", "Delete student '<%- student_id %>'s state on problem '<%- problem_id %>'?": "\u53d7\u8b1b\u8005 '<%- student_id %>' \u306e\u554f\u984c '<%- problem_id %>' \u306e\u56de\u7b54\u3092\u524a\u9664\u3057\u3066\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f", @@ -391,7 +390,6 @@ "Do you want to replace the edX transcript with the YouTube transcript?": "edX\u5b57\u5e55\u3092YouTube\u5b57\u5e55\u3067\u7f6e\u304d\u63db\u3048\u307e\u3059\u304b\uff1f", "Do you want to upload your file before submitting?": "\u63d0\u51fa\u524d\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u307e\u3059\u304b\uff1f", "Does the name on your ID match your account name: %(fullName)s?": "\u8eab\u5206\u8a3c\u660e\u66f8\u4e0a\u306e\u6c0f\u540d\u306f\u3042\u306a\u305f\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u6c0f\u540d\u3068\u4e00\u81f4\u3057\u307e\u3059\u304b\uff1f: %(fullName)s", - "Does the photo of you match your ID photo?": "\u8eab\u5206\u8a3c\u660e\u66f8\u306e\u5199\u771f\u3068\u3042\u306a\u305f\u306e\u5199\u771f\u306f\u4e00\u81f4\u3057\u307e\u3059\u304b\uff1f", "Does the photo of you show your whole face?": "\u5199\u771f\u306b\u3042\u306a\u305f\u306e\u9854\u5168\u4f53\u304c\u5199\u3063\u3066\u3044\u307e\u3059\u304b\uff1f", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u5199\u771f\u304c\u898b\u3048\u306a\u3044\u3067\u3059\u304b\uff1f\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u3001\u30d6\u30e9\u30a6\u30b6\u304c\u30ab\u30e1\u30e9\u3092\u4f7f\u3048\u308b\u72b6\u614b\u304b\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002", "Donate": "\u5bc4\u4ed8", @@ -538,7 +536,6 @@ "Generate": "\u751f\u6210", "Generate Exception Certificates": "\u4f8b\u5916\u4fee\u4e86\u8a3c\u3092\u751f\u6210", "Generate the user's certificate": "\u30e6\u30fc\u30b6\u30fc\u306e\u4fee\u4e86\u8a3c\u3092\u751f\u6210", - "Get Credit": "\u5358\u4f4d\u3092\u7372\u5f97\u3059\u308b", "Go Back": "\u623b\u308b", "Go to Dashboard": "\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u3078\u79fb\u52d5", "Go to your Dashboard": "\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u3078", @@ -583,7 +580,6 @@ "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u30e6\u30cb\u30c3\u30c8\u304c\u4ee5\u524d\u53d7\u8b1b\u8005\u306b\u516c\u958b\u3055\u308c\u3066\u3044\u305f\u5834\u5408\u3001\u975e\u516c\u958b\u4e2d\u306e\u5909\u66f4\u3082\u5f8c\u307b\u3069\u53d7\u8b1b\u8005\u306b\u8868\u793a\u3055\u308c\u307e\u3059\u3002", "If you do not yet have an account, use the button below to register.": "\u307e\u3060\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u767b\u9332\u3057\u3066\u3044\u306a\u3044\u306e\u3067\u3042\u308c\u3070\u3001\u4e0b\u306e\u30dc\u30bf\u30f3\u3092\u4f7f\u3063\u3066\u767b\u9332\u3057\u3066\u304f\u3060\u3055\u3044\u3002", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u3044\u307e\u3059\u3050\u672c\u4eba\u8a8d\u8a3c\u3092\u884c\u308f\u306a\u304f\u3066\u3082\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u3067\u8b1b\u5ea7\u3092\u63a2\u3059\u3053\u3068\u306f\u3067\u304d\u307e\u3059\u3002\u5b9a\u671f\u7684\u306b%(platformName)s\u304b\u3089\u672c\u4eba\u8a8d\u8a3c\u3092\u884c\u3046\u3088\u3046\u306b\u901a\u77e5\u304c\u3042\u308a\u307e\u3059\u3002", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u3059\u3050\u306b\u672c\u4eba\u8a8d\u8a3c\u3092\u884c\u308f\u306a\u3044\u5834\u5408\u3067\u3082\u3001\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u3067\u8b1b\u5ea7\u3092\u63a2\u3059\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u5b9a\u671f\u7684\u306b{platformName}\u304b\u3089\u672c\u4eba\u8a8d\u8a3c\u3092\u884c\u3046\u3088\u3046\u901a\u77e5\u304c\u3042\u308a\u307e\u3059\u3002", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "\u8fd4\u4fe1\u3092\u4fdd\u5b58\u307e\u305f\u306f\u63d0\u51fa\u305b\u305a\u306b\u5225\u306e\u30da\u30fc\u30b8\u3078\u79fb\u52d5\u3059\u308b\u5834\u5408\u3001\u8a18\u8ff0\u3057\u305f\u5185\u5bb9\u304c\u5931\u308f\u308c\u307e\u3059\u3002", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "\u30d4\u30a2\u30fb\u30a2\u30bb\u30b9\u30e1\u30f3\u30c8\u3092\u63d0\u51fa\u305b\u305a\u306b\u5225\u306e\u30da\u30fc\u30b8\u3078\u79fb\u52d5\u3059\u308b\u5834\u5408\u3001\u8a18\u8ff0\u3057\u305f\u5185\u5bb9\u304c\u5931\u308f\u308c\u307e\u3059\u3002", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "\u30bb\u30eb\u30d5\u30fb\u30a2\u30bb\u30b9\u30e1\u30f3\u30c8\u3092\u63d0\u51fa\u305b\u305a\u306b\u5225\u306e\u30da\u30fc\u30b8\u3078\u79fb\u52d5\u3059\u308b\u3068\u3001\u8a18\u8ff0\u3057\u305f\u5185\u5bb9\u304c\u5931\u308f\u308c\u307e\u3059\u3002", @@ -1088,7 +1084,6 @@ "Terms of Service and Honor Code": "\u5229\u7528\u898f\u7d04\u304a\u3088\u3073\u502b\u7406\u898f\u5b9a", "Textbook Name": "\u6559\u79d1\u66f8\u540d", "Textbook information": "\u6559\u79d1\u66f8\u60c5\u5831", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "%(full_name)s\u69d8\u3001\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3059\uff01%(course_name)s\u306b\u95a2\u3059\u308b\u304a\u652f\u6255\u3044\u3092\u53d7\u7406\u3057\u307e\u3057\u305f\u3002", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "{course_name}\u306e\u7d4c\u6e08\u63f4\u52a9\u7533\u8fbc\u66f8\u3092\u3054\u63d0\u51fa\u3044\u305f\u3060\u304d\u3001\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3059\uff012-4\u55b6\u696d\u65e5\u4ee5\u5185\u306b\u8fd4\u4fe1\u304c\u5c4a\u304d\u307e\u3059\u3002", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "\u5199\u771f\u3092\u3054\u63d0\u51fa\u3044\u305f\u3060\u304d\u3001\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3059\u3002\u307e\u3082\u306a\u304f\u78ba\u8a8d\u3044\u305f\u3057\u307e\u3059\u3002%(platformName)s\u306e\u8a8d\u8a3c\u4ed8\u304d\u4fee\u4e86\u8a3c\u3092\u767a\u884c\u3057\u3066\u3044\u308b\u8b1b\u5ea7\u306b\u767b\u9332\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u8a8d\u8a3c\u306f\uff11\u5e74\u9593\u6709\u52b9\u3067\u3059\u3002\uff11\u5e74\u5f8c\u306b\u518d\u3073\u8a8d\u8a3c\u7528\u5199\u771f\u306e\u63d0\u51fa\u304c\u5fc5\u8981\u3068\u306a\u308a\u307e\u3059\u3002", "Thank you! We have received your payment for {courseName}.": "\u3042\u308a\u304c\u3068\u3046\u3054\u3056\u3044\u307e\u3057\u305f\uff01 {courseName}\u8b1b\u5ea7\u306e\u652f\u6255\u3092\u53d7\u9818\u3057\u307e\u3057\u305f\u3002", @@ -1097,8 +1092,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u3053\u306e\u53d7\u8b1b\u8005\u306e\u4fee\u4e86\u8a3c\u306f\u518d\u5ea6\u6709\u52b9\u3068\u306a\u308a\u307e\u3057\u305f\u306e\u3067\u3001\u30b7\u30b9\u30c6\u30e0\u306f\u63a1\u70b9\u3092\u518d\u958b\u3057\u307e\u3059\u3002", "The cohort cannot be added": "\u30b3\u30db\u30fc\u30c8\u304c\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093", "The cohort cannot be saved": "\u30b3\u30db\u30fc\u30c8\u304c\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u7d44\u7e54\u540d\u3001\u30e9\u30a4\u30d6\u30e9\u30ea\u30b3\u30fc\u30c9\u6b04\u306e\u5408\u8a08\u6587\u5b57\u6570\u306f<%=limit%>\u6587\u5b57\u307e\u3067\u3067\u3059\u3002", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u7d44\u7e54\u540d\u3001\u8b1b\u5ea7\u756a\u53f7\u3001course run\u6b04\u306e\u5408\u8a08\u6587\u5b57\u6570\u306f<%=limit%>\u6587\u5b57\u307e\u3067\u3067\u3059\u3002", "The country or region where you live.": "\u304a\u4f4f\u307e\u3044\u306e\u56fd\u30fb\u5730\u57df\u3002", "The country that team members primarily identify with.": "\u30c1\u30fc\u30e0\u306e\u4e3b\u306a\u30e1\u30f3\u30d0\u30fc\u306e\u56fd\u3002", "The course end date must be later than the course start date.": "\u8b1b\u5ea7\u7d42\u4e86\u65e5\u306f\u3001\u8b1b\u5ea7\u958b\u59cb\u65e5\u3088\u308a\u5f8c\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002", @@ -1113,7 +1106,6 @@ "The following email addresses and/or usernames are invalid:": "\u6b21\u306e\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u307e\u305f\u306f\u30e6\u30fc\u30b6\u30fc\u540d\u304c\u7121\u52b9\u3067\u3059: ", "The following errors were generated:": "\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: ", "The following file types are not allowed: ": "\u6b21\u306b\u793a\u3059\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u306f\u4e0d\u6b63\u3067\u3059\uff1a", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "\u4ee5\u4e0b\u306e\u60c5\u5831\u306f\u3059\u3067\u306b\u3042\u306a\u305f\u306e{platform}\u306e\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u306b\u5165\u3063\u3066\u3044\u307e\u3059\u3002\u7533\u8fbc\u66f8\u306b\u4ee5\u4e0b\u306e\u60c5\u5831\u3092\u5165\u308c\u307e\u3057\u305f\u3002", "The following message will be displayed at the bottom of the courseware pages within your course:": "\u6b21\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u306f\u30b3\u30fc\u30b9\u30a6\u30a7\u30a2\u753b\u9762\u306e\u4e0b\u90e8\u306b\u8868\u793a\u3055\u308c\u307e\u3059: ", "The following options are available for the {license_name} license.": " {license_name}\u30e9\u30a4\u30bb\u30f3\u30b9\u3067\u306f\u3001\u4ee5\u4e0b\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u304c\u5229\u7528\u3067\u304d\u307e\u3059\u3002", "The following users are no longer enrolled in the course:": "\u6b21\u306e\u30e6\u30fc\u30b6\u30fc\u306f\u8b1b\u5ea7\u306b\u53d7\u8b1b\u767b\u9332\u3055\u308c\u3066\u3044\u307e\u305b\u3093: ", @@ -1127,7 +1119,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "\u3053\u306e\u8ab2\u984c\u30bf\u30a4\u30d7\u306e\u554f\u984c\u3092\u542b\u3080\u30b5\u30d6\u30bb\u30af\u30b7\u30e7\u30f3\u6570\u3002", "The organization that this signatory belongs to, as it should appear on certificates.": "\u4fee\u4e86\u8a3c\u306b\u8868\u793a\u3055\u308c\u308b\u3053\u306e\u7f72\u540d\u8005\u304c\u6240\u5c5e\u3057\u3066\u3044\u308b\u7d44\u7e54", "The page \"{route}\" could not be found.": "\"{route}\" \u3068\u3044\u3046\u30da\u30fc\u30b8\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002", - "The photo of your face matches the photo on your ID.": "\u9854\u5199\u771f\u3068ID\u306e\u5199\u771f\u304c\u4e00\u81f4\u3057\u3066\u3044\u308b\u3002", "The post you selected has been deleted.": "\u3042\u306a\u305f\u304c\u9078\u629e\u3057\u305f\u6295\u7a3f\u306f\u524a\u9664\u3055\u308c\u3066\u3044\u307e\u3059\u3002", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "\u516c\u958b\u6e08\u307f\u30d6\u30e9\u30f3\u30c1\u306e\u30d0\u30fc\u30b8\u30e7\u30f3{published}\u306f\u30c9\u30e9\u30d5\u30c8\u30d6\u30e9\u30f3\u30c1\u306e\u30d0\u30fc\u30b8\u30e7\u30f3{draft}\u306b\u30ea\u30bb\u30c3\u30c8\u3055\u308c\u307e\u3057\u305f\u3002", "The raw error message is:": "\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u539f\u6587\uff1a", @@ -1238,7 +1229,6 @@ "Titles more than 100 characters may prevent students from printing their certificate on a single page.": "\u5f79\u8077\u304c100\u6587\u5b57\u4ee5\u4e0a\u3060\u3068\u3001\u4fee\u4e86\u8a3c\u30921\u30da\u30fc\u30b8\u306b\u53ce\u3081\u3066\u5370\u5237\u3067\u304d\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002", "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "\u5168\u53d7\u8b1b\u8005\u304c\u52d5\u753b\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u308b\u3088\u3046\u306b\u3001.mp4\u3068.webm\u306e\u4e21\u65b9\u306e\u7a2e\u985e\u306e\u52d5\u753b\u3092\u63d0\u4f9b\u3059\u308b\u3053\u3068\u3092\u304a\u52e7\u3081\u3057\u307e\u3059\u3002\u5225\u306e\u7a2e\u985e\u306eURL\u3092\u8ffd\u52a0\u3059\u308b\u306b\u306f\u4ee5\u4e0b\u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059\u3002\u3053\u308c\u3089\u306eURL\u306fYouTube\u306f\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002\u4e00\u89a7\u306e\u4e2d\u304b\u3089\u53d7\u8b1b\u8005\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u306b\u5bfe\u5fdc\u3059\u308b\uff11\u756a\u76ee\u306e\u52d5\u753b\u304c\u518d\u751f\u3055\u308c\u307e\u3059\u3002", "To complete the program, you must earn a verified certificate for each course.": "\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u4fee\u4e86\u3059\u308b\u306b\u306f\u3001\u5404\u8b1b\u5ea7\u306e\u8a8d\u8a3c\u4ed8\u304d\u4fee\u4e86\u8a3c\u3092\u7372\u5f97\u3057\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "\u5358\u4f4d\u8a8d\u5b9a\u306e\u6700\u7d42\u51e6\u7406\u3092\u3059\u308b\u305f\u3081\u306b\u3001%(display_name)s\u3067\u306f%(platform_name)s\u53d7\u8b1b\u8005\u306b\u5358\u4f4d\u8a8d\u5b9a\u7533\u8acb\u3092\u63d0\u51fa\u3059\u308b\u3088\u3046\u6c42\u3081\u3066\u3044\u307e\u3059\u3002", "To invalidate a certificate for a particular learner, add the username or email address below.": "\u7279\u5b9a\u306e\u53d7\u8b1b\u8005\u306e\u4fee\u4e86\u8a3c\u3092\u7121\u52b9\u306b\u3059\u308b\u306b\u306f\u3001\u30e6\u30fc\u30b6\u30fc\u540d\u307e\u305f\u306f\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3092\u4ee5\u4e0b\u306b\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002", "To receive a certificate, you must also verify your identity before {date}.": "\u4fee\u4e86\u8a3c\u3092\u53d6\u5f97\u3059\u308b\u305f\u3081\u306b\u306f\u3001{date}\u307e\u3067\u306b\u672c\u4eba\u8a8d\u8a3c\u3092\u3057\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002", "To receive a certificate, you must also verify your identity.": "\u4fee\u4e86\u8a3c\u3092\u53d6\u5f97\u3059\u308b\u305f\u3081\u306b\u306f\u3001\u672c\u4eba\u8a8d\u8a3c\u3092\u3057\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002", @@ -1328,7 +1318,6 @@ "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "\u30c7\u30a3\u30b9\u30ab\u30c3\u30b7\u30e7\u30f3\u3092\u5206\u5272\u3059\u308b\u57fa\u6e96\u3068\u3057\u3066\u53d7\u8b1b\u767b\u9332\u30c8\u30e9\u30c3\u30af\u3092\u5229\u7528\u3057\u307e\u3059\u3002\u53d7\u8b1b\u767b\u9332\u30c8\u30e9\u30c3\u30af\u306b\u95a2\u4fc2\u306a\u304f\u3001\u5168\u53d7\u8b1b\u8005\u306b\u540c\u3058\u30c7\u30a3\u30b9\u30ab\u30c3\u30b7\u30e7\u30f3\u30fb\u30c8\u30d4\u30c3\u30af\u304c\u8868\u793a\u3055\u308c\u307e\u3059\u304c\u3001\u5206\u5272\u3055\u308c\u305f\u30c8\u30d4\u30c3\u30af\u5185\u3067\u306f\u540c\u3058\u53d7\u8b1b\u767b\u9332\u30c8\u30e9\u30c3\u30af\u306e\u53d7\u8b1b\u8005\u3060\u3051\u304c\u4e92\u3044\u306e\u6295\u7a3f\u3092\u898b\u305f\u308a\u8fd4\u4fe1\u3057\u305f\u308a\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002", "Use my institution/campus credentials": "\u6a5f\u95a2/\u5b66\u6821\u306e\u8a3c\u660e\u66f8\u3092\u4f7f\u3046", "Use the All Topics menu to find specific topics.": "\u7279\u5b9a\u306e\u30c8\u30d4\u30c3\u30af\u3092\u898b\u3064\u3051\u308b\u306b\u306f'\u5168\u30c8\u30d4\u30c3\u30af'\u30e1\u30cb\u30e5\u30fc\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u30a6\u30a7\u30d6\u30ab\u30e1\u30e9\u3092\u4f7f\u3063\u3066\u3001\u3042\u306a\u305f\u306eID\u306e\u5199\u771f\u3092\u64ae\u5f71\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u305d\u306e\u5199\u771f\u3092\u3042\u306a\u305f\u306e\u9854\u5199\u771f\u304a\u3088\u3073\u30a2\u30ab\u30a6\u30f3\u30c8\u306b\u8a2d\u5b9a\u3055\u308c\u305f\u540d\u524d\u3068\u7167\u5408\u3057\u307e\u3059\u3002", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u30a6\u30a7\u30d6\u30ab\u30e1\u30e9\u3092\u4f7f\u3063\u3066\u3001\u3042\u306a\u305f\u306e\u9854\u5199\u771f\u3092\u64ae\u5f71\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u3053\u306e\u5199\u771f\u3092\u3042\u306a\u305f\u306eID\u306e\u5199\u771f\u3068\u7167\u5408\u3057\u307e\u3059\u3002", "Used": "\u5229\u7528\u6e08", "Used in {count} location": [ @@ -1349,7 +1338,6 @@ "Verified Certificate upgrade": "\u8a8d\u8a3c\u4ed8\u304d\u4fee\u4e86\u8a3c\u306e\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9", "Verified Status": "\u8a8d\u8a3c\u30b9\u30c6\u30fc\u30bf\u30b9", "Verified mode price": "\u8a8d\u8a3c\u30e2\u30fc\u30c9\u4fa1\u683c", - "Verify Now": "\u3044\u307e\u3059\u3050\u8a8d\u8a3c\u3057\u3088\u3046", "Video Capture Error": "\u30d3\u30c7\u30aa\u30ad\u30e3\u30d7\u30c1\u30e3\u30a8\u30e9\u30fc", "Video ID": "\u52d5\u753bID", "Video duration is {humanizeDuration}": "\u52d5\u753b\u306e\u9577\u3055\u306f {humanizeDuration}", @@ -1377,7 +1365,6 @@ "We couldn't find any results for \"%s\".": "\"%s\" \u306e\u691c\u7d22\u7d50\u679c\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002", "We couldn't sign you in.": "\u30b5\u30a4\u30f3\u30a4\u30f3\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002", "We have encountered an error. Refresh your browser and then try again.": "\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u30d6\u30e9\u30a6\u30b6\u3092\u66f4\u65b0\u3057\u3066\u518d\u8a66\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "\u3042\u306a\u305f\u306e\u60c5\u5831\u3092\u53d7\u3051\u53d6\u308a\u3001\u672c\u4eba\u8a8d\u8a3c\u4e2d\u3067\u3059\u3002\u8a8d\u8a3c\u624b\u7d9a\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f\u3089\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u306b\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u8868\u793a\u3055\u308c\u307e\u3059(\u901a\u5e381\uff5e2\u65e5\u4ee5\u5185)\u3002\u305d\u306e\u9593\u3082\u8b1b\u5ea7\u30b3\u30f3\u30c6\u30f3\u30c4\u306b\u306f\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u3059\u3002", "We just need a little more information before you start learning with %(platformName)s.": "%(platformName)s\u3067\u306e\u5b66\u7fd2\u3092\u59cb\u3081\u308b\u306b\u3042\u305f\u3063\u3066\u3001\u3082\u3046\u5c11\u3057\u60c5\u5831\u304c\u5fc5\u8981\u3067\u3059\u3002", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "\u6700\u9ad8\u30ec\u30d9\u30eb\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u3067\u5199\u771f\u3092\u6697\u53f7\u5316\u3057\u3001\u8a8d\u8a3c\u30b5\u30fc\u30d3\u30b9\u3078\u9001\u308a\u307e\u3059\u3002\u8a8d\u8a3c\u624b\u7d9a\u304c\u5b8c\u4e86\u3057\u305f\u5f8c\u306f\u3001\u5199\u771f\u3084\u60c5\u5831\u3092%(platformName)s\u3067\u4fdd\u5b58\u3057\u305f\u308a\u95b2\u89a7\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002", "We've encountered an error. Refresh your browser and then try again.": "\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u30d6\u30e9\u30a6\u30b6\u3092\u66f4\u65b0\u3057\u3066\u518d\u8a66\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002", @@ -1449,11 +1436,8 @@ "You must sign out and sign back in before your language changes take effect.": "\u8a00\u8a9e\u306e\u5909\u66f4\u3092\u6709\u52b9\u306b\u3059\u308b\u306b\u306f\u3001\u4e00\u65e6\u30b5\u30a4\u30f3\u30a2\u30a6\u30c8\u3057\u3066\u304b\u3089\u518d\u5ea6\u30b5\u30a4\u30f3\u30a4\u30f3\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002", "You must specify a name for the cohort": "\u30b3\u30db\u30fc\u30c8\u306e\u540d\u524d\u3092\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u5168\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u3092\u516c\u958b\u3059\u308b\u305f\u3081\u306b\u306f\u3001\u8a95\u751f\u5e74\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u8a95\u751f\u5e74\u3092\u5165\u529b\u3059\u308b\u306b\u306f {account_settings_page_link}\u3078\u79fb\u52d5\u3057\u307e\u3059\u3002", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u540d\u524d\u3068\u5199\u771f\u304c\u8a18\u8f09\u3055\u308c\u3066\u3044\u308b\u514d\u8a31\u8a3c\u3001\u30d1\u30b9\u30dd\u30fc\u30c8\u307e\u305f\u306f\u653f\u5e9c\u767a\u884c\u306e\u8eab\u5206\u8a3c\u660e\u66f8\u304c\u5fc5\u8981\u3067\u3059\u3002", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u6c0f\u540d\u3068\u5199\u771f\u4ed8\u304d\u306eID\u304c\u5fc5\u8981\u3067\u3059\u3002\u904b\u8ee2\u514d\u8a31\u8a3c\u3001\u30d1\u30b9\u30dd\u30fc\u30c8\u307e\u305f\u306f\u653f\u5e9c\u767a\u884c\u306e\u8eab\u5206\u8a3c\u660e\u66f8\u304c\u6709\u52b9\u3067\u3059\u3002", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u8b1b\u5ea7\u306e\u53d7\u8b1b\u767b\u9332\u3092\u59cb\u3081\u308b\u524d\u306b\u3001\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u6709\u52b9\u5316\u3055\u305b\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u6709\u52b9\u5316\u306b\u95a2\u3059\u308b\u30e1\u30fc\u30eb\u304c\u5c4a\u3044\u3066\u3044\u308b\u304b\u3054\u78ba\u8a8d\u304f\u3060\u3055\u3044\u3002", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u8b1b\u5ea7\u306e\u53d7\u8b1b\u767b\u9332\u3092\u59cb\u3081\u308b\u524d\u306b\u3001\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u6709\u52b9\u5316\u3055\u305b\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u6709\u52b9\u5316\u306b\u95a2\u3059\u308b\u30e1\u30fc\u30eb\u304c\u5c4a\u3044\u3066\u3044\u308b\u304b\u3054\u78ba\u8a8d\u304f\u3060\u3055\u3044\u3002\u6709\u52b9\u5316\u304c\u5b8c\u4e86\u3057\u305f\u3089\u3001\u3053\u306e\u753b\u9762\u306b\u623b\u308a\u518d\u8aad\u8fbc\u3057\u3066\u304f\u3060\u3055\u3044\u3002", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u5358\u4f4d\u8a8d\u5b9a\u51e6\u7406\u3092\u5b8c\u4e86\u3059\u308b\u306b\u306f\u5f15\u304d\u7d9a\u304d%(display_name)s\u3092\u898b\u3066\u304f\u3060\u3055\u3044\u3002", "You will be refunded the amount you paid.": "\u304a\u652f\u6255\u3044\u3044\u305f\u3060\u3044\u305f\u91d1\u984d\u304c\u8fd4\u91d1\u3055\u308c\u307e\u3059\u3002", "You will not be refunded the amount you paid.": "\u304a\u652f\u6255\u3044\u3044\u305f\u3060\u3044\u305f\u91d1\u984d\u306f\u8fd4\u91d1\u3055\u308c\u307e\u305b\u3093\u3002", "You will not receive notification for emails that bounce, so double-check your spelling.": "\u623b\u3063\u3066\u304f\u308b\u30e1\u30fc\u30eb\u306b\u95a2\u3059\u308b\u901a\u77e5\u306f\u5c4a\u304d\u307e\u305b\u3093\u306e\u3067\u3001\u7db4\u308a\u306f\u30c0\u30d6\u30eb\u30c1\u30a7\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002", @@ -1624,7 +1608,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1688,9 +1672,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "n\u6708j\u65e5", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "Y/m/d G:i", "SHORT_DATE_FORMAT": "Y/m/d", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/kk-kz/djangojs.js b/lms/static/js/i18n/kk-kz/djangojs.js index b3d2d3342e61f8aefcc8945792a4835f5328e637..7d5ca2071be4313f12b7b0b10d5b9998ae8e201f 100644 --- a/lms/static/js/i18n/kk-kz/djangojs.js +++ b/lms/static/js/i18n/kk-kz/djangojs.js @@ -6,7 +6,7 @@ django.pluralidx = function(n) { - var v=0; + var v=(n!=1); if (typeof(v) == 'boolean') { return v ? 1 : 0; } else { @@ -21,6 +21,7 @@ var newcatalog = { "%(sel)s of %(cnt)s selected": [ + "%(cnt)s-\u04a3 %(sel)s-\u044b(\u0456) \u0442\u0430\u04a3\u0434\u0430\u043b\u0434\u044b", "%(cnt)s-\u04a3 %(sel)s-\u044b(\u0456) \u0442\u0430\u04a3\u0434\u0430\u043b\u0434\u044b" ], "6 a.m.": "06", @@ -61,7 +62,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -125,9 +126,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/km-kh/djangojs.js b/lms/static/js/i18n/km-kh/djangojs.js index b81c0e23b144d2b3aa608876cd99cea0418643bc..d0454035fb36405954c14ceb8d05a776a6bd4750 100644 --- a/lms/static/js/i18n/km-kh/djangojs.js +++ b/lms/static/js/i18n/km-kh/djangojs.js @@ -55,7 +55,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -119,9 +119,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "j M Y, G:i", "SHORT_DATE_FORMAT": "j M Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/kn/djangojs.js b/lms/static/js/i18n/kn/djangojs.js index d9e92345796feed018057d6118f81cc367c8ecf1..9a3e4908fc5084cc3f03c4feea0bba260a920844 100644 --- a/lms/static/js/i18n/kn/djangojs.js +++ b/lms/static/js/i18n/kn/djangojs.js @@ -59,7 +59,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -123,9 +123,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/ko-kr/djangojs.js b/lms/static/js/i18n/ko-kr/djangojs.js index 9ca94426c37ea76199c183c5e630ba92a929cf83..e6dec1a6a9472833bc67b3be00c6d02fb4df8902 100644 --- a/lms/static/js/i18n/ko-kr/djangojs.js +++ b/lms/static/js/i18n/ko-kr/djangojs.js @@ -398,7 +398,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -457,9 +457,9 @@ "%Y\ub144 %m\uc6d4 %d\uc77c" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "n\uc6d4 j\uc77c", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "Y-n-j H:i", "SHORT_DATE_FORMAT": "Y-n-j.", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/lt-lt/djangojs.js b/lms/static/js/i18n/lt-lt/djangojs.js index afccff2f29f6eadb236db063cb9857c1a7211c59..81595a3f289b18dc254be0e51de6f206403c85e6 100644 --- a/lms/static/js/i18n/lt-lt/djangojs.js +++ b/lms/static/js/i18n/lt-lt/djangojs.js @@ -51,6 +51,7 @@ "%(sel)s of %(cnt)s selected": [ "pasirinktas %(sel)s i\u0161 %(cnt)s", "pasirinkti %(sel)s i\u0161 %(cnt)s", + "pasirinkti %(sel)s i\u0161 %(cnt)s", "pasirinkti %(sel)s i\u0161 %(cnt)s" ], "%(team_count)s Team": [ @@ -382,11 +383,13 @@ "Note: You are %s hour ahead of server time.": [ "Pastaba: J\u016bs\u0173 laikrodis rodo %s valanda daugiau nei serverio laikrodis.", "Pastaba: J\u016bs\u0173 laikrodis rodo %s valandomis daugiau nei serverio laikrodis.", + "Pastaba: J\u016bs\u0173 laikrodis rodo %s valand\u0173 daugiau nei serverio laikrodis.", "Pastaba: J\u016bs\u0173 laikrodis rodo %s valand\u0173 daugiau nei serverio laikrodis." ], "Note: You are %s hour behind server time.": [ "Pastaba: J\u016bs\u0173 laikrodis rodo %s valanda ma\u017eiau nei serverio laikrodis.", "Pastaba: J\u016bs\u0173 laikrodis rodo %s valandomis ma\u017eiau nei serverio laikrodis.", + "Pastaba: J\u016bs\u0173 laikrodis rodo %s valand\u0173 ma\u017eiau nei serverio laikrodis.", "Pastaba: J\u016bs\u0173 laikrodis rodo %s valand\u0173 ma\u017eiau nei serverio laikrodis." ], "Noted in:": "Pa\u017eym\u0117ta:", @@ -783,7 +786,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -842,9 +845,9 @@ "%d.%m.%y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "E j \\d.", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "Y-m-d H:i", "SHORT_DATE_FORMAT": "Y-m-d", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/ml/djangojs.js b/lms/static/js/i18n/ml/djangojs.js index eb8845d2cd02aee5c670d40ce7ad28bdb378fd91..d514e594908e17edce92f8cd989762522999be28 100644 --- a/lms/static/js/i18n/ml/djangojs.js +++ b/lms/static/js/i18n/ml/djangojs.js @@ -25,16 +25,28 @@ "%(cnt)s\u0d32\u0d4d\u200d %(sel)s \u0d0e\u0d23\u0d4d\u0d23\u0d02 \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d24\u0d4d\u0d24\u0d41" ], "6 a.m.": "6 a.m.", + "6 p.m.": "6 p.m", + "April": "\u0d0f\u0d2a\u0d4d\u0d30\u0d3f\u0d7d", + "August": "\u0d06\u0d17\u0d38\u0d4d\u0d31\u0d4d\u0d31\u0d4d", "Available %s": "\u0d32\u0d2d\u0d4d\u0d2f\u0d2e\u0d3e\u0d2f %s", "Cancel": "\u0d31\u0d26\u0d4d\u0d26\u0d3e\u0d15\u0d4d\u0d15\u0d42", "Choose": "\u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d42", + "Choose a Date": "\u0d12\u0d30\u0d41 \u0d24\u0d40\u0d2f\u0d24\u0d3f \u0d24\u0d3f\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d41\u0d15", + "Choose a Time": "\u0d38\u0d2e\u0d2f\u0d02 \u0d24\u0d3f\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d41\u0d15", "Choose a time": "\u0d38\u0d2e\u0d2f\u0d02 \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d42", "Choose all": "\u0d0e\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d41\u0d15", "Chosen %s": "\u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d24\u0d4d\u0d24 %s", "Click to choose all %s at once.": "%s \u0d0e\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d12\u0d28\u0d4d\u0d28\u0d3f\u0d1a\u0d4d\u0d1a\u0d4d \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d3e\u0d28\u0d4d\u200d \u0d15\u0d4d\u0d32\u0d3f\u0d15\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15.", "Click to remove all chosen %s at once.": "\u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d2a\u0d4d\u0d2a\u0d46\u0d1f\u0d4d\u0d1f %s \u0d0e\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d12\u0d30\u0d41\u0d2e\u0d3f\u0d1a\u0d4d\u0d1a\u0d4d \u0d28\u0d40\u0d15\u0d4d\u0d15\u0d02 \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d28\u0d4d\u200d \u0d15\u0d4d\u0d32\u0d3f\u0d15\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15.", + "December": "\u0d21\u0d3f\u0d38\u0d02\u0d2c\u0d30\u0d4d", + "February": "\u0d2b\u0d46\u0d2c\u0d4d\u0d30\u0d41\u0d35\u0d30\u0d3f", "Filter": "Filter", "Hide": "\u0d2e\u0d31\u0d2f\u0d1f\u0d4d\u0d1f\u0d46", + "January": "\u0d1c\u0d28\u0d41\u0d35\u0d30\u0d3f", + "July": "\u0d1c\u0d42\u0d32\u0d48", + "June": "\u0d1c\u0d42\u0d7a", + "March": "\u0d2e\u0d3e\u0d7c\u0d1a\u0d4d\u0d1a\u0d4d", + "May": "\u0d2e\u0d46\u0d2f\u0d4d", "Midnight": "\u0d05\u0d30\u0d4d\u200d\u0d27\u0d30\u0d3e\u0d24\u0d4d\u0d30\u0d3f", "Noon": "\u0d09\u0d1a\u0d4d\u0d1a", "Note: You are %s hour ahead of server time.": [ @@ -45,9 +57,12 @@ "\u0d12\u0d7c\u0d15\u0d4d\u0d15\u0d41\u0d15: \u0d38\u0d46\u0d7c\u0d35\u0d7c \u0d38\u0d2e\u0d2f\u0d24\u0d4d\u0d24\u0d3f\u0d28\u0d46\u0d15\u0d4d\u0d15\u0d3e\u0d33\u0d41\u0d02 \u0d28\u0d3f\u0d19\u0d4d\u0d19\u0d7e %s \u0d38\u0d2e\u0d2f\u0d02 \u0d2a\u0d3f\u0d28\u0d4d\u0d28\u0d3f\u0d32\u0d3e\u0d23\u0d4d.", "\u0d12\u0d7c\u0d15\u0d4d\u0d15\u0d41\u0d15: \u0d38\u0d46\u0d7c\u0d35\u0d7c \u0d38\u0d2e\u0d2f\u0d24\u0d4d\u0d24\u0d3f\u0d28\u0d46\u0d15\u0d4d\u0d15\u0d3e\u0d33\u0d41\u0d02 \u0d28\u0d3f\u0d19\u0d4d\u0d19\u0d7e %s \u0d38\u0d2e\u0d2f\u0d02 \u0d2a\u0d3f\u0d28\u0d4d\u0d28\u0d3f\u0d32\u0d3e\u0d23\u0d4d." ], + "November": "\u0d28\u0d35\u0d02\u0d2c\u0d7c", "Now": "\u0d07\u0d2a\u0d4d\u0d2a\u0d4b\u0d33\u0d4d\u200d", + "October": "\u0d12\u0d15\u0d4d\u0d1f\u0d47\u0d3e\u0d2c\u0d7c", "Remove": "\u0d28\u0d40\u0d15\u0d4d\u0d15\u0d02 \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d42", "Remove all": "\u0d0e\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d28\u0d40\u0d15\u0d4d\u0d15\u0d02 \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15", + "September": "\u0d38\u0d46\u0d2a\u0d4d\u0d31\u0d4d\u0d31\u0d02\u0d2c\u0d7c", "Show": "\u0d15\u0d3e\u0d23\u0d1f\u0d4d\u0d1f\u0d46", "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "\u0d07\u0d24\u0d3e\u0d23\u0d4d \u0d32\u0d2d\u0d4d\u0d2f\u0d2e\u0d3e\u0d2f %s \u0d2a\u0d1f\u0d4d\u0d1f\u0d3f\u0d15. \u0d05\u0d24\u0d3f\u0d32\u0d4d\u200d \u0d1a\u0d3f\u0d32\u0d24\u0d4d \u0d24\u0d3f\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d3e\u0d28\u0d4d\u200d \u0d24\u0d3e\u0d34\u0d46 \u0d15\u0d33\u0d24\u0d4d\u0d24\u0d3f\u0d32\u0d4d\u200d \u0d28\u0d3f\u0d28\u0d4d\u0d28\u0d41\u0d02 \u0d09\u0d1a\u0d3f\u0d24\u0d2e\u0d3e\u0d2f\u0d35 \u0d38\u0d46\u0d32\u0d15\u0d4d\u0d1f\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d24 \u0d36\u0d47\u0d37\u0d02 \u0d30\u0d23\u0d4d\u0d1f\u0d41 \u0d15\u0d33\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d\u0d15\u0d4d\u0d15\u0d41\u0d2e\u0d3f\u0d1f\u0d2f\u0d3f\u0d32\u0d46 \"\u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d42\" \u0d05\u0d1f\u0d2f\u0d3e\u0d33\u0d24\u0d4d\u0d24\u0d3f\u0d32\u0d4d\u200d \u0d15\u0d4d\u0d32\u0d3f\u0d15\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15.", "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "\u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d2a\u0d4d\u0d2a\u0d46\u0d1f\u0d4d\u0d1f %s \u0d2a\u0d1f\u0d4d\u0d1f\u0d3f\u0d15\u0d2f\u0d3e\u0d23\u0d3f\u0d24\u0d4d. \u0d05\u0d35\u0d2f\u0d3f\u0d32\u0d4d\u200d \u0d1a\u0d3f\u0d32\u0d24\u0d4d \u0d12\u0d34\u0d3f\u0d35\u0d3e\u0d15\u0d4d\u0d15\u0d23\u0d2e\u0d46\u0d28\u0d4d\u0d28\u0d41\u0d23\u0d4d\u0d1f\u0d46\u0d19\u0d4d\u0d15\u0d3f\u0d32\u0d4d\u200d \u0d24\u0d3e\u0d34\u0d46 \u0d15\u0d33\u0d24\u0d4d\u0d24\u0d3f\u0d32\u0d4d\u200d \u0d28\u0d3f\u0d28\u0d4d\u0d28\u0d41\u0d02 \u0d05\u0d35 \u0d38\u0d46\u0d32\u0d15\u0d4d\u0d1f\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d24\u0d4d \u0d15\u0d33\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d\u0d15\u0d4d\u0d15\u0d3f\u0d1f\u0d2f\u0d3f\u0d32\u0d41\u0d33\u0d4d\u0d33 \"\u0d28\u0d40\u0d15\u0d4d\u0d15\u0d02 \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d42\" \u0d0e\u0d28\u0d4d\u0d28 \u0d05\u0d1f\u0d2f\u0d3e\u0d33\u0d24\u0d4d\u0d24\u0d3f\u0d32\u0d4d\u200d \u0d15\u0d4d\u0d32\u0d3f\u0d15\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15.", @@ -57,7 +72,14 @@ "Yesterday": "\u0d07\u0d28\u0d4d\u0d28\u0d32\u0d46", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "\u0d28\u0d3f\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d12\u0d30\u0d41 \u0d06\u0d15\u0d4d\u0d37\u0d28\u0d4d\u200d \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d24\u0d4d\u0d24\u0d3f\u0d1f\u0d4d\u0d1f\u0d41\u0d23\u0d4d\u0d1f\u0d4d. \u0d15\u0d33\u0d19\u0d4d\u0d19\u0d33\u0d3f\u0d32\u0d4d\u200d \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d24\u0d4d\u0d24 \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d07\u0d32\u0d4d\u0d32. \u0d28\u0d3f\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d\u0d38\u0d47\u0d35\u0d4d \u0d2c\u0d1f\u0d4d\u0d1f\u0d23\u0d4d\u200d \u0d24\u0d28\u0d4d\u0d28\u0d46\u0d2f\u0d3e\u0d23\u0d4b \u0d05\u0d24\u0d4b \u0d17\u0d4b \u0d2c\u0d1f\u0d4d\u0d1f\u0d23\u0d3e\u0d23\u0d4b \u0d09\u0d26\u0d4d\u0d26\u0d47\u0d36\u0d3f\u0d1a\u0d4d\u0d1a\u0d24\u0d4d.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "\u0d28\u0d3f\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d12\u0d30\u0d41 \u0d06\u0d15\u0d4d\u0d37\u0d28\u0d4d\u200d \u0d24\u0d46\u0d30\u0d1e\u0d4d\u0d1e\u0d46\u0d1f\u0d41\u0d24\u0d4d\u0d24\u0d3f\u0d1f\u0d4d\u0d1f\u0d41\u0d23\u0d4d\u0d1f\u0d4d. \u0d2a\u0d15\u0d4d\u0d37\u0d47, \u0d15\u0d33\u0d19\u0d4d\u0d19\u0d33\u0d3f\u0d32\u0d46 \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d07\u0d28\u0d3f\u0d2f\u0d41\u0d02 \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d28\u0d41\u0d23\u0d4d\u0d1f\u0d4d. \u0d06\u0d26\u0d4d\u0d2f\u0d02 \u0d38\u0d47\u0d35\u0d4d\u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d28\u0d3e\u0d2f\u0d3f OK \u0d15\u0d4d\u0d32\u0d3f\u0d15\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15. \u0d05\u0d24\u0d3f\u0d28\u0d41 \u0d36\u0d47\u0d37\u0d02 \u0d06\u0d15\u0d4d\u0d37\u0d28\u0d4d\u200d \u0d12\u0d28\u0d4d\u0d28\u0d41 \u0d15\u0d42\u0d1f\u0d3f \u0d2a\u0d4d\u0d30\u0d2f\u0d4b\u0d17\u0d3f\u0d15\u0d4d\u0d15\u0d47\u0d23\u0d4d\u0d1f\u0d3f \u0d35\u0d30\u0d41\u0d02.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "\u0d35\u0d30\u0d41\u0d24\u0d4d\u0d24\u0d3f\u0d2f \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d24\u0d3f\u0d1f\u0d4d\u0d1f\u0d3f\u0d32\u0d4d\u0d32. \u0d12\u0d30\u0d41 \u0d06\u0d15\u0d4d\u0d37\u0d28\u0d4d\u200d \u0d2a\u0d4d\u0d30\u0d2f\u0d4b\u0d17\u0d3f\u0d1a\u0d4d\u0d1a\u0d3e\u0d32\u0d4d\u200d \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d24\u0d4d\u0d24 \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d46\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d28\u0d37\u0d4d\u0d1f\u0d2a\u0d4d\u0d2a\u0d46\u0d1f\u0d41\u0d02." + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "\u0d35\u0d30\u0d41\u0d24\u0d4d\u0d24\u0d3f\u0d2f \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d4d\u200d \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d24\u0d3f\u0d1f\u0d4d\u0d1f\u0d3f\u0d32\u0d4d\u0d32. \u0d12\u0d30\u0d41 \u0d06\u0d15\u0d4d\u0d37\u0d28\u0d4d\u200d \u0d2a\u0d4d\u0d30\u0d2f\u0d4b\u0d17\u0d3f\u0d1a\u0d4d\u0d1a\u0d3e\u0d32\u0d4d\u200d \u0d38\u0d47\u0d35\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d3e\u0d24\u0d4d\u0d24 \u0d2e\u0d3e\u0d31\u0d4d\u0d31\u0d19\u0d4d\u0d19\u0d33\u0d46\u0d32\u0d4d\u0d32\u0d3e\u0d02 \u0d28\u0d37\u0d4d\u0d1f\u0d2a\u0d4d\u0d2a\u0d46\u0d1f\u0d41\u0d02.", + "one letter Friday\u0004F": "\u0d35\u0d46", + "one letter Monday\u0004M": "\u0d24\u0d3f", + "one letter Saturday\u0004S": "\u0d36", + "one letter Sunday\u0004S": "\u0d1e\u0d4d\u0d1e\u200d", + "one letter Thursday\u0004T": "\u0d35\u0d4d\u0d2f\u0d3e", + "one letter Tuesday\u0004T": "\u0d1a\u0d4a", + "one letter Wednesday\u0004W": "\u0d2c\u0d41" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -79,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -135,9 +157,9 @@ "%m/%d/%y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/mn/djangojs.js b/lms/static/js/i18n/mn/djangojs.js index 0ec7b611171ace2ce8dc056831a33feb29568809..024b2c328d9ad165b7cebbcabe52758201b56029 100644 --- a/lms/static/js/i18n/mn/djangojs.js +++ b/lms/static/js/i18n/mn/djangojs.js @@ -28,8 +28,8 @@ "%s ago": "%s \u04e9\u043c\u043d\u04e9", "(Optional)": "(\u041d\u044d\u043c\u044d\u043b\u0442)", "(Required Field)": "(\u0417\u0430\u0430\u0432\u0430\u043b \u0431\u04e9\u0433\u043b\u04e9\u0445 \u0442\u0430\u043b\u0431\u0430\u0440)", - "6 a.m.": "6 \u0446\u0430\u0433", - "6 p.m.": "\u041e\u0440\u043e\u0439\u043d 6 \u0446\u0430\u0433", + "6 a.m.": "06 \u0446\u0430\u0433", + "6 p.m.": "18 \u0446\u0430\u0433", "A valid email address is required": "\u0425\u04af\u0447\u0438\u043d\u0442\u044d\u0439 \u0446\u0430\u0445\u0438\u043c \u0445\u0430\u044f\u0433\u0438\u0439\u0433 \u0448\u0430\u0430\u0440\u0434\u0430\u0436 \u0431\u0430\u0439\u043d\u0430.", "ABCDEFGHIJKLMNOPQRSTUVWXYZ": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "About Me": "\u041c\u0438\u043d\u0438\u0439 \u0442\u0443\u0445\u0430\u0439", @@ -52,12 +52,14 @@ "Alternative source": "\u04e8\u04e9\u0440 \u044d\u0445 \u04af\u04af\u0441\u0432\u044d\u0440", "An error has occurred. Please try again.": "\u0410\u043b\u0434\u0430\u0430 \u0433\u0430\u0440\u043b\u0430\u0430. \u0414\u0430\u0445\u0438\u043d \u043e\u0440\u043e\u043b\u0434\u043e\u043d\u043e \u04af\u04af", "An error has occurred. Wait a few minutes, and then try again.": "\u0410\u043b\u0434\u0430\u0430 \u0433\u0430\u0440\u0441\u0430\u043d \u0431\u0430\u0439\u043d\u0430. \u0422\u04af\u0440 \u0445\u04af\u043b\u044d\u044d\u0433\u044d\u044d\u0434 \u0434\u0430\u0445\u0438\u043d \u043e\u0440\u043e\u043b\u0434\u043e\u043d\u043e \u0443\u0443.", + "April": "4-\u0440 \u0441\u0430\u0440", "Are you sure you want to delete this page? This action cannot be undone.": "\u0422\u0430 \u04af\u043d\u044d\u0445\u044d\u044d\u0440 \u044d\u043d\u044d \u0445\u0443\u0443\u0434\u0441\u044b\u0433 \u0443\u0441\u0442\u0433\u0430\u0445\u0434\u0430\u0430 \u0438\u0442\u0433\u044d\u043b\u0442\u044d\u0439 \u0431\u0430\u0439\u043d\u0430 \u0443\u0443? \u042d\u043d\u044d\u0445\u04af\u04af \u04af\u0439\u043b\u0434\u043b\u0438\u0439\u0433 \u0431\u0443\u0446\u0430\u0430\u0445 \u0431\u043e\u043b\u043e\u043c\u0436\u0433\u04af\u0439. ", "Are you sure you want to delete this update?": "\u042d\u043d\u044d \u0448\u0438\u043d\u044d\u0447\u043b\u044d\u043b\u0438\u0439\u0433 \u0443\u0441\u0442\u0433\u0430\u0445 \u0443\u0443?", "Are you sure you want to revert to the last published version of the unit? You cannot undo this action.": "\u042d\u043d\u044d \u043c\u043e\u0434\u0443\u043b\u0438\u0439\u043d \u0445\u044d\u0432\u043b\u044d\u0433\u0434\u0441\u044d\u043d \u0445\u044d\u0441\u0433\u0438\u0439\u0433 \u0441\u044d\u0440\u0433\u044d\u044d\u0445\u0438\u0439\u0433 \u0442\u0430 \u0445\u04af\u0441\u0447 \u0431\u0430\u0439\u043d\u0430? \u042d\u043d\u044d \u04af\u0439\u043b\u0434\u043b\u0438\u0439\u0433 \u0431\u0443\u0446\u0430\u0430\u0445 \u0431\u043e\u043b\u043e\u043c\u0436\u0433\u04af\u0439.", "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "\u042d\u043d\u044d \u0437\u04af\u0439\u043b\u0438\u0439\u0433 \u0443\u0441\u0442\u0433\u0430\u0432\u0430\u043b \u0430\u0445\u0438\u043d \u0441\u044d\u0440\u0433\u044d\u044d\u0445 \u0431\u043e\u043b\u043e\u043c\u0436\u0433\u04af\u0439!\n\n\u042d\u043d\u044d \u0445\u043e\u043b\u0431\u043e\u043e\u0441 \u0448\u0438\u0433 \u0437\u0430\u0440\u0438\u043c \u0430\u0433\u0443\u0443\u043b\u0433\u0443\u0443\u0434 /\u0445\u044d\u0441\u044d\u0433 \u0445\u0443\u0433\u0430\u0446\u0430\u0430\u043d\u0434 \u0430\u0436\u0438\u043b\u043b\u0430\u0445\u0433\u04af\u0439 \u0431\u0430\u0439\u0445 \u0431\u043e\u043b\u043e\u043c\u0436\u0442\u043e\u0439 (\u0430\u0448\u0438\u0433\u043b\u0430\u0433\u0434\u0430\u0445\u0433\u04af\u0439 \u0431\u043e\u043b\u0441\u043e\u043d \u0437\u0443\u0440\u0430\u0433/\u0445\u043e\u043b\u0431\u043e\u043e\u0441)", "Are you sure?": "\u0422\u0430 \u0438\u0442\u0433\u044d\u043b\u0442\u044d\u0439 \u0431\u0430\u0439\u043d\u0430 \u0443\u0443?", "Attribution": "\u0410\u0442\u0442\u0440\u0438\u0431\u0443\u0442", + "August": "8-\u0440 \u0441\u0430\u0440", "Author": "\u0417\u043e\u0445\u0438\u043e\u0433\u0447", "Automatic transcripts are disabled.": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442 \u0445\u0443\u0443\u043b\u0431\u0430\u0440\u044b\u0433 \u0438\u0434\u044d\u0432\u0445\u0433\u04af\u0439 \u0431\u043e\u043b\u0433\u043e\u0441\u043e\u043d \u0431\u0430\u0439\u043d\u0430.", "Available %s": "\u0411\u043e\u043b\u043e\u043c\u0436\u0442\u043e\u0439 %s", @@ -137,6 +139,7 @@ "Cut row": "\u041c\u04e9\u0440\u0438\u0439\u0433 \u0442\u0430\u0439\u0440\u0447 \u0430\u0432\u0430\u0445", "Date": "\u041e\u0433\u043d\u043e\u043e", "Date Added": "\u04e8\u0434\u04e9\u0440 \u0442\u043e\u0432\u043b\u043e\u0433\u0434\u043b\u043e\u043e.", + "December": "12-\u0440 \u0441\u0430\u0440", "Default": "\u04e8\u0433\u04e9\u0433\u0434\u043c\u04e9\u043b", "Delete": "\u0423\u0441\u0442\u0433\u0430\u0445", "Delete File Confirmation": "\u0424\u0430\u0439\u043b\u044b\u043d \u0431\u0430\u0442\u0430\u043b\u0433\u0430\u0430\u0436\u0443\u0443\u043b\u0430\u043b\u0442\u044b\u0433 \u0443\u0441\u0442\u0433\u0430\u0445", @@ -169,6 +172,7 @@ "Error removing user": "\u0425\u044d\u0440\u044d\u0433\u043b\u044d\u0433\u0447\u0438\u0439\u0433 \u0443\u0441\u0442\u0433\u0430\u0445 \u04af\u0435\u0438\u0439\u043d \u0430\u043b\u0434\u0430\u0430", "Expand Instructions": "\u0417\u0430\u0430\u0432\u0440\u0443\u0443\u0434\u044b\u0433 \u0434\u044d\u043b\u0433\u044d\u0445", "Explanation": "\u0422\u0430\u0439\u043b\u0431\u0430\u0440", + "February": "2-\u0440 \u0441\u0430\u0440", "File": "\u0424\u0430\u0439\u043b", "File format not supported. Please upload a file with a {ext} extension.": "\u0444\u0430\u0439\u043b\u044b\u043d \u0442\u04e9\u0440\u04e9\u043b \u0442\u043e\u0445\u0438\u0440\u043e\u0445\u0433\u04af\u0439 \u0431\u0430\u0439\u043d\u0430. {ext} \u04e9\u0440\u0433\u04e9\u0442\u0433\u04e9\u043b\u0442\u044d\u0439 \u0444\u0430\u0439\u043b \u043e\u0440\u0443\u0443\u043b\u043d\u0430 \u0443\u0443", "Files must be in JPEG or PNG format.": "\u0424\u0430\u0439\u043b\u044b\u043d \u0444\u043e\u0440\u043c\u0430\u0442 \u043d\u044c JPEG \u044d\u0441\u0432\u044d\u043b PNG \u0431\u0430\u0439\u043d\u0430.", @@ -218,8 +222,11 @@ "Insert video": "\u0411\u0438\u0447\u043b\u044d\u0433 \u043e\u0440\u0443\u0443\u043b\u0430\u0445", "Insert/edit link": "\u0425\u043e\u043b\u0431\u043e\u043e\u0441 \u043e\u0440\u0443\u0443\u043b\u0430\u0445/\u0437\u0430\u0441\u0430\u0445", "Insert/edit video": "\u0411\u0438\u0447\u043b\u044d\u0433 \u043e\u0440\u0443\u0443\u043b\u0430\u0445/\u0437\u0430\u0441\u0430\u0445", + "January": "1-\u0440 \u0441\u0430\u0440", "Joined": "\u042d\u043b\u0441\u0441\u044d\u043d", "Joined Date": "\u042d\u043b\u0441\u0441\u044d\u043d \u043e\u0433\u043d\u043e\u043e", + "July": "7-\u0440 \u0441\u0430\u0440", + "June": "6-\u0440 \u0441\u0430\u0440", "Justify": "\u041c\u04e9\u0440\u0438\u0439\u0433 \u0442\u044d\u0433\u0448\u043b\u044d\u0445", "KB": "KB", "Key should only contain letters, numbers, _, or -": "\u0422\u04af\u043b\u0445\u04af\u04af\u0440 \u04af\u0433 \u043d\u044c \u0437\u04e9\u0432\u0445\u04e9\u043d \u04af\u0441\u0433\u04af\u04af\u0434, \u0442\u043e\u043e, _ \u044d\u0441\u0432\u044d\u043b - \u0430\u0433\u0443\u0443\u043b\u0441\u0430\u043d \u0431\u0430\u0439\u0445 \u0448\u0430\u0430\u0440\u0434\u043b\u0430\u0433\u0430\u0442\u0430\u0439.", @@ -235,8 +242,10 @@ "Low": "\u0421\u0443\u043b", "MB": "MB", "Make Visible to Students": "\u041e\u044e\u0443\u0442\u043d\u0443\u0443\u0434\u0430\u0434 \u0445\u0430\u0440\u0430\u0433\u0434\u0434\u0430\u0433 \u0431\u043e\u043b\u0433\u043e\u0445", + "March": "3-\u0440 \u0441\u0430\u0440", "Max file size exceeded": "\u0424\u0430\u0439\u043b\u044b\u043d \u0434\u044d\u044d\u0434 \u0445\u044d\u043c\u0436\u044d\u044d \u0445\u044d\u0442\u044d\u0440\u0441\u044d\u043d \u0431\u0430\u0439\u043d\u0430", "Maximum": "\u0425\u0430\u043c\u0433\u0438\u0439\u043d \u0438\u0445", + "May": "5-\u0440 \u0441\u0430\u0440", "Membership": "\u0413\u0438\u0448\u04af\u04af\u043d\u0447\u043b\u044d\u043b", "Merge cells": "\u041d\u04af\u0434\u043d\u04af\u04af\u0434\u0438\u0439\u0433 \u043d\u044d\u0433\u0442\u0433\u044d\u0445", "Message:": "\u0417\u0443\u0440\u0432\u0430\u0441: ", @@ -266,9 +275,11 @@ "\u0422\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0438\u0439\u043d \u0446\u0430\u0433\u0430\u0430\u0441 %s \u0446\u0430\u0433\u0430\u0430\u0440 \u0445\u043e\u0446\u043e\u0440\u0447 \u0431\u0430\u0439\u043d\u0430", "\u0422\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0438\u0439\u043d \u0446\u0430\u0433\u0430\u0430\u0441 %s \u0446\u0430\u0433\u0430\u0430\u0440 \u0445\u043e\u0446\u043e\u0440\u0447 \u0431\u0430\u0439\u043d\u0430" ], + "November": "11-\u0440 \u0441\u0430\u0440", "Now": "\u041e\u0434\u043e\u043e", "Numbered list": "\u0414\u0443\u0433\u0430\u0430\u0440\u043b\u0430\u0441\u0430\u043d \u0436\u0430\u0433\u0441\u0430\u0430\u043b\u0442", "OK": "\u041e\u041a", + "October": "10-\u0440 \u0441\u0430\u0440", "Ok": "\u0422\u0438\u0439\u043c", "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u0417\u04e9\u0432\u0445\u04e9\u043d <%= fileTypes %> \u0444\u0430\u0439\u043b\u0443\u0443\u0434 \u043e\u0440\u0443\u0443\u043b\u0430\u0445 \u0431\u043e\u043b\u043e\u043c\u0436\u0442\u043e\u0439. <%= fileExtensions %> \u04e9\u0440\u0433\u04e9\u043b\u0442\u044d\u0439 \u0444\u0430\u0439\u043b \u043e\u0440\u0443\u0443\u043b\u043d\u0430 \u0443\u0443.", "Open Calculator": "\u0422\u043e\u043e\u043d\u044b \u043c\u0430\u0448\u0438\u043d \u043d\u044d\u044d\u0445 ", @@ -337,6 +348,7 @@ "Select language": "\u0425\u044d\u043b\u0438\u0439\u0433 \u0441\u043e\u043d\u0433\u043e\u0445", "Select turnaround": "\u04e8\u04e9\u0440\u0447\u043b\u04e9\u043b\u0442\u0438\u0439\u0433 \u0441\u043e\u043d\u0433\u043e", "Send to:": "\u0425\u0430\u0430\u0448\u0430\u0430 \u044f\u0432\u0443\u0443\u043b\u0430\u0445: ", + "September": "9-\u0440 \u0441\u0430\u0440", "Set up your certificate": "\u04e8\u04e9\u0440\u0438\u0439\u043d \u0433\u044d\u0440\u0447\u0438\u043b\u0433\u044d\u044d\u043d\u0438\u0439 \u0442\u043e\u0445\u0438\u0440\u0433\u043e\u043e", "Settings": "\u0422\u043e\u0445\u0438\u0440\u0433\u043e\u043e", "Settings updated": "\u0422\u043e\u0445\u0438\u0440\u0443\u0443\u043b\u0433\u0430 \u0448\u0438\u043d\u044d\u0447\u043b\u044d\u0433\u0434\u043b\u044d\u044d", @@ -476,6 +488,13 @@ "enter code here": "\u041a\u043e\u0434\u043e\u043e \u044d\u043d\u0434 \u043e\u0440\u0443\u0443\u043b\u043d\u0430 \u0443\u0443", "incorrect": "\u0411\u0443\u0440\u0443\u0443", "name": "\u041d\u044d\u0440", + "one letter Friday\u0004F": "\u0411\u0430", + "one letter Monday\u0004M": "\u0414", + "one letter Saturday\u0004S": "\u0411\u044f", + "one letter Sunday\u0004S": "\u041d", + "one letter Thursday\u0004T": "\u041f", + "one letter Tuesday\u0004T": "\u041c", + "one letter Wednesday\u0004W": "\u041b", "or": "\u044d\u0441\u0432\u044d\u043b", "section": "\u0445\u044d\u0441\u044d\u0433", "subsection": "\u0434\u044d\u0434 \u0445\u044d\u0441\u044d\u0433", @@ -507,7 +526,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -571,9 +590,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/mr/djangojs.js b/lms/static/js/i18n/mr/djangojs.js index 09ab0ad1017c413c3bafcb7fa641bef68644a979..f099ebfc1d7e1fb0cc02eda8cbc11276c49368c9 100644 --- a/lms/static/js/i18n/mr/djangojs.js +++ b/lms/static/js/i18n/mr/djangojs.js @@ -35,7 +35,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -99,9 +99,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/ms/djangojs.js b/lms/static/js/i18n/ms/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/lms/static/js/i18n/ms/djangojs.js +++ b/lms/static/js/i18n/ms/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/nb/djangojs.js b/lms/static/js/i18n/nb/djangojs.js index 85bcd2bf9bf715004dfa8396d7e18825433ec9e3..0efb343e44d338310e543dbc2304443493155b68 100644 --- a/lms/static/js/i18n/nb/djangojs.js +++ b/lms/static/js/i18n/nb/djangojs.js @@ -229,7 +229,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -285,9 +285,9 @@ "%d.%m.%y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/ne/djangojs.js b/lms/static/js/i18n/ne/djangojs.js index a048ff9f0979cbeed8d2b2ec70e4a81d78cf39f7..ca9b2ddb2a40fd798ac27ecb3ff1ecd3543febb7 100644 --- a/lms/static/js/i18n/ne/djangojs.js +++ b/lms/static/js/i18n/ne/djangojs.js @@ -82,7 +82,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -146,9 +146,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/nl-nl/djangojs.js b/lms/static/js/i18n/nl-nl/djangojs.js index c8a75c6f7ea672a2e2d9ae0a81ae72a6bfb69cca..5cb72ceef2991047703bd28b29cc5ebcce43501e 100644 --- a/lms/static/js/i18n/nl-nl/djangojs.js +++ b/lms/static/js/i18n/nl-nl/djangojs.js @@ -34,7 +34,7 @@ "Choose a Date": "Kies een datum", "Choose a Time": "Kies een tijdstip", "Choose a time": "Kies een tijd", - "Choose all": "Kies alle", + "Choose all": "Alle kiezen", "Chosen %s": "Gekozen %s", "Click to choose all %s at once.": "Klik om alle %s te kiezen.", "Click to remove all chosen %s at once.": "Klik om alle gekozen %s tegelijk te verwijderen.", @@ -50,12 +50,12 @@ "Midnight": "Middernacht", "Noon": "12 uur 's middags", "Note: You are %s hour ahead of server time.": [ - "Let op: U ligt %s uur voor ten opzichte van de server-tijd.", - "Let op: U ligt %s uren voor ten opzichte van de server-tijd." + "Let op: u ligt %s uur voor ten opzichte van de servertijd.", + "Let op: u ligt %s uur voor ten opzichte van de servertijd." ], "Note: You are %s hour behind server time.": [ - "Let op: U ligt %s uur achter ten opzichte van de server-tijd.", - "Let op: U ligt %s uren achter ten opzichte van de server-tijd." + "Let op: u ligt %s uur achter ten opzichte van de servertijd.", + "Let op: u ligt %s uur achter ten opzichte van de servertijd." ], "November": "november", "Now": "Nu", @@ -64,15 +64,15 @@ "Remove all": "Verwijder alles", "September": "september", "Show": "Tonen", - "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "Dit is de lijst met beschikbare %s. U kunt kiezen uit een aantal door ze te selecteren in het vak hieronder en vervolgens op de \"Kiezen\" pijl tussen de twee lijsten te klikken.", - "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "Dit is de lijst van de gekozen %s. Je kunt ze verwijderen door ze te selecteren in het vak hieronder en vervolgens op de \"Verwijderen\" pijl tussen de twee lijsten te klikken.", + "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "Dit is de lijst met beschikbare %s. U kunt er een aantal kiezen door ze in het vak hieronder te selecteren en daarna op de pijl 'Kiezen' tussen de twee vakken te klikken.", + "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "Dit is de lijst met gekozen %s. U kunt er een aantal verwijderen door ze in het vak hieronder te selecteren en daarna op de pijl 'Verwijderen' tussen de twee vakken te klikken.", "Today": "Vandaag", "Tomorrow": "Morgen", - "Type into this box to filter down the list of available %s.": "Type in dit vak om te filteren in de lijst met beschikbare %s.", + "Type into this box to filter down the list of available %s.": "Typ in dit vak om de lijst met beschikbare %s te filteren.", "Yesterday": "Gisteren", - "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "U heeft een actie geselecteerd en heeft geen wijzigingen gemaakt op de individuele velden. U zoekt waarschijnlijk naar de Gaan knop in plaats van de Opslaan knop.", - "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "U heeft een actie geselecteerd, maar heeft de wijzigingen op de individuele velden nog niet opgeslagen. Klik alstublieft op OK om op te slaan. U zult vervolgens de actie opnieuw moeten uitvoeren.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "U heeft niet opgeslagen wijzigingen op enkele indviduele velden. Als u nu een actie uitvoert zullen uw wijzigingen verloren gaan.", + "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "U hebt een actie geselecteerd, en geen wijzigingen in afzonderlijke velden aangebracht. Waarschijnlijk zoekt u de knop Gaan in plaats van de knop Opslaan.", + "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "U hebt een actie geselecteerd, maar uw wijzigingen in afzonderlijke velden nog niet opgeslagen. Klik op OK om op te slaan. U dient de actie opnieuw uit te voeren.", + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "U hebt niet-opgeslagen wijzigingen op afzonderlijke bewerkbare velden. Als u een actie uitvoert, gaan uw wijzigingen verloren.", "one letter Friday\u0004F": "F", "one letter Monday\u0004M": "M", "one letter Saturday\u0004S": "S", @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -183,9 +183,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j-n-Y H:i", "SHORT_DATE_FORMAT": "j-n-Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/or/djangojs.js b/lms/static/js/i18n/or/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/lms/static/js/i18n/or/djangojs.js +++ b/lms/static/js/i18n/or/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/pl/djangojs.js b/lms/static/js/i18n/pl/djangojs.js index 6ad335b42757b3cdfa5c96c16d6e8adfdb2bf361..3589c6a19059c880eb229354b634d67c7419e993 100644 --- a/lms/static/js/i18n/pl/djangojs.js +++ b/lms/static/js/i18n/pl/djangojs.js @@ -46,10 +46,10 @@ "%(new_item_message)s": "%(new_item_message)s", "%(programName)s Home Page.": "Strona g\u0142\u00f3wna programu %(programName)s.", "%(sel)s of %(cnt)s selected": [ - "Zaznaczono %(sel)s z %(cnt)s", - "Zaznaczono %(sel)s z %(cnt)s", - "Zaznaczono %(sel)s z %(cnt)s", - "Zaznaczono %(sel)s z %(cnt)s" + "Wybrano %(sel)s z %(cnt)s", + "Wybrano %(sel)s z %(cnt)s", + "Wybrano %(sel)s z %(cnt)s", + "Wybrano %(sel)s z %(cnt)s" ], "%(type)s Component Template Menu": "%(type)s menu szablon\u00f3w elementu", "(Add signatories for a certificate)": "(Dodaj sygnatariuszy certyfikatu)", @@ -402,7 +402,6 @@ "Default (Local Time Zone)": "Domy\u015blna (lokalna strefa czasowa)", "Default Timed Transcript": "Domy\u015blna transkrypcja", "Delete": "Usu\u0144", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "Usun\u0105\u0107 \"<%= signatoryName %>\" z listy sygnatariuszy?", "Delete File Confirmation": "Potwierdzenie usuni\u0119cia pliku", "Delete Team": "Usu\u0144 zesp\u00f3\u0142", "Delete student '<%- student_id %>'s state on problem '<%- problem_id %>'?": "Czy usun\u0105\u0107 stan studenta '<%- student_id %>' dla \u0107wiczenia '<%- problem_id %>'?", @@ -428,7 +427,6 @@ "Do you want to replace the edX transcript with the YouTube transcript?": "Czy chcesz podmieni\u0107 bie\u017c\u0105c\u0105 transkrypcj\u0119 na nowsz\u0105 transkrypcj\u0119 z YouTube?", "Do you want to upload your file before submitting?": "Czy chcesz wgra\u0107 sw\u00f3j plik przed wys\u0142aniem odpowiedzi?", "Does the name on your ID match your account name: %(fullName)s?": "Czy imi\u0119 i nazwisko na dokumencie zgadzaj\u0105 si\u0119 z danymi konta: %(fullName)s?", - "Does the photo of you match your ID photo?": "Czy zdj\u0119cie twojej twarzy odpowiada temu z dokumentu to\u017csamo\u015bci?", "Does the photo of you show your whole face?": "Czy na zdj\u0119ciu wida\u0107 ca\u0142\u0105 twoj\u0105 twarz?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Nie widzisz swojego zdj\u0119cia? Upewnij si\u0119, \u017ce zezwalasz swojej przegl\u0105darce na u\u017cycie kamerki, gdy pojawia si\u0119 pro\u015bba o zgod\u0119.", "Donate": "Przeka\u017c darowizn\u0119", @@ -564,7 +562,6 @@ "Files must be in JPEG or PNG format.": "Pliki musz\u0105 by\u0107 w formacie JPEG lub PNG.", "Filter": "Filtr", "Filter and sort topics": "Filtruj i sortuj tematy", - "Final Grade": "Ocena ko\u0144cowa", "Final Grade Received": "Uzyskana ocena ko\u0144cowa", "Financial Assistance": "Wsparcie finansowe", "Financial Assistance Application": "Program wsparcia finansowego", @@ -584,7 +581,6 @@ "Generate": "Wygeneruj", "Generate Exception Certificates": "Wygeneruj certyfikaty w wyj\u0105tku", "Generate the user's certificate": "Wygeneruj certyfikat studenta", - "Get Credit": "Odbierz punkty", "Go to Dashboard": "Przejd\u017a do pulpitu", "Go to your Dashboard": "Przejd\u017a do swojego pulpitu", "Going forward, your account information will be updated and maintained by {enterprise_name}.": "Informacje na temat Twojego konta b\u0119d\u0105 aktualizowane i zarz\u0105dzane przez {enterprise_name}.", @@ -633,7 +629,6 @@ "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "Je\u015bli ten ekran zosta\u0142 wcze\u015bniej opublikowany i upubliczniony dla student\u00f3w, wszystkie zmiany, jakich dokona\u0142e\u015b kiedy ekran by\u0142 ukryty, b\u0119d\u0105 teraz widoczne dla student\u00f3w.", "If you do not yet have an account, use the button below to register.": "Je\u015bli nie posiadasz konta, u\u017cyj poni\u017cszego przycisku, aby si\u0119 zarejestrowa\u0107.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "Je\u015bli nie potwierdzisz swojej to\u017csamo\u015bci ju\u017c teraz, wci\u0105\u017c mo\u017cesz uczestniczy\u0107 w kursie z poziomu pulpitu studenta. B\u0119dziesz otrzymywa\u0107 cykliczne powiadomienia od %(platformName)s z pro\u015bb\u0105 o poddanie si\u0119 weryfikacji to\u017csamo\u015bci.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "Je\u015bli nie potwierdzisz swojej to\u017csamo\u015bci ju\u017c teraz, wci\u0105\u017c mo\u017cesz uczestniczy\u0107 w kursie z poziomu pulpitu studenta. B\u0119dziesz otrzymywa\u0107 cykliczne powiadomienia od {platformName} z pro\u015bb\u0105 o poddanie si\u0119 weryfikacji to\u017csamo\u015bci.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "Je\u017celi opu\u015bcisz t\u0119 stron\u0119 bez zapisania lub przes\u0142ania swojej odpowiedzi, stracisz ca\u0142\u0105 swoj\u0105 prac\u0119.", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "Je\u017celi opu\u015bcisz t\u0119 stron\u0119 bez przes\u0142ania zadania do oceny, stracisz ca\u0142\u0105 swoj\u0105 prac\u0119.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "Je\u017celi opu\u015bcisz t\u0119 stron\u0119 bez przes\u0142ania swojego zadania, stracisz ca\u0142\u0105 swoj\u0105 prac\u0119.", @@ -1184,7 +1179,6 @@ "Terms of Service and Honor Code": "Warunki korzystania z Serwisu oraz Kodeks Honorowy", "Textbook Name": "Nazwa podr\u0119cznika", "Textbook information": "Informacje o podr\u0119czniku", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "Dzi\u0119kujemy, %(full_name)s! Otrzymali\u015bmy twoj\u0105 op\u0142at\u0119 za %(course_name)s.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "Dzi\u0119kujemy za twoje zg\u0142oszenie do wsparcia finansowego dla kursu {course_name}. Mo\u017cesz spodziewa\u0107 si\u0119 odpowiedzi w ci\u0105gu 2-4 dni roboczych.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Dzi\u0119kujemy za przes\u0142anie twoich zdj\u0119\u0107. Wkr\u00f3tce dokonamy ich sprawdzenia. Mo\u017cesz si\u0119 teraz zapisa\u0107 na dowolny kurs w %(platformName)s, kt\u00f3ry oferuje potwierdzone certyfikaty. Weryfikacja to\u017csamo\u015bci jest wa\u017cna przez okres jednego roku. Po tym okresie konieczne b\u0119dzie ponowne przes\u0142anie zdj\u0119\u0107 do cel\u00f3w potwierdzenia to\u017csamo\u015bci.", "Thank you! We have received your payment for {courseName}.": "Dzi\u0119kujemy! Otrzymali\u015bmy twoj\u0105 op\u0142at\u0119 za kurs {courseName}.", @@ -1194,8 +1188,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Certyfikat tego studenta zosta\u0142 ponownie zatwierdzony, a uzyskana ocena przywr\u00f3cona.", "The cohort cannot be added": "Kohorta nie mo\u017ce zosta\u0107 dodana", "The cohort cannot be saved": "Kohorta nie mo\u017ce zosta\u0107 zapisana", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u0141\u0105czna d\u0142ugo\u015b\u0107 p\u00f3l nazwy organizacji i kodu biblioteki nie mo\u017ce przekroczy\u0107 <%=limit%> znak\u00f3w.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u0141\u0105czna d\u0142ugo\u015b\u0107 nazwy organizacji, numeru kursu i edycji kursu nie mo\u017ce przekroczy\u0107 <%=limit%> znak\u00f3w.", "The country or region where you live.": "Kraj lub region w kt\u00f3rym mieszkasz.", "The country that team members primarily identify with.": "G\u0142\u00f3wny region, z kt\u00f3rym identyfikuj\u0105 si\u0119 cz\u0142onkowie zespo\u0142u.", "The course end date must be later than the course start date.": "Data zako\u0144czenia kursu musi by\u0107 p\u00f3\u017aniejsza od daty rozpocz\u0119cia.", @@ -1211,7 +1203,6 @@ "The following email addresses and/or usernames are invalid:": "Nast\u0119puj\u0105ce adresy e-mail i/lub nazwy u\u017cytkownika s\u0105 nieprawid\u0142owe:", "The following errors were generated:": "Wyst\u0105pi\u0142y nast\u0119puj\u0105ce b\u0142\u0119dy:", "The following file types are not allowed: ": "Nast\u0119puj\u0105ce typy plik\u00f3w s\u0105 niedozwolone:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "Poni\u017csze informacje s\u0105 cz\u0119\u015bci\u0105 twojego profilu w {platform}. Za\u0142\u0105czyli\u015bmy je jako element twojego zg\u0142oszenia.", "The following message will be displayed at the bottom of the courseware pages within your course:": "Nast\u0119puj\u0105ca wiadomo\u015b\u0107 b\u0119dzie wy\u015bwietlana w dolnej cz\u0119\u015bci stron twojego kursu:", "The following options are available for the {license_name} license.": "Nast\u0119puj\u0105ce opcje s\u0105 dost\u0119pne dla licencji {license_name}.", "The following users are no longer enrolled in the course:": "Nast\u0119puj\u0105cy u\u017cytkownicy nie s\u0105 ju\u017c zapisani na kurs:", @@ -1228,7 +1219,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Liczba lekcji kursu zawieraj\u0105cych \u0107wiczenia wykorzystuj\u0105ce tego typu zadanie.", "The organization that this signatory belongs to, as it should appear on certificates.": "Organizacja, do kt\u00f3rej nale\u017cy sygnatariusz, zapisana w takiej formie, w jakiem ma si\u0119 znale\u017a\u0107 na certyfikatach.", "The page \"{route}\" could not be found.": "Nie uda\u0142o si\u0119 odnale\u017a\u0107 strony \"{route}\".", - "The photo of your face matches the photo on your ID.": "Zdj\u0119cie twojej twarzy odpowiada temu z dokumentu to\u017csamo\u015bci.", "The post you selected has been deleted.": "Wybrany przez ciebie wpis zosta\u0142 usuni\u0119ty.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "Opublikowana wersja ga\u0142\u0119zi {published} zosta\u0142a zresetowana do wersji roboczej ga\u0142\u0119zi {draft}.", "The raw error message is:": "Surowy komunikat b\u0142\u0119du:", @@ -1350,7 +1340,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "Aby upewni\u0107 si\u0119, \u017ce wszyscy studenci b\u0119d\u0105 mogli odtworzy\u0107 film, zalecamy dostarczenie wersji filmu w formatach .mp4 jak i .webm. Kliknij poni\u017cej, aby doda\u0107 odno\u015bnik do kolejnej wersji. Odno\u015bnik nie mo\u017ce prowadzi\u0107 do Youtube. Studentowi odtworzony zostanie pierwszy film kompatybilny z jego komputerem.", "To complete the program, you must earn a verified certificate for each course.": "Aby uko\u0144czy\u0107 program, musisz uzyska\u0107 potwierdzony certyfikat z ka\u017cdego kursu.", "To continue learning with this account, sign in below.": "Aby kontynuowa\u0107 nauk\u0119 za po\u015brednictwem tego konta, zaloguj si\u0119.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "W celu sfinalizowania procesu przyznawania punkt\u00f3w edukacyjnych, %(display_name)s wymaga od student\u00f3w %(platform_name)s przes\u0142ania zg\u0142oszenia \u017c\u0105dania przyznania punkt\u00f3w.", "To invalidate a certificate for a particular learner, add the username or email address below.": "W celu uniewa\u017cnienia certyfikatu dla okre\u015blonego studenta, wprowad\u017a poni\u017cej jego nazw\u0119 u\u017cytkownika lub adres e-mail.", "To receive a certificate, you must also verify your identity before {date}.": "Aby otrzyma\u0107 certyfikat, musisz r\u00f3wnie\u017c potwierdzi\u0107 swoj\u0105 to\u017csamo\u015b\u0107 przed {date}.", "To receive a certificate, you must also verify your identity.": "Aby otrzyma\u0107 certyfikat, musisz r\u00f3wnie\u017c potwierdzi\u0107 swoj\u0105 to\u017csamo\u015b\u0107.", @@ -1446,7 +1435,6 @@ "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "U\u017cywaj \u015bcie\u017cek kursu jako podstawy do dzielenia dyskusji. Wszyscy studenci, niezale\u017cnie od ich \u015bcie\u017cki, widz\u0105 te same tematy dyskusji, natomiast wpisy wewn\u0105trz podzielonych dyskusji widz\u0105 wy\u0142\u0105cznie studenci b\u0119d\u0105cy na tych samych \u015bcie\u017ckach kursu.", "Use my institution/campus credentials": "U\u017cyj danych do logowania z mojej uczelni", "Use the All Topics menu to find specific topics.": "U\u017cyj menu \"Wszystkie tematy\", aby znale\u017a\u0107 okre\u015blone tematy.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "U\u017cyj kamerki internetowej, aby zrobi\u0107 zdj\u0119cie swojego dokumentu to\u017csamo\u015bci. Por\u00f3wnamy to zdj\u0119cie ze zdj\u0119ciem twojej twarzy oraz zweryfikujemy dane osobowe.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "U\u017cyj kamerki internetowej, aby zrobi\u0107 zdj\u0119cie swojej twarzy. Por\u00f3wnamy to zdj\u0119cie ze zdj\u0119ciem w twoim dokumencie to\u017csamo\u015bci.", "Used": "Wykorzystany", "Used in {count} location": [ @@ -1470,7 +1458,6 @@ "Verified Certificate upgrade": "Zg\u0142oszenie do potwierdzonego certyfikatu", "Verified Status": "Status potwierdzony", "Verified mode price": "Cena trybu potwierdzonego", - "Verify Now": "Potwierd\u017a teraz", "Video Capture Error": "B\u0142\u0105d przechwytywania obrazu wideo", "Video ID": "Identyfikator filmu", "Video Source Language": "Oryginalny j\u0119zyk filmu", @@ -1502,7 +1489,6 @@ "We couldn't find any results for \"%s\".": "Nie uda\u0142o si\u0119 znale\u017a\u0107 \u017cadnych wynik\u00f3w dla \"%s\".", "We couldn't sign you in.": "Logowanie nie powiod\u0142o si\u0119.", "We have encountered an error. Refresh your browser and then try again.": "Napotkali\u015bmy b\u0142\u0105d. Od\u015bwie\u017c przegl\u0105dark\u0119 i spr\u00f3buj jeszcze raz.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Otrzymali\u015bmy twoje dane i sprawdzimy je by potwierdzi\u0107 twoj\u0105 to\u017csamo\u015b\u0107. Na swoim pulpicie studenta znajdziesz wiadomo\u015b\u0107 gdy proces weryfikacyjny zostanie zako\u0144czony (zwykle w ci\u0105gu 1-2 dni). W mi\u0119dzyczasie mo\u017cesz bez przeszk\u00f3d korzysta\u0107 ze wszystkich materia\u0142\u00f3w kursowych.", "We just need a little more information before you start learning with %(platformName)s.": "Potrzebujemy jeszcze nieco informacji zanim b\u0119dziesz m\u00f3g\u0142 rozpocz\u0105\u0107 nauk\u0119 w %(platformName)s.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "U\u017cywamy najwy\u017cszych dost\u0119pnych poziom\u00f3w bezpiecze\u0144stwa w celu szyfrowania zdj\u0119\u0107 i przesy\u0142ania ich do sprawdzenia. Po zako\u0144czeniu czynno\u015bci weryfikacyjnych, twoje zdj\u0119cia i dane z dokumentu nie s\u0105 zapisywane ani widoczne gdziekolwiek na \u0142amach %(platformName)s.", "We've encountered an error. Refresh your browser and then try again.": "Napotkali\u015bmy b\u0142\u0105d. Od\u015bwie\u017c przegl\u0105dark\u0119 i spr\u00f3buj ponownie.", @@ -1582,12 +1568,9 @@ "You must sign out and sign back in before your language changes take effect.": "Musisz si\u0119 wylogowa\u0107 i ponownie zalogowa\u0107, aby zmiany j\u0119zykowe zacz\u0119\u0142y obowi\u0105zywa\u0107.", "You must specify a name for the cohort": "Musisz okre\u015bli\u0107 nazw\u0119 tej kohorty", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "Przed udost\u0119pnieniem swojego pe\u0142nego profilu musisz poda\u0107 rok urodzenia. Aby wskaza\u0107 sw\u00f3j rok urodzenia, odwied\u017a {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Potrzebujesz dowodu osobistego, paszportu lub innego oficjalnego dokumentu to\u017csamo\u015bci ze zdj\u0119ciem i twoim nazwiskiem.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Potrzebujesz dokumentu to\u017csamo\u015bci ze zdj\u0119ciem i danymi osobowymi. Zaakceptujemy dow\u00f3d osobisty, paszport, prawo jazdy lub inny oficjalny dokument.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Aby m\u00f3c zarejestrowa\u0107 si\u0119 na kursy, musisz najpierw aktywowa\u0107 swoje konto. Sprawd\u017a poczt\u0119 i odnajd\u017a e-mail z odno\u015bnikiem aktywacyjnym.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Przed zapisaniem si\u0119 na pierwszy kurs musisz aktywowa\u0107 swoje konto. Sprawd\u017a poczt\u0119 e-mail i znajd\u017a wiadomo\u015b\u0107 z instrukcj\u0105 aktywacji. Po jej dokonaniu wr\u00f3\u0107 i od\u015bwie\u017c t\u0119 stron\u0119.", "You receive messages from {platform_name} and course teams at this address.": "Na ten adres otrzymujesz wiadomo\u015bci z {platform_name} i od prowadz\u0105cych kursy.", - "You still need to visit the %(display_name)s website to complete the credit process.": "Wci\u0105\u017c musisz odwiedzi\u0107 stron\u0119 %(display_name)s w celu dope\u0142nienia formalno\u015bci zwi\u0105zanych z przyznaniem punkt\u00f3w edukacyjnych.", "You will be refunded the amount you paid.": "Zap\u0142acona kwota zostanie zwr\u00f3cona.", "You will not be refunded the amount you paid.": "Zap\u0142acona kwota nie zostanie zwr\u00f3cona.", "You will not receive notification for emails that bounce, so double-check your spelling.": "Nie otrzymasz powiadomie\u0144 na nieprawid\u0142owe adresy e-mail, dlatego raz jeszcze sprawd\u017a poprawno\u015b\u0107.", @@ -1658,7 +1641,6 @@ "enter code here": "Wprowad\u017a kod", "enter link description here": "Wprowad\u017a opis linku", "for": "za", - "for {courseName}": "z kursu {courseName}", "group configuration": "konfiguracja grupy", "image omitted": "pomini\u0119ty obrazek", "last activity": "ostatnia aktywno\u015b\u0107", @@ -1792,7 +1774,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1845,9 +1827,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", - "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "FIRST_DAY_OF_WEEK": 1, + "MONTH_DAY_FORMAT": "j E", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d-m-Y H:i", "SHORT_DATE_FORMAT": "d-m-Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/pt-br/djangojs.js b/lms/static/js/i18n/pt-br/djangojs.js index 22d490dbf52d6b6e47ef7f7c129246968665c98b..9b02020d582e51d0b8664033c1ed6be7ee7f878d 100644 --- a/lms/static/js/i18n/pt-br/djangojs.js +++ b/lms/static/js/i18n/pt-br/djangojs.js @@ -258,7 +258,6 @@ "December": "Dezembro", "Default Timed Transcript": "Transcri\u00e7\u00e3o Sincronizada Padr\u00e3o", "Delete": "Apagar", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "Apagar \"<%= signatoryName %>\" da lista de emissores?", "Delete File Confirmation": "Confirma\u00e7\u00e3o da exclus\u00e3o do arquivo", "Delete Team": "Apagar equipe.", "Delete student '<%- student_id %>'s state on problem '<%- problem_id %>'?": "Excluir status do aluno '<%- student_id %>' para o problema '<%- problem_id %>'?", @@ -277,7 +276,6 @@ "Do you want to replace the edX transcript with the YouTube transcript?": "Voc\u00ea quer substituir a transcri\u00e7\u00e3o do edX pela do YouTube?", "Do you want to upload your file before submitting?": "Voc\u00ea deseja fazer upload de seu arquivo antes de enviar?", "Does the name on your ID match your account name: %(fullName)s?": "O nome de sua identifica\u00e7\u00e3o correspondo ao nome de sua conta: %(fullName)s?", - "Does the photo of you match your ID photo?": "A foto a seguir \u00e9 a mesma foto de sua identidade?", "Does the photo of you show your whole face?": "A sua foto escolhida exibe todo o seu rosto?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "N\u00e3o v\u00ea sua fotografia? Certifique-se de permitir que o seu navegador utilize a c\u00e2mera quando ele pedir permiss\u00e3o.", "Donate": "Doar", @@ -385,7 +383,6 @@ "Generate": "Emitir", "Generate Exception Certificates": "Gerar certificados de exce\u00e7\u00e3o", "Generate the user's certificate": "Emitir certificado do usu\u00e1rio", - "Get Credit": "Obter Cr\u00e9dito", "Go to Dashboard": "Ir para a P\u00e1gina Inicial", "Go to your Dashboard": "Ir para o seu Painel de controle", "Government-Issued Photo ID": "Foto de um documento de identidade oficial", @@ -772,8 +769,6 @@ "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Obrigado por enviar suas fotos. N\u00f3s vamos analis\u00e1-las rapidamente. Voc\u00ea pode inscrever-se para qualquer curso da plataforma %(platformName)s que ofere\u00e7a certificados verificados. A verifica\u00e7\u00e3o \u00e9 v\u00e1lida por um ano. Depois disso, voc\u00ea precisa enviar fotos para verificar novamente.", "The cohort cannot be added": "O grupo n\u00e3o pode ser adicionado", "The cohort cannot be saved": "O grupo n\u00e3o p\u00f4de ser salvo", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "Os campos comprimento combinando da Organiza\u00e7\u00e3o e c\u00f3digo da biblioteca n\u00e3o podem ultrapassar <%=limit%> caracteres. ", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "Os campos comprimento total da Organiza\u00e7\u00e3o, n\u00famero do curso e funcionamento do curso n\u00e3o podem exceder <%=limit%> caracteres. ", "The country that team members primarily identify with.": "O pa\u00eds com o qual os membros da equipe se identificam.", "The course end date must be later than the course start date.": "A data do final do curso deve ser posterior \u00e0 data de in\u00edcio da matr\u00edcula. ", "The course must have an assigned start date.": "O curso deve ter uma data de in\u00edcio designada.", @@ -787,7 +782,6 @@ "The following email addresses and/or usernames are invalid:": "Os seguintes endere\u00e7os de email e/ou nomes de usu\u00e1rio s\u00e3o inv\u00e1lidos:", "The following errors were generated:": "Os seguintes erros foram gerados:", "The following file types are not allowed: ": "Os seguintes tipos de arquivos n\u00e3o s\u00e3o permitidos:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "As informa\u00e7\u00f5es a seguir j\u00e1 fazem parte do seu perfil {platform}. N\u00f3s as inclu\u00edmos aqui para seu pedido.", "The following message will be displayed at the bottom of the courseware pages within your course:": "A mensagem a seguir ser\u00e1 exibida na parte inferior das p\u00e1ginas do seu curso:", "The following options are available for the {license_name} license.": "As seguintes op\u00e7\u00f5es est\u00e3o dispon\u00edveis para a licen\u00e7a {license_name}.", "The following users are no longer enrolled in the course:": "Os seguintes usu\u00e1rios n\u00e3o est\u00e3o mais inscritos no curso:", @@ -796,7 +790,6 @@ "The minimum grade for course credit is not set.": "A nota m\u00ednima para obter cr\u00e9ditos para o curso n\u00e3o est\u00e1 especificada.", "The name of this signatory as it should appear on certificates.": "O nome deste signat\u00e1rio conforme deve aparecer nos certificados.", "The organization that this signatory belongs to, as it should appear on certificates.": "A organiza\u00e7\u00e3o a qual este signat\u00e1rio pertence, conforme deve aparecer nos certificados.", - "The photo of your face matches the photo on your ID.": "A foto do seu rosto corresponde \u00e0 foto no seu documento.", "The raw error message is:": "A mensagem bruta de erro \u00e9:", "The selected content group does not exist": "O grupo de conte\u00fado selecionado n\u00e3o existe", "The server could not be contacted.": "N\u00e3o foi poss\u00edvel contactar o servidor.", @@ -860,7 +853,6 @@ "Title of the signatory": "T\u00edtulo da assinatura", "Titles more than 100 characters may prevent students from printing their certificate on a single page.": "T\u00edtulos com mais de 100 caracteres podem impedir que os estudantes imprimam seu certificado em uma \u00fanica p\u00e1gina.", "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "Para garantir que todos os estudantes poder\u00e3o acessar o video, n\u00f3s recomendamos providenciar vers\u00f5es em .mp4 e .webm do video. Clique abaixo para adicionar um URL para outra vers\u00e3o. Esses URLs n\u00e3o podem ser do YouTube. O primeiro v\u00eddeo que for compat\u00edvel com o computador dos alunos ser\u00e1 exibido.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "Para finalizar os cr\u00e9ditos do curso, %(display_name)s exige que os alunos %(platform_name)s enviem uma solicita\u00e7\u00e3o de cr\u00e9ditos. ", "To invalidate a certificate for a particular learner, add the username or email address below.": "Para invalidar um certificado para um aluno em particular, adicionar o nome do usu\u00e1rio ou endere\u00e7o de e-mail abaixo", "To receive a certificate, you must also verify your identity.": "Para receber um certificado, voc\u00ea tamb\u00e9m deve verificar a sua identidade.", "To take a successful photo, make sure that:": "Para tirar uma foto corretamente, certifique-se que:", @@ -917,7 +909,6 @@ "Use a practice proctored exam to introduce learners to the proctoring tools and processes. Results of a practice exam do not affect a learner's grade.": "Usar uma prova supervisionada pr\u00e1tica para apresentar aos alunos as ferramentas e processos de supervis\u00e3o. Os resultados de prova pr\u00e1tica n\u00e3o afetam a nota dos alunos", "Use a timed exam to limit the time learners can spend on problems in this subsection. Learners must submit answers before the time expires. You can allow additional time for individual learners through the Instructor Dashboard.": "Use uma prova cronometrada para limitar o tempo que os alunos podem gastar nos problemas nesta subse\u00e7\u00e3o. Os alunos devem enviar as respostas antes que o tempo acabe. Voc\u00ea pode permitir um tempo adicional para alunos individuais atrav\u00e9s do Painel do Instrutor.", "Use my institution/campus credentials": "Entrar com credenciais de Institui\u00e7\u00e3o/Campus", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Use a webcam para tirar uma foto do seu documento. N\u00f3s vamos conferir esta foto com a foto do seu rosto e o nome na sua conta.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Use a webcam para tirar uma foto do seu rosto. N\u00f3s vamos conferir essa foto com a do seu documento de identidade.", "Used": "Usado", "User Email": "E-mail do Usu\u00e1rio", @@ -934,7 +925,6 @@ "Verified Certificate upgrade": "Atualiza\u00e7\u00e3o do certificado verificado", "Verified Status": "Status verificado", "Verified mode price": "Pre\u00e7o de modo verificado", - "Verify Now": "Verifique agora", "Video Capture Error": "Falha na captura de v\u00eddeo", "Video ID": "ID do V\u00eddeo", "View": "Visualizar", @@ -950,7 +940,6 @@ "Warning": "Aviso", "Warnings": "Avisos", "We couldn't find any results for \"%s\".": "N\u00e3o foi poss\u00edvel encontrar resultados para \"%s\".", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Recebemos as suas informa\u00e7\u00f5es e estamos verificando a sua identifica\u00e7\u00e3o. Voc\u00ea receber\u00e1 uma mensagem em seu painel de controle quando o processo de verifica\u00e7\u00e3o estiver conclu\u00eddo (normalmente entre 1-2 dias). Enquanto isso, voc\u00ea ainda pode acessar a todo o conte\u00fado do curso.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "N\u00f3s usamos os mais altos n\u00edveis de seguran\u00e7a dispon\u00edveis para encriptar sua foto e envi\u00e1-la para no servi\u00e7o de autoriza\u00e7\u00e3o para an\u00e1lise. Informa\u00e7\u00f5es sobre voc\u00ea e sua foto n\u00e3o s\u00e3o salvas ou vis\u00edveis em qualquer lugar em %(platformName)s depois que o processo de verifica\u00e7\u00e3o \u00e9 completado.", "We've encountered an error. Refresh your browser and then try again.": "Encontramos um erro. Atualize seu navegador e tente novamente.", "Web:": "Web:", @@ -1001,11 +990,8 @@ "You must provide a learner name.": "Voc\u00ea deve fornecer o nome do aluno.", "You must sign out and sign back in before your language changes take effect.": "Voc\u00ea deve sair e entrar antes que as mudan\u00e7as de idioma tenham efeito.", "You must specify a name for the cohort": "Voc\u00ea deve especificar um nome para o grupo", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Voc\u00ea precisa de uma carteira de habilita\u00e7\u00e3o, passaporte ou outra identifica\u00e7\u00e3o emitida pelo governo que possua o seu nome e foto.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Voc\u00ea precisa de um documento com o seu nome e foto. Uma carteira de motorista, passaporte ou outro documento emitido pelo governo s\u00e3o aceit\u00e1veis.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Voc\u00ea precisa ativar a sua conta antes de se matricular nos cursos. Verifique em sua caixa de entrada o e-mail de ativa\u00e7\u00e3o.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Voc\u00ea precisa ativar a sua conta antes de matricular-se nos cursos. Confira se o e-mail de ativa\u00e7\u00e3o est\u00e1 na sua caixa de entrada. Depois de completar a ativa\u00e7\u00e3o, voc\u00ea pode voltar e atualizar esta p\u00e1gina.", - "You still need to visit the %(display_name)s website to complete the credit process.": "Voc\u00ea ainda precisa visitar o site %(display_name)s para completar o processo de cr\u00e9dito.", "You will not receive notification for emails that bounce, so double-check your spelling.": "Voc\u00ea n\u00e3o receber\u00e1 notifica\u00e7\u00f5es de e-mails que n\u00e3o entregues, ent\u00e3o verifique novamente se digitou corretamente.", "You will use your webcam to take a picture of your face and of your government-issued photo ID.": "Voc\u00ea vai usar sua webcam para tirar uma foto do seu rosto e do seu documento com foto emitido pelo governo.", "You!": "Voc\u00ea!", @@ -1102,7 +1088,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1158,9 +1144,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/pt-pt/djangojs.js b/lms/static/js/i18n/pt-pt/djangojs.js index 7053973d23d04878cd2329032dd316dcc0d5cf81..e29688adc7b3484782642ac2d6cd747f0a40f87d 100644 --- a/lms/static/js/i18n/pt-pt/djangojs.js +++ b/lms/static/js/i18n/pt-pt/djangojs.js @@ -27,8 +27,10 @@ "(required):": "(obrigat\u00f3rio):", "6 a.m.": "6 a.m.", "6 p.m.": "6 p.m.", + "April": "Abril", "Assessment": "Avalia\u00e7\u00e3o", "Assessments": "Avalia\u00e7\u00f5es", + "August": "Agosto", "Available %s": "Dispon\u00edvel %s", "Back to Full List": "Voltar \u00e0 lista completa", "Block view is unavailable": "A visualiza\u00e7\u00e3o em grelha n\u00e3o est\u00e1 dispon\u00edvel", @@ -47,10 +49,12 @@ "Couldn't Save This Assignment": "N\u00e3o \u00e9 poss\u00edvel guardar esta tarefa", "Criterion Added": "Crit\u00e9rio Adicionado", "Criterion Deleted": "Crit\u00e9rio eliminado", + "December": "Dezembro", "Describe ": "Descreva", "Do you want to upload your file before submitting?": "Deseja carregar o seu ficheiro antes de submeter?", "Error": "Erro", "Error getting the number of ungraded responses": "Erro ao obter o n\u00famero de respostas sem classifica\u00e7\u00e3o", + "February": "Fevereiro", "Feedback available for selection.": "Coment\u00e1rio dispon\u00edvel para a sele\u00e7\u00e3o.", "File type is not allowed.": "O tipo de ficheiro n\u00e3o \u00e9 permitido.", "File types can not be empty.": "Indique o tipo de ficheiro. ", @@ -65,7 +69,12 @@ "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "Caso saia desta p\u00e1gina sem submeter o seu teste, ir\u00e1 perder todo o trabalho at\u00e9 aqui realizado.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "Caso saia desta p\u00e1gina sem submeter a sua auto-avalia\u00e7\u00e3o, ir\u00e1 perder todo o trabalho at\u00e9 aqui realizado.", "If you leave this page without submitting your staff assessment, you will lose any work you have done.": "Caso saia desta p\u00e1gina sem submeter a sua avalia\u00e7\u00e3o individual, ir\u00e1 perder todo o trabalho at\u00e9 aqui realizado.", + "January": "Janeiro", + "July": "Julho", + "June": "Junho", "List of Open Assessments is unavailable": "Lista de Avalia\u00e7\u00f5es Abertas n\u00e3o est\u00e1 dispon\u00edvel", + "March": "Mar\u00e7o", + "May": "Maio", "Midnight": "Meia-noite", "Noon": "Meio-dia", "Not Selected": "N\u00e3o Selecionado", @@ -77,7 +86,9 @@ "Nota: O use fuso hor\u00e1rio est\u00e1 %s hora atrasado em rela\u00e7\u00e3o ao servidor.", "Nota: O use fuso hor\u00e1rio est\u00e1 %s horas atrasado em rela\u00e7\u00e3o ao servidor." ], + "November": "Novembro", "Now": "Agora", + "October": "Outubro", "One or more rescheduling tasks failed.": "Ocorreu erro no reagendamento de uma ou mais tarefas.", "Option Deleted": "Op\u00e7\u00e3o eliminada", "Paragraph": "Par\u00e1grafo", @@ -89,6 +100,7 @@ "Remove all": "Remover todos", "Saving...": "A guardar...", "Self": "Auto", + "September": "Setembro", "Server error.": "Erro de servidor.", "Show": "Mostrar", "Staff": "Equipa", @@ -133,7 +145,14 @@ "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Tem mudan\u00e7as por guardar nos campos individuais. Se usar uma a\u00e7\u00e3o, as suas mudan\u00e7as por guardar ser\u00e3o perdidas.", "You must provide a learner name.": "Deve indicar o nome de um estudante.", "You're about to submit your response for this assignment. After you submit this response, you can't change it or submit a new response.": "Est\u00e1 prestes a submeter a sua resposta para esta tarefa. Depois de a submeter, n\u00e3o \u00e9 poss\u00edvel alter\u00e1-la ou submeter uma nova resposta.", - "Your file ": "O seu ficheiro " + "Your file ": "O seu ficheiro ", + "one letter Friday\u0004F": "S", + "one letter Monday\u0004M": "S", + "one letter Saturday\u0004S": "S", + "one letter Sunday\u0004S": "D", + "one letter Thursday\u0004T": "Q", + "one letter Tuesday\u0004T": "T", + "one letter Wednesday\u0004W": "Q" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -155,7 +174,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -211,9 +230,9 @@ "%d/%m/%y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j \\d\\e F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d/m/Y H:i", "SHORT_DATE_FORMAT": "d/m/Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/ro/djangojs.js b/lms/static/js/i18n/ro/djangojs.js index 00d4da422f1220007f5244390c0af2b53ff7f483..eefb5186216cb1ce2de6321a52942b5b6b25d287 100644 --- a/lms/static/js/i18n/ro/djangojs.js +++ b/lms/static/js/i18n/ro/djangojs.js @@ -27,6 +27,8 @@ ], "6 a.m.": "6 a.m.", "6 p.m.": "6 p.m.", + "April": "Aprilie", + "August": "August", "Available %s": "%s disponibil", "Cancel": "Anuleaz\u0103", "Choose": "Alege", @@ -39,32 +41,42 @@ "Click to remove all chosen %s at once.": "Click pentru a elimina toate %s alese.", "Could not retrieve download url.": "Nu s-a putut ob\u0163ine linkul de desc\u0103rcare.", "Could not retrieve upload url.": "Nu s-a putut ob\u0163ine linkul de \u00eenc\u0103rcare.", + "December": "Decembrie", "Error": "Eroare", + "February": "Februarie", "Filter": "Filtru", "Heading 3": "Titlu 3", "Heading 4": "Titlu 4", "Heading 5": "Titlu 5", "Heading 6": "Titlu 6", "Hide": "Ascunde", + "January": "Ianuarie", + "July": "Iulie", + "June": "Iunie", + "March": "Martie", + "May": "Mai", "Midnight": "Miezul nop\u021bii", "Noon": "Amiaz\u0103", "Note: You are %s hour ahead of server time.": [ - "Not\u0103: Sunte\u021bi cu %s ora \u00eenaintea orei serverului.", + "Not\u0103: Sunte\u021bi cu %s or\u0103 \u00eenaintea orei serverului.", "Not\u0103: Sunte\u021bi cu %s ore \u00eenaintea orei serverului.", - "Not\u0103: Sunte\u021bi cu %s ore \u00eenaintea orei serverului." + "Not\u0103: Sunte\u021bi cu %s de ore \u00eenaintea orei serverului." ], "Note: You are %s hour behind server time.": [ "Not\u0103: Sunte\u021bi cu %s or\u0103 \u00een urma orei serverului.", "Not\u0103: Sunte\u021bi cu %s ore \u00een urma orei serverului.", - "Not\u0103: Sunte\u021bi cu %s ore \u00een urma orei serverului." + "Not\u0103: Sunte\u021bi cu %s de ore \u00een urma orei serverului." ], + "November": "Noiembrie", "Now": "Acum", + "October": "Octombrie", "One or more rescheduling tasks failed.": "Una sau mai multe reprogram\u0103ri au e\u015fuat.", "Paragraph": "Paragraf", "Preformatted": "Preformatat", "Remove": "Elimin\u0103", "Remove all": "Elimin\u0103 toate", "Saving...": "Se salveaz\u0103...", + "September": "Septembrie", "Server error.": "Eroare de server.", "Show": "Arat\u0103", "Status of Your Response": "Statusul r\u0103spunsului t\u0103u", @@ -86,7 +98,14 @@ "Yesterday": "Ieri", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "A\u021bi selectat o ac\u0163iune \u0219i nu a\u021b\u0163i f\u0103cut modific\u0103ri \u00een c\u00eempuri individuale. Probabil c\u0103uta\u021bi butonul Go, \u00een loc de Salveaz\u0103.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "A\u0163i selectat o ac\u0163iune, dar nu a\u0163i salvat \u00eenc\u0103 modific\u0103rile la c\u00e2mpuri individuale. Face\u0163i clic pe OK pentru a salva. Va trebui s\u0103 executa\u021bi ac\u021biunea din nou.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Ave\u0163i modific\u0103ri nesalvate \u00een c\u00eempuri individuale editabile. Dac\u0103 executa\u0163i o ac\u021biune, modific\u0103rile nesalvate vor fi pierdute." + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Ave\u0163i modific\u0103ri nesalvate \u00een c\u00eempuri individuale editabile. Dac\u0103 executa\u0163i o ac\u021biune, modific\u0103rile nesalvate vor fi pierdute.", + "one letter Friday\u0004F": "V", + "one letter Monday\u0004M": "L", + "one letter Saturday\u0004S": "S", + "one letter Sunday\u0004S": "D", + "one letter Thursday\u0004T": "J", + "one letter Tuesday\u0004T": "M", + "one letter Wednesday\u0004W": "M" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -108,7 +127,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -144,45 +163,35 @@ django.formats = { "DATETIME_FORMAT": "j F Y, H:i", "DATETIME_INPUT_FORMATS": [ + "%d.%m.%Y, %H:%M", + "%d.%m.%Y, %H:%M:%S", + "%d.%B.%Y, %H:%M", + "%d.%B.%Y, %H:%M:%S", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", "%Y-%m-%d %H:%M", - "%Y-%m-%d", - "%m/%d/%Y %H:%M:%S", - "%m/%d/%Y %H:%M:%S.%f", - "%m/%d/%Y %H:%M", - "%m/%d/%Y", - "%m/%d/%y %H:%M:%S", - "%m/%d/%y %H:%M:%S.%f", - "%m/%d/%y %H:%M", - "%m/%d/%y" + "%Y-%m-%d" ], "DATE_FORMAT": "j F Y", "DATE_INPUT_FORMATS": [ - "%Y-%m-%d", - "%m/%d/%Y", - "%m/%d/%y", - "%b %d %Y", - "%b %d, %Y", - "%d %b %Y", - "%d %b, %Y", - "%B %d %Y", - "%B %d, %Y", + "%d.%m.%Y", + "%d.%b.%Y", "%d %B %Y", - "%d %B, %Y" + "%A, %d %B %Y", + "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y, H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": ".", "TIME_FORMAT": "H:i", "TIME_INPUT_FORMATS": [ + "%H:%M", "%H:%M:%S", - "%H:%M:%S.%f", - "%H:%M" + "%H:%M:%S.%f" ], "YEAR_MONTH_FORMAT": "F Y" }; diff --git a/lms/static/js/i18n/rtl/djangojs.js b/lms/static/js/i18n/rtl/djangojs.js index 961551da9b06a3f391453168f81bff9f67105836..a1ef603fdfcb800a0c27b90cd1178b4116f372d9 100644 --- a/lms/static/js/i18n/rtl/djangojs.js +++ b/lms/static/js/i18n/rtl/djangojs.js @@ -27,6 +27,7 @@ " \u0648\u062b\u0648\u0632\u062b\u0642\u0633" ], " and ": " \u0634\u0631\u064a ", + " as many questions may have already been answered.": " \u0634\u0633 \u0648\u0634\u0631\u063a \u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631\u0633 \u0648\u0634\u063a \u0627\u0634\u062f\u062b \u0634\u0645\u0642\u062b\u0634\u064a\u063a \u0632\u062b\u062b\u0631 \u0634\u0631\u0633\u0635\u062b\u0642\u062b\u064a.", " learner does not exist in LMS and not added to the exception list": " \u0645\u062b\u0634\u0642\u0631\u062b\u0642 \u064a\u062e\u062b\u0633 \u0631\u062e\u0641 \u062b\u0637\u0647\u0633\u0641 \u0647\u0631 \u0645\u0648\u0633 \u0634\u0631\u064a \u0631\u062e\u0641 \u0634\u064a\u064a\u062b\u064a \u0641\u062e \u0641\u0627\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0645\u0647\u0633\u0641", " learner is already white listed and not added to the exception list": " \u0645\u062b\u0634\u0642\u0631\u062b\u0642 \u0647\u0633 \u0634\u0645\u0642\u062b\u0634\u064a\u063a \u0635\u0627\u0647\u0641\u062b \u0645\u0647\u0633\u0641\u062b\u064a \u0634\u0631\u064a \u0631\u062e\u0641 \u0634\u064a\u064a\u062b\u064a \u0641\u062e \u0641\u0627\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0645\u0647\u0633\u0641", " learner is not enrolled in course and not added to the exception list": " \u0645\u062b\u0634\u0642\u0631\u062b\u0642 \u0647\u0633 \u0631\u062e\u0641 \u062b\u0631\u0642\u062e\u0645\u0645\u062b\u064a \u0647\u0631 \u0630\u062e\u0639\u0642\u0633\u062b \u0634\u0631\u064a \u0631\u062e\u0641 \u0634\u064a\u064a\u062b\u064a \u0641\u062e \u0641\u0627\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0645\u0647\u0633\u0641", @@ -39,6 +40,8 @@ " records are not in correct format and not added to the exception list": " \u0642\u062b\u0630\u062e\u0642\u064a\u0633 \u0634\u0642\u062b \u0631\u062e\u0641 \u0647\u0631 \u0630\u062e\u0642\u0642\u062b\u0630\u0641 \u0628\u062e\u0642\u0648\u0634\u0641 \u0634\u0631\u064a \u0631\u062e\u0641 \u0634\u064a\u064a\u062b\u064a \u0641\u062e \u0641\u0627\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0645\u0647\u0633\u0641", "${listPrice}": "${listPrice}", "%(cohort_name)s (%(user_count)s)": "%(cohort_name)s (%(user_count)s)", + "%(comments_count)s %(span_sr_open)scomments %(span_close)s": "%(comments_count)s %(span_sr_open)s\u0630\u062e\u0648\u0648\u062b\u0631\u0641\u0633 %(span_close)s", + "%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s unread comments)%(span_close)s": "%(comments_count)s %(span_sr_open)s\u0630\u062e\u0648\u0648\u062b\u0631\u0641\u0633 (%(unread_comments_count)s \u0639\u0631\u0642\u062b\u0634\u064a \u0630\u062e\u0648\u0648\u062b\u0631\u0641\u0633)%(span_close)s", "%(errorCount)s error found in form.": [ "%(errorCount)s \u062b\u0642\u0642\u062e\u0642 \u0628\u062e\u0639\u0631\u064a \u0647\u0631 \u0628\u062e\u0642\u0648.", "%(errorCount)s \u062b\u0642\u0642\u062e\u0642\u0633 \u0628\u062e\u0639\u0631\u064a \u0647\u0631 \u0628\u062e\u0642\u0648." @@ -80,6 +83,7 @@ "%s from now": "%s \u0628\u0642\u062e\u0648 \u0631\u062e\u0635", "(Add signatories for a certificate)": "(\u0634\u064a\u064a \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u0647\u062b\u0633 \u0628\u062e\u0642 \u0634 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b)", "(Caption will be displayed when you start playing the video.)": "(\u0630\u0634\u062d\u0641\u0647\u062e\u0631 \u0635\u0647\u0645\u0645 \u0632\u062b \u064a\u0647\u0633\u062d\u0645\u0634\u063a\u062b\u064a \u0635\u0627\u062b\u0631 \u063a\u062e\u0639 \u0633\u0641\u0634\u0642\u0641 \u062d\u0645\u0634\u063a\u0647\u0631\u0644 \u0641\u0627\u062b \u062f\u0647\u064a\u062b\u062e.)", + "(Community TA)": "(\u0630\u062e\u0648\u0648\u0639\u0631\u0647\u0641\u063a \u0641\u0634)", "(Optional)": "(\u062e\u062d\u0641\u0647\u062e\u0631\u0634\u0645)", "(Read-only)": "(\u0642\u062b\u0634\u064a-\u062e\u0631\u0645\u063a)", "(Required Field)": "(\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a \u0628\u0647\u062b\u0645\u064a)", @@ -87,6 +91,7 @@ "(Self-paced) Ends {end}": "(\u0633\u062b\u0645\u0628-\u062d\u0634\u0630\u062b\u064a) \u062b\u0631\u064a\u0633 {end}", "(Self-paced) Started {start}": "(\u0633\u062b\u0645\u0628-\u062d\u0634\u0630\u062b\u064a) \u0633\u0641\u0634\u0642\u0641\u062b\u064a {start}", "(Self-paced) Starts {start}": "(\u0633\u062b\u0645\u0628-\u062d\u0634\u0630\u062b\u064a) \u0633\u0641\u0634\u0642\u0641\u0633 {start}", + "(Staff)": "(\u0633\u0641\u0634\u0628\u0628)", "(contains %(student_count)s student)": [ "(\u0630\u062e\u0631\u0641\u0634\u0647\u0631\u0633 %(student_count)s \u0633\u0641\u0639\u064a\u062b\u0631\u0641)", "(\u0630\u062e\u0631\u0641\u0634\u0647\u0631\u0633 %(student_count)s \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633)" @@ -145,7 +150,12 @@ "Add URLs for additional versions": "\u0634\u064a\u064a \u0639\u0642\u0645\u0633 \u0628\u062e\u0642 \u0634\u064a\u064a\u0647\u0641\u0647\u062e\u0631\u0634\u0645 \u062f\u062b\u0642\u0633\u0647\u062e\u0631\u0633", "Add a Chapter": "\u0634\u064a\u064a \u0634 \u0630\u0627\u0634\u062d\u0641\u062b\u0642", "Add a New Cohort": "\u0634\u064a\u064a \u0634 \u0631\u062b\u0635 \u0630\u062e\u0627\u062e\u0642\u0641", + "Add a Post": "\u0634\u064a\u064a \u0634 \u062d\u062e\u0633\u0641", + "Add a Response": "\u0634\u064a\u064a \u0634 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b", + "Add a clear and descriptive title to encourage participation. (Required)": "\u0634\u064a\u064a \u0634 \u0630\u0645\u062b\u0634\u0642 \u0634\u0631\u064a \u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062f\u062b \u0641\u0647\u0641\u0645\u062b \u0641\u062e \u062b\u0631\u0630\u062e\u0639\u0642\u0634\u0644\u062b \u062d\u0634\u0642\u0641\u0647\u0630\u0647\u062d\u0634\u0641\u0647\u062e\u0631. (\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a)", + "Add a comment": "\u0634\u064a\u064a \u0634 \u0630\u062e\u0648\u0648\u062b\u0631\u0641", "Add a learning outcome here": "\u0634\u064a\u064a \u0634 \u0645\u062b\u0634\u0642\u0631\u0647\u0631\u0644 \u062e\u0639\u0641\u0630\u062e\u0648\u062b \u0627\u062b\u0642\u062b", + "Add a response:": "\u0634\u064a\u064a \u0634 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b:", "Add another group": "\u0634\u064a\u064a \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u0644\u0642\u062e\u0639\u062d", "Add language": "\u0634\u064a\u064a \u0645\u0634\u0631\u0644\u0639\u0634\u0644\u062b", "Add learners to this cohort": "\u0634\u064a\u064a \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0641\u062e \u0641\u0627\u0647\u0633 \u0630\u062e\u0627\u062e\u0642\u0641", @@ -155,6 +165,7 @@ "Add your first content group": "\u0634\u064a\u064a \u063a\u062e\u0639\u0642 \u0628\u0647\u0642\u0633\u0641 \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0644\u0642\u062e\u0639\u062d", "Add your first group configuration": "\u0634\u064a\u064a \u063a\u062e\u0639\u0642 \u0628\u0647\u0642\u0633\u0641 \u0644\u0642\u062e\u0639\u062d \u0630\u062e\u0631\u0628\u0647\u0644\u0639\u0642\u0634\u0641\u0647\u062e\u0631", "Add your first textbook": "\u0634\u064a\u064a \u063a\u062e\u0639\u0642 \u0628\u0647\u0642\u0633\u0641 \u0641\u062b\u0637\u0641\u0632\u062e\u062e\u0646", + "Add your post to a relevant topic to help others find it. (Required)": "\u0634\u064a\u064a \u063a\u062e\u0639\u0642 \u062d\u062e\u0633\u0641 \u0641\u062e \u0634 \u0642\u062b\u0645\u062b\u062f\u0634\u0631\u0641 \u0641\u062e\u062d\u0647\u0630 \u0641\u062e \u0627\u062b\u0645\u062d \u062e\u0641\u0627\u062b\u0642\u0633 \u0628\u0647\u0631\u064a \u0647\u0641. (\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a)", "Add {role} Access": "\u0634\u064a\u064a {role} \u0634\u0630\u0630\u062b\u0633\u0633", "Adding": "\u0634\u064a\u064a\u0647\u0631\u0644", "Adding the selected course to your cart": "\u0634\u064a\u064a\u0647\u0631\u0644 \u0641\u0627\u062b \u0633\u062b\u0645\u062b\u0630\u0641\u062b\u064a \u0630\u062e\u0639\u0642\u0633\u062b \u0641\u062e \u063a\u062e\u0639\u0642 \u0630\u0634\u0642\u0641", @@ -173,6 +184,7 @@ "Align left": "\u0634\u0645\u0647\u0644\u0631 \u0645\u062b\u0628\u0641", "Align right": "\u0634\u0645\u0647\u0644\u0631 \u0642\u0647\u0644\u0627\u0641", "Alignment": "\u0634\u0645\u0647\u0644\u0631\u0648\u062b\u0631\u0641", + "All Groups": "\u0634\u0645\u0645 \u0644\u0642\u062e\u0639\u062d\u0633", "All Learners and Staff": "\u0634\u0645\u0645 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0634\u0631\u064a \u0633\u0641\u0634\u0628\u0628", "All Posts": "\u0634\u0645\u0645 \u062d\u062e\u0633\u0641\u0633", "All Rights Reserved": "\u0634\u0645\u0645 \u0642\u0647\u0644\u0627\u0641\u0633 \u0642\u062b\u0633\u062b\u0642\u062f\u062b\u064a", @@ -254,6 +266,7 @@ "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "\u0634\u0642\u062b \u063a\u062e\u0639 \u0633\u0639\u0642\u062b \u063a\u062e\u0639 \u0635\u0647\u0633\u0627 \u0641\u062e \u064a\u062b\u0645\u062b\u0641\u062b \u0641\u0627\u0647\u0633 \u0647\u0641\u062b\u0648. \u0647\u0641 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0642\u062b\u062f\u062b\u0642\u0633\u062b\u064a!\n\n\u0634\u0645\u0633\u062e \u0634\u0631\u063a \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0641\u0627\u0634\u0641 \u0645\u0647\u0631\u0646\u0633/\u0642\u062b\u0628\u062b\u0642\u0633 \u0641\u062e \u0641\u0627\u0647\u0633 \u0647\u0641\u062b\u0648 \u0635\u0647\u0645\u0645 \u0631\u062e \u0645\u062e\u0631\u0644\u062b\u0642 \u0635\u062e\u0642\u0646 (\u062b.\u0644. \u0632\u0642\u062e\u0646\u062b\u0631 \u0647\u0648\u0634\u0644\u062b\u0633 \u0634\u0631\u064a/\u062e\u0642 \u0645\u0647\u0631\u0646\u0633)", "Are you sure?": "\u0634\u0642\u062b \u063a\u062e\u0639 \u0633\u0639\u0642\u062b?", "As part of the verification process, you take a photo of both your face and a government-issued photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u0634\u0633 \u062d\u0634\u0642\u0641 \u062e\u0628 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633, \u063a\u062e\u0639 \u0641\u0634\u0646\u062b \u0634 \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u0632\u062e\u0641\u0627 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b \u0634\u0631\u064a \u0634 \u0644\u062e\u062f\u062b\u0642\u0631\u0648\u062b\u0631\u0641-\u0647\u0633\u0633\u0639\u062b\u064a \u062d\u0627\u062e\u0641\u062e \u0647\u064a. \u062e\u0639\u0642 \u0634\u0639\u0641\u0627\u062e\u0642\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0633\u062b\u0642\u062f\u0647\u0630\u062b \u0630\u062e\u0631\u0628\u0647\u0642\u0648\u0633 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0632\u063a \u0630\u062e\u0648\u062d\u0634\u0642\u0647\u0631\u0644 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u063a\u062e\u0639 \u0641\u0634\u0646\u062b \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0631 \u063a\u062e\u0639\u0642 \u0647\u064a.", + "As part of the verification process, you take a photo of both your face and a photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u0634\u0633 \u062d\u0634\u0642\u0641 \u062e\u0628 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633, \u063a\u062e\u0639 \u0641\u0634\u0646\u062b \u0634 \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u0632\u062e\u0641\u0627 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b \u0634\u0631\u064a \u0634 \u062d\u0627\u062e\u0641\u062e \u0647\u064a. \u062e\u0639\u0642 \u0634\u0639\u0641\u0627\u062e\u0642\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0633\u062b\u0642\u062f\u0647\u0630\u062b \u0630\u062e\u0631\u0628\u0647\u0642\u0648\u0633 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0632\u063a \u0630\u062e\u0648\u062d\u0634\u0642\u0647\u0631\u0644 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u063a\u062e\u0639 \u0641\u0634\u0646\u062b \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0631 \u063a\u062e\u0639\u0642 \u0647\u064a.", "As you complete courses, you will see them listed here.": "\u0634\u0633 \u063a\u062e\u0639 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0630\u062e\u0639\u0642\u0633\u062b\u0633, \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0633\u062b\u062b \u0641\u0627\u062b\u0648 \u0645\u0647\u0633\u0641\u062b\u064a \u0627\u062b\u0642\u062b.", "Assessment Results Visibility": "\u0634\u0633\u0633\u062b\u0633\u0633\u0648\u062b\u0631\u0641 \u0642\u062b\u0633\u0639\u0645\u0641\u0633 \u062f\u0647\u0633\u0647\u0632\u0647\u0645\u0647\u0641\u063a", "Assign Team Memberships": "\u0634\u0633\u0633\u0647\u0644\u0631 \u0641\u062b\u0634\u0648 \u0648\u062b\u0648\u0632\u062b\u0642\u0633\u0627\u0647\u062d\u0633", @@ -381,6 +394,7 @@ "Click to edit": "\u0630\u0645\u0647\u0630\u0646 \u0641\u062e \u062b\u064a\u0647\u0641", "Close": "\u0630\u0645\u062e\u0633\u062b", "Close Calculator": "\u0630\u0645\u062e\u0633\u062b \u0630\u0634\u0645\u0630\u0639\u0645\u0634\u0641\u062e\u0642", + "Closed": "\u0630\u0645\u062e\u0633\u062b\u064a", "Code": "\u0630\u062e\u064a\u062b", "Code Sample (Ctrl+K)": "\u0630\u062e\u064a\u062b \u0633\u0634\u0648\u062d\u0645\u062b (\u0630\u0641\u0642\u0645+\u0646)", "Code block": "\u0630\u062e\u064a\u062b \u0632\u0645\u062e\u0630\u0646", @@ -399,6 +413,7 @@ "Coming Soon": "\u0630\u062e\u0648\u0647\u0631\u0644 \u0633\u062e\u062e\u0631", "Commentary": "\u0630\u062e\u0648\u0648\u062b\u0631\u0641\u0634\u0642\u063a", "Common Problem Types": "\u0630\u062e\u0648\u0648\u062e\u0631 \u062d\u0642\u062e\u0632\u0645\u062b\u0648 \u0641\u063a\u062d\u062b\u0633", + "Community TA": "\u0630\u062e\u0648\u0648\u0639\u0631\u0647\u0641\u063a \u0641\u0634", "Complete courses on your schedule to ensure you stand out in your field!": "\u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0630\u062e\u0639\u0642\u0633\u062b\u0633 \u062e\u0631 \u063a\u062e\u0639\u0642 \u0633\u0630\u0627\u062b\u064a\u0639\u0645\u062b \u0641\u062e \u062b\u0631\u0633\u0639\u0642\u062b \u063a\u062e\u0639 \u0633\u0641\u0634\u0631\u064a \u062e\u0639\u0641 \u0647\u0631 \u063a\u062e\u0639\u0642 \u0628\u0647\u062b\u0645\u064a!", "Completed": "\u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b\u064a", "Component": "\u0630\u062e\u0648\u062d\u062e\u0631\u062b\u0631\u0641", @@ -445,6 +460,7 @@ ], "Course Content": "\u0630\u062e\u0639\u0642\u0633\u062b \u0630\u062e\u0631\u0641\u062b\u0631\u0641", "Course Credit Requirements": "\u0630\u062e\u0639\u0642\u0633\u062b \u0630\u0642\u062b\u064a\u0647\u0641 \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0648\u062b\u0631\u0641\u0633", + "Course Discussion Forum": "\u0630\u062e\u0639\u0642\u0633\u062b \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0628\u062e\u0642\u0639\u0648", "Course End": "\u0630\u062e\u0639\u0642\u0633\u062b \u062b\u0631\u064a", "Course Handouts": "\u0630\u062e\u0639\u0642\u0633\u062b \u0627\u0634\u0631\u064a\u062e\u0639\u0641\u0633", "Course ID": "\u0630\u062e\u0639\u0642\u0633\u062b \u0647\u064a", @@ -467,6 +483,7 @@ "Create": "\u0630\u0642\u062b\u0634\u0641\u062b", "Create Account": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Create Re-run": "\u0630\u0642\u062b\u0634\u0641\u062b \u0642\u062b-\u0642\u0639\u0631", + "Create Support Ticket": "\u0630\u0642\u062b\u0634\u0641\u062b \u0633\u0639\u062d\u062d\u062e\u0642\u0641 \u0641\u0647\u0630\u0646\u062b\u0641", "Create a New Team": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634 \u0631\u062b\u0635 \u0641\u062b\u0634\u0648", "Create a content group": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634 \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0644\u0642\u062e\u0639\u062d", "Create a new team if you can't find an existing team to join, or if you would like to learn with friends you know.": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634 \u0631\u062b\u0635 \u0641\u062b\u0634\u0648 \u0647\u0628 \u063a\u062e\u0639 \u0630\u0634\u0631'\u0641 \u0628\u0647\u0631\u064a \u0634\u0631 \u062b\u0637\u0647\u0633\u0641\u0647\u0631\u0644 \u0641\u062b\u0634\u0648 \u0641\u062e \u062a\u062e\u0647\u0631, \u062e\u0642 \u0647\u0628 \u063a\u062e\u0639 \u0635\u062e\u0639\u0645\u064a \u0645\u0647\u0646\u062b \u0641\u062e \u0645\u062b\u0634\u0642\u0631 \u0635\u0647\u0641\u0627 \u0628\u0642\u0647\u062b\u0631\u064a\u0633 \u063a\u062e\u0639 \u0646\u0631\u062e\u0635.", @@ -474,6 +491,7 @@ "Create account using %(providerName)s.": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0639\u0633\u0647\u0631\u0644 %(providerName)s.", "Create an Account": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0631 \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Create an Account.": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0631 \u0634\u0630\u0630\u062e\u0639\u0631\u0641.", + "Create an account": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0631 \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Create an account using": "\u0630\u0642\u062b\u0634\u0641\u062b \u0634\u0631 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0639\u0633\u0647\u0631\u0644", "Create team.": "\u0630\u0642\u062b\u0634\u0641\u062b \u0641\u062b\u0634\u0648.", "Creating missing groups": "\u0630\u0642\u062b\u0634\u0641\u0647\u0631\u0644 \u0648\u0647\u0633\u0633\u0647\u0631\u0644 \u0644\u0642\u062e\u0639\u062d\u0633", @@ -496,13 +514,14 @@ "Date Placed": "\u064a\u0634\u0641\u062b \u062d\u0645\u0634\u0630\u062b\u064a", "Date added": "\u064a\u0634\u0641\u062b \u0634\u064a\u064a\u062b\u064a", "Deactivate": "\u064a\u062b\u0634\u0630\u0641\u0647\u062f\u0634\u0641\u062b", + "Deactivating": "\u064a\u062b\u0634\u0630\u0641\u0647\u062f\u0634\u0641\u0647\u0631\u0644", "Deadlines": "\u064a\u062b\u0634\u064a\u0645\u0647\u0631\u062b\u0633", "Decrease indent": "\u064a\u062b\u0630\u0642\u062b\u0634\u0633\u062b \u0647\u0631\u064a\u062b\u0631\u0641", "Default": "\u064a\u062b\u0628\u0634\u0639\u0645\u0641", "Default (Local Time Zone)": "\u064a\u062b\u0628\u0634\u0639\u0645\u0641 (\u0645\u062e\u0630\u0634\u0645 \u0641\u0647\u0648\u062b \u0638\u062e\u0631\u062b)", "Default Timed Transcript": "\u064a\u062b\u0628\u0634\u0639\u0645\u0641 \u0641\u0647\u0648\u062b\u064a \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641", "Delete": "\u064a\u062b\u0645\u062b\u0641\u062b", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u064a\u062b\u0645\u062b\u0641\u062b \"<%= signatoryName %>\" \u0628\u0642\u062e\u0648 \u0641\u0627\u062b \u0645\u0647\u0633\u0641 \u062e\u0628 \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u0647\u062b\u0633?", + "Delete \"<%- signatoryName %>\" from the list of signatories?": "\u064a\u062b\u0645\u062b\u0641\u062b \"<%- signatoryName %>\" \u0628\u0642\u062e\u0648 \u0641\u0627\u062b \u0645\u0647\u0633\u0641 \u062e\u0628 \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u0647\u062b\u0633?", "Delete File Confirmation": "\u064a\u062b\u0645\u062b\u0641\u062b \u0628\u0647\u0645\u062b \u0630\u062e\u0631\u0628\u0647\u0642\u0648\u0634\u0641\u0647\u062e\u0631", "Delete My Account": "\u064a\u062b\u0645\u062b\u0641\u062b \u0648\u063a \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Delete Page Confirmation": "\u064a\u062b\u0645\u062b\u0641\u062b \u062d\u0634\u0644\u062b \u0630\u062e\u0631\u0628\u0647\u0642\u0648\u0634\u0641\u0647\u062e\u0631", @@ -529,11 +548,14 @@ "Description": "\u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631", "Description of the certificate": "\u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631 \u062e\u0628 \u0641\u0627\u062b \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b", "Details": "\u064a\u062b\u0641\u0634\u0647\u0645\u0633", + "Device with Camera": "\u064a\u062b\u062f\u0647\u0630\u062b \u0635\u0647\u0641\u0627 \u0630\u0634\u0648\u062b\u0642\u0634", "Dimensions": "\u064a\u0647\u0648\u062b\u0631\u0633\u0647\u062e\u0631\u0633", "Disc": "\u064a\u0647\u0633\u0630", "Discard Changes": "\u064a\u0647\u0633\u0630\u0634\u0642\u064a \u0630\u0627\u0634\u0631\u0644\u062b\u0633", "Discarding Changes": "\u064a\u0647\u0633\u0630\u0634\u0642\u064a\u0647\u0631\u0644 \u0630\u0627\u0634\u0631\u0644\u062b\u0633", + "Discussion": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631", "Discussion Home": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0627\u062e\u0648\u062b", + "Discussion admins, moderators, and TAs can make their posts visible to all students or specify a single group.": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0634\u064a\u0648\u0647\u0631\u0633, \u0648\u062e\u064a\u062b\u0642\u0634\u0641\u062e\u0642\u0633, \u0634\u0631\u064a \u0641\u0634\u0633 \u0630\u0634\u0631 \u0648\u0634\u0646\u062b \u0641\u0627\u062b\u0647\u0642 \u062d\u062e\u0633\u0641\u0633 \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u0634\u0645\u0645 \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633 \u062e\u0642 \u0633\u062d\u062b\u0630\u0647\u0628\u063a \u0634 \u0633\u0647\u0631\u0644\u0645\u062b \u0644\u0642\u062e\u0639\u062d.", "Discussion topics in the course are not divided.": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0641\u062e\u062d\u0647\u0630\u0633 \u0647\u0631 \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0634\u0642\u062b \u0631\u062e\u0641 \u064a\u0647\u062f\u0647\u064a\u062b\u064a.", "Discussions are unified; all learners interact with posts from other learners, regardless of the group they are in.": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631\u0633 \u0634\u0642\u062b \u0639\u0631\u0647\u0628\u0647\u062b\u064a; \u0634\u0645\u0645 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0647\u0631\u0641\u062b\u0642\u0634\u0630\u0641 \u0635\u0647\u0641\u0627 \u062d\u062e\u0633\u0641\u0633 \u0628\u0642\u062e\u0648 \u062e\u0641\u0627\u062b\u0642 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633, \u0642\u062b\u0644\u0634\u0642\u064a\u0645\u062b\u0633\u0633 \u062e\u0628 \u0641\u0627\u062b \u0644\u0642\u062e\u0639\u062d \u0641\u0627\u062b\u063a \u0634\u0642\u062b \u0647\u0631.", "Display Name": "\u064a\u0647\u0633\u062d\u0645\u0634\u063a \u0631\u0634\u0648\u062b", @@ -545,7 +567,6 @@ "Do you want to replace the edX transcript with the YouTube transcript?": "\u064a\u062e \u063a\u062e\u0639 \u0635\u0634\u0631\u0641 \u0641\u062e \u0642\u062b\u062d\u0645\u0634\u0630\u062b \u0641\u0627\u062b \u062b\u064a\u0637 \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641 \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u063a\u062e\u0639\u0641\u0639\u0632\u062b \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641?", "Document properties": "\u064a\u062e\u0630\u0639\u0648\u062b\u0631\u0641 \u062d\u0642\u062e\u062d\u062b\u0642\u0641\u0647\u062b\u0633", "Does the name on your ID match your account name: %(fullName)s?": "\u064a\u062e\u062b\u0633 \u0641\u0627\u062b \u0631\u0634\u0648\u062b \u062e\u0631 \u063a\u062e\u0639\u0642 \u0647\u064a \u0648\u0634\u0641\u0630\u0627 \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0631\u0634\u0648\u062b: %(fullName)s?", - "Does the photo of you match your ID photo?": "\u064a\u062e\u062b\u0633 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639 \u0648\u0634\u0641\u0630\u0627 \u063a\u062e\u0639\u0642 \u0647\u064a \u062d\u0627\u062e\u0641\u062e?", "Does the photo of you show your whole face?": "\u064a\u062e\u062b\u0633 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639 \u0633\u0627\u062e\u0635 \u063a\u062e\u0639\u0642 \u0635\u0627\u062e\u0645\u062b \u0628\u0634\u0630\u062b?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u064a\u062e\u0631'\u0641 \u0633\u062b\u062b \u063a\u062e\u0639\u0642 \u062d\u0647\u0630\u0641\u0639\u0642\u062b? \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u062e \u0634\u0645\u0645\u062e\u0635 \u063a\u062e\u0639\u0642 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u0641\u062e \u0639\u0633\u062b \u063a\u062e\u0639\u0642 \u0630\u0634\u0648\u062b\u0642\u0634 \u0635\u0627\u062b\u0631 \u0647\u0641 \u0634\u0633\u0646\u0633 \u0628\u062e\u0642 \u062d\u062b\u0642\u0648\u0647\u0633\u0633\u0647\u062e\u0631.", "Donate": "\u064a\u062e\u0631\u0634\u0641\u062b", @@ -566,6 +587,7 @@ "Due Date:": "\u064a\u0639\u062b \u064a\u0634\u0641\u062b:", "Due Time in UTC:": "\u064a\u0639\u062b \u0641\u0647\u0648\u062b \u0647\u0631 \u0639\u0641\u0630:", "Due date cannot be before start date.": "\u064a\u0639\u062b \u064a\u0634\u0641\u062b \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0632\u062b\u0628\u062e\u0642\u062b \u0633\u0641\u0634\u0642\u0641 \u064a\u0634\u0641\u062b.", + "Due to the recent increase in interest in online education and edX, we are currently experiencing an unusually high volume of support requests. We appreciate your patience as we work to review each request. Please check the ": "\u064a\u0639\u062b \u0641\u062e \u0641\u0627\u062b \u0642\u062b\u0630\u062b\u0631\u0641 \u0647\u0631\u0630\u0642\u062b\u0634\u0633\u062b \u0647\u0631 \u0647\u0631\u0641\u062b\u0642\u062b\u0633\u0641 \u0647\u0631 \u062e\u0631\u0645\u0647\u0631\u062b \u062b\u064a\u0639\u0630\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u062b\u064a\u0637, \u0635\u062b \u0634\u0642\u062b \u0630\u0639\u0642\u0642\u062b\u0631\u0641\u0645\u063a \u062b\u0637\u062d\u062b\u0642\u0647\u062b\u0631\u0630\u0647\u0631\u0644 \u0634\u0631 \u0639\u0631\u0639\u0633\u0639\u0634\u0645\u0645\u063a \u0627\u0647\u0644\u0627 \u062f\u062e\u0645\u0639\u0648\u062b \u062e\u0628 \u0633\u0639\u062d\u062d\u062e\u0642\u0641 \u0642\u062b\u0636\u0639\u062b\u0633\u0641\u0633. \u0635\u062b \u0634\u062d\u062d\u0642\u062b\u0630\u0647\u0634\u0641\u062b \u063a\u062e\u0639\u0642 \u062d\u0634\u0641\u0647\u062b\u0631\u0630\u062b \u0634\u0633 \u0635\u062b \u0635\u062e\u0642\u0646 \u0641\u062e \u0642\u062b\u062f\u0647\u062b\u0635 \u062b\u0634\u0630\u0627 \u0642\u062b\u0636\u0639\u062b\u0633\u0641. \u062d\u0645\u062b\u0634\u0633\u062b \u0630\u0627\u062b\u0630\u0646 \u0641\u0627\u062b ", "Due:": "\u064a\u0639\u062b:", "Duplicate": "\u064a\u0639\u062d\u0645\u0647\u0630\u0634\u0641\u062b", "Duplicating": "\u064a\u0639\u062d\u0645\u0647\u0630\u0634\u0641\u0647\u0631\u0644", @@ -585,8 +607,12 @@ "Edit Title": "\u062b\u064a\u0647\u0641 \u0641\u0647\u0641\u0645\u062b", "Edit Your Name": "\u062b\u064a\u0647\u0641 \u063a\u062e\u0639\u0642 \u0631\u0634\u0648\u062b", "Edit this certificate?": "\u062b\u064a\u0647\u0641 \u0641\u0627\u0647\u0633 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b?", + "Edit your post below.": "\u062b\u064a\u0647\u0641 \u063a\u062e\u0639\u0642 \u062d\u062e\u0633\u0641 \u0632\u062b\u0645\u062e\u0635.", "Editable": "\u062b\u064a\u0647\u0641\u0634\u0632\u0645\u062b", "Editing access for: {title}": "\u062b\u064a\u0647\u0641\u0647\u0631\u0644 \u0634\u0630\u0630\u062b\u0633\u0633 \u0628\u062e\u0642: {title}", + "Editing comment": "\u062b\u064a\u0647\u0641\u0647\u0631\u0644 \u0630\u062e\u0648\u0648\u062b\u0631\u0641", + "Editing post": "\u062b\u064a\u0647\u0641\u0647\u0631\u0644 \u062d\u062e\u0633\u0641", + "Editing response": "\u062b\u064a\u0647\u0641\u0647\u0631\u0644 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b", "Editing: {title}": "\u062b\u064a\u0647\u0641\u0647\u0631\u0644: {title}", "Editor": "\u062b\u064a\u0647\u0641\u062e\u0642", "Education Completed": "\u062b\u064a\u0639\u0630\u0634\u0641\u0647\u062e\u0631 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b\u064a", @@ -604,6 +630,7 @@ "Encoding": "\u062b\u0631\u0630\u062e\u064a\u0647\u0631\u0644", "End My Exam": "\u062b\u0631\u064a \u0648\u063a \u062b\u0637\u0634\u0648", "End of transcript. Skip to the start.": "\u062b\u0631\u064a \u062e\u0628 \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641. \u0633\u0646\u0647\u062d \u0641\u062e \u0641\u0627\u062b \u0633\u0641\u0634\u0642\u0641.", + "Endorse": "\u062b\u0631\u064a\u062e\u0642\u0633\u062b", "Ends {end}": "\u062b\u0631\u064a\u0633 {end}", "Engage with posts": "\u062b\u0631\u0644\u0634\u0644\u062b \u0635\u0647\u0641\u0627 \u062d\u062e\u0633\u0641\u0633", "Enroll Now": "\u062b\u0631\u0642\u062e\u0645\u0645 \u0631\u062e\u0635", @@ -658,6 +685,7 @@ "Error getting task history for problem '<%- problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "\u062b\u0642\u0642\u062e\u0642 \u0644\u062b\u0641\u0641\u0647\u0631\u0644 \u0641\u0634\u0633\u0646 \u0627\u0647\u0633\u0641\u062e\u0642\u063a \u0628\u062e\u0642 \u062d\u0642\u062e\u0632\u0645\u062b\u0648 '<%- problem_id %>' \u0634\u0631\u064a \u0633\u0641\u0639\u064a\u062b\u0631\u0641 '<%- student_id %>'. \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u0627\u0634\u0641 \u0641\u0627\u062b \u062d\u0642\u062e\u0632\u0645\u062b\u0648 \u0634\u0631\u064a \u0633\u0641\u0639\u064a\u062b\u0631\u0641 \u0647\u064a\u062b\u0631\u0641\u0647\u0628\u0647\u062b\u0642\u0633 \u0634\u0642\u062b \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0634\u0631\u064a \u0630\u062e\u0642\u0642\u062b\u0630\u0641.", "Error importing course": "\u062b\u0642\u0642\u062e\u0642 \u0647\u0648\u062d\u062e\u0642\u0641\u0647\u0631\u0644 \u0630\u062e\u0639\u0642\u0633\u062b", "Error listing task history for this student and problem.": "\u062b\u0642\u0642\u062e\u0642 \u0645\u0647\u0633\u0641\u0647\u0631\u0644 \u0641\u0634\u0633\u0646 \u0627\u0647\u0633\u0641\u062e\u0642\u063a \u0628\u062e\u0642 \u0641\u0627\u0647\u0633 \u0633\u0641\u0639\u064a\u062b\u0631\u0641 \u0634\u0631\u064a \u062d\u0642\u062e\u0632\u0645\u062b\u0648.", + "Error posting your message.": "\u062b\u0642\u0642\u062e\u0642 \u062d\u062e\u0633\u0641\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u0648\u062b\u0633\u0633\u0634\u0644\u062b.", "Error removing user": "\u062b\u0642\u0642\u062e\u0642 \u0642\u062b\u0648\u062e\u062f\u0647\u0631\u0644 \u0639\u0633\u062b\u0642", "Error resetting entrance exam attempts for student '{student_id}'. Make sure student identifier is correct.": "\u062b\u0642\u0642\u062e\u0642 \u0642\u062b\u0633\u062b\u0641\u0641\u0647\u0631\u0644 \u062b\u0631\u0641\u0642\u0634\u0631\u0630\u062b \u062b\u0637\u0634\u0648 \u0634\u0641\u0641\u062b\u0648\u062d\u0641\u0633 \u0628\u062e\u0642 \u0633\u0641\u0639\u064a\u062b\u0631\u0641 '{student_id}'. \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0633\u0641\u0639\u064a\u062b\u0631\u0641 \u0647\u064a\u062b\u0631\u0641\u0647\u0628\u0647\u062b\u0642 \u0647\u0633 \u0630\u062e\u0642\u0642\u062b\u0630\u0641.", "Error resetting problem attempts for problem '<%= problem_id %>' and student '<%- student_id %>'. Make sure that the problem and student identifiers are complete and correct.": "\u062b\u0642\u0642\u062e\u0642 \u0642\u062b\u0633\u062b\u0641\u0641\u0647\u0631\u0644 \u062d\u0642\u062e\u0632\u0645\u062b\u0648 \u0634\u0641\u0641\u062b\u0648\u062d\u0641\u0633 \u0628\u062e\u0642 \u062d\u0642\u062e\u0632\u0645\u062b\u0648 '<%= problem_id %>' \u0634\u0631\u064a \u0633\u0641\u0639\u064a\u062b\u0631\u0641 '<%- student_id %>'. \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u0627\u0634\u0641 \u0641\u0627\u062b \u062d\u0642\u062e\u0632\u0645\u062b\u0648 \u0634\u0631\u064a \u0633\u0641\u0639\u064a\u062b\u0631\u0641 \u0647\u064a\u062b\u0631\u0641\u0647\u0628\u0647\u062b\u0642\u0633 \u0634\u0642\u062b \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0634\u0631\u064a \u0630\u062e\u0642\u0642\u062b\u0630\u0641.", @@ -709,7 +737,6 @@ "Files that you upload must be smaller than 5MB in size.": "\u0628\u0647\u0645\u062b\u0633 \u0641\u0627\u0634\u0641 \u063a\u062e\u0639 \u0639\u062d\u0645\u062e\u0634\u064a \u0648\u0639\u0633\u0641 \u0632\u062b \u0633\u0648\u0634\u0645\u0645\u062b\u0642 \u0641\u0627\u0634\u0631 5\u0648\u0632 \u0647\u0631 \u0633\u0647\u0638\u062b.", "Fill browser": "\u0628\u0647\u0645\u0645 \u0632\u0642\u062e\u0635\u0633\u062b\u0642", "Filter and sort topics": "\u0628\u0647\u0645\u0641\u062b\u0642 \u0634\u0631\u064a \u0633\u062e\u0642\u0641 \u0641\u062e\u062d\u0647\u0630\u0633", - "Final Grade": "\u0628\u0647\u0631\u0634\u0645 \u0644\u0642\u0634\u064a\u062b", "Financial Aid": "\u0628\u0647\u0631\u0634\u0631\u0630\u0647\u0634\u0645 \u0634\u0647\u064a", "Financial Assistance": "\u0628\u0647\u0631\u0634\u0631\u0630\u0647\u0634\u0645 \u0634\u0633\u0633\u0647\u0633\u0641\u0634\u0631\u0630\u062b", "Financial Assistance Application": "\u0628\u0647\u0631\u0634\u0631\u0630\u0647\u0634\u0645 \u0634\u0633\u0633\u0647\u0633\u0641\u0634\u0631\u0630\u062b \u0634\u062d\u062d\u0645\u0647\u0630\u0634\u0641\u0647\u062e\u0631", @@ -722,12 +749,15 @@ "Find previous": "\u0628\u0647\u0631\u064a \u062d\u0642\u062b\u062f\u0647\u062e\u0639\u0633", "Finish": "\u0628\u0647\u0631\u0647\u0633\u0627", "First time here?": "\u0628\u0647\u0642\u0633\u0641 \u0641\u0647\u0648\u062b \u0627\u062b\u0642\u062b?", + "Follow": "\u0628\u062e\u0645\u0645\u062e\u0635", "Follow or unfollow posts": "\u0628\u062e\u0645\u0645\u062e\u0635 \u062e\u0642 \u0639\u0631\u0628\u062e\u0645\u0645\u062e\u0635 \u062d\u062e\u0633\u0641\u0633", + "Following": "\u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644", "Font Family": "\u0628\u062e\u0631\u0641 \u0628\u0634\u0648\u0647\u0645\u063a", "Font Sizes": "\u0628\u062e\u0631\u0641 \u0633\u0647\u0638\u062b\u0633", "Footer": "\u0628\u062e\u062e\u0641\u062b\u0642", "For grading to work, you must change all {oldName} subsections to {newName}.": "\u0628\u062e\u0642 \u0644\u0642\u0634\u064a\u0647\u0631\u0644 \u0641\u062e \u0635\u062e\u0642\u0646, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0630\u0627\u0634\u0631\u0644\u062b \u0634\u0645\u0645 {oldName} \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631\u0633 \u0641\u062e {newName}.", "For inquiries regarding assignments, grades, or structure of a specific course, please post in the discussion forums for that course directly.": "\u0628\u062e\u0642 \u0647\u0631\u0636\u0639\u0647\u0642\u0647\u062b\u0633 \u0642\u062b\u0644\u0634\u0642\u064a\u0647\u0631\u0644 \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641\u0633, \u0644\u0642\u0634\u064a\u062b\u0633, \u062e\u0642 \u0633\u0641\u0642\u0639\u0630\u0641\u0639\u0642\u062b \u062e\u0628 \u0634 \u0633\u062d\u062b\u0630\u0647\u0628\u0647\u0630 \u0630\u062e\u0639\u0642\u0633\u062b, \u062d\u0645\u062b\u0634\u0633\u062b \u062d\u062e\u0633\u0641 \u0647\u0631 \u0641\u0627\u062b \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0628\u062e\u0642\u0639\u0648\u0633 \u0628\u062e\u0642 \u0641\u0627\u0634\u0641 \u0630\u062e\u0639\u0642\u0633\u062b \u064a\u0647\u0642\u062b\u0630\u0641\u0645\u063a.", + "Forgot my password": "\u0628\u062e\u0642\u0644\u062e\u0641 \u0648\u063a \u062d\u0634\u0633\u0633\u0635\u062e\u0642\u064a", "Format": "\u0628\u062e\u0642\u0648\u0634\u0641", "Formats": "\u0628\u062e\u0642\u0648\u0634\u0641\u0633", "Free text notes": "\u0628\u0642\u062b\u062b \u0641\u062b\u0637\u0641 \u0631\u062e\u0641\u062b\u0633", @@ -742,7 +772,6 @@ "Generate": "\u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b", "Generate Exception Certificates": "\u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b\u0633", "Generate the user's certificate": "\u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b \u0641\u0627\u062b \u0639\u0633\u062b\u0642'\u0633 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b", - "Get Credit": "\u0644\u062b\u0641 \u0630\u0642\u062b\u064a\u0647\u0641", "Go to Dashboard": "\u0644\u062e \u0641\u062e \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a", "Go to my Dashboard": "\u0644\u062e \u0641\u062e \u0648\u063a \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a", "Go to your Dashboard": "\u0644\u062e \u0641\u062e \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a", @@ -823,10 +852,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "\u0647\u0628 \u0641\u0627\u062b \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631 \u064a\u062e\u062b\u0633 \u0631\u062e\u0641 \u0627\u0634\u062f\u062b \u0634 \u064a\u0639\u062b \u064a\u0634\u0641\u062b, \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0634\u0645\u0635\u0634\u063a\u0633 \u0633\u062b\u062b \u0641\u0627\u062b\u0647\u0642 \u0633\u0630\u062e\u0642\u062b\u0633 \u0635\u0627\u062b\u0631 \u0641\u0627\u062b\u063a \u0633\u0639\u0632\u0648\u0647\u0641 \u0634\u0631\u0633\u0635\u062b\u0642\u0633 \u0641\u062e \u0634\u0633\u0633\u062b\u0633\u0633\u0648\u062b\u0631\u0641\u0633.", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u0647\u0628 \u0641\u0627\u062b \u0639\u0631\u0647\u0641 \u0635\u0634\u0633 \u062d\u0642\u062b\u062f\u0647\u062e\u0639\u0633\u0645\u063a \u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0634\u0631\u064a \u0642\u062b\u0645\u062b\u0634\u0633\u062b\u064a \u0641\u062e \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633, \u0634\u0631\u063a \u0630\u0627\u0634\u0631\u0644\u062b\u0633 \u063a\u062e\u0639 \u0648\u0634\u064a\u062b \u0641\u062e \u0641\u0627\u062b \u0639\u0631\u0647\u0641 \u0635\u0627\u062b\u0631 \u0647\u0641 \u0635\u0634\u0633 \u0627\u0647\u064a\u064a\u062b\u0631 \u0635\u0647\u0645\u0645 \u0631\u062e\u0635 \u0632\u062b \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633.", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "\u0647\u0628 \u0641\u0627\u062b \u0639\u0631\u0647\u0641 \u0635\u0634\u0633 \u062d\u0642\u062b\u062f\u0647\u062e\u0639\u0633\u0645\u063a \u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0634\u0631\u064a \u0642\u062b\u0645\u062b\u0634\u0633\u062b\u064a \u0641\u062e \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633, \u0634\u0631\u063a \u0630\u0627\u0634\u0631\u0644\u062b\u0633 \u063a\u062e\u0639 \u0648\u0634\u064a\u062b \u0641\u062e \u0641\u0627\u062b \u0639\u0631\u0647\u0641 \u0635\u0627\u062b\u0631 \u0647\u0641 \u0635\u0634\u0633 \u0627\u0647\u064a\u064a\u062b\u0631 \u0635\u0647\u0645\u0645 \u0631\u062e\u0635 \u0632\u062b \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633. \u064a\u062e \u063a\u062e\u0639 \u0635\u0634\u0631\u0641 \u0641\u062e \u062d\u0642\u062e\u0630\u062b\u062b\u064a?", - "If you are unable to access your account contact us via email using {email}.": "\u0647\u0628 \u063a\u062e\u0639 \u0634\u0642\u062b \u0639\u0631\u0634\u0632\u0645\u062b \u0641\u062e \u0634\u0630\u0630\u062b\u0633\u0633 \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0630\u062e\u0631\u0641\u0634\u0630\u0641 \u0639\u0633 \u062f\u0647\u0634 \u062b\u0648\u0634\u0647\u0645 \u0639\u0633\u0647\u0631\u0644 {email}.", "If you do not yet have an account, use the button below to register.": "\u0647\u0628 \u063a\u062e\u0639 \u064a\u062e \u0631\u062e\u0641 \u063a\u062b\u0641 \u0627\u0634\u062f\u062b \u0634\u0631 \u0634\u0630\u0630\u062e\u0639\u0631\u0641, \u0639\u0633\u062b \u0641\u0627\u062b \u0632\u0639\u0641\u0641\u062e\u0631 \u0632\u062b\u0645\u062e\u0635 \u0641\u062e \u0642\u062b\u0644\u0647\u0633\u0641\u062b\u0642.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u0647\u0628 \u063a\u062e\u0639 \u064a\u062e\u0631'\u0641 \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0631\u062e\u0635, \u063a\u062e\u0639 \u0630\u0634\u0631 \u0633\u0641\u0647\u0645\u0645 \u062b\u0637\u062d\u0645\u062e\u0642\u062b \u063a\u062e\u0639\u0642 \u0630\u062e\u0639\u0642\u0633\u062b \u0628\u0642\u062e\u0648 \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a. \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u062d\u062b\u0642\u0647\u062e\u064a\u0647\u0630 \u0642\u062b\u0648\u0647\u0631\u064a\u062b\u0642\u0633 \u0628\u0642\u062e\u0648 %(platformName)s \u0641\u062e \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u0647\u0628 \u063a\u062e\u0639 \u064a\u062e\u0631'\u0641 \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0631\u062e\u0635, \u063a\u062e\u0639 \u0630\u0634\u0631 \u0633\u0641\u0647\u0645\u0645 \u062b\u0637\u062d\u0645\u062e\u0642\u062b \u063a\u062e\u0639\u0642 \u0630\u062e\u0639\u0642\u0633\u062b \u0628\u0642\u062e\u0648 \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a. \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u062d\u062b\u0642\u0647\u062e\u064a\u0647\u0630 \u0642\u062b\u0648\u0647\u0631\u064a\u062b\u0642\u0633 \u0628\u0642\u062e\u0648 {platformName} \u0641\u062e \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a.", "If you leave, you can no longer post in this team's discussions.Your place will be available to another learner.": "\u0647\u0628 \u063a\u062e\u0639 \u0645\u062b\u0634\u062f\u062b, \u063a\u062e\u0639 \u0630\u0634\u0631 \u0631\u062e \u0645\u062e\u0631\u0644\u062b\u0642 \u062d\u062e\u0633\u0641 \u0647\u0631 \u0641\u0627\u0647\u0633 \u0641\u062b\u0634\u0648'\u0633 \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631\u0633.\u063a\u062e\u0639\u0642 \u062d\u0645\u0634\u0630\u062b \u0635\u0647\u0645\u0645 \u0632\u062b \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b \u0641\u062e \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u0645\u062b\u0634\u0642\u0631\u062b\u0642.", "If you make significant changes, make sure you notify members of the team before making these changes.": "\u0647\u0628 \u063a\u062e\u0639 \u0648\u0634\u0646\u062b \u0633\u0647\u0644\u0631\u0647\u0628\u0647\u0630\u0634\u0631\u0641 \u0630\u0627\u0634\u0631\u0644\u062b\u0633, \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u063a\u062e\u0639 \u0631\u062e\u0641\u0647\u0628\u063a \u0648\u062b\u0648\u0632\u062b\u0642\u0633 \u062e\u0628 \u0641\u0627\u062b \u0641\u062b\u0634\u0648 \u0632\u062b\u0628\u062e\u0642\u062b \u0648\u0634\u0646\u0647\u0631\u0644 \u0641\u0627\u062b\u0633\u062b \u0630\u0627\u0634\u0631\u0644\u062b\u0633.", "If you make this %(xblockType)s visible to learners, learners will be able to see its content after the release date has passed and you have published the unit. Only units that are explicitly hidden from learners will remain hidden after you clear this option for the %(xblockType)s.": "\u0647\u0628 \u063a\u062e\u0639 \u0648\u0634\u0646\u062b \u0641\u0627\u0647\u0633 %(xblockType)s \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633, \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0635\u0647\u0645\u0645 \u0632\u062b \u0634\u0632\u0645\u062b \u0641\u062e \u0633\u062b\u062b \u0647\u0641\u0633 \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0634\u0628\u0641\u062b\u0642 \u0641\u0627\u062b \u0642\u062b\u0645\u062b\u0634\u0633\u062b \u064a\u0634\u0641\u062b \u0627\u0634\u0633 \u062d\u0634\u0633\u0633\u062b\u064a \u0634\u0631\u064a \u063a\u062e\u0639 \u0627\u0634\u062f\u062b \u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0641\u0627\u062b \u0639\u0631\u0647\u0641. \u062e\u0631\u0645\u063a \u0639\u0631\u0647\u0641\u0633 \u0641\u0627\u0634\u0641 \u0634\u0642\u062b \u062b\u0637\u062d\u0645\u0647\u0630\u0647\u0641\u0645\u063a \u0627\u0647\u064a\u064a\u062b\u0631 \u0628\u0642\u062e\u0648 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0635\u0647\u0645\u0645 \u0642\u062b\u0648\u0634\u0647\u0631 \u0627\u0647\u064a\u064a\u062b\u0631 \u0634\u0628\u0641\u062b\u0642 \u063a\u062e\u0639 \u0630\u0645\u062b\u0634\u0642 \u0641\u0627\u0647\u0633 \u062e\u062d\u0641\u0647\u062e\u0631 \u0628\u062e\u0642 \u0641\u0627\u062b %(xblockType)s.", @@ -948,6 +975,7 @@ "Live view of webcam": "\u0645\u0647\u062f\u062b \u062f\u0647\u062b\u0635 \u062e\u0628 \u0635\u062b\u0632\u0630\u0634\u0648", "Load Another File": "\u0645\u062e\u0634\u064a \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u0628\u0647\u0645\u062b", "Load all responses": "\u0645\u062e\u0634\u064a \u0634\u0645\u0645 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b\u0633", + "Load more": "\u0645\u062e\u0634\u064a \u0648\u062e\u0642\u062b", "Load next {numResponses} responses": "\u0645\u062e\u0634\u064a \u0631\u062b\u0637\u0641 {numResponses} \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b\u0633", "Load next {num_items} result": [ "\u0645\u062e\u0634\u064a \u0631\u062b\u0637\u0641 {num_items} \u0642\u062b\u0633\u0639\u0645\u0641", @@ -980,6 +1008,7 @@ "Manage Learners": "\u0648\u0634\u0631\u0634\u0644\u062b \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633", "Manual": "\u0648\u0634\u0631\u0639\u0634\u0645", "Mark Exam As Completed": "\u0648\u0634\u0642\u0646 \u062b\u0637\u0634\u0648 \u0634\u0633 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b\u064a", + "Mark as Answer": "\u0648\u0634\u0642\u0646 \u0634\u0633 \u0634\u0631\u0633\u0635\u062b\u0642", "Mark enrollment code as unused": "\u0648\u0634\u0642\u0646 \u062b\u0631\u0642\u062e\u0645\u0645\u0648\u062b\u0631\u0641 \u0630\u062e\u064a\u062b \u0634\u0633 \u0639\u0631\u0639\u0633\u062b\u064a", "Markdown Editing Help": "\u0648\u0634\u0642\u0646\u064a\u062e\u0635\u0631 \u062b\u064a\u0647\u0641\u0647\u0631\u0644 \u0627\u062b\u0645\u062d", "Masters": "\u0648\u0634\u0633\u0641\u062b\u0642\u0633", @@ -1018,6 +1047,8 @@ "Name or short description of the configuration": "\u0631\u0634\u0648\u062b \u062e\u0642 \u0633\u0627\u062e\u0642\u0641 \u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631 \u062e\u0628 \u0641\u0627\u062b \u0630\u062e\u0631\u0628\u0647\u0644\u0639\u0642\u0634\u0641\u0647\u062e\u0631", "Navigate up": "\u0631\u0634\u062f\u0647\u0644\u0634\u0641\u062b \u0639\u062d", "Need help logging in?": "\u0631\u062b\u062b\u064a \u0627\u062b\u0645\u062d \u0645\u062e\u0644\u0644\u0647\u0631\u0644 \u0647\u0631?", + "Need help signing in?": "\u0631\u062b\u062b\u064a \u0627\u062b\u0645\u062d \u0633\u0647\u0644\u0631\u0647\u0631\u0644 \u0647\u0631?", + "Need other help signing in?": "\u0631\u062b\u062b\u064a \u062e\u0641\u0627\u062b\u0642 \u0627\u062b\u0645\u062d \u0633\u0647\u0644\u0631\u0647\u0631\u0644 \u0647\u0631?", "Needs verified certificate ": "\u0631\u062b\u062b\u064a\u0633 \u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b ", "Never published": "\u0631\u062b\u062f\u062b\u0642 \u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a", "Never show assessment results": "\u0631\u062b\u062f\u062b\u0642 \u0633\u0627\u062e\u0635 \u0634\u0633\u0633\u062b\u0633\u0633\u0648\u062b\u0631\u0641 \u0642\u062b\u0633\u0639\u0645\u0641\u0633", @@ -1037,6 +1068,7 @@ "No Flash Detected": "\u0631\u062e \u0628\u0645\u0634\u0633\u0627 \u064a\u062b\u0641\u062b\u0630\u0641\u062b\u064a", "No Timed Transcript": "\u0631\u062e \u0641\u0647\u0648\u062b\u064a \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641", "No Webcam Detected": "\u0631\u062e \u0635\u062b\u0632\u0630\u0634\u0648 \u064a\u062b\u0641\u062b\u0630\u0641\u062b\u064a", + "No assignments for team": "\u0631\u062e \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641\u0633 \u0628\u062e\u0642 \u0641\u062b\u0634\u0648", "No color": "\u0631\u062e \u0630\u062e\u0645\u062e\u0642", "No content-specific discussion topics exist.": "\u0631\u062e \u0630\u062e\u0631\u0641\u062b\u0631\u0641-\u0633\u062d\u062b\u0630\u0647\u0628\u0647\u0630 \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0641\u062e\u062d\u0647\u0630\u0633 \u062b\u0637\u0647\u0633\u0641.", "No description available": "\u0631\u062e \u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631 \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b", @@ -1085,9 +1117,10 @@ "Once in position, use the Take Photo button {icon} to capture your photo": "\u062e\u0631\u0630\u062b \u0647\u0631 \u062d\u062e\u0633\u0647\u0641\u0647\u062e\u0631, \u0639\u0633\u062b \u0641\u0627\u062b \u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e \u0632\u0639\u0641\u0641\u062e\u0631 {icon} \u0641\u062e \u0630\u0634\u062d\u0641\u0639\u0642\u062b \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e", "Once you complete one of the program requirements you have a program record. This record is marked complete once you meet all program requirements. A program record can be used to continue your learning journey and demonstrate your learning to others.": "\u062e\u0631\u0630\u062b \u063a\u062e\u0639 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u062e\u0631\u062b \u062e\u0628 \u0641\u0627\u062b \u062d\u0642\u062e\u0644\u0642\u0634\u0648 \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0648\u062b\u0631\u0641\u0633 \u063a\u062e\u0639 \u0627\u0634\u062f\u062b \u0634 \u062d\u0642\u062e\u0644\u0642\u0634\u0648 \u0642\u062b\u0630\u062e\u0642\u064a. \u0641\u0627\u0647\u0633 \u0642\u062b\u0630\u062e\u0642\u064a \u0647\u0633 \u0648\u0634\u0642\u0646\u062b\u064a \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u062e\u0631\u0630\u062b \u063a\u062e\u0639 \u0648\u062b\u062b\u0641 \u0634\u0645\u0645 \u062d\u0642\u062e\u0644\u0642\u0634\u0648 \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0648\u062b\u0631\u0641\u0633. \u0634 \u062d\u0642\u062e\u0644\u0642\u0634\u0648 \u0642\u062b\u0630\u062e\u0642\u064a \u0630\u0634\u0631 \u0632\u062b \u0639\u0633\u062b\u064a \u0641\u062e \u0630\u062e\u0631\u0641\u0647\u0631\u0639\u062b \u063a\u062e\u0639\u0642 \u0645\u062b\u0634\u0642\u0631\u0647\u0631\u0644 \u062a\u062e\u0639\u0642\u0631\u062b\u063a \u0634\u0631\u064a \u064a\u062b\u0648\u062e\u0631\u0633\u0641\u0642\u0634\u0641\u062b \u063a\u062e\u0639\u0642 \u0645\u062b\u0634\u0642\u0631\u0647\u0631\u0644 \u0641\u062e \u062e\u0641\u0627\u062b\u0642\u0633.", "Once your account is deleted, you cannot use it to take courses on the {platformName} app, {siteName}, or any other site hosted by {platformName}.": "\u062e\u0631\u0630\u062b \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0647\u0633 \u064a\u062b\u0645\u062b\u0641\u062b\u064a, \u063a\u062e\u0639 \u0630\u0634\u0631\u0631\u062e\u0641 \u0639\u0633\u062b \u0647\u0641 \u0641\u062e \u0641\u0634\u0646\u062b \u0630\u062e\u0639\u0642\u0633\u062b\u0633 \u062e\u0631 \u0641\u0627\u062b {platformName} \u0634\u062d\u062d, {siteName}, \u062e\u0642 \u0634\u0631\u063a \u062e\u0641\u0627\u062b\u0642 \u0633\u0647\u0641\u062b \u0627\u062e\u0633\u0641\u062b\u064a \u0632\u063a {platformName}.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u062e\u0631\u0645\u063a <%= fileTypes %> \u0628\u0647\u0645\u062b\u0633 \u0630\u0634\u0631 \u0632\u062b \u0639\u062d\u0645\u062e\u0634\u064a\u062b\u064a. \u062d\u0645\u062b\u0634\u0633\u062b \u0633\u062b\u0645\u062b\u0630\u0641 \u0634 \u0628\u0647\u0645\u062b \u062b\u0631\u064a\u0647\u0631\u0644 \u0647\u0631 <%= fileExtensions %> \u0641\u062e \u0639\u062d\u0645\u062e\u0634\u064a.", + "Only <%- fileTypes %> files can be uploaded. Please select a file ending in <%- (fileExtensions) %> to upload.": "\u062e\u0631\u0645\u063a <%- fileTypes %> \u0628\u0647\u0645\u062b\u0633 \u0630\u0634\u0631 \u0632\u062b \u0639\u062d\u0645\u062e\u0634\u064a\u062b\u064a. \u062d\u0645\u062b\u0634\u0633\u062b \u0633\u062b\u0645\u062b\u0630\u0641 \u0634 \u0628\u0647\u0645\u062b \u062b\u0631\u064a\u0647\u0631\u0644 \u0647\u0631 <%- (fileExtensions) %> \u0641\u062e \u0639\u062d\u0645\u062e\u0634\u064a.", "Only properly formatted .csv files will be accepted.": "\u062e\u0631\u0645\u063a \u062d\u0642\u062e\u062d\u062b\u0642\u0645\u063a \u0628\u062e\u0642\u0648\u0634\u0641\u0641\u062b\u064a .\u0630\u0633\u062f \u0628\u0647\u0645\u062b\u0633 \u0635\u0647\u0645\u0645 \u0632\u062b \u0634\u0630\u0630\u062b\u062d\u0641\u062b\u064a.", "Only the parent course staff of a CCX can create content groups.": "\u062e\u0631\u0645\u063a \u0641\u0627\u062b \u062d\u0634\u0642\u062b\u0631\u0641 \u0630\u062e\u0639\u0642\u0633\u062b \u0633\u0641\u0634\u0628\u0628 \u062e\u0628 \u0634 \u0630\u0630\u0637 \u0630\u0634\u0631 \u0630\u0642\u062b\u0634\u0641\u062b \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0644\u0642\u062e\u0639\u062d\u0633.", + "Open": "\u062e\u062d\u062b\u0631", "Open Calculator": "\u062e\u062d\u062b\u0631 \u0630\u0634\u0645\u0630\u0639\u0645\u0634\u0641\u062e\u0642", "Open language menu": "\u062e\u062d\u062b\u0631 \u0645\u0634\u0631\u0644\u0639\u0634\u0644\u062b \u0648\u062b\u0631\u0639", "Open the certificate you earned for the %(title)s program.": "\u062e\u062d\u062b\u0631 \u0641\u0627\u062b \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u063a\u062e\u0639 \u062b\u0634\u0642\u0631\u062b\u064a \u0628\u062e\u0642 \u0641\u0627\u062b %(title)s \u062d\u0642\u062e\u0644\u0642\u0634\u0648.", @@ -1107,6 +1140,7 @@ "Organization of the signatory": "\u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u062e\u0628 \u0641\u0627\u062b \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u063a", "Organization:": "\u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631:", "Other": "\u062e\u0641\u0627\u062b\u0642", + "Other sign-in issues": "\u062e\u0641\u0627\u062b\u0642 \u0633\u0647\u0644\u0631-\u0647\u0631 \u0647\u0633\u0633\u0639\u062b\u0633", "Overall Score": "\u062e\u062f\u062b\u0642\u0634\u0645\u0645 \u0633\u0630\u062e\u0642\u062b", "PDF Chapters": "\u062d\u064a\u0628 \u0630\u0627\u0634\u062d\u0641\u062b\u0642\u0633", "Page break": "\u062d\u0634\u0644\u062b \u0632\u0642\u062b\u0634\u0646", @@ -1135,6 +1169,8 @@ "Photo of %(fullName)s's ID": "\u062d\u0627\u062e\u0641\u062e \u062e\u0628 %(fullName)s'\u0633 \u0647\u064a", "Photo requirements:": "\u062d\u0627\u062e\u0641\u062e \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0648\u062b\u0631\u0641\u0633:", "Photos don't meet the requirements?": "\u062d\u0627\u062e\u0641\u062e\u0633 \u064a\u062e\u0631'\u0641 \u0648\u062b\u062b\u0641 \u0641\u0627\u062b \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0648\u062b\u0631\u0641\u0633?", + "Pin": "\u062d\u0647\u0631", + "Pinned": "\u062d\u0647\u0631\u0631\u062b\u064a", "Placeholder": "\u062d\u0645\u0634\u0630\u062b\u0627\u062e\u0645\u064a\u062b\u0642", "Play": "\u062d\u0645\u0634\u063a", "Play video": "\u062d\u0645\u0634\u063a \u062f\u0647\u064a\u062b\u062e", @@ -1177,6 +1213,7 @@ "Please verify that your webcam is connected and that you have allowed your browser to access it.": "\u062d\u0645\u062b\u0634\u0633\u062b \u062f\u062b\u0642\u0647\u0628\u063a \u0641\u0627\u0634\u0641 \u063a\u062e\u0639\u0642 \u0635\u062b\u0632\u0630\u0634\u0648 \u0647\u0633 \u0630\u062e\u0631\u0631\u062b\u0630\u0641\u062b\u064a \u0634\u0631\u064a \u0641\u0627\u0634\u0641 \u063a\u062e\u0639 \u0627\u0634\u062f\u062b \u0634\u0645\u0645\u062e\u0635\u062b\u064a \u063a\u062e\u0639\u0642 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u0641\u062e \u0634\u0630\u0630\u062b\u0633\u0633 \u0647\u0641.", "Plugins": "\u062d\u0645\u0639\u0644\u0647\u0631\u0633", "Post": "\u062d\u062e\u0633\u0641", + "Post type": "\u062d\u062e\u0633\u0641 \u0641\u063a\u062d\u062b", "Poster": "\u062d\u062e\u0633\u0641\u062b\u0642", "Practice Proctored": "\u062d\u0642\u0634\u0630\u0641\u0647\u0630\u062b \u062d\u0642\u062e\u0630\u0641\u062e\u0642\u062b\u064a", "Practice proctored Exam": "\u062d\u0642\u0634\u0630\u0641\u0647\u0630\u062b \u062d\u0642\u062e\u0630\u0641\u062e\u0642\u062b\u064a \u062b\u0637\u0634\u0648", @@ -1231,6 +1268,8 @@ "Published and Live": "\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0634\u0631\u064a \u0645\u0647\u062f\u062b", "Publishing": "\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u0647\u0631\u0644", "Publishing Status": "\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u0647\u0631\u0644 \u0633\u0641\u0634\u0641\u0639\u0633", + "Question": "\u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631", + "Questions raise issues that need answers. Discussions share ideas and start conversations. (Required)": "\u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631\u0633 \u0642\u0634\u0647\u0633\u062b \u0647\u0633\u0633\u0639\u062b\u0633 \u0641\u0627\u0634\u0641 \u0631\u062b\u062b\u064a \u0634\u0631\u0633\u0635\u062b\u0642\u0633. \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631\u0633 \u0633\u0627\u0634\u0642\u062b \u0647\u064a\u062b\u0634\u0633 \u0634\u0631\u064a \u0633\u0641\u0634\u0642\u0641 \u0630\u062e\u0631\u062f\u062b\u0642\u0633\u0634\u0641\u0647\u062e\u0631\u0633. (\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a)", "Queued": "\u0636\u0639\u062b\u0639\u062b\u064a", "REMAINING COURSES": "\u0642\u062b\u0648\u0634\u0647\u0631\u0647\u0631\u0644 \u0630\u062e\u0639\u0642\u0633\u062b\u0633", "Re-run Course": "\u0642\u062b-\u0642\u0639\u0631 \u0630\u062e\u0639\u0642\u0633\u062b", @@ -1250,6 +1289,7 @@ "Regenerate": "\u0642\u062b\u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b", "Regenerate the user's certificate": "\u0642\u062b\u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b \u0641\u0627\u062b \u0639\u0633\u062b\u0642'\u0633 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b", "Register with Institution/Campus Credentials": "\u0642\u062b\u0644\u0647\u0633\u0641\u062b\u0642 \u0635\u0647\u0641\u0627 \u0647\u0631\u0633\u0641\u0647\u0641\u0639\u0641\u0647\u062e\u0631/\u0630\u0634\u0648\u062d\u0639\u0633 \u0630\u0642\u062b\u064a\u062b\u0631\u0641\u0647\u0634\u0645\u0633", + "Related to: %(courseware_title_linked)s": "\u0642\u062b\u0645\u0634\u0641\u062b\u064a \u0641\u062e: %(courseware_title_linked)s", "Release Date and Time": "\u0642\u062b\u0645\u062b\u0634\u0633\u062b \u064a\u0634\u0641\u062b \u0634\u0631\u064a \u0641\u0647\u0648\u062b", "Release Date:": "\u0642\u062b\u0645\u062b\u0634\u0633\u062b \u064a\u0634\u0641\u062b:", "Release Status:": "\u0642\u062b\u0645\u062b\u0634\u0633\u062b \u0633\u0641\u0634\u0641\u0639\u0633:", @@ -1277,7 +1317,10 @@ "Replace all": "\u0642\u062b\u062d\u0645\u0634\u0630\u062b \u0634\u0645\u0645", "Replace with": "\u0642\u062b\u062d\u0645\u0634\u0630\u062b \u0635\u0647\u0641\u0627", "Reply to Annotation": "\u0642\u062b\u062d\u0645\u063a \u0641\u062e \u0634\u0631\u0631\u062e\u0641\u0634\u0641\u0647\u062e\u0631", + "Report": "\u0642\u062b\u062d\u062e\u0642\u0641", + "Report abuse": "\u0642\u062b\u062d\u062e\u0642\u0641 \u0634\u0632\u0639\u0633\u062b", "Report abuse, topics, and responses": "\u0642\u062b\u062d\u062e\u0642\u0641 \u0634\u0632\u0639\u0633\u062b, \u0641\u062e\u062d\u0647\u0630\u0633, \u0634\u0631\u064a \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b\u0633", + "Reported": "\u0642\u062b\u062d\u062e\u0642\u0641\u062b\u064a", "Requester": "\u0642\u062b\u0636\u0639\u062b\u0633\u0641\u062b\u0642", "Required": "\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a", "Required field.": "\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a \u0628\u0647\u062b\u0645\u064a.", @@ -1296,6 +1339,7 @@ "Return and add email address": "\u0642\u062b\u0641\u0639\u0642\u0631 \u0634\u0631\u064a \u0634\u064a\u064a \u062b\u0648\u0634\u0647\u0645 \u0634\u064a\u064a\u0642\u062b\u0633\u0633", "Return to Export": "\u0642\u062b\u0641\u0639\u0642\u0631 \u0641\u062e \u062b\u0637\u062d\u062e\u0642\u0641", "Return to Your Dashboard": "\u0642\u062b\u0641\u0639\u0642\u0631 \u0641\u062e \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a", + "Return to all posts": "\u0642\u062b\u0641\u0639\u0642\u0631 \u0641\u062e \u0634\u0645\u0645 \u062d\u062e\u0633\u0641\u0633", "Return to team listing": "\u0642\u062b\u0641\u0639\u0642\u0631 \u0641\u062e \u0641\u062b\u0634\u0648 \u0645\u0647\u0633\u0641\u0647\u0631\u0644", "Review Rules": "\u0642\u062b\u062f\u0647\u062b\u0635 \u0642\u0639\u0645\u062b\u0633", "Review Your Photos": "\u0642\u062b\u062f\u0647\u062b\u0635 \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e\u0633", @@ -1373,6 +1417,10 @@ "Short explanation": "\u0633\u0627\u062e\u0642\u0641 \u062b\u0637\u062d\u0645\u0634\u0631\u0634\u0641\u0647\u062e\u0631", "Show All": "\u0633\u0627\u062e\u0635 \u0634\u0645\u0645", "Show Annotations": "\u0633\u0627\u062e\u0635 \u0634\u0631\u0631\u062e\u0641\u0634\u0641\u0647\u062e\u0631\u0633", + "Show Comment (%(num_comments)s)": [ + "\u0633\u0627\u062e\u0635 \u0630\u062e\u0648\u0648\u062b\u0631\u0641 (%(num_comments)s)", + "\u0633\u0627\u062e\u0635 \u0630\u062e\u0648\u0648\u062b\u0631\u0641\u0633 (%(num_comments)s)" + ], "Show Deprecated Settings": "\u0633\u0627\u062e\u0635 \u064a\u062b\u062d\u0642\u062b\u0630\u0634\u0641\u062b\u064a \u0633\u062b\u0641\u0641\u0647\u0631\u0644\u0633", "Show Discussion": "\u0633\u0627\u062e\u0635 \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631", "Show Less": "\u0633\u0627\u062e\u0635 \u0645\u062b\u0633\u0633", @@ -1409,6 +1457,7 @@ "Sign in using %(providerName)s": "\u0633\u0647\u0644\u0631 \u0647\u0631 \u0639\u0633\u0647\u0631\u0644 %(providerName)s", "Sign in with %(providerName)s": "\u0633\u0647\u0644\u0631 \u0647\u0631 \u0635\u0647\u0641\u0627 %(providerName)s", "Sign in with Institution/Campus Credentials": "\u0633\u0647\u0644\u0631 \u0647\u0631 \u0635\u0647\u0641\u0627 \u0647\u0631\u0633\u0641\u0647\u0641\u0639\u0641\u0647\u062e\u0631/\u0630\u0634\u0648\u062d\u0639\u0633 \u0630\u0642\u062b\u064a\u062b\u0631\u0641\u0647\u0634\u0645\u0633", + "Sign in with your company or school": "\u0633\u0647\u0644\u0631 \u0647\u0631 \u0635\u0647\u0641\u0627 \u063a\u062e\u0639\u0642 \u0630\u062e\u0648\u062d\u0634\u0631\u063a \u062e\u0642 \u0633\u0630\u0627\u062e\u062e\u0645", "Sign in.": "\u0633\u0647\u0644\u0631 \u0647\u0631.", "Signatory": "\u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u063a", "Signatory field(s) has invalid data.": "\u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u063a \u0628\u0647\u062b\u0645\u064a(\u0633) \u0627\u0634\u0633 \u0647\u0631\u062f\u0634\u0645\u0647\u064a \u064a\u0634\u0641\u0634.", @@ -1515,6 +1564,7 @@ "Task inputs": "\u0641\u0634\u0633\u0646 \u0647\u0631\u062d\u0639\u0641\u0633", "Teaching Assistant": "\u0641\u062b\u0634\u0630\u0627\u0647\u0631\u0644 \u0634\u0633\u0633\u0647\u0633\u0641\u0634\u0631\u0641", "Team \"{team}\" successfully deleted.": "\u0641\u062b\u0634\u0648 \"{team}\" \u0633\u0639\u0630\u0630\u062b\u0633\u0633\u0628\u0639\u0645\u0645\u063a \u064a\u062b\u0645\u062b\u0641\u062b\u064a.", + "Team Assignments": "\u0641\u062b\u0634\u0648 \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641\u0633", "Team Description (Required) *": "\u0641\u062b\u0634\u0648 \u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631 (\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a) *", "Team Details": "\u0641\u062b\u0634\u0648 \u064a\u062b\u0641\u0634\u0647\u0645\u0633", "Team Name (Required) *": "\u0641\u062b\u0634\u0648 \u0631\u0634\u0648\u062b (\u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a) *", @@ -1533,9 +1583,8 @@ "Textbook Name": "\u0641\u062b\u0637\u0641\u0632\u062e\u062e\u0646 \u0631\u0634\u0648\u062b", "Textbook information": "\u0641\u062b\u0637\u0641\u0632\u062e\u062e\u0646 \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631", "Textbook name is required": "\u0641\u062b\u0637\u0641\u0632\u062e\u062e\u0646 \u0631\u0634\u0648\u062b \u0647\u0633 \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 %(full_name)s! \u0635\u062b \u0627\u0634\u062f\u062b \u0642\u062b\u0630\u062b\u0647\u062f\u062b\u064a \u063a\u062e\u0639\u0642 \u062d\u0634\u063a\u0648\u062b\u0631\u0641 \u0628\u062e\u0642 %(course_name)s.", "Thank you for setting your course goal to {goal}!": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 \u0628\u062e\u0642 \u0633\u062b\u0641\u0641\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u0630\u062e\u0639\u0642\u0633\u062b \u0644\u062e\u0634\u0645 \u0641\u062e {goal}!", - "Thank you for submitting a request! We will contact you within 24 hours.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 \u0628\u062e\u0642 \u0633\u0639\u0632\u0648\u0647\u0641\u0641\u0647\u0631\u0644 \u0634 \u0642\u062b\u0636\u0639\u062b\u0633\u0641! \u0635\u062b \u0635\u0647\u0645\u0645 \u0630\u062e\u0631\u0641\u0634\u0630\u0641 \u063a\u062e\u0639 \u0635\u0647\u0641\u0627\u0647\u0631 24 \u0627\u062e\u0639\u0642\u0633.", + "Thank you for submitting a request! We appreciate your patience while we work to review your request.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 \u0628\u062e\u0642 \u0633\u0639\u0632\u0648\u0647\u0641\u0641\u0647\u0631\u0644 \u0634 \u0642\u062b\u0636\u0639\u062b\u0633\u0641! \u0635\u062b \u0634\u062d\u062d\u0642\u062b\u0630\u0647\u0634\u0641\u062b \u063a\u062e\u0639\u0642 \u062d\u0634\u0641\u0647\u062b\u0631\u0630\u062b \u0635\u0627\u0647\u0645\u062b \u0635\u062b \u0635\u062e\u0642\u0646 \u0641\u062e \u0642\u062b\u062f\u0647\u062b\u0635 \u063a\u062e\u0639\u0642 \u0642\u062b\u0636\u0639\u062b\u0633\u0641.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 \u0628\u062e\u0642 \u0633\u0639\u0632\u0648\u0647\u0641\u0641\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u0628\u0647\u0631\u0634\u0631\u0630\u0647\u0634\u0645 \u0634\u0633\u0633\u0647\u0633\u0641\u0634\u0631\u0630\u062b \u0634\u062d\u062d\u0645\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u0628\u062e\u0642 {course_name}! \u063a\u062e\u0639 \u0630\u0634\u0631 \u062b\u0637\u062d\u062b\u0630\u0641 \u0634 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b \u0647\u0631 2-4 \u0632\u0639\u0633\u0647\u0631\u062b\u0633\u0633 \u064a\u0634\u063a\u0633.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639 \u0628\u062e\u0642 \u0633\u0639\u0632\u0648\u0647\u0641\u0641\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e\u0633. \u0635\u062b \u0635\u0647\u0645\u0645 \u0642\u062b\u062f\u0647\u062b\u0635 \u0641\u0627\u062b\u0648 \u0633\u0627\u062e\u0642\u0641\u0645\u063a. \u063a\u062e\u0639 \u0630\u0634\u0631 \u0631\u062e\u0635 \u0633\u0647\u0644\u0631 \u0639\u062d \u0628\u062e\u0642 \u0634\u0631\u063a %(platformName)s \u0630\u062e\u0639\u0642\u0633\u062b \u0641\u0627\u0634\u0641 \u062e\u0628\u0628\u062b\u0642\u0633 \u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b\u0633. \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u0647\u0633 \u0644\u062e\u062e\u064a \u0628\u062e\u0642 \u062e\u0631\u062b \u063a\u062b\u0634\u0642. \u0634\u0628\u0641\u062b\u0642 \u062e\u0631\u062b \u063a\u062b\u0634\u0642, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0633\u0639\u0632\u0648\u0647\u0641 \u062d\u0627\u062e\u0641\u062e\u0633 \u0628\u062e\u0642 \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u0634\u0644\u0634\u0647\u0631.", "Thank you! We have received your payment for {courseName}.": "\u0641\u0627\u0634\u0631\u0646 \u063a\u062e\u0639! \u0635\u062b \u0627\u0634\u062f\u062b \u0642\u062b\u0630\u062b\u0647\u062f\u062b\u064a \u063a\u062e\u0639\u0642 \u062d\u0634\u063a\u0648\u062b\u0631\u0641 \u0628\u062e\u0642 {courseName}.", @@ -1547,8 +1596,8 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u0641\u0627\u062b \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u0628\u062e\u0642 \u0641\u0627\u0647\u0633 \u0645\u062b\u0634\u0642\u0631\u062b\u0642 \u0627\u0634\u0633 \u0632\u062b\u062b\u0631 \u0642\u062b-\u062f\u0634\u0645\u0647\u064a\u0634\u0641\u062b\u064a \u0634\u0631\u064a \u0641\u0627\u062b \u0633\u063a\u0633\u0641\u062b\u0648 \u0647\u0633 \u0642\u062b-\u0642\u0639\u0631\u0631\u0647\u0631\u0644 \u0641\u0627\u062b \u0644\u0642\u0634\u064a\u062b \u0628\u062e\u0642 \u0641\u0627\u0647\u0633 \u0645\u062b\u0634\u0642\u0631\u062b\u0642.", "The cohort cannot be added": "\u0641\u0627\u062b \u0630\u062e\u0627\u062e\u0642\u0641 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0634\u064a\u064a\u062b\u064a", "The cohort cannot be saved": "\u0641\u0627\u062b \u0630\u062e\u0627\u062e\u0642\u0641 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0633\u0634\u062f\u062b\u064a", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u0641\u0627\u062b \u0630\u062e\u0648\u0632\u0647\u0631\u062b\u064a \u0645\u062b\u0631\u0644\u0641\u0627 \u062e\u0628 \u0641\u0627\u062b \u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u0645\u0647\u0632\u0642\u0634\u0642\u063a \u0630\u062e\u064a\u062b \u0628\u0647\u062b\u0645\u064a\u0633 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0648\u062e\u0642\u062b \u0641\u0627\u0634\u0631 <%=limit%> \u0630\u0627\u0634\u0642\u0634\u0630\u0641\u062b\u0642\u0633.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u0641\u0627\u062b \u0630\u062e\u0648\u0632\u0647\u0631\u062b\u064a \u0645\u062b\u0631\u0644\u0641\u0627 \u062e\u0628 \u0641\u0627\u062b \u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631, \u0630\u062e\u0639\u0642\u0633\u062b \u0631\u0639\u0648\u0632\u062b\u0642, \u0634\u0631\u064a \u0630\u062e\u0639\u0642\u0633\u062b \u0642\u0639\u0631 \u0628\u0647\u062b\u0645\u064a\u0633 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0648\u062e\u0642\u062b \u0641\u0627\u0634\u0631 <%=limit%> \u0630\u0627\u0634\u0642\u0634\u0630\u0641\u062b\u0642\u0633.", + "The combined length of the organization and library code fields cannot be more than <%- limit %> characters.": "\u0641\u0627\u062b \u0630\u062e\u0648\u0632\u0647\u0631\u062b\u064a \u0645\u062b\u0631\u0644\u0641\u0627 \u062e\u0628 \u0641\u0627\u062b \u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u0645\u0647\u0632\u0642\u0634\u0642\u063a \u0630\u062e\u064a\u062b \u0628\u0647\u062b\u0645\u064a\u0633 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0648\u062e\u0642\u062b \u0641\u0627\u0634\u0631 <%- limit %> \u0630\u0627\u0634\u0642\u0634\u0630\u0641\u062b\u0642\u0633.", + "The combined length of the organization, course number, and course run fields cannot be more than <%- limit %> characters.": "\u0641\u0627\u062b \u0630\u062e\u0648\u0632\u0647\u0631\u062b\u064a \u0645\u062b\u0631\u0644\u0641\u0627 \u062e\u0628 \u0641\u0627\u062b \u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631, \u0630\u062e\u0639\u0642\u0633\u062b \u0631\u0639\u0648\u0632\u062b\u0642, \u0634\u0631\u064a \u0630\u062e\u0639\u0642\u0633\u062b \u0642\u0639\u0631 \u0628\u0647\u062b\u0645\u064a\u0633 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u0648\u062e\u0642\u062b \u0641\u0627\u0634\u0631 <%- limit %> \u0630\u0627\u0634\u0642\u0634\u0630\u0641\u062b\u0642\u0633.", "The country or region where you live.": "\u0641\u0627\u062b \u0630\u062e\u0639\u0631\u0641\u0642\u063a \u062e\u0642 \u0642\u062b\u0644\u0647\u062e\u0631 \u0635\u0627\u062b\u0642\u062b \u063a\u062e\u0639 \u0645\u0647\u062f\u062b.", "The country that team members primarily identify with.": "\u0641\u0627\u062b \u0630\u062e\u0639\u0631\u0641\u0642\u063a \u0641\u0627\u0634\u0641 \u0641\u062b\u0634\u0648 \u0648\u062b\u0648\u0632\u062b\u0642\u0633 \u062d\u0642\u0647\u0648\u0634\u0642\u0647\u0645\u063a \u0647\u064a\u062b\u0631\u0641\u0647\u0628\u063a \u0635\u0647\u0641\u0627.", "The course end date must be later than the course start date.": "\u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u062b\u0631\u064a \u064a\u0634\u0641\u062b \u0648\u0639\u0633\u0641 \u0632\u062b \u0645\u0634\u0641\u062b\u0642 \u0641\u0627\u0634\u0631 \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0633\u0641\u0634\u0642\u0641 \u064a\u0634\u0641\u062b.", @@ -1563,7 +1612,7 @@ "The file you are trying to upload is too large.": "\u0641\u0627\u062b \u0628\u0647\u0645\u062b \u063a\u062e\u0639 \u0634\u0642\u062b \u0641\u0642\u063a\u0647\u0631\u0644 \u0641\u062e \u0639\u062d\u0645\u062e\u0634\u064a \u0647\u0633 \u0641\u062e\u062e \u0645\u0634\u0642\u0644\u062b.", "The following email addresses and/or usernames are invalid:": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u062b\u0648\u0634\u0647\u0645 \u0634\u064a\u064a\u0642\u062b\u0633\u0633\u062b\u0633 \u0634\u0631\u064a/\u062e\u0642 \u0639\u0633\u062b\u0642\u0631\u0634\u0648\u062b\u0633 \u0634\u0642\u062b \u0647\u0631\u062f\u0634\u0645\u0647\u064a:", "The following errors were generated:": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u062b\u0642\u0642\u062e\u0642\u0633 \u0635\u062b\u0642\u062b \u0644\u062b\u0631\u062b\u0642\u0634\u0641\u062b\u064a:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0647\u0633 \u0634\u0645\u0642\u062b\u0634\u064a\u063a \u0634 \u062d\u0634\u0642\u0641 \u062e\u0628 \u063a\u062e\u0639\u0642 {platform} \u062d\u0642\u062e\u0628\u0647\u0645\u062b. \u0635\u062b\\'\u062f\u062b \u0647\u0631\u0630\u0645\u0639\u064a\u062b\u064a \u0647\u0641 \u0627\u062b\u0642\u062b \u0628\u062e\u0642 \u063a\u062e\u0639\u0642 \u0634\u062d\u062d\u0645\u0647\u0630\u0634\u0641\u0647\u062e\u0631.", + "The following information is already a part of your {platform} profile. We've included it here for your application.": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0647\u0633 \u0634\u0645\u0642\u062b\u0634\u064a\u063a \u0634 \u062d\u0634\u0642\u0641 \u062e\u0628 \u063a\u062e\u0639\u0642 {platform} \u062d\u0642\u062e\u0628\u0647\u0645\u062b. \u0635\u062b'\u062f\u062b \u0647\u0631\u0630\u0645\u0639\u064a\u062b\u064a \u0647\u0641 \u0627\u062b\u0642\u062b \u0628\u062e\u0642 \u063a\u062e\u0639\u0642 \u0634\u062d\u062d\u0645\u0647\u0630\u0634\u0641\u0647\u062e\u0631.", "The following message will be displayed at the bottom of the courseware pages within your course:": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u0648\u062b\u0633\u0633\u0634\u0644\u062b \u0635\u0647\u0645\u0645 \u0632\u062b \u064a\u0647\u0633\u062d\u0645\u0634\u063a\u062b\u064a \u0634\u0641 \u0641\u0627\u062b \u0632\u062e\u0641\u0641\u062e\u0648 \u062e\u0628 \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b\u0635\u0634\u0642\u062b \u062d\u0634\u0644\u062b\u0633 \u0635\u0647\u0641\u0627\u0647\u0631 \u063a\u062e\u0639\u0642 \u0630\u062e\u0639\u0642\u0633\u062b:", "The following options are available for the {license_name} license.": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u062e\u062d\u0641\u0647\u062e\u0631\u0633 \u0634\u0642\u062b \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b \u0628\u062e\u0642 \u0641\u0627\u062b {license_name} \u0645\u0647\u0630\u062b\u0631\u0633\u062b.", "The following users are no longer enrolled in the course:": "\u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u0639\u0633\u062b\u0642\u0633 \u0634\u0642\u062b \u0631\u062e \u0645\u062e\u0631\u0644\u062b\u0642 \u062b\u0631\u0642\u062e\u0645\u0645\u062b\u064a \u0647\u0631 \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b:", @@ -1575,7 +1624,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "\u0641\u0627\u062b \u0648\u0647\u0631\u0647\u0648\u0639\u0648 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u0647\u062e\u0631 \u062d\u062b\u0642\u0630\u062b\u0631\u0641\u0634\u0644\u062b \u0648\u0639\u0633\u0641 \u0632\u062b \u0634 \u0635\u0627\u062e\u0645\u062b \u0631\u0639\u0648\u0632\u062b\u0642 \u0632\u062b\u0641\u0635\u062b\u062b\u0631 0 \u0634\u0631\u064a 100.", "The minimum grade for course credit is not set.": "\u0641\u0627\u062b \u0648\u0647\u0631\u0647\u0648\u0639\u0648 \u0644\u0642\u0634\u064a\u062b \u0628\u062e\u0642 \u0630\u062e\u0639\u0642\u0633\u062b \u0630\u0642\u062b\u064a\u0647\u0641 \u0647\u0633 \u0631\u062e\u0641 \u0633\u062b\u0641.", "The minimum score percentage must be a whole number between 0 and 100.": "\u0641\u0627\u062b \u0648\u0647\u0631\u0647\u0648\u0639\u0648 \u0633\u0630\u062e\u0642\u062b \u062d\u062b\u0642\u0630\u062b\u0631\u0641\u0634\u0644\u062b \u0648\u0639\u0633\u0641 \u0632\u062b \u0634 \u0635\u0627\u062e\u0645\u062b \u0631\u0639\u0648\u0632\u062b\u0642 \u0632\u062b\u0641\u0635\u062b\u062b\u0631 0 \u0634\u0631\u064a 100.", - "The more you tell us, the more quickly and helpfully we can respond!": "\u0641\u0627\u062b \u0648\u062e\u0642\u062b \u063a\u062e\u0639 \u0641\u062b\u0645\u0645 \u0639\u0633, \u0641\u0627\u062b \u0648\u062e\u0642\u062b \u0636\u0639\u0647\u0630\u0646\u0645\u063a \u0634\u0631\u064a \u0627\u062b\u0645\u062d\u0628\u0639\u0645\u0645\u063a \u0635\u062b \u0630\u0634\u0631 \u0642\u062b\u0633\u062d\u062e\u0631\u064a!", "The name of this signatory as it should appear on certificates.": "\u0641\u0627\u062b \u0631\u0634\u0648\u062b \u062e\u0628 \u0641\u0627\u0647\u0633 \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u063a \u0634\u0633 \u0647\u0641 \u0633\u0627\u062e\u0639\u0645\u064a \u0634\u062d\u062d\u062b\u0634\u0642 \u062e\u0631 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b\u0633.", "The name that identifies you on {platform_name}. You cannot change your username.": "\u0641\u0627\u062b \u0631\u0634\u0648\u062b \u0641\u0627\u0634\u0641 \u0647\u064a\u062b\u0631\u0641\u0647\u0628\u0647\u062b\u0633 \u063a\u062e\u0639 \u062e\u0631 {platform_name}. \u063a\u062e\u0639 \u0630\u0634\u0631\u0631\u062e\u0641 \u0630\u0627\u0634\u0631\u0644\u062b \u063a\u062e\u0639\u0642 \u0639\u0633\u062b\u0642\u0631\u0634\u0648\u062b.", "The name that is used for ID verification and that appears on your certificates.": "\u0641\u0627\u062b \u0631\u0634\u0648\u062b \u0641\u0627\u0634\u0641 \u0647\u0633 \u0639\u0633\u062b\u064a \u0628\u062e\u0642 \u0647\u064a \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u0641\u0627\u0634\u0641 \u0634\u062d\u062d\u062b\u0634\u0642\u0633 \u062e\u0631 \u063a\u062e\u0639\u0642 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b\u0633.", @@ -1583,7 +1631,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "\u0641\u0627\u062b \u0631\u0639\u0648\u0632\u062b\u0642 \u062e\u0628 \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631\u0633 \u0647\u0631 \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0641\u0627\u0634\u0641 \u0630\u062e\u0631\u0641\u0634\u0647\u0631 \u062d\u0642\u062e\u0632\u0645\u062b\u0648\u0633 \u062e\u0628 \u0641\u0627\u0647\u0633 \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641 \u0641\u063a\u062d\u062b.", "The organization that this signatory belongs to, as it should appear on certificates.": "\u0641\u0627\u062b \u062e\u0642\u0644\u0634\u0631\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0641\u0627\u0634\u0641 \u0641\u0627\u0647\u0633 \u0633\u0647\u0644\u0631\u0634\u0641\u062e\u0642\u063a \u0632\u062b\u0645\u062e\u0631\u0644\u0633 \u0641\u062e, \u0634\u0633 \u0647\u0641 \u0633\u0627\u062e\u0639\u0645\u064a \u0634\u062d\u062d\u062b\u0634\u0642 \u062e\u0631 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b\u0633.", "The page \"{route}\" could not be found.": "\u0641\u0627\u062b \u062d\u0634\u0644\u062b \"{route}\" \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0628\u062e\u0639\u0631\u064a.", - "The photo of your face matches the photo on your ID.": "\u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b \u0648\u0634\u0641\u0630\u0627\u062b\u0633 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0631 \u063a\u062e\u0639\u0642 \u0647\u064a.", "The post you selected has been deleted.": "\u0641\u0627\u062b \u062d\u062e\u0633\u0641 \u063a\u062e\u0639 \u0633\u062b\u0645\u062b\u0630\u0641\u062b\u064a \u0627\u0634\u0633 \u0632\u062b\u062b\u0631 \u064a\u062b\u0645\u062b\u0641\u062b\u064a.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "\u0641\u0627\u062b \u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0632\u0642\u0634\u0631\u0630\u0627 \u062f\u062b\u0642\u0633\u0647\u062e\u0631, {published}, \u0635\u0634\u0633 \u0642\u062b\u0633\u062b\u0641 \u0641\u062e \u0641\u0627\u062b \u064a\u0642\u0634\u0628\u0641 \u0632\u0642\u0634\u0631\u0630\u0627 \u062f\u062b\u0642\u0633\u0647\u062e\u0631, {draft}.", "The raw error message is:": "\u0641\u0627\u062b \u0642\u0634\u0635 \u062b\u0642\u0642\u062e\u0642 \u0648\u062b\u0633\u0633\u0634\u0644\u062b \u0647\u0633:", @@ -1675,6 +1722,10 @@ "This post could not be reopened. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0642\u062b\u062e\u062d\u062b\u0631\u062b\u064a. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", "This post could not be unflagged for abuse. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0639\u0631\u0628\u0645\u0634\u0644\u0644\u062b\u064a \u0628\u062e\u0642 \u0634\u0632\u0639\u0633\u062b. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", "This post could not be unpinned. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0639\u0631\u062d\u0647\u0631\u0631\u062b\u064a. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", + "This post is visible only to %(group_name)s.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0647\u0633 \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u062e\u0631\u0645\u063a \u0641\u062e %(group_name)s.", + "This post is visible to everyone.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0647\u0633 \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u062b\u062f\u062b\u0642\u063a\u062e\u0631\u062b.", + "This post will be visible only to %(group_name)s.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0635\u0647\u0645\u0645 \u0632\u062b \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u062e\u0631\u0645\u063a \u0641\u062e %(group_name)s.", + "This post will be visible to everyone.": "\u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641 \u0635\u0647\u0645\u0645 \u0632\u062b \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u062b\u062f\u062b\u0642\u063a\u062e\u0631\u062b.", "This problem has been reset.": "\u0641\u0627\u0647\u0633 \u062d\u0642\u062e\u0632\u0645\u062b\u0648 \u0627\u0634\u0633 \u0632\u062b\u062b\u0631 \u0642\u062b\u0633\u062b\u0641.", "This response could not be marked as an answer. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0648\u0634\u0642\u0646\u062b\u064a \u0634\u0633 \u0634\u0631 \u0634\u0631\u0633\u0635\u062b\u0642. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", "This response could not be marked as endorsed. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0648\u0634\u0642\u0646\u062b\u064a \u0634\u0633 \u062b\u0631\u064a\u062e\u0642\u0633\u062b\u064a. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", @@ -1682,8 +1733,11 @@ "This response could not be unmarked as an answer. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u0639\u0631\u0648\u0634\u0642\u0646\u062b\u064a \u0634\u0633 \u0634\u0631 \u0634\u0631\u0633\u0635\u062b\u0642. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", "This role requires a divided discussions scheme.": "\u0641\u0627\u0647\u0633 \u0642\u062e\u0645\u062b \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0633 \u0634 \u064a\u0647\u062f\u0647\u064a\u062b\u064a \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631\u0633 \u0633\u0630\u0627\u062b\u0648\u062b.", "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.": "\u0641\u0627\u0647\u0633 \u0633\u0627\u062e\u0642\u0641 \u0631\u0634\u0648\u062b \u0628\u062e\u0642 \u0641\u0627\u062b \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641 \u0641\u063a\u062d\u062b (\u0628\u062e\u0642 \u062b\u0637\u0634\u0648\u062d\u0645\u062b, \u0627\u0635 \u062e\u0642 \u0648\u0647\u064a\u0641\u062b\u0642\u0648) \u0634\u062d\u062d\u062b\u0634\u0642\u0633 \u0631\u062b\u0637\u0641 \u0641\u062e \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641\u0633 \u062e\u0631 \u0634 \u0645\u062b\u0634\u0642\u0631\u062b\u0642'\u0633 \u062d\u0642\u062e\u0644\u0642\u062b\u0633\u0633 \u062d\u0634\u0644\u062b.", + "This special exam has been released to learners. You may not convert it to another type of special exam. You may revert this subsection back to being a basic exam by selecting 'None', but you will NOT be able to configure it as a special exam in the future.": "\u0641\u0627\u0647\u0633 \u0633\u062d\u062b\u0630\u0647\u0634\u0645 \u062b\u0637\u0634\u0648 \u0627\u0634\u0633 \u0632\u062b\u062b\u0631 \u0642\u062b\u0645\u062b\u0634\u0633\u062b\u064a \u0641\u062e \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633. \u063a\u062e\u0639 \u0648\u0634\u063a \u0631\u062e\u0641 \u0630\u062e\u0631\u062f\u062b\u0642\u0641 \u0647\u0641 \u0641\u062e \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u0641\u063a\u062d\u062b \u062e\u0628 \u0633\u062d\u062b\u0630\u0647\u0634\u0645 \u062b\u0637\u0634\u0648. \u063a\u062e\u0639 \u0648\u0634\u063a \u0642\u062b\u062f\u062b\u0642\u0641 \u0641\u0627\u0647\u0633 \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631 \u0632\u0634\u0630\u0646 \u0641\u062e \u0632\u062b\u0647\u0631\u0644 \u0634 \u0632\u0634\u0633\u0647\u0630 \u062b\u0637\u0634\u0648 \u0632\u063a \u0633\u062b\u0645\u062b\u0630\u0641\u0647\u0631\u0644 '\u0631\u062e\u0631\u062b', \u0632\u0639\u0641 \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0631\u062e\u0641 \u0632\u062b \u0634\u0632\u0645\u062b \u0641\u062e \u0630\u062e\u0631\u0628\u0647\u0644\u0639\u0642\u062b \u0647\u0641 \u0634\u0633 \u0634 \u0633\u062d\u062b\u0630\u0647\u0634\u0645 \u062b\u0637\u0634\u0648 \u0647\u0631 \u0641\u0627\u062b \u0628\u0639\u0641\u0639\u0642\u062b.", + "This subsection was released to learners as a special exam, but was reverted back to a basic exam. You may not configure it as a special exam now. Contact edX Support for assistance.": "\u0641\u0627\u0647\u0633 \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631 \u0635\u0634\u0633 \u0642\u062b\u0645\u062b\u0634\u0633\u062b\u064a \u0641\u062e \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0634\u0633 \u0634 \u0633\u062d\u062b\u0630\u0647\u0634\u0645 \u062b\u0637\u0634\u0648, \u0632\u0639\u0641 \u0635\u0634\u0633 \u0642\u062b\u062f\u062b\u0642\u0641\u062b\u064a \u0632\u0634\u0630\u0646 \u0641\u062e \u0634 \u0632\u0634\u0633\u0647\u0630 \u062b\u0637\u0634\u0648. \u063a\u062e\u0639 \u0648\u0634\u063a \u0631\u062e\u0641 \u0630\u062e\u0631\u0628\u0647\u0644\u0639\u0642\u062b \u0647\u0641 \u0634\u0633 \u0634 \u0633\u062d\u062b\u0630\u0647\u0634\u0645 \u062b\u0637\u0634\u0648 \u0631\u062e\u0635. \u0630\u062e\u0631\u0641\u0634\u0630\u0641 \u062b\u064a\u0637 \u0633\u0639\u062d\u062d\u062e\u0642\u0641 \u0628\u062e\u0642 \u0634\u0633\u0633\u0647\u0633\u0641\u0634\u0631\u0630\u062b.", "This team does not have any members.": "\u0641\u0627\u0647\u0633 \u0641\u062b\u0634\u0648 \u064a\u062e\u062b\u0633 \u0631\u062e\u0641 \u0627\u0634\u062f\u062b \u0634\u0631\u063a \u0648\u062b\u0648\u0632\u062b\u0642\u0633.", "This team is full.": "\u0641\u0627\u0647\u0633 \u0641\u062b\u0634\u0648 \u0647\u0633 \u0628\u0639\u0645\u0645.", + "This thread is closed.": "\u0641\u0627\u0647\u0633 \u0641\u0627\u0642\u062b\u0634\u064a \u0647\u0633 \u0630\u0645\u062e\u0633\u062b\u064a.", "This unit has validation issues.": "\u0641\u0627\u0647\u0633 \u0639\u0631\u0647\u0641 \u0627\u0634\u0633 \u062f\u0634\u0645\u0647\u064a\u0634\u0641\u0647\u062e\u0631 \u0647\u0633\u0633\u0639\u062b\u0633.", "This vote could not be processed. Refresh the page and try again.": "\u0641\u0627\u0647\u0633 \u062f\u062e\u0641\u062b \u0630\u062e\u0639\u0645\u064a \u0631\u062e\u0641 \u0632\u062b \u062d\u0642\u062e\u0630\u062b\u0633\u0633\u062b\u064a. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u062b \u062d\u0634\u0644\u062b \u0634\u0631\u064a \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", "This {parentCategory} has no {childCategory}": "\u0641\u0627\u0647\u0633 {parentCategory} \u0627\u0634\u0633 \u0631\u062e {childCategory}", @@ -1708,7 +1762,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "\u0641\u062e \u0632\u062b \u0633\u0639\u0642\u062b \u0634\u0645\u0645 \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633 \u0630\u0634\u0631 \u0634\u0630\u0630\u062b\u0633\u0633 \u0641\u0627\u062b \u062f\u0647\u064a\u062b\u062e, \u0635\u062b \u0642\u062b\u0630\u062e\u0648\u0648\u062b\u0631\u064a \u062d\u0642\u062e\u062f\u0647\u064a\u0647\u0631\u0644 \u0632\u062e\u0641\u0627 \u0634\u0631 .\u0648\u062d4 \u0634\u0631\u064a \u0634 .\u0635\u062b\u0632\u0648 \u062f\u062b\u0642\u0633\u0647\u062e\u0631 \u062e\u0628 \u063a\u062e\u0639\u0642 \u062f\u0647\u064a\u062b\u062e. \u0630\u0645\u0647\u0630\u0646 \u0632\u062b\u0645\u062e\u0635 \u0641\u062e \u0634\u064a\u064a \u0634 \u0639\u0642\u0645 \u0628\u062e\u0642 \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u062f\u062b\u0642\u0633\u0647\u062e\u0631. \u0641\u0627\u062b\u0633\u062b \u0639\u0642\u0645\u0633 \u0630\u0634\u0631\u0631\u062e\u0641 \u0632\u062b \u063a\u062e\u0639\u0641\u0639\u0632\u062b \u0639\u0642\u0645\u0633. \u0641\u0627\u062b \u0628\u0647\u0642\u0633\u0641 \u0645\u0647\u0633\u0641\u062b\u064a \u062f\u0647\u064a\u062b\u062e \u0641\u0627\u0634\u0641'\u0633 \u0630\u062e\u0648\u062d\u0634\u0641\u0647\u0632\u0645\u062b \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u0633\u0641\u0639\u064a\u062b\u0631\u0641'\u0633 \u0630\u062e\u0648\u062d\u0639\u0641\u062b\u0642 \u0635\u0647\u0645\u0645 \u062d\u0645\u0634\u063a.", "To complete the program, you must earn a verified certificate for each course.": "\u0641\u062e \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0641\u0627\u062b \u062d\u0642\u062e\u0644\u0642\u0634\u0648, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u062b\u0634\u0642\u0631 \u0634 \u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u0628\u062e\u0642 \u062b\u0634\u0630\u0627 \u0630\u062e\u0639\u0642\u0633\u062b.", "To continue learning with this account, sign in below.": "\u0641\u062e \u0630\u062e\u0631\u0641\u0647\u0631\u0639\u062b \u0645\u062b\u0634\u0642\u0631\u0647\u0631\u0644 \u0635\u0647\u0641\u0627 \u0641\u0627\u0647\u0633 \u0634\u0630\u0630\u062e\u0639\u0631\u0641, \u0633\u0647\u0644\u0631 \u0647\u0631 \u0632\u062b\u0645\u062e\u0635.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "\u0641\u062e \u0628\u0647\u0631\u0634\u0645\u0647\u0638\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0630\u0642\u062b\u064a\u0647\u0641, %(display_name)s \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u0633 %(platform_name)s \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0641\u062e \u0633\u0639\u0632\u0648\u0647\u0641 \u0634 \u0630\u0642\u062b\u064a\u0647\u0641 \u0642\u062b\u0636\u0639\u062b\u0633\u0641.", "To invalidate a certificate for a particular learner, add the username or email address below.": "\u0641\u062e \u0647\u0631\u062f\u0634\u0645\u0647\u064a\u0634\u0641\u062b \u0634 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u0628\u062e\u0642 \u0634 \u062d\u0634\u0642\u0641\u0647\u0630\u0639\u0645\u0634\u0642 \u0645\u062b\u0634\u0642\u0631\u062b\u0642, \u0634\u064a\u064a \u0641\u0627\u062b \u0639\u0633\u062b\u0642\u0631\u0634\u0648\u062b \u062e\u0642 \u062b\u0648\u0634\u0647\u0645 \u0634\u064a\u064a\u0642\u062b\u0633\u0633 \u0632\u062b\u0645\u062e\u0635.", "To receive a certificate, you must also verify your identity before {date}.": "\u0641\u062e \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u0634 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0634\u0645\u0633\u062e \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0632\u062b\u0628\u062e\u0642\u062b {date}.", "To receive a certificate, you must also verify your identity.": "\u0641\u062e \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u0634 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0634\u0645\u0633\u062e \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a.", @@ -1716,13 +1769,14 @@ "To review learner cohort assignments or see the results of uploading a CSV file, download course profile information or cohort results on the {link_start}Data Download{link_end} page.": "\u0641\u062e \u0642\u062b\u062f\u0647\u062b\u0635 \u0645\u062b\u0634\u0642\u0631\u062b\u0642 \u0630\u062e\u0627\u062e\u0642\u0641 \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641\u0633 \u062e\u0642 \u0633\u062b\u062b \u0641\u0627\u062b \u0642\u062b\u0633\u0639\u0645\u0641\u0633 \u062e\u0628 \u0639\u062d\u0645\u062e\u0634\u064a\u0647\u0631\u0644 \u0634 \u0630\u0633\u062f \u0628\u0647\u0645\u062b, \u064a\u062e\u0635\u0631\u0645\u062e\u0634\u064a \u0630\u062e\u0639\u0642\u0633\u062b \u062d\u0642\u062e\u0628\u0647\u0645\u062b \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u062e\u0642 \u0630\u062e\u0627\u062e\u0642\u0641 \u0642\u062b\u0633\u0639\u0645\u0641\u0633 \u062e\u0631 \u0641\u0627\u062b {link_start}\u064a\u0634\u0641\u0634 \u064a\u062e\u0635\u0631\u0645\u062e\u0634\u064a{link_end} \u062d\u0634\u0644\u062b.", "To share your certificate on Mozilla Backpack, you must first have a Backpack account. Complete the following steps to add your certificate to Backpack.": "\u0641\u062e \u0633\u0627\u0634\u0642\u062b \u063a\u062e\u0639\u0642 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u062e\u0631 \u0648\u062e\u0638\u0647\u0645\u0645\u0634 \u0632\u0634\u0630\u0646\u062d\u0634\u0630\u0646, \u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0628\u0647\u0642\u0633\u0641 \u0627\u0634\u062f\u062b \u0634 \u0632\u0634\u0630\u0646\u062d\u0634\u0630\u0646 \u0634\u0630\u0630\u062e\u0639\u0631\u0641. \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0641\u0627\u062b \u0628\u062e\u0645\u0645\u062e\u0635\u0647\u0631\u0644 \u0633\u0641\u062b\u062d\u0633 \u0641\u062e \u0634\u064a\u064a \u063a\u062e\u0639\u0642 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u0641\u062e \u0632\u0634\u0630\u0646\u062d\u0634\u0630\u0646.", "To take a successful photo, make sure that:": "\u0641\u062e \u0641\u0634\u0646\u062b \u0634 \u0633\u0639\u0630\u0630\u062b\u0633\u0633\u0628\u0639\u0645 \u062d\u0627\u062e\u0641\u062e, \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u0627\u0634\u0641:", - "To use the current photo, select the Take Photo button {icon}. To take another photo, select the Retake Photo button {icon}.": "\u0641\u062e \u0639\u0633\u062b \u0641\u0627\u062b \u0630\u0639\u0642\u0642\u062b\u0631\u0641 \u062d\u0627\u062e\u0641\u062e, \u0633\u062b\u0645\u062b\u0630\u0641 \u0641\u0627\u062b \u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e \u0632\u0639\u0641\u0641\u062e\u0631 {icon}. \u0641\u062e \u0641\u0634\u0646\u062b \u0634\u0631\u062e\u0641\u0627\u062b\u0642 \u062d\u0627\u062e\u0641\u062e, \u0633\u062b\u0645\u062b\u0630\u0641 \u0641\u0627\u062b \u0642\u062b\u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e \u0632\u0639\u0641\u0641\u062e\u0631 {icon}.", + "To take the photo of your face, click on the camera button {icon}. If you need to try again, click 'Retake Photo'.": "\u0641\u062e \u0641\u0634\u0646\u062b \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b, \u0630\u0645\u0647\u0630\u0646 \u062e\u0631 \u0641\u0627\u062b \u0630\u0634\u0648\u062b\u0642\u0634 \u0632\u0639\u0641\u0641\u062e\u0631 {icon}. \u0647\u0628 \u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0641\u062e \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631, \u0630\u0645\u0647\u0630\u0646 '\u0642\u062b\u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e'.", "To verify your identity, you need a webcam and a government-issued photo ID.": "\u0641\u062e \u062f\u062b\u0642\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a, \u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634 \u0635\u062b\u0632\u0630\u0634\u0648 \u0634\u0631\u064a \u0634 \u0644\u062e\u062f\u062b\u0642\u0631\u0648\u062b\u0631\u0641-\u0647\u0633\u0633\u0639\u062b\u064a \u062d\u0627\u062e\u0641\u062e \u0647\u064a.", "Toggle Account Password (Usable/Unusable)": "\u0641\u062e\u0644\u0644\u0645\u062b \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u062d\u0634\u0633\u0633\u0635\u062e\u0642\u064a (\u0639\u0633\u0634\u0632\u0645\u062b/\u0639\u0631\u0639\u0633\u0634\u0632\u0645\u062b)", "Toggle Notifications Setting": "\u0641\u062e\u0644\u0644\u0645\u062b \u0631\u062e\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631\u0633 \u0633\u062b\u0641\u0641\u0647\u0631\u0644", "Tools": "\u0641\u062e\u062e\u0645\u0633", "Top": "\u0641\u062e\u062d", "Topic": "\u0641\u062e\u062d\u0647\u0630", + "Topic area": "\u0641\u062e\u062d\u0647\u0630 \u0634\u0642\u062b\u0634", "Topics": "\u0641\u062e\u062d\u0647\u0630\u0633", "Total": "\u0641\u062e\u0641\u0634\u0645", "Total Number": "\u0641\u062e\u0641\u0634\u0645 \u0631\u0639\u0648\u0632\u062b\u0642", @@ -1749,6 +1803,8 @@ "Undo Changes": "\u0639\u0631\u064a\u062e \u0630\u0627\u0634\u0631\u0644\u062b\u0633", "Undo move": "\u0639\u0631\u064a\u062e \u0648\u062e\u062f\u062b", "Undo moving": "\u0639\u0631\u064a\u062e \u0648\u062e\u062f\u0647\u0631\u0644", + "Unendorse": "\u0639\u0631\u062b\u0631\u064a\u062e\u0642\u0633\u062b", + "Unfollow": "\u0639\u0631\u0628\u062e\u0645\u0645\u062e\u0635", "Ungraded": "\u0639\u0631\u0644\u0642\u0634\u064a\u062b\u064a", "Unit": "\u0639\u0631\u0647\u0641", "Unit Access": "\u0639\u0631\u0647\u0641 \u0634\u0630\u0630\u062b\u0633\u0633", @@ -1759,13 +1815,19 @@ "Unlink This Account": "\u0639\u0631\u0645\u0647\u0631\u0646 \u0641\u0627\u0647\u0633 \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Unlink your {accountName} account": "\u0639\u0631\u0645\u0647\u0631\u0646 \u063a\u062e\u0639\u0642 {accountName} \u0634\u0630\u0630\u062e\u0639\u0631\u0641", "Unlinking": "\u0639\u0631\u0645\u0647\u0631\u0646\u0647\u0631\u0644", + "Unmark as Answer": "\u0639\u0631\u0648\u0634\u0642\u0646 \u0634\u0633 \u0634\u0631\u0633\u0635\u062b\u0642", "Unmute": "\u0639\u0631\u0648\u0639\u0641\u062b", + "Unpin": "\u0639\u0631\u062d\u0647\u0631", "Unpublished changes to content that will release in the future": "\u0639\u0631\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0630\u0627\u0634\u0631\u0644\u062b\u0633 \u0641\u062e \u0630\u062e\u0631\u0641\u062b\u0631\u0641 \u0641\u0627\u0634\u0641 \u0635\u0647\u0645\u0645 \u0642\u062b\u0645\u062b\u0634\u0633\u062b \u0647\u0631 \u0641\u0627\u062b \u0628\u0639\u0641\u0639\u0642\u062b", "Unpublished changes to live content": "\u0639\u0631\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0630\u0627\u0634\u0631\u0644\u062b\u0633 \u0641\u062e \u0645\u0647\u062f\u062b \u0630\u062e\u0631\u0641\u062b\u0631\u0641", "Unpublished units will not be released": "\u0639\u0631\u062d\u0639\u0632\u0645\u0647\u0633\u0627\u062b\u064a \u0639\u0631\u0647\u0641\u0633 \u0635\u0647\u0645\u0645 \u0631\u062e\u0641 \u0632\u062b \u0642\u062b\u0645\u062b\u0634\u0633\u062b\u064a", + "Unreport": "\u0639\u0631\u0642\u062b\u062d\u062e\u0642\u0641", "Unscheduled": "\u0639\u0631\u0633\u0630\u0627\u062b\u064a\u0639\u0645\u062b\u064a", "Update": "\u0639\u062d\u064a\u0634\u0641\u062b", "Update Settings": "\u0639\u062d\u064a\u0634\u0641\u062b \u0633\u062b\u0641\u0641\u0647\u0631\u0644\u0633", + "Update comment": "\u0639\u062d\u064a\u0634\u0641\u062b \u0630\u062e\u0648\u0648\u062b\u0631\u0641", + "Update post": "\u0639\u062d\u064a\u0634\u0641\u062b \u062d\u062e\u0633\u0641", + "Update response": "\u0639\u062d\u064a\u0634\u0641\u062b \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b", "Update team.": "\u0639\u062d\u064a\u0634\u0641\u062b \u0641\u062b\u0634\u0648.", "Updating Tags": "\u0639\u062d\u064a\u0634\u0641\u0647\u0631\u0644 \u0641\u0634\u0644\u0633", "Updating with latest library content": "\u0639\u062d\u064a\u0634\u0641\u0647\u0631\u0644 \u0635\u0647\u0641\u0627 \u0645\u0634\u0641\u062b\u0633\u0641 \u0645\u0647\u0632\u0642\u0634\u0642\u063a \u0630\u062e\u0631\u0641\u062b\u0631\u0641", @@ -1787,7 +1849,7 @@ "Upload Videos": "\u0639\u062d\u0645\u062e\u0634\u064a \u062f\u0647\u064a\u062b\u062e\u0633", "Upload a CSV file": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634 \u0630\u0633\u062f \u0628\u0647\u0645\u062b", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634 \u0630\u062e\u0648\u0648\u0634 \u0633\u062b\u062d\u0634\u0642\u0634\u0641\u062b\u064a \u062f\u0634\u0645\u0639\u062b\u0633 (.\u0630\u0633\u062f) \u0628\u0647\u0645\u062b \u0641\u0627\u0634\u0641 \u0630\u062e\u0631\u0641\u0634\u0647\u0631\u0633 \u0641\u0627\u062b \u0639\u0633\u062b\u0642\u0631\u0634\u0648\u062b\u0633 \u062e\u0642 \u062b\u0648\u0634\u0647\u0645 \u0634\u064a\u064a\u0642\u062b\u0633\u0633\u062b\u0633 \u062e\u0628 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0635\u0627\u062e \u0627\u0634\u062f\u062b \u0632\u062b\u062b\u0631 \u0644\u0647\u062f\u062b\u0631 \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631\u0633. \u0647\u0631\u0630\u0645\u0639\u064a\u062b \u0641\u0627\u062b \u0639\u0633\u062b\u0642\u0631\u0634\u0648\u062b \u062e\u0642 \u062b\u0648\u0634\u0647\u0645 \u0634\u064a\u064a\u0642\u062b\u0633\u0633 \u0647\u0631 \u0641\u0627\u062b \u0628\u0647\u0642\u0633\u0641 \u0630\u062e\u0648\u0648\u0634 \u0633\u062b\u062d\u0634\u0642\u0634\u0641\u062b\u064a \u0628\u0647\u062b\u0645\u064a. \u063a\u062e\u0639 \u0630\u0634\u0631 \u0647\u0631\u0630\u0645\u0639\u064a\u062b \u0634\u0631 \u062e\u062d\u0641\u0647\u062e\u0631\u0634\u0645 \u0631\u062e\u0641\u062b \u064a\u062b\u0633\u0630\u0642\u0647\u0632\u0647\u0631\u0644 \u0641\u0627\u062b \u0642\u062b\u0634\u0633\u062e\u0631 \u0628\u062e\u0642 \u0641\u0627\u062b \u062b\u0637\u0630\u062b\u062d\u0641\u0647\u062e\u0631 \u0647\u0631 \u0641\u0627\u062b \u0633\u062b\u0630\u062e\u0631\u064a \u0630\u062e\u0648\u0648\u0634 \u0633\u062b\u062d\u0634\u0642\u0634\u0641\u062b\u064a \u0628\u0647\u062b\u0645\u064a.", - "Upload a new PDF to \u201c<%= name %>\u201d": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634 \u0631\u062b\u0635 \u062d\u064a\u0628 \u0641\u062e \u201c<%= name %>\u201d", + "Upload a new PDF to \u201c<%- name %>\u201d": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634 \u0631\u062b\u0635 \u062d\u064a\u0628 \u0641\u062e \u201c<%- name %>\u201d", "Upload an image": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634\u0631 \u0647\u0648\u0634\u0644\u062b", "Upload an image or capture one with your web or phone camera.": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634\u0631 \u0647\u0648\u0634\u0644\u062b \u062e\u0642 \u0630\u0634\u062d\u0641\u0639\u0642\u062b \u062e\u0631\u062b \u0635\u0647\u0641\u0627 \u063a\u062e\u0639\u0642 \u0635\u062b\u0632 \u062e\u0642 \u062d\u0627\u062e\u0631\u062b \u0630\u0634\u0648\u062b\u0642\u0634.", "Upload completed": "\u0639\u062d\u0645\u062e\u0634\u064a \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b\u064a", @@ -1822,7 +1884,7 @@ "Use my university info": "\u0639\u0633\u062b \u0648\u063a \u0639\u0631\u0647\u062f\u062b\u0642\u0633\u0647\u0641\u063a \u0647\u0631\u0628\u062e", "Use the All Topics menu to find specific topics.": "\u0639\u0633\u062b \u0641\u0627\u062b \u0634\u0645\u0645 \u0641\u062e\u062d\u0647\u0630\u0633 \u0648\u062b\u0631\u0639 \u0641\u062e \u0628\u0647\u0631\u064a \u0633\u062d\u062b\u0630\u0647\u0628\u0647\u0630 \u0641\u062e\u062d\u0647\u0630\u0633.", "Use the Retake Photo button if you are not pleased with your photo": "\u0639\u0633\u062b \u0641\u0627\u062b \u0642\u062b\u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e \u0632\u0639\u0641\u0641\u062e\u0631 \u0647\u0628 \u063a\u062e\u0639 \u0634\u0642\u062b \u0631\u062e\u0641 \u062d\u0645\u062b\u0634\u0633\u062b\u064a \u0635\u0647\u0641\u0627 \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u0639\u0633\u062b \u063a\u062e\u0639\u0642 \u0635\u062b\u0632\u0630\u0634\u0648 \u0641\u062e \u0641\u0634\u0646\u062b \u0634 \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0647\u064a. \u0635\u062b \u0635\u0647\u0645\u0645 \u0648\u0634\u0641\u0630\u0627 \u0641\u0627\u0647\u0633 \u062d\u0627\u062e\u0641\u062e \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b \u0634\u0631\u064a \u0641\u0627\u062b \u0631\u0634\u0648\u062b \u062e\u0631 \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641.", + "Use your webcam to take a photo of your ID.": "\u0639\u0633\u062b \u063a\u062e\u0639\u0642 \u0635\u062b\u0632\u0630\u0634\u0648 \u0641\u062e \u0641\u0634\u0646\u062b \u0634 \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0647\u064a.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u0639\u0633\u062b \u063a\u062e\u0639\u0642 \u0635\u062b\u0632\u0630\u0634\u0648 \u0641\u062e \u0641\u0634\u0646\u062b \u0634 \u062d\u0627\u062e\u0641\u062e \u062e\u0628 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b. \u0635\u062b \u0635\u0647\u0645\u0645 \u0648\u0634\u0641\u0630\u0627 \u0641\u0627\u0647\u0633 \u062d\u0627\u062e\u0641\u062e \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u062d\u0627\u062e\u0641\u062e \u062e\u0631 \u063a\u062e\u0639\u0642 \u0647\u064a.", "Used": "\u0639\u0633\u062b\u064a", "Used in {count} location": [ @@ -1845,7 +1907,6 @@ "Verified Certificate upgrade": "\u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b \u0639\u062d\u0644\u0642\u0634\u064a\u062b", "Verified Status": "\u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0633\u0641\u0634\u0641\u0639\u0633", "Verified mode price": "\u062f\u062b\u0642\u0647\u0628\u0647\u062b\u064a \u0648\u062e\u064a\u062b \u062d\u0642\u0647\u0630\u062b", - "Verify Now": "\u062f\u062b\u0642\u0647\u0628\u063a \u0631\u062e\u0635", "Version": "\u062f\u062b\u0642\u0633\u0647\u062e\u0631", "Vertical space": "\u062f\u062b\u0642\u0641\u0647\u0630\u0634\u0645 \u0633\u062d\u0634\u0630\u062b", "Very loud": "\u062f\u062b\u0642\u063a \u0645\u062e\u0639\u064a", @@ -1872,16 +1933,19 @@ "View Teams in the {topic_name} Topic": "\u062f\u0647\u062b\u0635 \u0641\u062b\u0634\u0648\u0633 \u0647\u0631 \u0641\u0627\u062b {topic_name} \u0641\u062e\u062d\u0647\u0630", "View all errors": "\u062f\u0647\u062b\u0635 \u0634\u0645\u0645 \u062b\u0642\u0642\u062e\u0642\u0633", "View child items": "\u062f\u0647\u062b\u0635 \u0630\u0627\u0647\u0645\u064a \u0647\u0641\u062b\u0648\u0633", + "View discussion": "\u062f\u0647\u062b\u0635 \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631", "View {span_start} {team_name} {span_end}": "\u062f\u0647\u062b\u0635 {span_start} {team_name} {span_end}", "Viewing %s course": [ "\u062f\u0647\u062b\u0635\u0647\u0631\u0644 %s \u0630\u062e\u0639\u0642\u0633\u062b", "\u062f\u0647\u062b\u0635\u0647\u0631\u0644 %s \u0630\u062e\u0639\u0642\u0633\u062b\u0633" ], "Visibility": "\u062f\u0647\u0633\u0647\u0632\u0647\u0645\u0647\u0641\u063a", + "Visible to": "\u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e", "Visible to Staff Only": "\u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0641\u062e \u0633\u0641\u0634\u0628\u0628 \u062e\u0631\u0645\u063a", "Visual aids": "\u062f\u0647\u0633\u0639\u0634\u0645 \u0634\u0647\u064a\u0633", "Volume": "\u062f\u062e\u0645\u0639\u0648\u062b", "Vote for good posts and responses": "\u062f\u062e\u0641\u062b \u0628\u062e\u0642 \u0644\u062e\u062e\u064a \u062d\u062e\u0633\u0641\u0633 \u0634\u0631\u064a \u0642\u062b\u0633\u062d\u062e\u0631\u0633\u062b\u0633", + "Vote for this post,": "\u062f\u062e\u0641\u062b \u0628\u062e\u0642 \u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641,", "Want to confirm your identity later?": "\u0635\u0634\u0631\u0641 \u0641\u062e \u0630\u062e\u0631\u0628\u0647\u0642\u0648 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0645\u0634\u0641\u062b\u0642?", "Warning": "\u0635\u0634\u0642\u0631\u0647\u0631\u0644", "Warnings": "\u0635\u0634\u0642\u0631\u0647\u0631\u0644\u0633", @@ -1890,9 +1954,11 @@ "We couldn't find any results for \"%s\".": "\u0635\u062b \u0630\u062e\u0639\u0645\u064a\u0631'\u0641 \u0628\u0647\u0631\u064a \u0634\u0631\u063a \u0642\u062b\u0633\u0639\u0645\u0641\u0633 \u0628\u062e\u0642 \"%s\".", "We couldn't sign you in.": "\u0635\u062b \u0630\u062e\u0639\u0645\u064a\u0631'\u0641 \u0633\u0647\u0644\u0631 \u063a\u062e\u0639 \u0647\u0631.", "We have encountered an error. Refresh your browser and then try again.": "\u0635\u062b \u0627\u0634\u062f\u062b \u062b\u0631\u0630\u062e\u0639\u0631\u0641\u062b\u0642\u062b\u064a \u0634\u0631 \u062b\u0642\u0642\u062e\u0642. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u063a\u062e\u0639\u0642 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u0634\u0631\u064a \u0641\u0627\u062b\u0631 \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "\u0635\u062b \u0627\u0634\u062f\u062b \u0642\u062b\u0630\u062b\u0647\u062f\u062b\u064a \u063a\u062e\u0639\u0642 \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u0634\u0642\u062b \u062f\u062b\u0642\u0647\u0628\u063a\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a. \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0633\u062b\u062b \u0634 \u0648\u062b\u0633\u0633\u0634\u0644\u062b \u062e\u0631 \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a \u0635\u0627\u062b\u0631 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633 \u0647\u0633 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b (\u0639\u0633\u0639\u0634\u0645\u0645\u063a \u0635\u0647\u0641\u0627\u0647\u0631 1-2 \u064a\u0634\u063a\u0633). \u0647\u0631 \u0641\u0627\u062b \u0648\u062b\u0634\u0631\u0641\u0647\u0648\u062b, \u063a\u062e\u0639 \u0630\u0634\u0631 \u0633\u0641\u0647\u0645\u0645 \u0634\u0630\u0630\u062b\u0633\u0633 \u0634\u0645\u0645 \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0630\u062e\u0631\u0641\u062b\u0631\u0641.", + "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days). In the meantime, you can still access all available course content.": "\u0635\u062b \u0627\u0634\u062f\u062b \u0642\u062b\u0630\u062b\u0647\u062f\u062b\u064a \u063a\u062e\u0639\u0642 \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0634\u0631\u064a \u0634\u0642\u062b \u062f\u062b\u0642\u0647\u0628\u063a\u0647\u0631\u0644 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a. \u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0633\u062b\u062b \u0634 \u0648\u062b\u0633\u0633\u0634\u0644\u062b \u062e\u0631 \u063a\u062e\u0639\u0642 \u064a\u0634\u0633\u0627\u0632\u062e\u0634\u0642\u064a \u0635\u0627\u062b\u0631 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633 \u0647\u0633 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b (\u0639\u0633\u0639\u0634\u0645\u0645\u063a \u0635\u0647\u0641\u0627\u0647\u0631 5-7 \u064a\u0634\u063a\u0633). \u0647\u0631 \u0641\u0627\u062b \u0648\u062b\u0634\u0631\u0641\u0647\u0648\u062b, \u063a\u062e\u0639 \u0630\u0634\u0631 \u0633\u0641\u0647\u0645\u0645 \u0634\u0630\u0630\u062b\u0633\u0633 \u0634\u0645\u0645 \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0630\u062e\u0631\u0641\u062b\u0631\u0641.", "We just need a little more information before you start learning with %(platformName)s.": "\u0635\u062b \u062a\u0639\u0633\u0641 \u0631\u062b\u062b\u064a \u0634 \u0645\u0647\u0641\u0641\u0645\u062b \u0648\u062e\u0642\u062b \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0632\u062b\u0628\u062e\u0642\u062b \u063a\u062e\u0639 \u0633\u0641\u0634\u0642\u0641 \u0645\u062b\u0634\u0642\u0631\u0647\u0631\u0644 \u0635\u0647\u0641\u0627 %(platformName)s.", + "We securely encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "\u0635\u062b \u0633\u062b\u0630\u0639\u0642\u062b\u0645\u063a \u062b\u0631\u0630\u0642\u063a\u062d\u0641 \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e \u0634\u0631\u064a \u0633\u062b\u0631\u064a \u0647\u0641 \u0641\u062e \u062e\u0639\u0642 \u0634\u0639\u0641\u0627\u062e\u0642\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0633\u062b\u0642\u062f\u0647\u0630\u062b \u0628\u062e\u0642 \u0642\u062b\u062f\u0647\u062b\u0635. \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e \u0634\u0631\u064a \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0634\u0642\u062b \u0631\u062e\u0641 \u0633\u0634\u062f\u062b\u064a \u062e\u0642 \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0634\u0631\u063a\u0635\u0627\u062b\u0642\u062b \u062e\u0631 %(platformName)s \u0634\u0628\u0641\u062b\u0642 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633 \u0647\u0633 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "\u0635\u062b \u0639\u0633\u062b \u0641\u0627\u062b \u0627\u0647\u0644\u0627\u062b\u0633\u0641 \u0645\u062b\u062f\u062b\u0645\u0633 \u062e\u0628 \u0633\u062b\u0630\u0639\u0642\u0647\u0641\u063a \u0634\u062f\u0634\u0647\u0645\u0634\u0632\u0645\u062b \u0641\u062e \u062b\u0631\u0630\u0642\u063a\u062d\u0641 \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e \u0634\u0631\u064a \u0633\u062b\u0631\u064a \u0647\u0641 \u0641\u062e \u062e\u0639\u0642 \u0634\u0639\u0641\u0627\u062e\u0642\u0647\u0638\u0634\u0641\u0647\u062e\u0631 \u0633\u062b\u0642\u062f\u0647\u0630\u062b \u0628\u062e\u0642 \u0642\u062b\u062f\u0647\u062b\u0635. \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e \u0634\u0631\u064a \u0647\u0631\u0628\u062e\u0642\u0648\u0634\u0641\u0647\u062e\u0631 \u0634\u0642\u062b \u0631\u062e\u0641 \u0633\u0634\u062f\u062b\u064a \u062e\u0642 \u062f\u0647\u0633\u0647\u0632\u0645\u062b \u0634\u0631\u063a\u0635\u0627\u062b\u0642\u062b \u062e\u0631 %(platformName)s \u0634\u0628\u0641\u062b\u0642 \u0641\u0627\u062b \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0642\u062e\u0630\u062b\u0633\u0633 \u0647\u0633 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b.", + "We use your verification photos to confirm your identity and ensure the validity of your certificate.": "\u0635\u062b \u0639\u0633\u062b \u063a\u062e\u0639\u0642 \u062f\u062b\u0642\u0647\u0628\u0647\u0630\u0634\u0641\u0647\u062e\u0631 \u062d\u0627\u062e\u0641\u062e\u0633 \u0641\u062e \u0630\u062e\u0631\u0628\u0647\u0642\u0648 \u063a\u062e\u0639\u0642 \u0647\u064a\u062b\u0631\u0641\u0647\u0641\u063a \u0634\u0631\u064a \u062b\u0631\u0633\u0639\u0642\u062b \u0641\u0627\u062b \u062f\u0634\u0645\u0647\u064a\u0647\u0641\u063a \u062e\u0628 \u063a\u062e\u0639\u0642 \u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b.", "We're sorry to see you go! Your account will be deleted shortly.": "\u0635\u062b'\u0642\u062b \u0633\u062e\u0642\u0642\u063a \u0641\u062e \u0633\u062b\u062b \u063a\u062e\u0639 \u0644\u062e! \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0635\u0647\u0645\u0645 \u0632\u062b \u064a\u062b\u0645\u062b\u0641\u062b\u064a \u0633\u0627\u062e\u0642\u0641\u0645\u063a.", "We're sorry, there was an error": "\u0635\u062b'\u0642\u062b \u0633\u062e\u0642\u0642\u063a, \u0641\u0627\u062b\u0642\u062b \u0635\u0634\u0633 \u0634\u0631 \u062b\u0642\u0642\u062e\u0642", "We've encountered an error. Refresh your browser and then try again.": "\u0635\u062b'\u062f\u062b \u062b\u0631\u0630\u062e\u0639\u0631\u0641\u062b\u0642\u062b\u064a \u0634\u0631 \u062b\u0642\u0642\u062e\u0642. \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u063a\u062e\u0639\u0642 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u0634\u0631\u064a \u0641\u0627\u062b\u0631 \u0641\u0642\u063a \u0634\u0644\u0634\u0647\u0631.", @@ -1915,6 +1981,7 @@ "When learners submit an answer to an assessment, they immediately see whether the answer is correct or incorrect, and the score received.": "\u0635\u0627\u062b\u0631 \u0645\u062b\u0634\u0642\u0631\u062b\u0642\u0633 \u0633\u0639\u0632\u0648\u0647\u0641 \u0634\u0631 \u0634\u0631\u0633\u0635\u062b\u0642 \u0641\u062e \u0634\u0631 \u0634\u0633\u0633\u062b\u0633\u0633\u0648\u062b\u0631\u0641, \u0641\u0627\u062b\u063a \u0647\u0648\u0648\u062b\u064a\u0647\u0634\u0641\u062b\u0645\u063a \u0633\u062b\u062b \u0635\u0627\u062b\u0641\u0627\u062b\u0642 \u0641\u0627\u062b \u0634\u0631\u0633\u0635\u062b\u0642 \u0647\u0633 \u0630\u062e\u0642\u0642\u062b\u0630\u0641 \u062e\u0642 \u0647\u0631\u0630\u062e\u0642\u0642\u062b\u0630\u0641, \u0634\u0631\u064a \u0641\u0627\u062b \u0633\u0630\u062e\u0642\u062b \u0642\u062b\u0630\u062b\u0647\u062f\u062b\u064a.", "When your face is in position, use the Take Photo button {icon} below to take your photo.": "\u0635\u0627\u062b\u0631 \u063a\u062e\u0639\u0642 \u0628\u0634\u0630\u062b \u0647\u0633 \u0647\u0631 \u062d\u062e\u0633\u0647\u0641\u0647\u062e\u0631, \u0639\u0633\u062b \u0641\u0627\u062b \u0641\u0634\u0646\u062b \u062d\u0627\u062e\u0641\u062e \u0632\u0639\u0641\u0641\u062e\u0631 {icon} \u0632\u062b\u0645\u062e\u0635 \u0641\u062e \u0641\u0634\u0646\u062b \u063a\u062e\u0639\u0642 \u062d\u0627\u062e\u0641\u062e.", "Which timed transcript would you like to use?": "\u0635\u0627\u0647\u0630\u0627 \u0641\u0647\u0648\u062b\u064a \u0641\u0642\u0634\u0631\u0633\u0630\u0642\u0647\u062d\u0641 \u0635\u062e\u0639\u0645\u064a \u063a\u062e\u0639 \u0645\u0647\u0646\u062b \u0641\u062e \u0639\u0633\u062b?", + "While our support team is happy to assist with the edX platform, the course staff has the expertise for specific assignment questions, grading or the proper procedures in each course. Please post all course related questions within the Discussion Forum where the Course Staff can directly respond.": "\u0635\u0627\u0647\u0645\u062b \u062e\u0639\u0642 \u0633\u0639\u062d\u062d\u062e\u0642\u0641 \u0641\u062b\u0634\u0648 \u0647\u0633 \u0627\u0634\u062d\u062d\u063a \u0641\u062e \u0634\u0633\u0633\u0647\u0633\u0641 \u0635\u0647\u0641\u0627 \u0641\u0627\u062b \u062b\u064a\u0637 \u062d\u0645\u0634\u0641\u0628\u062e\u0642\u0648, \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0633\u0641\u0634\u0628\u0628 \u0627\u0634\u0633 \u0641\u0627\u062b \u062b\u0637\u062d\u062b\u0642\u0641\u0647\u0633\u062b \u0628\u062e\u0642 \u0633\u062d\u062b\u0630\u0647\u0628\u0647\u0630 \u0634\u0633\u0633\u0647\u0644\u0631\u0648\u062b\u0631\u0641 \u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631\u0633, \u0644\u0642\u0634\u064a\u0647\u0631\u0644 \u062e\u0642 \u0641\u0627\u062b \u062d\u0642\u062e\u062d\u062b\u0642 \u062d\u0642\u062e\u0630\u062b\u064a\u0639\u0642\u062b\u0633 \u0647\u0631 \u062b\u0634\u0630\u0627 \u0630\u062e\u0639\u0642\u0633\u062b. \u062d\u0645\u062b\u0634\u0633\u062b \u062d\u062e\u0633\u0641 \u0634\u0645\u0645 \u0630\u062e\u0639\u0642\u0633\u062b \u0642\u062b\u0645\u0634\u0641\u062b\u064a \u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631\u0633 \u0635\u0647\u0641\u0627\u0647\u0631 \u0641\u0627\u062b \u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u0628\u062e\u0642\u0639\u0648 \u0635\u0627\u062b\u0642\u062b \u0641\u0627\u062b \u0630\u062e\u0639\u0642\u0633\u062b \u0633\u0641\u0634\u0628\u0628 \u0630\u0634\u0631 \u064a\u0647\u0642\u062b\u0630\u0641\u0645\u063a \u0642\u062b\u0633\u062d\u062e\u0631\u064a.", "Whole words": "\u0635\u0627\u062e\u0645\u062b \u0635\u062e\u0642\u064a\u0633", "Why activate?": "\u0635\u0627\u063a \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u062b?", "Why does %(platformName)s need my photo?": "\u0635\u0627\u063a \u064a\u062e\u062b\u0633 %(platformName)s \u0631\u062b\u062b\u064a \u0648\u063a \u062d\u0627\u062e\u0641\u062e?", @@ -1987,14 +2054,13 @@ "You must specify a name": "\u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0633\u062d\u062b\u0630\u0647\u0628\u063a \u0634 \u0631\u0634\u0648\u062b", "You must specify a name for the cohort": "\u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0633\u062d\u062b\u0630\u0647\u0628\u063a \u0634 \u0631\u0634\u0648\u062b \u0628\u062e\u0642 \u0641\u0627\u062b \u0630\u062e\u0627\u062e\u0642\u0641", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u063a\u062e\u0639 \u0648\u0639\u0633\u0641 \u0633\u062d\u062b\u0630\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0632\u0647\u0642\u0641\u0627 \u063a\u062b\u0634\u0642 \u0632\u062b\u0628\u062e\u0642\u062b \u063a\u062e\u0639 \u0630\u0634\u0631 \u0633\u0627\u0634\u0642\u062b \u063a\u062e\u0639\u0642 \u0628\u0639\u0645\u0645 \u062d\u0642\u062e\u0628\u0647\u0645\u062b. \u0641\u062e \u0633\u062d\u062b\u0630\u0647\u0628\u063a \u063a\u062e\u0639\u0642 \u0632\u0647\u0642\u0641\u0627 \u063a\u062b\u0634\u0642, \u0644\u062e \u0641\u062e \u0641\u0627\u062b {account_settings_page_link}", - "You need a computer or cell phone that has a webcam. When you receive a browser prompt, make sure that you allow access to the camera.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634 \u0630\u062e\u0648\u062d\u0639\u0641\u062b\u0642 \u062e\u0642 \u0630\u062b\u0645\u0645 \u062d\u0627\u062e\u0631\u062b \u0641\u0627\u0634\u0641 \u0627\u0634\u0633 \u0634 \u0635\u062b\u0632\u0630\u0634\u0648. \u0635\u0627\u062b\u0631 \u063a\u062e\u0639 \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u0634 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u062d\u0642\u062e\u0648\u062d\u0641, \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u0627\u0634\u0641 \u063a\u062e\u0639 \u0634\u0645\u0645\u062e\u0635 \u0634\u0630\u0630\u062b\u0633\u0633 \u0641\u062e \u0641\u0627\u062b \u0630\u0634\u0648\u062b\u0642\u0634.", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634 \u064a\u0642\u0647\u062f\u062b\u0642'\u0633 \u0645\u0647\u0630\u062b\u0631\u0633\u062b, \u062d\u0634\u0633\u0633\u062d\u062e\u0642\u0641, \u062e\u0642 \u062e\u0641\u0627\u062b\u0642 \u0644\u062e\u062f\u062b\u0642\u0631\u0648\u062b\u0631\u0641-\u0647\u0633\u0633\u0639\u062b\u064a \u0647\u064a \u0641\u0627\u0634\u0641 \u0627\u0634\u0633 \u063a\u062e\u0639\u0642 \u0631\u0634\u0648\u062b \u0634\u0631\u064a \u062d\u0627\u062e\u0641\u062e.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634\u0631 \u0647\u064a \u0635\u0647\u0641\u0627 \u063a\u062e\u0639\u0642 \u0631\u0634\u0648\u062b \u0634\u0631\u064a \u062d\u0627\u062e\u0641\u062e. \u0634 \u064a\u0642\u0647\u062f\u062b\u0642'\u0633 \u0645\u0647\u0630\u062b\u0631\u0633\u062b, \u062d\u0634\u0633\u0633\u062d\u062e\u0642\u0641, \u062e\u0642 \u062e\u0641\u0627\u062b\u0642 \u0644\u062e\u062f\u062b\u0642\u0631\u0648\u062b\u0631\u0641-\u0647\u0633\u0633\u0639\u062b\u064a \u0647\u064a\u0633 \u0634\u0642\u062b \u0634\u0645\u0645 \u0634\u0630\u0630\u062b\u062d\u0641\u0634\u0632\u0645\u062b.", + "You need a device that has a webcam. If you receive a browser prompt for access to your camera, please make sure to click 'Allow'.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634 \u064a\u062b\u062f\u0647\u0630\u062b \u0641\u0627\u0634\u0641 \u0627\u0634\u0633 \u0634 \u0635\u062b\u0632\u0630\u0634\u0648. \u0647\u0628 \u063a\u062e\u0639 \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u0634 \u0632\u0642\u062e\u0635\u0633\u062b\u0642 \u062d\u0642\u062e\u0648\u062d\u0641 \u0628\u062e\u0642 \u0634\u0630\u0630\u062b\u0633\u0633 \u0641\u062e \u063a\u062e\u0639\u0642 \u0630\u0634\u0648\u062b\u0642\u0634, \u062d\u0645\u062b\u0634\u0633\u062b \u0648\u0634\u0646\u062b \u0633\u0639\u0642\u062b \u0641\u062e \u0630\u0645\u0647\u0630\u0646 '\u0634\u0645\u0645\u062e\u0635'.", + "You need a valid ID that contains your full name and photo.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634 \u062f\u0634\u0645\u0647\u064a \u0647\u064a \u0641\u0627\u0634\u0641 \u0630\u062e\u0631\u0641\u0634\u0647\u0631\u0633 \u063a\u062e\u0639\u0642 \u0628\u0639\u0645\u0645 \u0631\u0634\u0648\u062b \u0634\u0631\u064a \u062d\u0627\u062e\u0641\u062e.", + "You need an ID with your name and photo. A driver's license, passport, or ID are all acceptable.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0634\u0631 \u0647\u064a \u0635\u0647\u0641\u0627 \u063a\u062e\u0639\u0642 \u0631\u0634\u0648\u062b \u0634\u0631\u064a \u062d\u0627\u062e\u0641\u062e. \u0634 \u064a\u0642\u0647\u062f\u062b\u0642'\u0633 \u0645\u0647\u0630\u062b\u0631\u0633\u062b, \u062d\u0634\u0633\u0633\u062d\u062e\u0642\u0641, \u062e\u0642 \u0647\u064a \u0634\u0642\u062b \u0634\u0645\u0645 \u0634\u0630\u0630\u062b\u062d\u0641\u0634\u0632\u0645\u062b.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0641\u062e \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u062b \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0632\u062b\u0628\u062e\u0642\u062b \u063a\u062e\u0639 \u0630\u0634\u0631 \u062b\u0631\u0642\u062e\u0645\u0645 \u0647\u0631 \u0630\u062e\u0639\u0642\u0633\u062b\u0633. \u0630\u0627\u062b\u0630\u0646 \u063a\u062e\u0639\u0642 \u0647\u0631\u0632\u062e\u0637 \u0628\u062e\u0642 \u0634\u0631 \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u0647\u062e\u0631 \u062b\u0648\u0634\u0647\u0645.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u063a\u062e\u0639 \u0631\u062b\u062b\u064a \u0641\u062e \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u062b \u063a\u062e\u0639\u0642 \u0634\u0630\u0630\u062e\u0639\u0631\u0641 \u0632\u062b\u0628\u062e\u0642\u062b \u063a\u062e\u0639 \u0630\u0634\u0631 \u062b\u0631\u0642\u062e\u0645\u0645 \u0647\u0631 \u0630\u062e\u0639\u0642\u0633\u062b\u0633. \u0630\u0627\u062b\u0630\u0646 \u063a\u062e\u0639\u0642 \u0647\u0631\u0632\u062e\u0637 \u0628\u062e\u0642 \u0634\u0631 \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u0647\u062e\u0631 \u062b\u0648\u0634\u0647\u0645. \u0634\u0628\u0641\u062b\u0642 \u063a\u062e\u0639 \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0634\u0630\u0641\u0647\u062f\u0634\u0641\u0647\u062e\u0631 \u063a\u062e\u0639 \u0630\u0634\u0631 \u0642\u062b\u0641\u0639\u0642\u0631 \u0634\u0631\u064a \u0642\u062b\u0628\u0642\u062b\u0633\u0627 \u0641\u0627\u0647\u0633 \u062d\u0634\u0644\u062b.", "You receive messages from {platform_name} and course teams at this address.": "\u063a\u062e\u0639 \u0642\u062b\u0630\u062b\u0647\u062f\u062b \u0648\u062b\u0633\u0633\u0634\u0644\u062b\u0633 \u0628\u0642\u062e\u0648 {platform_name} \u0634\u0631\u064a \u0630\u062e\u0639\u0642\u0633\u062b \u0641\u062b\u0634\u0648\u0633 \u0634\u0641 \u0641\u0627\u0647\u0633 \u0634\u064a\u064a\u0642\u062b\u0633\u0633.", "You reserve all rights for your work": "\u063a\u062e\u0639 \u0642\u062b\u0633\u062b\u0642\u062f\u062b \u0634\u0645\u0645 \u0642\u0647\u0644\u0627\u0641\u0633 \u0628\u062e\u0642 \u063a\u062e\u0639\u0642 \u0635\u062e\u0642\u0646", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u063a\u062e\u0639 \u0633\u0641\u0647\u0645\u0645 \u0631\u062b\u062b\u064a \u0641\u062e \u062f\u0647\u0633\u0647\u0641 \u0641\u0627\u062b %(display_name)s \u0635\u062b\u0632\u0633\u0647\u0641\u062b \u0641\u062e \u0630\u062e\u0648\u062d\u0645\u062b\u0641\u062b \u0641\u0627\u062b \u0630\u0642\u062b\u064a\u0647\u0641 \u062d\u0642\u062e\u0630\u062b\u0633\u0633.", "You submitted {filename}; only {allowedFiles} are allowed.": "\u063a\u062e\u0639 \u0633\u0639\u0632\u0648\u0647\u0641\u0641\u062b\u064a {filename}; \u062e\u0631\u0645\u063a {allowedFiles} \u0634\u0642\u062b \u0634\u0645\u0645\u062e\u0635\u062b\u064a.", "You waive some rights for your work, such that others can use it too": "\u063a\u062e\u0639 \u0635\u0634\u0647\u062f\u062b \u0633\u062e\u0648\u062b \u0642\u0647\u0644\u0627\u0641\u0633 \u0628\u062e\u0642 \u063a\u062e\u0639\u0642 \u0635\u062e\u0642\u0646, \u0633\u0639\u0630\u0627 \u0641\u0627\u0634\u0641 \u062e\u0641\u0627\u062b\u0642\u0633 \u0630\u0634\u0631 \u0639\u0633\u062b \u0647\u0641 \u0641\u062e\u062e", "You will be refunded the amount you paid.": "\u063a\u062e\u0639 \u0635\u0647\u0645\u0645 \u0632\u062b \u0642\u062b\u0628\u0639\u0631\u064a\u062b\u064a \u0641\u0627\u062b \u0634\u0648\u062e\u0639\u0631\u0641 \u063a\u062e\u0639 \u062d\u0634\u0647\u064a.", @@ -2061,6 +2127,7 @@ "and others": "\u0634\u0631\u064a \u062e\u0641\u0627\u062b\u0642\u0633", "anonymous": "\u0634\u0631\u062e\u0631\u063a\u0648\u062e\u0639\u0633", "answer": "\u0634\u0631\u0633\u0635\u062b\u0642", + "answered question": "\u0634\u0631\u0633\u0635\u062b\u0642\u062b\u064a \u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631", "asset_path is required": "\u0634\u0633\u0633\u062b\u0641_\u062d\u0634\u0641\u0627 \u0647\u0633 \u0642\u062b\u0636\u0639\u0647\u0642\u062b\u064a", "bytes": "\u0632\u063a\u0641\u062b\u0633", "certificate": "\u0630\u062b\u0642\u0641\u0647\u0628\u0647\u0630\u0634\u0641\u062b", @@ -2072,6 +2139,8 @@ "delete chapter": "\u064a\u062b\u0645\u062b\u0641\u062b \u0630\u0627\u0634\u062d\u0641\u062b\u0642", "delete group": "\u064a\u062b\u0645\u062b\u0641\u062b \u0644\u0642\u062e\u0639\u062d", "details about the failure": "\u064a\u062b\u0641\u0634\u0647\u0645\u0633 \u0634\u0632\u062e\u0639\u0641 \u0641\u0627\u062b \u0628\u0634\u0647\u0645\u0639\u0642\u062b", + "discussion": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631", + "discussion posted %(time_ago)s by %(author)s": "\u064a\u0647\u0633\u0630\u0639\u0633\u0633\u0647\u062e\u0631 \u062d\u062e\u0633\u0641\u062b\u064a %(time_ago)s \u0632\u063a %(author)s", "dragging": "\u064a\u0642\u0634\u0644\u0644\u0647\u0631\u0644", "dragging out of slider": "\u064a\u0642\u0634\u0644\u0644\u0647\u0631\u0644 \u062e\u0639\u0641 \u062e\u0628 \u0633\u0645\u0647\u064a\u062b\u0642", "dropped in slider": "\u064a\u0642\u062e\u062d\u062d\u062b\u064a \u0647\u0631 \u0633\u0645\u0647\u064a\u062b\u0642", @@ -2081,15 +2150,19 @@ "e.g. 'http://google.com'": "\u062b.\u0644. '\u0627\u0641\u0641\u062d://\u0644\u062e\u062e\u0644\u0645\u062b.\u0630\u062e\u0648'", "e.g. johndoe@example.com, JaneDoe, joeydoe@example.com": "\u062b.\u0644. \u062a\u062e\u0627\u0631\u064a\u062e\u062b@\u062b\u0637\u0634\u0648\u062d\u0645\u062b.\u0630\u062e\u0648, \u062a\u0634\u0631\u062b\u064a\u062e\u062b, \u062a\u062e\u062b\u063a\u064a\u062e\u062b@\u062b\u0637\u0634\u0648\u062d\u0645\u062b.\u0630\u062e\u0648", "emphasized text": "\u062b\u0648\u062d\u0627\u0634\u0633\u0647\u0638\u062b\u064a \u0641\u062b\u0637\u0641", + "endorsed %(time_ago)s": "\u062b\u0631\u064a\u062e\u0642\u0633\u062b\u064a %(time_ago)s", + "endorsed %(time_ago)s by %(user)s": "\u062b\u0631\u064a\u062e\u0642\u0633\u062b\u064a %(time_ago)s \u0632\u063a %(user)s", "enter code here": "\u062b\u0631\u0641\u062b\u0642 \u0630\u062e\u064a\u062b \u0627\u062b\u0642\u062b", "enter link description here": "\u062b\u0631\u0641\u062b\u0642 \u0645\u0647\u0631\u0646 \u064a\u062b\u0633\u0630\u0642\u0647\u062d\u0641\u0647\u062e\u0631 \u0627\u062b\u0642\u062b", + "follow this post": "\u0628\u062e\u0645\u0645\u062e\u0635 \u0641\u0627\u0647\u0633 \u062d\u062e\u0633\u0641", "for": "\u0628\u062e\u0642", - "for {courseName}": "\u0628\u062e\u0642 {courseName}", "group configuration": "\u0644\u0642\u062e\u0639\u062d \u0630\u062e\u0631\u0628\u0647\u0644\u0639\u0642\u0634\u0641\u0647\u062e\u0631", "image omitted": "\u0647\u0648\u0634\u0644\u062b \u062e\u0648\u0647\u0641\u0641\u062b\u064a", "incorrect": "\u0647\u0631\u0630\u062e\u0642\u0642\u062b\u0630\u0641", "last activity": "\u0645\u0634\u0633\u0641 \u0634\u0630\u0641\u0647\u062f\u0647\u0641\u063a", "less than a minute": "\u0645\u062b\u0633\u0633 \u0641\u0627\u0634\u0631 \u0634 \u0648\u0647\u0631\u0639\u0641\u062b", + "marked as answer %(time_ago)s": "\u0648\u0634\u0642\u0646\u062b\u064a \u0634\u0633 \u0634\u0631\u0633\u0635\u062b\u0642 %(time_ago)s", + "marked as answer %(time_ago)s by %(user)s": "\u0648\u0634\u0642\u0646\u062b\u064a \u0634\u0633 \u0634\u0631\u0633\u0635\u062b\u0642 %(time_ago)s \u0632\u063a %(user)s", "minute": "\u0648\u0647\u0631\u0639\u0641\u062b", "minutes": "\u0648\u0647\u0631\u0639\u0641\u062b\u0633", "name": "\u0631\u0634\u0648\u062b", @@ -2100,9 +2173,13 @@ "or create a new one here": "\u062e\u0642 \u0630\u0642\u062b\u0634\u0641\u062b \u0634 \u0631\u062b\u0635 \u062e\u0631\u062b \u0627\u062b\u0642\u062b", "or sign in with": "\u062e\u0642 \u0633\u0647\u0644\u0631 \u0647\u0631 \u0635\u0647\u0641\u0627", "path/to/introductionToCookieBaking-CH{order}.pdf": "\u062d\u0634\u0641\u0627/\u0641\u062e/\u0647\u0631\u0641\u0642\u062e\u064a\u0639\u0630\u0641\u0647\u062e\u0631\u0641\u062e\u0630\u062e\u062e\u0646\u0647\u062b\u0632\u0634\u0646\u0647\u0631\u0644-\u0630\u0627{order}.\u062d\u064a\u0628", + "post anonymously": "\u062d\u062e\u0633\u0641 \u0634\u0631\u062e\u0631\u063a\u0648\u062e\u0639\u0633\u0645\u063a", + "post anonymously to classmates": "\u062d\u062e\u0633\u0641 \u0634\u0631\u062e\u0631\u063a\u0648\u062e\u0639\u0633\u0645\u063a \u0641\u062e \u0630\u0645\u0634\u0633\u0633\u0648\u0634\u0641\u062b\u0633", + "posted %(time_ago)s by %(author)s": "\u062d\u062e\u0633\u0641\u062b\u064a %(time_ago)s \u0632\u063a %(author)s", "price": "\u062d\u0642\u0647\u0630\u062b", "provide the title/name of the chapter that will be used in navigating": "\u062d\u0642\u062e\u062f\u0647\u064a\u062b \u0641\u0627\u062b \u0641\u0647\u0641\u0645\u062b/\u0631\u0634\u0648\u062b \u062e\u0628 \u0641\u0627\u062b \u0630\u0627\u0634\u062d\u0641\u062b\u0642 \u0641\u0627\u0634\u0641 \u0635\u0647\u0645\u0645 \u0632\u062b \u0639\u0633\u062b\u064a \u0647\u0631 \u0631\u0634\u062f\u0647\u0644\u0634\u0641\u0647\u0631\u0644", "provide the title/name of the text book as you would like your students to see it": "\u062d\u0642\u062e\u062f\u0647\u064a\u062b \u0641\u0627\u062b \u0641\u0647\u0641\u0645\u062b/\u0631\u0634\u0648\u062b \u062e\u0628 \u0641\u0627\u062b \u0641\u062b\u0637\u0641 \u0632\u062e\u062e\u0646 \u0634\u0633 \u063a\u062e\u0639 \u0635\u062e\u0639\u0645\u064a \u0645\u0647\u0646\u062b \u063a\u062e\u0639\u0642 \u0633\u0641\u0639\u064a\u062b\u0631\u0641\u0633 \u0641\u062e \u0633\u062b\u062b \u0647\u0641", + "question posted %(time_ago)s by %(author)s": "\u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631 \u062d\u062e\u0633\u0641\u062b\u064a %(time_ago)s \u0632\u063a %(author)s", "remove": "\u0642\u062b\u0648\u062e\u062f\u062b", "remove all": "\u0642\u062b\u0648\u062e\u062f\u062b \u0634\u0645\u0645", "second": "\u0633\u062b\u0630\u062e\u0631\u064a", @@ -2114,6 +2191,7 @@ "team count": "\u0641\u062b\u0634\u0648 \u0630\u062e\u0639\u0631\u0641", "text_word_{uniqueId}": "\u0641\u062b\u0637\u0641_\u0635\u062e\u0642\u064a_{uniqueId}", "text_word_{uniqueId} title_word_{uniqueId}": "\u0641\u062b\u0637\u0641_\u0635\u062e\u0642\u064a_{uniqueId} \u0641\u0647\u0641\u0645\u062b_\u0635\u062e\u0642\u064a_{uniqueId}", + "the more quickly and helpfully we can respond!": "\u0641\u0627\u062b \u0648\u062e\u0642\u062b \u0636\u0639\u0647\u0630\u0646\u0645\u063a \u0634\u0631\u064a \u0627\u062b\u0645\u062d\u0628\u0639\u0645\u0645\u063a \u0635\u062b \u0630\u0634\u0631 \u0642\u062b\u0633\u062d\u062e\u0631\u064a!", "there is currently {numVotes} vote": [ "\u0641\u0627\u062b\u0642\u062b \u0647\u0633 \u0630\u0639\u0642\u0642\u062b\u0631\u0641\u0645\u063a {numVotes} \u062f\u062e\u0641\u062b", "\u0641\u0627\u062b\u0642\u062b \u0634\u0642\u062b \u0630\u0639\u0642\u0642\u062b\u0631\u0641\u0645\u063a {numVotes} \u062f\u062e\u0641\u062b\u0633" @@ -2121,6 +2199,7 @@ "title_word_{uniqueId}": "\u0641\u0647\u0641\u0645\u062b_\u0635\u062e\u0642\u064a_{uniqueId}", "toggle chapter %(displayName)s": "\u0641\u062e\u0644\u0644\u0645\u062b \u0630\u0627\u0634\u062d\u0641\u062b\u0642 %(displayName)s", "toggle subsection %(displayName)s": "\u0641\u062e\u0644\u0644\u0645\u062b \u0633\u0639\u0632\u0633\u062b\u0630\u0641\u0647\u062e\u0631 %(displayName)s", + "unanswered question": "\u0639\u0631\u0634\u0631\u0633\u0635\u062b\u0642\u062b\u064a \u0636\u0639\u062b\u0633\u0641\u0647\u062e\u0631", "unit": "\u0639\u0631\u0647\u0641", "unsubmitted": "\u0639\u0631\u0633\u0639\u0632\u0648\u0647\u0641\u0641\u062b\u064a", "upload a PDF file or provide the path to a Studio asset file": "\u0639\u062d\u0645\u062e\u0634\u064a \u0634 \u062d\u064a\u0628 \u0628\u0647\u0645\u062b \u062e\u0642 \u062d\u0642\u062e\u062f\u0647\u064a\u062b \u0641\u0627\u062b \u062d\u0634\u0641\u0627 \u0641\u062e \u0634 \u0633\u0641\u0639\u064a\u0647\u062e \u0634\u0633\u0633\u062b\u0641 \u0628\u0647\u0645\u062b", @@ -2217,6 +2296,7 @@ ], "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}": "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}", "{type} Progress": "{type} \u062d\u0642\u062e\u0644\u0642\u062b\u0633\u0633", + "{unread_comments_count} new": "{unread_comments_count} \u0631\u062b\u0635", "\u2026": "\u2026" }; for (var key in newcatalog) { @@ -2239,7 +2319,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2303,9 +2383,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/ru/djangojs.js b/lms/static/js/i18n/ru/djangojs.js index b52cf6d11bacd37aa7b8e4ecfe4ff7c2d6badd8a..885aa1addf59ccddb624fa3e7dd1972ea28e7c82 100644 --- a/lms/static/js/i18n/ru/djangojs.js +++ b/lms/static/js/i18n/ru/djangojs.js @@ -568,7 +568,6 @@ "Default (Local Time Zone)": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e (\u043c\u0435\u0441\u0442\u043d\u044b\u0439 \u0447\u0430\u0441\u043e\u0432\u043e\u0439 \u043f\u043e\u044f\u0441)", "Default Timed Transcript": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e", "Delete": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u00ab<%= signatoryName %>\u00bb \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u0435\u043b\u0435\u0439?", "Delete File Confirmation": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430", "Delete My Account": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043c\u043e\u0439 \u0430\u043a\u043a\u0430\u0443\u043d\u0442", "Delete Team": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443", @@ -604,7 +603,6 @@ "Do you want to upload your file before submitting?": "\u0412\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u0434\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043e\u0442\u0432\u0435\u0442\u0430?", "Document properties": "\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430", "Does the name on your ID match your account name: %(fullName)s?": "\u0421\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043b\u0438 \u0438\u043c\u044f \u0432 \u0432\u0430\u0448\u0435\u043c \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0438 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u0432 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438: %(fullName)s?", - "Does the photo of you match your ID photo?": "\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c\u0430 \u043b\u0438 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f \u0441 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0435\u0439 \u0432 \u0432\u0430\u0448\u0435\u043c \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0438 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438?", "Does the photo of you show your whole face?": "\u0412\u0438\u0434\u043d\u043e \u043b\u0438 \u043d\u0430 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 \u0432\u0430\u0448\u0435 \u043b\u0438\u0446\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c?", "Doing so means that you are no longer eligible for academic credit.": "\u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u0430\u0447\u0451\u0442\u043d\u044b\u0439 \u0431\u0430\u043b\u043b\u044b.", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u041d\u0435 \u0432\u0438\u0434\u0438\u0442\u0435 \u0432\u0430\u0448\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435? \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u044b \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u043b\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0431-\u043a\u0430\u043c\u0435\u0440\u0443, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u043a \u043d\u0435\u0439 \u0434\u043e\u0441\u0442\u0443\u043f.", @@ -777,7 +775,6 @@ "Generate": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c", "Generate Exception Certificates": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b \u0434\u043b\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432", "Generate the user's certificate": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442", - "Get Credit": "\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u0430\u0447\u0451\u0442", "Go Back": "\u0412\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f", "Go to Dashboard": "\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f", "Go to my Dashboard": "\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043c\u043e\u0435\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f", @@ -851,7 +848,6 @@ "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u0415\u0441\u043b\u0438 \u0431\u043b\u043e\u043a \u0431\u044b\u043b \u043f\u0440\u0435\u0436\u0434\u0435 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044f\u043c, \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u0432\u043d\u0435\u0441\u0451\u043d\u043d\u044b\u0435 \u0432 \u043d\u0435\u0433\u043e, \u043f\u043e\u043a\u0430 \u043e\u043d \u0431\u044b\u043b \u0441\u043a\u0440\u044b\u0442, \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0435\u0439.", "If you do not yet have an account, use the button below to register.": "\u0415\u0449\u0451 \u043d\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b? \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u043d\u0438\u0436\u0435.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u0441\u0432\u043e\u0438 \u0434\u0430\u043d\u043d\u044b\u0435, \u0432\u044b \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u0443\u0440\u0441 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u043d\u0435\u043b\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0412\u044b \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0443\u0434\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u00ab%(platformName)s\u00bb.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u0441\u0432\u043e\u044e \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441, \u0432\u044b \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u0443\u0440\u0441\u0443 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u043d\u0435\u043b\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0412\u044b \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0443\u0434\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u044f \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u00ab{platformName}\u00bb.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043a\u0438\u043d\u0435\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0432 \u0438\u043b\u0438 \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0432 \u0441\u0432\u043e\u0439 \u043e\u0442\u0432\u0435\u0442, \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0439 \u0432\u0430\u043c\u0438 \u043e\u0442\u0432\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0442\u0435\u0440\u044f\u043d.", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043a\u0438\u043d\u0435\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0432 \u0432\u0430\u0448\u0443 \u043e\u0446\u0435\u043d\u043a\u0443, \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u0432\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u044b.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043a\u0438\u043d\u0435\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0432 \u0438\u043b\u0438 \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0432 \u0441\u0432\u043e\u0439 \u043e\u0442\u0432\u0435\u0442, \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435 \u0432\u0430\u043c\u0438 \u043e\u0442\u0432\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0442\u0435\u0440\u044f\u043d.", @@ -1495,7 +1491,6 @@ "Text to display": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442", "Textbook Name": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0443\u0447\u0435\u0431\u043d\u0438\u043a\u0430", "Textbook information": "\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u0443\u0447\u0435\u0431\u043d\u0438\u043a\u0435", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "\u0421\u043f\u0430\u0441\u0438\u0431\u043e, %(full_name)s! \u0412\u0430\u0448 \u043f\u043b\u0430\u0442\u0451\u0436 \u0437\u0430 \u043a\u0443\u0440\u0441 %(course_name)s \u043f\u0440\u0438\u043d\u044f\u0442.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u043c \u0432\u0430\u0441 \u0437\u0430 \u043f\u043e\u0434\u0430\u0447\u0443 \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0433\u0440\u0430\u043d\u0442 \u043f\u043e \u043a\u0443\u0440\u0441\u0443 {course_name}! \u0412\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0442\u0432\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 2-4 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0434\u043d\u044f.", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "\u0421\u043f\u0430\u0441\u0438\u0431\u043e, \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0444\u043e\u0442\u043e! \u041c\u044b \u0441\u043a\u043e\u0440\u043e \u0438\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c. \u0421\u0435\u0439\u0447\u0430\u0441 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u0438\u0437 \u043a\u0443\u0440\u0441\u043e\u0432 %(platformName)s, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0449\u0438\u0445 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u044b. \u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0434\u0438\u043d \u0433\u043e\u0434. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0444\u043e\u0442\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e.", "Thank you! We have received your payment for {courseName}.": "\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u043c \u0412\u0430\u0441! \u0412\u0430\u0448 \u043f\u043b\u0430\u0442\u0451\u0436 \u0437\u0430 \u043a\u0443\u0440\u0441 {courseName} \u043f\u0440\u0438\u043d\u044f\u0442.", @@ -1507,8 +1502,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0430\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043f\u0435\u0440\u0435\u0441\u0447\u0451\u0442 \u043e\u0446\u0435\u043d\u043a\u0438.", "The cohort cannot be added": "\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443", "The cohort cannot be saved": "\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u0421\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u0430\u044f \u0434\u043b\u0438\u043d\u0430 \u043a\u043e\u0434\u0430 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c <%=limit%> \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u0421\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u0430\u044f \u0434\u043b\u0438\u043d\u0430 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u043d\u043e\u043c\u0435\u0440\u0430 \u0438 \u043f\u0435\u0440\u0438\u043e\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u0430 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c <%=limit%> \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432.", "The country or region where you live.": "\u0421\u0442\u0440\u0430\u043d\u0430 \u0438\u043b\u0438 \u0440\u0435\u0433\u0438\u043e\u043d, \u0433\u0434\u0435 \u0432\u044b \u0436\u0438\u0432\u0451\u0442\u0435.", "The country that team members primarily identify with.": "\u0421\u0442\u0440\u0430\u043d\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043e\u0442\u043e\u0436\u0434\u0435\u0441\u0442\u0432\u043b\u044f\u044e\u0442 \u0441\u0435\u0431\u044f.", "The course end date must be later than the course start date.": "\u0414\u0430\u0442\u0430 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u0434\u0430\u0442\u044b \u043d\u0430\u0447\u0430\u043b\u0430 \u043a\u0443\u0440\u0441\u0430.", @@ -1523,7 +1516,6 @@ "The following email addresses and/or usernames are invalid:": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0430\u0434\u0440\u0435\u0441\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u0438/\u0438\u043b\u0438 \u0438\u043c\u0435\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b:", "The following errors were generated:": "\u0431\u044b\u043b\u0438 \u0434\u043e\u043f\u0443\u0449\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 ", "The following file types are not allowed: ": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0442\u0438\u043f\u044b \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0443\u0436\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043d\u0430 {platform}.", "The following message will be displayed at the bottom of the courseware pages within your course:": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043e \u0432\u043d\u0438\u0437\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u043a\u0443\u0440\u0441\u0430:", "The following options are available for the {license_name} license.": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u043f\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438 {license_name}", "The following users are no longer enrolled in the course:": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043e\u0442\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u0441 \u043a\u0443\u0440\u0441\u0430:", @@ -1538,7 +1530,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432 \u043a\u0443\u0440\u0441\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430.", "The organization that this signatory belongs to, as it should appear on certificates.": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043b\u0438\u0446\u043e, \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0432\u0448\u0435\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442.", "The page \"{route}\" could not be found.": "\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u00ab{route}\u00bb \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430.", - "The photo of your face matches the photo on your ID.": "\u0424\u043e\u0442\u043e \u0432\u0430\u0448\u0435\u0433\u043e \u043b\u0438\u0446\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0444\u043e\u0442\u043e \u0432 \u0432\u0430\u0448\u0435\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435.", "The post you selected has been deleted.": "\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u0430\u044f \u0432\u0430\u043c\u0438 \u0442\u0435\u043c\u0430 \u0431\u044b\u043b\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0430.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f, {published}, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0430 \u043d\u0430 \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e, {draft}.", "The raw error message is:": "\u041f\u043e\u043b\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435:", @@ -1645,7 +1636,6 @@ "Titles more than 100 characters may prevent students from printing their certificate on a single page.": "\u0415\u0441\u043b\u0438 \u0434\u043b\u0438\u043d\u0430 \u0437\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u0442 100 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u043f\u0435\u0447\u0430\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0439\u0442\u0438 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.", "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "\u0427\u0442\u043e\u0431\u044b \u0431\u044b\u0442\u044c \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u043c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0438\u0434\u0435\u043e, \u043c\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445 .mp4 \u0438 .webm. \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u043d\u0438\u0436\u0435, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0444\u0430\u0439\u043b \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 YouTube \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f. \u041d\u0430 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044f \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e \u043f\u0435\u0440\u0432\u043e\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0435 \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u0435\u043e \u0438\u0437 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430.", "To complete the program, you must earn a verified certificate for each course.": "\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0440\u043e\u0439\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043a\u0443\u0440\u0441\u0443.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u0430\u0447\u0451\u0442\u043d\u044b\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u044b, %(display_name)s \u043e\u0442 %(platform_name)s \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u0434\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441.", "To invalidate a certificate for a particular learner, add the username or email address below.": "\u0414\u043b\u044f \u0430\u043d\u043d\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0441\u044e\u0434\u0430 \u0435\u0433\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441.", "To pass this exam, you must complete the problems in the time allowed.": "\u0412\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0432\u0441\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.", "To receive a certificate, you must also verify your identity before {date}.": "\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430 \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u044c \u0434\u043e {date}.", @@ -1751,7 +1741,6 @@ "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0436\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0439. \u0412\u0441\u0435 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0440\u0435\u0436\u0438\u043c\u0430 \u0437\u0430\u043f\u0438\u0441\u0438, \u0432\u0438\u0434\u044f\u0442 \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0442\u0435\u043c\u044b \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0439, \u043d\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438 \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c \u0440\u0435\u0436\u0438\u043c\u043e\u043c \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043d\u0430 \u0447\u0443\u0436\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f.", "Use my institution/campus credentials": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0439 \u043b\u043e\u0433\u0438\u043d \u0438 \u043f\u0430\u0440\u043e\u043b\u044c", "Use the All Topics menu to find specific topics.": "\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0439\u0442\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u0442\u0435\u043c\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043c\u0435\u043d\u044e \u00ab\u0412\u0441\u0435 \u0442\u0435\u043c\u044b\u00bb.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u041f\u043e\u043b\u044c\u0437\u0443\u044f\u0441\u044c \u0432\u0435\u0431-\u043a\u0430\u043c\u0435\u0440\u043e\u0439, \u0441\u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0441\u043d\u0438\u043c\u043e\u043a \u0441\u0432\u043e\u0435\u0433\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u044f \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438. \u041c\u044b \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u044d\u0442\u043e\u0442 \u0441\u043d\u0438\u043c\u043e\u043a \u0441\u043e \u0441\u043d\u0438\u043c\u043a\u043e\u043c \u0432\u0430\u0448\u0435\u0433\u043e \u043b\u0438\u0446\u0430 \u0438 \u0438\u043c\u0435\u043d\u0435\u043c \u0432 \u0432\u0430\u0448\u0435\u0439 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u041f\u043e\u043b\u044c\u0437\u0443\u044f\u0441\u044c \u0432\u0435\u0431-\u043a\u0430\u043c\u0435\u0440\u043e\u0439, \u0441\u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0441\u043d\u0438\u043c\u043e\u043a \u0441\u0432\u043e\u0435\u0433\u043e \u043b\u0438\u0446\u0430. \u041c\u044b \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u044d\u0442\u043e\u0442 \u0441\u043d\u0438\u043c\u043e\u043a \u0441 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0435\u0439 \u0432 \u0432\u0430\u0448\u0435\u043c \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0438 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438.", "Used": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043e", "User Email": "\u0410\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", @@ -1771,7 +1760,6 @@ "Verified Certificate upgrade": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430", "Verified Status": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u044b\u0439 \u0441\u0442\u0430\u0442\u0443\u0441", "Verified mode price": "\u0421\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430", - "Verify Now": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c", "Vertical space": "\u041e\u0442\u0441\u0442\u0443\u043f \u043f\u043e \u0432\u044b\u0441\u043e\u0442\u0435", "Very loud": "\u041e\u0447\u0435\u043d\u044c \u0433\u0440\u043e\u043c\u043a\u043e", "Very low": "\u041e\u0447\u0435\u043d\u044c \u0442\u0438\u0445\u043e", @@ -1810,7 +1798,6 @@ "We couldn't find any results for \"%s\".": "\u041d\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0434\u043b\u044f \u00ab%s\u00bb.", "We couldn't sign you in.": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u043e\u0439\u0442\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.", "We have encountered an error. Refresh your browser and then try again.": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430. \u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "\u041c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0432\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0438\u0445 \u0432 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f (1-2 \u0434\u043d\u044f). \u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u044b, \u043d\u0430 \u0432\u0430\u0448\u0435\u0439 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0435. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0432\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u0441\u0435 \u0443\u0447\u0435\u0431\u043d\u044b\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b.", "We just need a little more information before you start learning with %(platformName)s.": "\u041f\u0435\u0440\u0435\u0434 \u043d\u0430\u0447\u0430\u043b\u043e\u043c \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 \u00ab%(platformName)s\u00bb \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0430\u043c\u044b\u0439 \u0432\u044b\u0441\u043e\u043a\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0437\u0430\u0449\u0438\u0449\u0451\u043d\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u0444\u043e\u0442\u043e \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0435\u0433\u043e \u043d\u0430 \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u0412\u0430\u0448\u0430 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u0438\u0433\u0434\u0435 \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 \u00ab%(platformName)s\u00bb \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d.", "We've encountered an error. Refresh your browser and then try again.": "\u0412\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430. \u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437.", @@ -1891,11 +1878,8 @@ "You must sign out and sign back in before your language changes take effect.": "\u0427\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u044f\u0437\u044b\u043a\u0430 \u0432\u0441\u0442\u0443\u043f\u0438\u043b\u043e \u0432 \u0441\u0438\u043b\u0443, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u0439\u0442\u0438 \u0438 \u0441\u043d\u043e\u0432\u0430 \u0432\u043e\u0439\u0442\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.", "You must specify a name for the cohort": "\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u0443", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u0414\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0433\u043e\u0434 \u0432\u0430\u0448\u0435\u0433\u043e \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0432 {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u0412\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u0430, \u043f\u0430\u0441\u043f\u043e\u0440\u0442 \u0438\u043b\u0438 \u0438\u043d\u043e\u0439 \u0433\u043e\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0435\u0441\u0442\u044c \u0432\u0430\u0448\u0435 \u0438\u043c\u044f \u0438 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u0412\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0435 \u043b\u0438\u0447\u043d\u043e\u0441\u0442\u0438 \u0441 \u0432\u0430\u0448\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c \u0438 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0435\u0439. \u041f\u043e\u0434\u043e\u0439\u0434\u0451\u0442 \u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0435\u043d\u0438\u0435, \u043f\u0430\u0441\u043f\u043e\u0440\u0442 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u0433\u043e\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0437\u0446\u0430.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043a\u0443\u0440\u0441\u044b, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0443\u0447\u0451\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c. \u041f\u0438\u0441\u044c\u043c\u043e \u0434\u043b\u044f \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u0438 \u0432\u044b\u0441\u043b\u0430\u043d\u043e \u0432\u0430\u043c \u043d\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0443\u044e \u043f\u043e\u0447\u0442\u0443.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043a\u0443\u0440\u0441\u044b, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0443\u0447\u0451\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c. \u041f\u0438\u0441\u044c\u043c\u043e \u0434\u043b\u044f \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u0438 \u0432\u044b\u0441\u043b\u0430\u043d\u043e \u0432\u0430\u043c \u043d\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0443\u044e \u043f\u043e\u0447\u0442\u0443. \u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044e, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u0442\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0435\u0451.", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u0412\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u044c %(display_name)s \u0432\u0435\u0431-\u0441\u0430\u0439\u0442 \u0434\u043b\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u043a\u0443\u043f\u043a\u0438.", "You submitted {filename}; only {allowedFiles} are allowed.": "\u0412\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b\u0438 \u0444\u0430\u0439\u043b {filename}; \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u044b {allowedFiles}.", "You will be refunded the amount you paid.": "\u0412\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u0430 \u0441\u0443\u043c\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u044b \u0437\u0430\u043f\u043b\u0430\u0442\u0438\u043b\u0438.", "You will not be refunded the amount you paid.": "\u0412\u0430\u043c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u0430 \u0441\u0443\u043c\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u044b \u0437\u0430\u043f\u043b\u0430\u0442\u0438\u043b\u0438.", @@ -2098,7 +2082,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2154,9 +2138,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/si/djangojs.js b/lms/static/js/i18n/si/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/lms/static/js/i18n/si/djangojs.js +++ b/lms/static/js/i18n/si/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/sk/djangojs.js b/lms/static/js/i18n/sk/djangojs.js index 8a6b91d45074213dd2e5e1ab46dc8c8f0546d81a..ee1356ee745f156be44e68ec2e568ac79be9cf1d 100644 --- a/lms/static/js/i18n/sk/djangojs.js +++ b/lms/static/js/i18n/sk/djangojs.js @@ -23,9 +23,11 @@ "%(sel)s of %(cnt)s selected": [ "%(sel)s z %(cnt)s vybran\u00e9", "%(sel)s z %(cnt)s vybran\u00e9", + "%(sel)s z %(cnt)s vybran\u00fdch", "%(sel)s z %(cnt)s vybran\u00fdch" ], "6 a.m.": "6:00", + "6 p.m.": "18:00", "A valid email address is required": "Vy\u017eaduje sa platn\u00e1 e-mailov\u00e1 adresa", "ABCDEFGHIJKLMNOPQRSTUVWXYZ": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "Account": "\u00da\u010det", @@ -52,12 +54,14 @@ "Amount": "\u010ciastka", "Anchor": "Ukotvi\u0165", "Anchors": "Ukotvenia", + "April": "apr\u00edl", "Are you sure you want to delete this update?": "Skuto\u010dne chcete odstr\u00e1ni\u0165 t\u00fato aktualiz\u00e1ciu?", "Are you sure you want to delete {email} from the course team for \u201c{container}\u201d?": "Skuto\u010dne chcete vymaza\u0165 {email} z t\u00edmu spravuj\u00faceho kurz pre \u201c{container}\u201d?", "Are you sure you want to delete {email} from the library \u201c{container}\u201d?": "Skuto\u010dne chcete odstr\u00e1ni\u0165 {email} z kni\u017enice \u201c{container}\u201d?", "Are you sure you want to restrict {email} access to \u201c{container}\u201d?": "Naozaj chcete obmedzi\u0165 {email} pr\u00edstup ku \u201c{container}\u201d?", "Are you sure you wish to delete this item. It cannot be reversed!\n\nAlso any content that links/refers to this item will no longer work (e.g. broken images and/or links)": "Skuto\u010dne si prajete odstr\u00e1ni\u0165 t\u00fato polo\u017eku? Tento stav nie je mo\u017en\u00e9 zvr\u00e1ti\u0165!\n\nTaktie\u017e ak\u00fdko\u013evek obsah, ktor\u00fd odkazuje na t\u00fato polo\u017eku, nebude viac funk\u010dn\u00fd (t.j. nena\u010d\u00edtan\u00e9 obr\u00e1zky a/alebo nefunk\u010dn\u00e9 odkazy)", "Are you sure?": "Ste si ist\u00ed?", + "August": "august", "Author": "Autor", "Available %s": "Dostupn\u00e9 %s", "Average": "Priemern\u00fd", @@ -87,6 +91,8 @@ "Changes to steps that are not selected as part of the assignment will not be saved.": "Zmeny pre kroky, ktor\u00e9 nie s\u00fa zvolen\u00e9 ako s\u00fa\u010das\u0165 tohto zadania, nebud\u00fa ulo\u017een\u00e9.", "Choose": "Vybra\u0165", "Choose File": "Vybra\u0165 s\u00fabor", + "Choose a Date": "Vybra\u0165 D\u00e1tum", + "Choose a Time": "Vybra\u0165 \u010cas", "Choose a time": "Vybra\u0165 \u010das", "Choose all": "Vybra\u0165 v\u0161etko", "Chosen %s": "Vybran\u00e9 %s", @@ -138,6 +144,7 @@ "Cut row": "Vystrihn\u00fa\u0165 riadok", "Date": "D\u00e1tum", "Date Added": "Doplnen\u00fd d\u00e1tum", + "December": "december", "Decrease indent": "Zmen\u0161i\u0165 odsadenie", "Default": "Predvolen\u00e9", "Delete": "Odstr\u00e1ni\u0165", @@ -179,6 +186,7 @@ "Errors": "Chyby", "Exit full browser": "Ukon\u010di\u0165 re\u017eim celej obrazovky", "Expand Instructions": "Roz\u0161\u00edri\u0165 in\u0161trukcie", + "February": "febru\u00e1r", "File": "S\u00fabor", "File type is not allowed.": "Typ s\u00faboru nie je povolen\u00fd.", "File types can not be empty.": "Typy s\u00faborov nem\u00f4\u017eu by\u0165 pr\u00e1zdne.", @@ -258,6 +266,9 @@ "Insert/edit video": "Vlo\u017ei\u0165/editova\u0165 video", "Italic": "Kurz\u00edva", "Italic (Ctrl+I)": "Kurz\u00edva (Ctrl+I)", + "January": "janu\u00e1r", + "July": "j\u00fal", + "June": "j\u00fan", "Justify": "Zarovna\u0165", "Key should only contain letters, numbers, _, or -": "K\u013e\u00fa\u010d by mal obsahova\u0165 iba p\u00edsmen\u00e1, \u010d\u00edsla, _, alebo -", "Keywords": "K\u013e\u00fa\u010dov\u00e9 slov\u00e1", @@ -276,8 +287,10 @@ "Loading more threads": "Na\u010d\u00edta\u0165 viac vl\u00e1kien", "Loud": "Hlasn\u00fd", "Low": "N\u00edzko", + "March": "marec", "Max file size exceeded": "Prekro\u010den\u00e1 maxim\u00e1lna ve\u013ekos\u0165", "Maximum": "Maximum", + "May": "m\u00e1j", "Membership": "\u010clenstvo", "Merge cells": "Zl\u00fa\u010di\u0165 bunky", "Middle": "Stredn\u00e9", @@ -303,19 +316,23 @@ "Note: You are %s hour ahead of server time.": [ "Pozn\u00e1mka: Ste %s hodinu pred \u010dasom servera.", "Pozn\u00e1mka: Ste %s hodiny pred \u010dasom servera.", + "Pozn\u00e1mka: Ste %s hod\u00edn pred \u010dasom servera.", "Pozn\u00e1mka: Ste %s hod\u00edn pred \u010dasom servera." ], "Note: You are %s hour behind server time.": [ "Pozn\u00e1mka: Ste %s hodinu za \u010dasom servera.", "Pozn\u00e1mka: Ste %s hodiny za \u010dasom servera.", + "Pozn\u00e1mka: Ste %s hod\u00edn za \u010dasom servera.", "Pozn\u00e1mka: Ste %s hod\u00edn za \u010dasom servera." ], "Noted in:": "Pridan\u00e1 pozn\u00e1mka v:", + "November": "november", "Now": "Teraz", "Number of Students": "Po\u010det \u0161tudentov", "Numbered List (Ctrl+O)": "\u010c\u00edslovan\u00fd zoznam (Ctrl+O)", "Numbered list": "\u010c\u00edslovan\u00fd zoznam", "OK": "OK", + "October": "okt\u00f3ber", "Ok": "Ok", "One or more rescheduling tasks failed.": "Jedna alebo viac \u00faloh pre zmenu term\u00ednu zlyhala.", "Open Calculator": "Otvori\u0165 kalkula\u010dku", @@ -394,6 +411,7 @@ "Search teams": "H\u013eadanie t\u00edmov", "Select all": "Vybra\u0165 v\u0161etko", "Sent By": "Odoslan\u00e9", + "September": "september", "Set up your certificate": "Nastavenie v\u00e1\u0161ho certifik\u00e1tu", "Settings": "Nastavenia", "Short explanation": "kr\u00e1tke vysvetlenie", @@ -575,6 +593,13 @@ "last activity": "posledn\u00e1 aktivita", "less than a minute": "menej ako min\u00fatu", "name": "n\u00e1zov", + "one letter Friday\u0004F": "P", + "one letter Monday\u0004M": "P", + "one letter Saturday\u0004S": "S", + "one letter Sunday\u0004S": "N", + "one letter Thursday\u0004T": "\u0160", + "one letter Tuesday\u0004T": "U", + "one letter Wednesday\u0004W": "S", "open slots": "vo\u013en\u00e9 sloty", "remove": "vymaza\u0165", "remove all": "vymaza\u0165 v\u0161etko", @@ -602,7 +627,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -655,9 +680,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y G:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/sl/djangojs.js b/lms/static/js/i18n/sl/djangojs.js index 5cefeba49fa1aef57e22446ef893c0d2e17fe49e..740ec8172b47929278f200dad4228273ba6c0422 100644 --- a/lms/static/js/i18n/sl/djangojs.js +++ b/lms/static/js/i18n/sl/djangojs.js @@ -107,7 +107,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -178,9 +178,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j.n.Y. H:i", "SHORT_DATE_FORMAT": "j. M. Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/sq/djangojs.js b/lms/static/js/i18n/sq/djangojs.js index 514c688171b9ba8a0b190b9e5e5c8820284b3540..bddad372e1fbda85d54699ba35b43dc4b4d03f84 100644 --- a/lms/static/js/i18n/sq/djangojs.js +++ b/lms/static/js/i18n/sq/djangojs.js @@ -26,6 +26,8 @@ ], "6 a.m.": "6 a.m.", "6 p.m.": "6 p.m.", + "April": "Prill", + "August": "Gusht", "Available %s": "%s i gatsh\u00ebm", "Cancel": "Anuloje", "Choose": "Zgjidhni", @@ -36,9 +38,16 @@ "Chosen %s": "U zgjodh %s", "Click to choose all %s at once.": "Klikoni q\u00eb t\u00eb zgjidhen krejt %s nj\u00ebher\u00ebsh.", "Click to remove all chosen %s at once.": "Klikoni q\u00eb t\u00eb hiqen krejt %s e zgjedhura nj\u00ebher\u00ebsh.", + "December": "Dhjetor", "Error": "Problem", + "February": "Shkurt", "Filter": "Filtro", "Hide": "Fshihe", + "January": "Janar", + "July": "Korrik", + "June": "Qershor", + "March": "Mars", + "May": "Maj", "Midnight": "Mesnat\u00eb", "Noon": "Mesdit\u00eb", "Not Selected": "E pa selektuar", @@ -50,11 +59,14 @@ "Sh\u00ebnim: Jeni %s or\u00eb pas koh\u00ebs s\u00eb sh\u00ebrbyesit.", "Sh\u00ebnim: Jeni %s or\u00eb pas koh\u00ebs s\u00eb sh\u00ebrbyesit." ], + "November": "N\u00ebntor", "Now": "Tani", + "October": "Tetor", "Option Deleted": "Opsioni u fshia", "Remove": "Hiqe", "Remove all": "Hiqi krejt", "Saving...": "Ruaj...", + "September": "Shtator", "Show": "Shfaqe", "Status of Your Response": "Statusi i p\u00ebrgjigjjes suaj", "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "Kjo \u00ebsht\u00eb lista e %s t\u00eb gatsh\u00ebm. Mund t\u00eb zgjidhni disa duke i p\u00ebrzgjedhur te kutiza m\u00eb posht\u00eb dhe mandej duke klikuar mbi shigjet\u00ebn \"Zgjidhe\" mes dy kutizave.", @@ -70,7 +82,14 @@ "Yesterday": "Dje", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "Keni p\u00ebrzgjedhur nj\u00eb veprim, dhe nuk keni b\u00ebr\u00eb ndonj\u00eb ndryshim te fusha individuale. Ndoshta po k\u00ebrkonit p\u00ebr butonin Shko, n\u00eb vend se p\u00ebr butonin Ruaje.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "Keni p\u00ebrzgjedhur nj\u00eb veprim, por nuk keni ruajtur ende ndryshimet q\u00eb b\u00ebt\u00eb te fusha individuale. Ju lutemi, klikoni OK q\u00eb t\u00eb b\u00ebhet ruajtja. Do t\u2019ju duhet ta rib\u00ebni veprimin.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Keni ndryshime t\u00eb paruajtura te fusha individuale t\u00eb ndryshueshme. N\u00ebse kryeni nj\u00eb veprim, ndryshimet e paruajtura do t\u00eb humbin." + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "Keni ndryshime t\u00eb paruajtura te fusha individuale t\u00eb ndryshueshme. N\u00ebse kryeni nj\u00eb veprim, ndryshimet e paruajtura do t\u00eb humbin.", + "one letter Friday\u0004F": "P", + "one letter Monday\u0004M": "H", + "one letter Saturday\u0004S": "S", + "one letter Sunday\u0004S": "D", + "one letter Thursday\u0004T": "E", + "one letter Tuesday\u0004T": "M", + "one letter Wednesday\u0004W": "M" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -92,7 +111,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -156,9 +175,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "Y-m-d", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/sr/djangojs.js b/lms/static/js/i18n/sr/djangojs.js index 58f1e74e22b6ccee660b211da7682260814acaf4..5a4be1d7f3e34c2a379793cf948c0837732ea11c 100644 --- a/lms/static/js/i18n/sr/djangojs.js +++ b/lms/static/js/i18n/sr/djangojs.js @@ -26,21 +26,46 @@ "%(sel)s \u043e\u0434 %(cnt)s \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0438\u0445" ], "6 a.m.": "18\u0447", + "6 p.m.": "18\u0447", + "April": "\u0410\u043f\u0440\u0438\u043b", + "August": "\u0410\u0432\u0433\u0443\u0441\u0442", "Available %s": "\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0438 %s", "Cancel": "\u041f\u043e\u043d\u0438\u0448\u0442\u0438", "Choose": "\u0418\u0437\u0430\u0431\u0435\u0440\u0438", + "Choose a Date": "\u041e\u0434\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0430\u0442\u0443\u043c", + "Choose a Time": "\u041e\u0434\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0440\u0435\u043c\u0435", "Choose a time": "\u041e\u0434\u0430\u0431\u0438\u0440 \u0432\u0440\u0435\u043c\u0435\u043d\u0430", "Choose all": "\u0418\u0437\u0430\u0431\u0435\u0440\u0438 \u0441\u0432\u0435", "Chosen %s": "\u0418\u0437\u0430\u0431\u0440\u0430\u043d\u043e \u201e%s\u201c", "Click to choose all %s at once.": "\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0432\u0435 \u201e%s\u201c \u043e\u0434\u0458\u0435\u0434\u043d\u043e\u043c.", "Click to remove all chosen %s at once.": "\u0423\u043a\u043b\u043e\u043d\u0438\u0442\u0435 \u0441\u0432\u0435 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0435 \u201e%s\u201c \u043e\u0434\u0458\u0435\u0434\u043d\u043e\u043c.", + "December": "\u0414\u0435\u0446\u0435\u043c\u0431\u0430\u0440", + "February": "\u0424\u0435\u0431\u0440\u0443\u0430\u0440", "Filter": "\u0424\u0438\u043b\u0442\u0435\u0440", "Hide": "\u0421\u0430\u043a\u0440\u0438\u0458", + "January": "\u0408\u0430\u043d\u0443\u0430\u0440", + "July": "\u0408\u0443\u043b", + "June": "\u0408\u0443\u043d", + "March": "\u041c\u0430\u0440\u0442", + "May": "\u041c\u0430\u0458", "Midnight": "\u041f\u043e\u043d\u043e\u045b", "Noon": "\u041f\u043e\u0434\u043d\u0435", + "Note: You are %s hour ahead of server time.": [ + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442 \u0441\u0442\u0435 \u0438\u0441\u043f\u0440\u0435\u0434 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430.", + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442\u0430 \u0441\u0442\u0435 \u0438\u0441\u043f\u0440\u0435\u0434 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430.", + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442\u0438 \u0441\u0442\u0435 \u0438\u0441\u043f\u0440\u0435\u0434 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430." + ], + "Note: You are %s hour behind server time.": [ + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442 \u0441\u0442\u0435 \u0438\u0437\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430.", + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442\u0430 \u0441\u0442\u0435 \u0438\u0437\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430.", + "\u041e\u0431\u0430\u0432\u0435\u0448\u0442\u0435\u045a\u0435: %s \u0441\u0430\u0442\u0438 \u0441\u0442\u0435 \u0438\u0437\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0441\u043a\u043e\u0433 \u0432\u0440\u0435\u043c\u0435\u043d\u0430." + ], + "November": "\u041d\u043e\u0432\u0435\u043c\u0431\u0430\u0440", "Now": "\u0422\u0440\u0435\u043d\u0443\u0442\u043d\u043e \u0432\u0440\u0435\u043c\u0435", + "October": "\u041e\u043a\u0442\u043e\u0431\u0430\u0440", "Remove": "\u0423\u043a\u043b\u043e\u043d\u0438", "Remove all": "\u0423\u043a\u043b\u043e\u043d\u0438 \u0441\u0432\u0435", + "September": "\u0421\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440", "Show": "\u041f\u043e\u043a\u0430\u0436\u0438", "This is the list of available %s. You may choose some by selecting them in the box below and then clicking the \"Choose\" arrow between the two boxes.": "\u041e\u0432\u043e \u0458\u0435 \u043b\u0438\u0441\u0442\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0445 \u201e%s\u201c. \u041c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u0430\u0431\u0440\u0430\u0442\u0438 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0435 \u0442\u0430\u043a\u043e \u0448\u0442\u043e \u045b\u0435\u0442\u0435 \u0438\u0445 \u0438\u0437\u0430\u0431\u0440\u0430\u0442\u0438 \u0443 \u043b\u0438\u0441\u0442\u0438 \u0438 \u043a\u043b\u0438\u043a\u043d\u0443\u0442\u0438 \u043d\u0430 \u201e\u0418\u0437\u0430\u0431\u0435\u0440\u0438\u201c.", "This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the \"Remove\" arrow between the two boxes.": "\u041e\u0432\u043e \u0458\u0435 \u043b\u0438\u0441\u0442\u0430 \u0438\u0437\u0430\u0431\u0440\u0430\u043d\u0438\u0445 \u201e%s\u201c. \u041c\u043e\u0436\u0435\u0442\u0435 \u0443\u043a\u043b\u043e\u043d\u0438\u0442\u0438 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0435 \u0442\u0430\u043a\u043e \u0448\u0442\u043e \u045b\u0435\u0442\u0435 \u0438\u0445 \u0438\u0437\u0430\u0431\u0440\u0430\u0442\u0438 \u0443 \u043b\u0438\u0441\u0442\u0438 \u0438 \u043a\u043b\u0438\u043a\u043d\u0443\u0442\u0438 \u043d\u0430 \u201e\u0423\u043a\u043b\u043e\u043d\u0438\u201c.", @@ -50,7 +75,14 @@ "Yesterday": "\u0408\u0443\u0447\u0435", "You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.": "\u0418\u0437\u0430\u0431\u0440\u0430\u043b\u0438 \u0441\u0442\u0435 \u0430\u043a\u0446\u0438\u0458\u0443 \u0430\u043b\u0438 \u043d\u0438\u0441\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438 \u043d\u0438 \u0458\u0435\u0434\u043d\u043e \u043f\u043e\u0459\u0435.", "You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.": "\u0418\u0437\u0430\u0431\u0440\u0430\u043b\u0438 \u0441\u0442\u0435 \u0430\u043a\u0446\u0438\u0458\u0443 \u0430\u043b\u0438 \u043d\u0438\u0441\u0442\u0435 \u0441\u0430\u0447\u0443\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u043c\u0435\u043d\u0435 \u043f\u043e\u0459\u0430.", - "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "\u0418\u043c\u0430\u0442\u0435 \u043d\u0435\u0441\u0430\u0447\u0438\u0432\u0430\u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0435. \u0410\u043a\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0435\u0442\u0435 \u0430\u043a\u0446\u0438\u0458\u0443, \u0438\u0437\u043c\u0435\u043d\u0435 \u045b\u0435 \u0431\u0438\u0442\u0438 \u0438\u0437\u0433\u0443\u0431\u0459\u0435\u043d\u0435." + "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.": "\u0418\u043c\u0430\u0442\u0435 \u043d\u0435\u0441\u0430\u0447\u0438\u0432\u0430\u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0435. \u0410\u043a\u043e \u043f\u043e\u043a\u0440\u0435\u043d\u0435\u0442\u0435 \u0430\u043a\u0446\u0438\u0458\u0443, \u0438\u0437\u043c\u0435\u043d\u0435 \u045b\u0435 \u0431\u0438\u0442\u0438 \u0438\u0437\u0433\u0443\u0431\u0459\u0435\u043d\u0435.", + "one letter Friday\u0004F": "\u041f", + "one letter Monday\u0004M": "\u041f", + "one letter Saturday\u0004S": "\u0421", + "one letter Sunday\u0004S": "\u041d", + "one letter Thursday\u0004T": "\u0427", + "one letter Tuesday\u0004T": "\u0423", + "one letter Wednesday\u0004W": "\u0421" }; for (var key in newcatalog) { django.catalog[key] = newcatalog[key]; @@ -72,7 +104,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -138,9 +170,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j. F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j.m.Y. H:i", "SHORT_DATE_FORMAT": "j.m.Y.", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/sv/djangojs.js b/lms/static/js/i18n/sv/djangojs.js index 8351228d59e7681cee06c137475b91a348534b8e..410215dbe73b9d039c48b4991f4dfea4c780b9e5 100644 --- a/lms/static/js/i18n/sv/djangojs.js +++ b/lms/static/js/i18n/sv/djangojs.js @@ -101,7 +101,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -157,9 +157,9 @@ "%m/%d/%y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "Y-m-d H:i", "SHORT_DATE_FORMAT": "Y-m-d", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/sw/djangojs.js b/lms/static/js/i18n/sw/djangojs.js index 1b7f576bb5c53b938b58aec1dc858c538964e0c0..59dd4b1b4eab7231b9cac29ea1802e9663c5ee69 100644 --- a/lms/static/js/i18n/sw/djangojs.js +++ b/lms/static/js/i18n/sw/djangojs.js @@ -79,7 +79,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -143,9 +143,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/ta/djangojs.js b/lms/static/js/i18n/ta/djangojs.js index f0a891c0f2be4be6976395c24c63e7ebf693b3b4..f15ff7285b4d4c5df6e66bc93d95621af6a96afa 100644 --- a/lms/static/js/i18n/ta/djangojs.js +++ b/lms/static/js/i18n/ta/djangojs.js @@ -55,7 +55,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -119,9 +119,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M, Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/te/djangojs.js b/lms/static/js/i18n/te/djangojs.js index b4eb9bf12cec3ccba357564c42e518e36bab448e..1a65f9c18512f9875e0f8766f73592da64b4b223 100644 --- a/lms/static/js/i18n/te/djangojs.js +++ b/lms/static/js/i18n/te/djangojs.js @@ -57,7 +57,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -121,9 +121,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "j M Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/th/djangojs.js b/lms/static/js/i18n/th/djangojs.js index 2077af1c299308641013f2318a4337e472d88c4d..1748ce550a96cc4022d49a9f2b7f26c975791280 100644 --- a/lms/static/js/i18n/th/djangojs.js +++ b/lms/static/js/i18n/th/djangojs.js @@ -46,6 +46,7 @@ "(contains %(student_count)s students)" ], "6 a.m.": "\u0e2b\u0e01\u0e42\u0e21\u0e07\u0e40\u0e0a\u0e49\u0e32", + "6 p.m.": "\u0e2b\u0e01\u0e42\u0e21\u0e07\u0e40\u0e22\u0e47\u0e19", "A driver's license, passport, or government-issued ID with your name and photo.": "\u0e43\u0e1a\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e02\u0e31\u0e1a\u0e02\u0e35\u0e48 \u0e2b\u0e19\u0e31\u0e07\u0e2a\u0e37\u0e2d\u0e40\u0e14\u0e34\u0e19\u0e17\u0e32\u0e07\u0e2b\u0e23\u0e37\u0e2d\u0e40\u0e2d\u0e01\u0e2a\u0e32\u0e23\u0e17\u0e35\u0e48\u0e2d\u0e2d\u0e01\u0e42\u0e14\u0e22\u0e20\u0e32\u0e04\u0e23\u0e31\u0e10\u0e2d\u0e37\u0e48\u0e19\u0e46 \u0e17\u0e35\u0e48\u0e21\u0e35\u0e0a\u0e37\u0e48\u0e2d\u0e41\u0e25\u0e30\u0e23\u0e39\u0e1b\u0e20\u0e32\u0e1e\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13", "A driver's license, passport, or other government-issued ID with your name and photo": "\u0e04\u0e38\u0e13\u0e15\u0e49\u0e2d\u0e07\u0e21\u0e35\u0e43\u0e1a\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e02\u0e31\u0e1a\u0e02\u0e35\u0e48 \u0e2b\u0e19\u0e31\u0e07\u0e2a\u0e37\u0e2d\u0e40\u0e14\u0e34\u0e19\u0e17\u0e32\u0e07\u0e2b\u0e23\u0e37\u0e2d\u0e40\u0e2d\u0e01\u0e2a\u0e32\u0e23\u0e17\u0e35\u0e48\u0e2d\u0e2d\u0e01\u0e42\u0e14\u0e22\u0e20\u0e32\u0e04\u0e23\u0e31\u0e10\u0e2d\u0e37\u0e48\u0e19\u0e46 \u0e17\u0e35\u0e48\u0e21\u0e35\u0e0a\u0e37\u0e48\u0e2d\u0e41\u0e25\u0e30\u0e23\u0e39\u0e1b\u0e20\u0e32\u0e1e\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13", "A list of courses you have just enrolled in as a verified student": "\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e2b\u0e25\u0e31\u0e01\u0e2a\u0e39\u0e15\u0e23\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e44\u0e14\u0e49\u0e17\u0e33\u0e01\u0e32\u0e23\u0e25\u0e07\u0e17\u0e30\u0e40\u0e1a\u0e35\u0e22\u0e19\u0e40\u0e1b\u0e47\u0e19\u0e19\u0e31\u0e01\u0e40\u0e23\u0e35\u0e22\u0e19\u0e17\u0e35\u0e48\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e01\u0e32\u0e23\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19", @@ -90,6 +91,7 @@ "An error occurred. Please try again.": "\u0e40\u0e01\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 \u0e01\u0e23\u0e38\u0e13\u0e32\u0e25\u0e2d\u0e07\u0e43\u0e2b\u0e21\u0e48\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07", "An error occurred. Try again.": "\u0e40\u0e01\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 \u0e01\u0e23\u0e38\u0e13\u0e32\u0e25\u0e2d\u0e07\u0e43\u0e2b\u0e21\u0e48\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07", "An unexpected error occurred. Please try again.": "\u0e40\u0e01\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e04\u0e32\u0e14\u0e04\u0e34\u0e14 \u0e01\u0e23\u0e38\u0e13\u0e32\u0e25\u0e2d\u0e07\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07", + "April": "\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19", "Are you having trouble finding a team to join?": "\u0e04\u0e38\u0e13\u0e01\u0e33\u0e25\u0e31\u0e07\u0e21\u0e35\u0e1b\u0e31\u0e0d\u0e2b\u0e32\u0e43\u0e19\u0e01\u0e32\u0e23\u0e2b\u0e32\u0e17\u0e35\u0e21?", "Are you sure you want to delete this comment?": "\u0e04\u0e38\u0e13\u0e41\u0e19\u0e48\u0e43\u0e08\u0e2b\u0e23\u0e37\u0e2d\u0e27\u0e48\u0e32\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e17\u0e35\u0e48\u0e08\u0e30\u0e25\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e04\u0e34\u0e14\u0e40\u0e2b\u0e47\u0e19\u0e19\u0e35\u0e49", "Are you sure you want to delete this post?": "\u0e04\u0e38\u0e13\u0e41\u0e19\u0e48\u0e43\u0e08\u0e2b\u0e23\u0e37\u0e2d\u0e27\u0e48\u0e32\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e17\u0e35\u0e48\u0e08\u0e30\u0e25\u0e1a\u0e42\u0e1e\u0e2a\u0e15\u0e4c\u0e19\u0e35\u0e49", @@ -102,6 +104,7 @@ "As part of the verification process, you take a photo of both your face and a government-issued photo ID. Our authorization service confirms your identity by comparing the photo you take with the photo on your ID.": "\u0e43\u0e19\u0e2a\u0e48\u0e27\u0e19\u0e02\u0e2d\u0e07\u0e01\u0e23\u0e30\u0e1a\u0e27\u0e19\u0e01\u0e32\u0e23\u0e01\u0e32\u0e23\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19 \u0e04\u0e38\u0e13\u0e16\u0e48\u0e32\u0e22\u0e23\u0e39\u0e1b\u0e08\u0e32\u0e01\u0e43\u0e1a\u0e2b\u0e19\u0e49\u0e32\u0e41\u0e25\u0e30\u0e23\u0e39\u0e1b\u0e1b\u0e23\u0e30\u0e08\u0e33\u0e15\u0e31\u0e27\u0e17\u0e35\u0e48\u0e23\u0e31\u0e10\u0e2d\u0e2d\u0e01\u0e43\u0e2b\u0e49 \u0e01\u0e32\u0e23\u0e43\u0e2b\u0e49\u0e1a\u0e23\u0e34\u0e01\u0e32\u0e23\u0e02\u0e2d\u0e07\u0e40\u0e23\u0e32\u0e15\u0e49\u0e2d\u0e07\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e2d\u0e31\u0e15\u0e25\u0e31\u0e01\u0e29\u0e13\u0e4c\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e42\u0e14\u0e22\u0e01\u0e32\u0e23\u0e40\u0e1b\u0e23\u0e35\u0e22\u0e1a\u0e40\u0e17\u0e35\u0e22\u0e1a\u0e23\u0e39\u0e1b\u0e17\u0e35\u0e48\u0e16\u0e48\u0e32\u0e22\u0e01\u0e31\u0e1a\u0e23\u0e39\u0e1b\u0e1a\u0e31\u0e15\u0e23\u0e1b\u0e23\u0e30\u0e0a\u0e32\u0e0a\u0e19", "Assign students to cohorts by uploading a CSV file.": "\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e19\u0e31\u0e01\u0e40\u0e23\u0e35\u0e22\u0e19\u0e25\u0e07\u0e01\u0e25\u0e38\u0e48\u0e21\u0e42\u0e14\u0e22\u0e01\u0e32\u0e23\u0e2d\u0e31\u0e1e\u0e42\u0e2b\u0e25\u0e14\u0e44\u0e1f\u0e25\u0e4c CSV", "Associated Content Group": "\u0e01\u0e25\u0e38\u0e48\u0e21\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32\u0e17\u0e35\u0e48\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e02\u0e49\u0e2d\u0e07", + "August": "\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21", "Automatic": "\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34", "Available %s": "%s\u0e17\u0e35\u0e48\u0e21\u0e35\u0e2d\u0e22\u0e39\u0e48", "Back to sign in": "\u0e01\u0e25\u0e31\u0e1a\u0e44\u0e1b\u0e17\u0e35\u0e48\u0e40\u0e02\u0e49\u0e32\u0e2a\u0e39\u0e48\u0e23\u0e30\u0e1a\u0e1a", @@ -131,6 +134,8 @@ "Checkout with {processor}": "\u0e0a\u0e33\u0e23\u0e30\u0e40\u0e07\u0e34\u0e19\u0e14\u0e49\u0e27\u0e22 {processor}", "Choose": "\u0e40\u0e25\u0e37\u0e2d\u0e01", "Choose a .csv file": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e44\u0e1f\u0e25\u0e4c .csv", + "Choose a Date": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e27\u0e31\u0e19", + "Choose a Time": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e40\u0e27\u0e25\u0e32", "Choose a content group to associate": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e01\u0e25\u0e38\u0e48\u0e21\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32\u0e17\u0e35\u0e48\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e42\u0e22\u0e07\u0e01\u0e31\u0e19", "Choose a time": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e40\u0e27\u0e25\u0e32", "Choose all": "\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14", @@ -187,6 +192,7 @@ "Current tab": "\u0e41\u0e17\u0e47\u0e1a\u0e1b\u0e31\u0e08\u0e08\u0e38\u0e1a\u0e31\u0e19", "Date": "\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48", "Date Added": "\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\u0e40\u0e1e\u0e34\u0e48\u0e21", + "December": "\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21", "Delete": "\u0e25\u0e1a", "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u0e25\u0e1a \"<%= signatoryName %>\" \u0e08\u0e32\u0e01\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e01\u0e32\u0e23\u0e25\u0e07\u0e19\u0e32\u0e21?", "Delete File Confirmation": "\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e01\u0e32\u0e23\u0e25\u0e1a\u0e44\u0e1f\u0e25\u0e4c", @@ -261,6 +267,7 @@ "Errors": "\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14", "Expand All": "\u0e41\u0e2a\u0e14\u0e07\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14", "Explore your course!": "\u0e2a\u0e33\u0e23\u0e27\u0e08\u0e2b\u0e25\u0e31\u0e01\u0e2a\u0e39\u0e15\u0e23\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13", + "February": "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c", "File Name": "\u0e0a\u0e37\u0e48\u0e2d\u0e44\u0e1f\u0e25\u0e4c", "File {filename} exceeds maximum size of {maxFileSizeInMBs} MB": "\u0e44\u0e1f\u0e25\u0e4c {filename} \u0e40\u0e01\u0e34\u0e19\u0e02\u0e19\u0e32\u0e14\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 {maxFileSizeInMBs} MB", "Files must be in JPEG or PNG format.": "\u0e44\u0e1f\u0e25\u0e4c\u0e08\u0e30\u0e15\u0e49\u0e2d\u0e07\u0e2d\u0e22\u0e39\u0e48\u0e43\u0e19\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a JPEG \u0e2b\u0e23\u0e37\u0e2d PNG", @@ -308,8 +315,11 @@ "Instructor tools": "\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e21\u0e37\u0e2d\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e1c\u0e39\u0e49\u0e2a\u0e2d\u0e19", "Is your name on your ID readable?": "\u0e0a\u0e37\u0e48\u0e2d\u0e43\u0e19\u0e1a\u0e31\u0e15\u0e23\u0e1b\u0e23\u0e30\u0e0a\u0e32\u0e0a\u0e19\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e2d\u0e48\u0e32\u0e19\u0e44\u0e14\u0e49\u0e2b\u0e23\u0e37\u0e2d\u0e44\u0e21\u0e48?", "Italic (Ctrl+I)": "\u0e15\u0e31\u0e27\u0e40\u0e2d\u0e35\u0e22\u0e07 (Ctrl+I)", + "January": "\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21", "Join Team": "\u0e40\u0e02\u0e49\u0e32\u0e23\u0e48\u0e27\u0e21\u0e17\u0e35\u0e21", "Joined %(date)s": "\u0e40\u0e02\u0e49\u0e32\u0e23\u0e48\u0e27\u0e21\u0e40\u0e21\u0e37\u0e48\u0e2d %(date)s", + "July": "\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21", + "June": "\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19", "KB": "\u0e01\u0e34\u0e42\u0e25\u0e44\u0e1a\u0e15\u0e4c", "Key should only contain letters, numbers, _, or -": "\u0e04\u0e35\u0e22\u0e4c\u0e04\u0e27\u0e23\u0e1b\u0e23\u0e30\u0e01\u0e2d\u0e1a\u0e14\u0e49\u0e27\u0e22\u0e15\u0e31\u0e27\u0e2d\u0e31\u0e01\u0e29\u0e23 \u0e15\u0e31\u0e27\u0e40\u0e25\u0e02, _,\u0e2b\u0e23\u0e37\u0e2d - \u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19", "LEARN MORE": "\u0e40\u0e23\u0e35\u0e22\u0e19\u0e23\u0e39\u0e49\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e40\u0e15\u0e34\u0e21", @@ -342,10 +352,12 @@ "Make sure your ID is well-lit": "\u0e41\u0e19\u0e48\u0e43\u0e08\u0e27\u0e48\u0e32ID\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07", "Make sure your face is well-lit": "\u0e41\u0e19\u0e48\u0e43\u0e08\u0e27\u0e48\u0e32\u0e23\u0e39\u0e1b\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07", "Manual": "\u0e14\u0e49\u0e27\u0e22\u0e15\u0e19\u0e40\u0e2d\u0e07", + "March": "\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21", "Mark Exam As Completed": "\u0e17\u0e33\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e27\u0e48\u0e32\u0e01\u0e32\u0e23\u0e2a\u0e2d\u0e1a\u0e2a\u0e21\u0e1a\u0e39\u0e23\u0e13\u0e4c\u0e41\u0e25\u0e49\u0e27", "Mark enrollment code as unused": "\u0e17\u0e33\u0e2a\u0e31\u0e0d\u0e25\u0e31\u0e01\u0e29\u0e13\u0e4c\u0e27\u0e48\u0e32\u0e40\u0e1b\u0e47\u0e19\u0e23\u0e2b\u0e31\u0e2a\u0e25\u0e07\u0e17\u0e30\u0e40\u0e1a\u0e35\u0e22\u0e19\u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e43\u0e0a\u0e49", "Markdown Editing Help": "\u0e25\u0e14\u0e04\u0e27\u0e32\u0e21\u0e0a\u0e48\u0e27\u0e22\u0e40\u0e2b\u0e25\u0e37\u0e2d\u0e43\u0e19\u0e01\u0e32\u0e23\u0e41\u0e01\u0e49\u0e44\u0e02", "Max file size exceeded": "\u0e40\u0e01\u0e34\u0e19\u0e01\u0e27\u0e48\u0e32\u0e02\u0e19\u0e32\u0e14\u0e44\u0e1f\u0e25\u0e4c\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14", + "May": "\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21", "Membership": "\u0e2a\u0e21\u0e32\u0e0a\u0e34\u0e01", "Message:": "\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21:", "Midnight": "\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07\u0e04\u0e37\u0e19", @@ -372,14 +384,22 @@ "Not in Use": "\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19", "Not selected": "\u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e40\u0e25\u0e37\u0e2d\u0e01", "Note": "\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e2b\u0e15\u0e38", + "Note: You are %s hour ahead of server time.": [ + "\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e2b\u0e15\u0e38: \u0e40\u0e27\u0e25\u0e32\u0e04\u0e38\u0e13\u0e40\u0e23\u0e47\u0e27\u0e01\u0e27\u0e48\u0e32\u0e40\u0e27\u0e25\u0e32\u0e1a\u0e19\u0e40\u0e0b\u0e34\u0e23\u0e4c\u0e1f\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e2d\u0e22\u0e39\u0e48 %s \u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07." + ], + "Note: You are %s hour behind server time.": [ + "\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e2b\u0e15\u0e38: \u0e40\u0e27\u0e25\u0e32\u0e04\u0e38\u0e13\u0e0a\u0e49\u0e32\u0e01\u0e27\u0e48\u0e32\u0e40\u0e27\u0e25\u0e32\u0e1a\u0e19\u0e40\u0e0b\u0e34\u0e23\u0e4c\u0e1f\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e2d\u0e22\u0e39\u0e48 %s \u0e0a\u0e31\u0e48\u0e27\u0e42\u0e21\u0e07." + ], "Noted in:": "\u0e41\u0e08\u0e49\u0e07\u0e43\u0e19:", "Notes hidden": "\u0e0b\u0e48\u0e2d\u0e19\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01", "Notes visible": "\u0e21\u0e2d\u0e07\u0e40\u0e2b\u0e47\u0e19\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e44\u0e14\u0e49", + "November": "\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19", "Now": "\u0e02\u0e13\u0e30\u0e19\u0e35\u0e49", "Number Sent": "\u0e08\u0e33\u0e19\u0e27\u0e19\u0e17\u0e35\u0e48\u0e2a\u0e48\u0e07\u0e41\u0e25\u0e49\u0e27", "Number of Students": "\u0e08\u0e33\u0e19\u0e27\u0e19\u0e02\u0e2d\u0e07\u0e1c\u0e39\u0e49\u0e40\u0e23\u0e35\u0e22\u0e19", "Numbered List (Ctrl+O)": "\u0e23\u0e32\u0e22\u0e0a\u0e37\u0e48\u0e2d\u0e15\u0e31\u0e27\u0e40\u0e25\u0e02 (Ctrl + O)", "OK": "\u0e15\u0e01\u0e25\u0e07", + "October": "\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21", "One or more rescheduling tasks failed.": "\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e2b\u0e23\u0e37\u0e2d\u0e21\u0e32\u0e01\u0e01\u0e27\u0e48\u0e32\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e07\u0e32\u0e19\u0e17\u0e35\u0e48\u0e25\u0e49\u0e21\u0e40\u0e2b\u0e25\u0e27\u0e43\u0e19\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e31\u0e1a\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e15\u0e32\u0e23\u0e32\u0e07", "Only properly formatted .csv files will be accepted.": "\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a\u0e17\u0e35\u0e48\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e40\u0e17\u0e48\u0e32\u0e19\u0e31\u0e49\u0e19 .csv \u0e16\u0e36\u0e07\u0e08\u0e30\u0e22\u0e2d\u0e21\u0e23\u0e31\u0e1a", "Option Deleted": "\u0e15\u0e31\u0e27\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e16\u0e39\u0e01\u0e25\u0e1a", @@ -469,6 +489,7 @@ "Sent By": "\u0e2a\u0e48\u0e07\u0e42\u0e14\u0e22:", "Sent By:": "\u0e2a\u0e48\u0e07\u0e42\u0e14\u0e22:", "Sent To:": "\u0e2a\u0e48\u0e07\u0e44\u0e1b:", + "September": "\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19", "Set up your certificate": "\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e43\u0e1a\u0e23\u0e31\u0e1a\u0e23\u0e2d\u0e07\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13", "Settings": "\u0e01\u0e32\u0e23\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e15\u0e48\u0e32\u0e07\u0e46 ", "Show": "\u0e41\u0e2a\u0e14\u0e07", @@ -739,6 +760,13 @@ "group configuration": "\u0e01\u0e32\u0e23\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e04\u0e48\u0e32\u0e01\u0e25\u0e38\u0e48\u0e21", "last activity": "\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e38\u0e14\u0e17\u0e49\u0e32\u0e22", "name": "\u0e0a\u0e37\u0e48\u0e2d", + "one letter Friday\u0004F": "\u0e28.", + "one letter Monday\u0004M": "\u0e08.", + "one letter Saturday\u0004S": "\u0e2a.", + "one letter Sunday\u0004S": "\u0e2d\u0e32.", + "one letter Thursday\u0004T": "\u0e1e\u0e24.", + "one letter Tuesday\u0004T": "\u0e2d.", + "one letter Wednesday\u0004W": "\u0e1e.", "open slots": "\u0e40\u0e1b\u0e34\u0e14\u0e0a\u0e48\u0e2d\u0e07\u0e43\u0e2a\u0e48", "or": "\u0e2b\u0e23\u0e37\u0e2d", "or create a new one here": "\u0e2b\u0e23\u0e37\u0e2d\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e1a\u0e31\u0e0d\u0e0a\u0e35\u0e43\u0e2b\u0e21\u0e48\u0e17\u0e35\u0e48\u0e19\u0e35\u0e48", @@ -773,7 +801,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -809,8 +837,8 @@ django.formats = { "DATETIME_FORMAT": "j F Y, G:i", "DATETIME_INPUT_FORMATS": [ - "%d/%m/%Y %H:%M:%S.%f", "%d/%m/%Y %H:%M:%S", + "%d/%m/%Y %H:%M:%S.%f", "%d/%m/%Y %H:%M", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", @@ -825,16 +853,16 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "j M Y, G:i", "SHORT_DATE_FORMAT": "j M Y", "THOUSAND_SEPARATOR": ",", "TIME_FORMAT": "G:i", "TIME_INPUT_FORMATS": [ - "%H:%M:%S.%f", "%H:%M:%S", + "%H:%M:%S.%f", "%H:%M" ], "YEAR_MONTH_FORMAT": "F Y" diff --git a/lms/static/js/i18n/tr-tr/djangojs.js b/lms/static/js/i18n/tr-tr/djangojs.js index 3c665246851ab269c35075167db24e29ffe3d6b3..326ba3d22d3c73d535ced523b944c0efb9633985 100644 --- a/lms/static/js/i18n/tr-tr/djangojs.js +++ b/lms/static/js/i18n/tr-tr/djangojs.js @@ -139,6 +139,7 @@ "%s from now": "\u015eimdiden itibaren %s", "(Add signatories for a certificate)": "(Sertifika i\u00e7in imza sahibi ekle)", "(Caption will be displayed when you start playing the video.)": "(Altyaz\u0131 videoyu oynatmaya ba\u015flad\u0131\u011f\u0131n\u0131zda g\u00f6sterilecek.)", + "(Community TA)": "(Topluluk \u00d6\u011fretim Eleman\u0131)", "(Optional)": "(\u0130ste\u011fe Ba\u011fl\u0131)", "(Read-only)": "(Salt-okunur)", "(Required Field)": "(Gerekli Alan)", @@ -146,6 +147,7 @@ "(Self-paced) Ends {end}": "(Kendi kendine) Biti\u015f {end}", "(Self-paced) Started {start}": "(Kendi kendine) Ba\u015flad\u0131 {start}", "(Self-paced) Starts {start}": "(Kendi kendine) Ba\u015flang\u0131\u00e7 {start}", + "(Staff)": "(Personel)", "(optional)": "(iste\u011fe ba\u011fl\u0131)", "(required)": "(gerekli)", "(required):": "(gerekli):", @@ -203,7 +205,12 @@ "Add URLs for additional versions": "Ek s\u00fcr\u00fcmler i\u00e7in URL'leri ekle", "Add a Chapter": "Bir b\u00f6l\u00fcm ekle", "Add a New Cohort": "Yeni Topluluk Ekle", + "Add a Post": "\u0130leti Ekle", + "Add a Response": "Bir Cevap Ekle", + "Add a clear and descriptive title to encourage participation. (Required)": "Kat\u0131l\u0131ma te\u015fvik etmek i\u00e7in a\u00e7\u0131k ve tan\u0131t\u0131c\u0131 bir ba\u015fl\u0131k ekle. (Gerekli)", + "Add a comment": "Bir yorum ekleyin", "Add a learning outcome here": "\u00d6\u011frenme \u00e7\u0131kt\u0131s\u0131n\u0131 buraya ekleyin", + "Add a response:": "Bir cevap ekle:", "Add another group": "Ba\u015fka grup ekle", "Add language": "Dil ekle", "Add learners to this cohort": "Bu toplulu\u011fa \u00f6\u011frenci ekle", @@ -233,6 +240,7 @@ "Align left": "Sola yasla", "Align right": "Sa\u011fa yasla", "Alignment": "Hizalama", + "All Groups": "B\u00fct\u00fcn Gruplar", "All Learners and Staff": "T\u00fcm \u00d6\u011frenciler ve Personeller", "All Posts": "T\u00fcm G\u00f6nderiler", "All Rights Reserved": "T\u00fcm Haklar\u0131 Sakl\u0131d\u0131r", @@ -318,6 +326,7 @@ "Assessment": "De\u011ferlendirme", "Assessment Results Visibility": "De\u011ferlendirme Sonu\u00e7lar\u0131 G\u00f6r\u00fcn\u00fcrl\u00fc\u011f\u00fc", "Assessments": "De\u011ferlendirmeler", + "Assign Team Memberships": "Tak\u0131m \u00dcyeliklerini Belirle", "Assign learners to cohorts by uploading a CSV file": "CSV dosyas\u0131 y\u00fckleyerek \u00f6\u011frencileri topluluklara atay\u0131n", "Assign students to cohorts by uploading a CSV file.": "CSV dosyas\u0131n\u0131 y\u00fckleyerek toplulu\u011fa \u00f6\u011frencileri ata.", "Assignment Type Name": "G\u00f6rev T\u00fcr\u00fc \u0130smi", @@ -454,6 +463,7 @@ "Click to remove all chosen %s at once.": "Bir kerede t\u00fcm se\u00e7ilen %s kald\u0131r\u0131lmas\u0131 i\u00e7in t\u0131klay\u0131n.", "Close": "Kapat", "Close Calculator": "Hesap Makinesini Kapat", + "Closed": "Kapat\u0131ld\u0131", "Code": "Kod", "Code Sample (Ctrl+K)": "Kod \u00d6rne\u011fi (Ctrl+K)", "Code block": "Kod blo\u011fu", @@ -472,6 +482,8 @@ "Coming Soon": "Yak\u0131nda", "Commentary": "Yorum", "Common Problem Types": "S\u0131k Kar\u015f\u0131la\u015f\u0131lan Problem T\u00fcrleri", + "Community TA": "Topluluk \u00d6\u011fretim Eleman\u0131", + "Complete courses on your schedule to ensure you stand out in your field!": "Alan\u0131n\u0131zda \u00f6ne \u00e7\u0131kman\u0131z\u0131 sa\u011flamak i\u00e7in derslerinizi tamamlay\u0131n!", "Completed": "Tamamland\u0131", "Component": "Bile\u015fen", "Components": "Bile\u015fenler", @@ -514,8 +526,13 @@ "Country": "\u00dclke", "Country of residence": "\u0130kamet edilen \u00fclke", "Country or Region of Residence": "\u0130kamet Edilen \u00dclke ya da B\u00f6lge", + "Course": [ + "Ders", + "Dersler" + ], "Course Content": "Ders \u0130\u00e7eri\u011fi", "Course Credit Requirements": "Ders Kredisi Gereklilikleri", + "Course Discussion Forum": "Ders Tart\u0131\u015fma Forumu", "Course End": "Ders Biti\u015fi", "Course Handouts": "Ders Notlar\u0131", "Course ID": "Ders No", @@ -578,7 +595,6 @@ "Default (Local Time Zone)": "Varsay\u0131lan (Yerel Zaman Dilimi)", "Default Timed Transcript": "Varsay\u0131lan Zamanlar\u0131 \u0130\u015faretlenmi\u015f Altyaz\u0131", "Delete": "Sil", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u0130mza sahipleri listesinden \"<%= signatoryName %>\" sil?", "Delete File Confirmation": "Dosya Onay\u0131n\u0131 Kald\u0131r", "Delete My Account": "Hesab\u0131m\u0131 Sil", "Delete Page Confirmation": "Sayfa Onay\u0131n\u0131 Kald\u0131r", @@ -609,6 +625,7 @@ "Disc": "Disk", "Discard Changes": "De\u011fi\u015fiklikleri \u00c7\u0131kart", "Discarding Changes": "\u00c7\u0131kar\u0131lan De\u011fi\u015fiklikler", + "Discussion": "Forum", "Discussion Home": "Tart\u0131\u015fma Anasayfas\u0131", "Discussion topics in the course are not divided.": "Dersteki tart\u0131\u015fma ba\u015fl\u0131klar\u0131 b\u00f6l\u00fcnmemi\u015f.", "Discussions are unified; all learners interact with posts from other learners, regardless of the group they are in.": "Tart\u0131\u015fmalar birle\u015ftirilmi\u015f durumda; t\u00fcm \u00f6\u011frenciler i\u00e7inde olduklar\u0131 gruplardan ba\u011f\u0131ms\u0131z olarak, di\u011fer \u00f6\u011frencilerin g\u00f6nderileriyle etkile\u015fime girebilir.", @@ -622,7 +639,6 @@ "Do you want to upload your file before submitting?": " G\u00f6ndermeden \u00f6nce dosyan\u0131z\u0131 y\u00fcklemek istiyor musunuz?", "Document properties": "Belge \u00f6zellikleri", "Does the name on your ID match your account name: %(fullName)s?": "ID niz \u00fczerindeki isim hesab\u0131n\u0131zdaki isimle e\u015fle\u015fiyor mu: %(fullName)s?", - "Does the photo of you match your ID photo?": "Foto\u011fraf kimlik foto\u011fraf\u0131na uyuyor mu?", "Does the photo of you show your whole face?": "Foto\u011fraf y\u00fcz\u00fcn\u00fcz\u00fcn tamam\u0131n\u0131 g\u00f6steriyor mu?", "Doing so means that you are no longer eligible for academic credit.": "Bu \u015fekilde yapmak, akademik kredinizi dolduramayaca\u011f\u0131n\u0131z anlam\u0131na gelir.", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Resminizi g\u00f6rm\u00fcyor musunuz? Web izleyiciniz izin istedi\u011finde kameran\u0131z\u0131 kullanabilmesi i\u00e7in izin veriniz.", @@ -636,6 +652,7 @@ "Download the user's certificate": "Kullan\u0131c\u0131n\u0131n sertifikas\u0131n\u0131 indir", "Draft (Never published)": "Taslak (Hi\u00e7 yay\u0131nlanmad\u0131)", "Draft (Unpublished changes)": "Taslak (Yay\u0131mlanmayan de\u011fi\u015fiklikler)", + "Draft saved on {lastSavedStart}{editedOn}{lastSavedEnd} by {editedByStart}{editedBy}{editedByEnd}": "Taslak {lastSavedStart}{editedOn}{lastSavedEnd} tarihinde {editedByStart}{editedBy}{editedByEnd} taraf\u0131ndan kaydedildi", "Drag and drop or {spanStart}browse your computer{spanEnd}.": "S\u00fcr\u00fckle b\u0131rak veya {spanStart}bilgisayar\u0131n\u0131z\u0131n dizinlerini taray\u0131n{spanEnd}.", "Drag to reorder": "Tekrar d\u00fczenlemek i\u00e7in s\u00fcr\u00fckle", "Drop target image": "Hedef g\u00f6rseli b\u0131rak\u0131n", @@ -662,8 +679,12 @@ "Edit Title": "Ba\u015fl\u0131\u011f\u0131 D\u00fczenle", "Edit Your Name": "\u0130sminizi D\u00fczeltiniz", "Edit this certificate?": "Bu sertifikay\u0131 d\u00fczenle?", + "Edit your post below.": "\u0130letinizi a\u015fa\u011f\u0131da d\u00fczenleyin.", "Editable": "D\u00fczenlenebilir", "Editing access for: {title}": "{title} i\u00e7in eri\u015fim d\u00fczenleniyor", + "Editing comment": "Yorum de\u011fi\u015ftiriliyor", + "Editing post": "\u0130leti d\u00fczenleniyor", + "Editing response": "Cevap d\u00fczenleniyor", "Editing: {title}": "D\u00fczenleme: {title}", "Editor": "Edit\u00f6r", "Education Completed": "Tamamlanan E\u011fitim", @@ -681,6 +702,7 @@ "Encoding": "Kodlama", "End My Exam": "S\u0131nav\u0131m\u0131 Bitir", "End of transcript. Skip to the start.": "Altyaz\u0131n\u0131n sonu. Ba\u015flang\u0131ca atla.", + "Endorse": "Destekle", "Ends {end}": "Bitti {end}", "Engage with posts": "G\u00f6nderilerle etkile\u015fimde bulunun", "Enroll Now": "Hemen Kaydol", @@ -785,7 +807,6 @@ "Fill browser": "Taray\u0131c\u0131y\u0131 doldurun", "Filter": "S\u00fczge\u00e7", "Filter and sort topics": "Konular\u0131 filtrele ve s\u0131rala", - "Final Grade": "Final Notu", "Final Grade Received": "Final Notu Al\u0131nd\u0131", "Financial Aid": "M\u00e2li Yard\u0131m", "Financial Assistance": "M\u00e2li Yard\u0131m", @@ -799,7 +820,9 @@ "Find previous": "\u00d6ncekini bul", "Finish": "Bitir", "First time here?": "\u0130lk kez mi buradas\u0131n\u0131z?", + "Follow": "Takip et", "Follow or unfollow posts": "G\u00f6nderileri takip et veya takipten \u00e7\u0131k", + "Following": "Takip ediliyor", "Font Family": "Yaz\u0131tipi Ailesi", "Font Sizes": "Yaz\u0131 Boyutlar\u0131", "Footer": "Alt bilgi", @@ -818,7 +841,6 @@ "Generate": "Olu\u015ftur", "Generate Exception Certificates": "\u0130stisna Sertifikalar\u0131 Olu\u015ftur", "Generate the user's certificate": "Kullan\u0131c\u0131n\u0131n sertifikas\u0131n\u0131 olu\u015ftur", - "Get Credit": "Kredi Al", "Go Back": "Geri D\u00f6n", "Go to Dashboard": "Ana Panele Git", "Go to my Dashboard": "Panelime Git", @@ -897,10 +919,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "Bir alt b\u00f6l\u00fcm\u00fcn son tarihi yoksa, \u00f6\u011frenciler cevaplar\u0131n\u0131 de\u011ferlendirmeye g\u00f6nderdi\u011finde notlar\u0131n\u0131 g\u00f6r\u00fcrler.", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "E\u011fer \u00fcnite \u00f6\u011frencilere daha \u00f6nce a\u00e7\u0131ld\u0131 ve yay\u0131nland\u0131ysa, gizliyken \u00fcnitede yapt\u0131\u011f\u0131n\u0131z t\u00fcm de\u011fi\u015fiklikler \u015fimdi \u00f6\u011frencilere g\u00f6r\u00fcn\u00fcr olacak.", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "E\u011fer \u00fcnite \u00f6nceden yay\u0131nlanm\u0131\u015f ve \u00f6\u011frencilere a\u00e7\u0131lm\u0131\u015fsa, \u00fcnite gizliyken yapt\u0131\u011f\u0131n\u0131z de\u011fi\u015fiklikler \u00f6\u011frencilere art\u0131k g\u00f6r\u00fcn\u00fcr olacak. Devam etmek istiyor musunuz?", - "If you are unable to access your account contact us via email using {email}.": "Hesab\u0131n\u0131za ula\u015fam\u0131yorsan\u0131z bizimle {email} e-posta adresi \u00fczerinden ileti\u015fime ge\u00e7ebilirsiniz.", "If you do not yet have an account, use the button below to register.": "Hen\u00fcz bir hesab\u0131n\u0131z yoksa, kay\u0131t i\u00e7in a\u015fa\u011f\u0131daki d\u00fc\u011fmeyi kullan\u0131n.", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "E\u011fer kimli\u011finizi \u015fimdi do\u011frulamazsan\u0131z, hala daha ana panelinizden dersinizi ke\u015ffedebilirsiniz. Kimli\u011finizi do\u011frulamak i\u00e7in %(platformName)s \u00fczerinden periyodik hat\u0131rlatma alacaks\u0131n\u0131z.", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u015eu an kimli\u011finizi onaylamasan\u0131z da, dersinize h\u00e2l\u00e2 panelinizden ula\u015fabilirsiniz. Kimli\u011finizi onaylaman\u0131z i\u00e7in, {platformName} size d\u00fczenli bildirimler g\u00f6nderecek.", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "E\u011fer sayfadan cevab\u0131n\u0131z\u0131 kaydetmeden ya da g\u00f6ndermeden ayr\u0131l\u0131rsan\u0131z, cevap i\u00e7in yapt\u0131\u011f\u0131n\u0131z i\u015flemleri kaybedeceksiniz.", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "Bu sayfay\u0131 \u00f6zde\u011ferlendirmenizi yazmadan terk etmeniz durumunda, yapt\u0131\u011f\u0131n\u0131z t\u00fcm i\u015fleri kaybedeceksiniz.", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "Bu sayfay\u0131 de\u011ferlendirmenizi yazmadan terk etmeniz durumunda, yapt\u0131\u011f\u0131n\u0131z t\u00fcm i\u015fleri kaybedeceksiniz.", @@ -985,6 +1005,7 @@ "Last activity {date}": "Son faaliyet {date}", "Last modified by": "Son g\u00fcncelleyen ", "Last published %(last_published_date)s by %(publish_username)s": "%(publish_username)s taraf\u0131ndan son yay\u0131nlanan %(last_published_date)s", + "Last published {lastPublishedStart}{publishedOn}{lastPublishedEnd} by {publishedByStart}{publishedBy}{publishedByEnd}": "En son {lastPublishedStart}{publishedOn}{lastPublishedEnd} tarihinde {publishedByStart}{publishedBy}{publishedByEnd} taraf\u0131ndan yay\u0131na al\u0131nd\u0131", "Last updated": "Son g\u00fcncelleme", "Learn More": "Daha Fazlas\u0131n\u0131 \u00d6\u011fren", "Learn more about {license_name}": "{license_name} hakk\u0131nda daha fazla \u00f6\u011fren", @@ -1025,6 +1046,7 @@ "Live view of webcam": "Web kameran\u0131z\u0131n canl\u0131 g\u00f6r\u00fcnt\u00fcs\u00fc", "Load Another File": "Ba\u015fka Bir Dosya Y\u00fckle", "Load all responses": "B\u00fct\u00fcn cevaplar\u0131 y\u00fckle", + "Load more": "Daha fazla y\u00fckle", "Load next {numResponses} responses": "Sonraki {numResponses} cevap y\u00fckleniyor", "Loading": "Y\u00fckl\u00fcyor...", "Loading content": "\u0130\u00e7erik y\u00fckleniyor", @@ -1054,6 +1076,7 @@ "Manual": "El ile", "March": "Mart", "Mark Exam As Completed": "S\u0131nav\u0131 Tamamland\u0131 Olarak \u0130\u015faretle", + "Mark as Answer": "Cevap olarak \u0130\u015faretle", "Mark enrollment code as unused": "Kay\u0131tlanma kodunu kullan\u0131lmayan olarak i\u015faretle", "Markdown Editing Help": "Markdown \u0130\u015faretleme Dili Yard\u0131m\u0131", "Masters": "Y\u00fcksek Lisanslar", @@ -1167,8 +1190,8 @@ "Ok": "Tamam", "One or more rescheduling tasks failed.": "Bir veya daha fazla yeniden zamanlama g\u00f6revi ba\u015far\u0131s\u0131z oldu.", "Only ": "Sadece", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "Sadece <%= fileTypes %> dosya uzant\u0131lar\u0131n\u0131 y\u00fckleyebilirsiniz. L\u00fctfen sonunda <%= fileExtensions %> uzant\u0131s\u0131 olan bir dosya y\u00fckleyin.", "Only properly formatted .csv files will be accepted.": "Sadece d\u00fczg\u00fcn formatlanm\u0131\u015f .csv dosyalar\u0131 kabul edilecek.", + "Open": "A\u00e7", "Open Calculator": "Hesap Makinesini A\u00e7", "Open language menu": "Dil men\u00fcs\u00fcn\u00fc a\u00e7\u0131n", "Open the certificate you earned for the %(title)s program.": "%(title)s program\u0131nda hak kazand\u0131\u011f\u0131n\u0131z sertifikay\u0131 a\u00e7\u0131n.", @@ -1220,6 +1243,8 @@ "Photo of %(fullName)s's ID": "%(fullName)s'in Foto\u011frafl\u0131 Kimli\u011fi ", "Photo requirements:": "Foto\u011fraf gereklilikleri:", "Photos don't meet the requirements?": "Foto\u011fraflar gereksinimleri kar\u015f\u0131l\u0131yor mu?", + "Pin": "\u0130\u015faretle", + "Pinned": "\u0130\u015faretli", "Placeholder": "Yer tutucu", "Play": "Oynat", "Play video": "Videoyu oynat", @@ -1263,6 +1288,7 @@ "Please wait": "L\u00fctfen bekleyin", "Plugins": "Eklentiler", "Post": "G\u00f6nderi", + "Post type": "G\u00f6nderi t\u00fcr\u00fc", "Poster": "Poster", "Practice Exam Completed": "Al\u0131\u015ft\u0131rma S\u0131nav\u0131 Tamamland\u0131", "Practice Exam Failed": "Al\u0131\u015ft\u0131rma S\u0131nav\u0131 Ba\u015far\u0131s\u0131z", @@ -1322,6 +1348,7 @@ "Published and Live": "Yay\u0131nland\u0131 ve Canl\u0131", "Publishing": "Yay\u0131nlama", "Publishing Status": "Yay\u0131nlanma Durumu", + "Question": "Soru", "Queued": "Kuyru\u011fa Al\u0131nd\u0131", "REMAINING COURSES": "KALAN DERSLER", "Re-run Course": "Dersi Yeniden \u00c7al\u0131\u015ft\u0131r", @@ -1344,6 +1371,7 @@ "Regenerate the user's certificate": "Kullan\u0131c\u0131n\u0131n sertifikas\u0131n\u0131 yeniden olu\u015ftur", "Register with Institution/Campus Credentials": "Kurum / Kamp\u00fcs Kimlik Bilgileri ile Kay\u0131t", "Rejected": "Reddedildi", + "Related to: %(courseware_title_linked)s": "\u0130lgili: %(courseware_title_linked)s", "Release Date and Time": "Yay\u0131m Tarih ve Zaman\u0131", "Release Date:": "Yay\u0131m Tarihi:", "Release Status:": "Yay\u0131n Durumu:", @@ -1372,7 +1400,10 @@ "Replace all": "T\u00fcm\u00fcn\u00fc de\u011fi\u015ftir", "Replace with": "De\u011fi\u015ftir", "Reply to Annotation": "\u0130pu\u00e7lar\u0131na Yan\u0131t Ver", + "Report": "Raporla", + "Report abuse": "K\u00f6t\u00fc kullan\u0131m\u0131 bildir", "Report abuse, topics, and responses": "\u0130hlalleri, konular\u0131 ve yan\u0131tlar\u0131 bildir", + "Reported": "Rapor edildi", "Requester": "\u0130steyen", "Required": "Gerekli", "Required field.": "Gerekli alan.", @@ -1625,9 +1656,7 @@ "Textbook Name": "Ders Kitab\u0131 Ad\u0131", "Textbook information": "Ders Kitab\u0131 bilgisi", "Textbook name is required": "Ders kitab\u0131 ad\u0131 gerekli", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "%(course_name)s dersi i\u00e7in \u00f6demenizi ald\u0131k. Te\u015fekk\u00fcrler %(full_name)s!", "Thank you for setting your course goal to {goal}!": "Ders hedefinizi {goal} olarak belirledi\u011finiz i\u00e7in te\u015fekk\u00fcr ederiz!", - "Thank you for submitting a request! We will contact you within 24 hours.": "Bize talebinizi iletti\u011finiz i\u00e7in te\u015fekk\u00fcr ederiz! Size 24 saat i\u00e7inde geri d\u00f6nece\u011fiz.", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "{course_name} i\u00e7in mali yard\u0131m ba\u015fvurunuzu g\u00f6nderdi\u011finiz i\u00e7in te\u015fekk\u00fcrler ! 2-4 i\u015f g\u00fcn\u00fc i\u00e7erisinde size geri d\u00f6nece\u011fiz. ", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "Foto\u011fraflar\u0131n\u0131z\u0131 g\u00f6nderdi\u011finiz i\u00e7in te\u015fekk\u00fcr ederiz. K\u0131sa s\u00fcre i\u00e7inde de\u011ferlendirece\u011fiz. \u015eimdi onayl\u0131 sertifika sunan herhangi bir %(platformName)s derse kay\u0131t olabilirsiniz. Do\u011frulama bir y\u0131l i\u00e7indir. Bir y\u0131ldan sonra yeniden do\u011frulama i\u00e7in foto\u011fraflar\u0131n\u0131z\u0131 tekrar g\u00f6ndermelisiniz.", "Thank you! We have received your payment for {courseName}.": "Te\u015fekk\u00fcrler! {courseName} i\u00e7in olan \u00f6demenizi ald\u0131k.", @@ -1639,8 +1668,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Bu \u00f6\u011frenci i\u00e7in sertifika yeniden de\u011ferlendiriliyor ve sistem bu \u00f6\u011frencinin notlar\u0131n\u0131 yeniden hesapl\u0131yor.", "The cohort cannot be added": "Topluluk eklenemedi", "The cohort cannot be saved": "Tapluluk kaydedilemedi", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "Organizasyonun birle\u015fik boyutu ve k\u00fct\u00fcphane kodu alanlar\u0131 <%=limit%> karakterden fazla olamaz.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "Organizasyonun birle\u015fik boyutu, ders say\u0131s\u0131, ve ders alanlar\u0131 <%=limit%> karakterden fazla olamaz.", "The country or region where you live.": "\u0130kamet etti\u011finiz \u00fclke veya b\u00f6lge.", "The country that team members primarily identify with.": "Tak\u0131m \u00fcyelerinin \u00f6ncelikli olarak \u00f6zde\u015fle\u015ftirildi\u011fi \u00fclke.", "The course end date must be later than the course start date.": "Dersin biti\u015f tarihi, ba\u015flang\u0131\u00e7 tarihinden sonra olmal\u0131d\u0131r.", @@ -1656,7 +1683,6 @@ "The following email addresses and/or usernames are invalid:": "A\u015fa\u011f\u0131daki e-posta adresleri veya kullan\u0131c\u0131 adlar\u0131 ge\u00e7ersizdir.", "The following errors were generated:": "A\u015fa\u011f\u0131daki hatalar olu\u015ftu:", "The following file types are not allowed: ": "A\u015fa\u011f\u0131daki dosya t\u00fcr\u00fcne izin verilmiyor:", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "A\u015fa\u011f\u0131daki bilgiler profilinizde mevcut {platform} bulunuyor. Ba\u015fvurunuz i\u00e7in buraya ekledik.", "The following message will be displayed at the bottom of the courseware pages within your course:": "A\u015fa\u011f\u0131daki ileti e\u011fitiminizdeki ders yaz\u0131l\u0131m sayfas\u0131n\u0131n alt\u0131nda g\u00f6r\u00fcnt\u00fclenecektir.", "The following options are available for the {license_name} license.": "A\u015fa\u011f\u0131daki se\u00e7enekler {license_name} lisans\u0131 i\u00e7in ge\u00e7erlidir. ", "The following users are no longer enrolled in the course:": "A\u015fa\u011f\u0131daki kullan\u0131c\u0131lar art\u0131k bu derse kay\u0131tl\u0131 de\u011filler:", @@ -1668,7 +1694,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "Minimum tamamlama y\u00fczdesi 0 ile 100 aras\u0131nda bir tamsay\u0131 olmal\u0131.", "The minimum grade for course credit is not set.": "Ders kredisi i\u00e7in minimum not ayarlanmad\u0131.", "The minimum score percentage must be a whole number between 0 and 100.": "Minimum not y\u00fczdesi 0 ile 100 aras\u0131nda bir tamsay\u0131 olmal\u0131.", - "The more you tell us, the more quickly and helpfully we can respond!": "Bize ne kadar \u00e7ok ayr\u0131nt\u0131 verirseniz, size o kadar h\u0131zl\u0131 ve faydal\u0131 bir \u015fekilde cevap verebiliriz!", "The name of this signatory as it should appear on certificates.": "Bu imza sahibinin ad\u0131 sertifikada g\u00f6r\u00fcnd\u00fc\u011f\u00fc gibidir.", "The name that identifies you on {platform_name}. You cannot change your username.": "Sizi {platform_name} platformunda tan\u0131mlayan kullan\u0131c\u0131 ad\u0131n\u0131z. Kullan\u0131c\u0131 ad\u0131n\u0131z\u0131 de\u011fi\u015ftiremezsiniz. ", "The name that is used for ID verification and that appears on your certificates.": "Kimlik do\u011frulamas\u0131nda ve sertifikalar\u0131n\u0131z\u0131n \u00fczerinde kullan\u0131lacak isim.", @@ -1676,7 +1701,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "Bu g\u00f6rev t\u00fcr\u00fc problemlerini i\u00e7eren ders altb\u00f6l\u00fcmlerinin say\u0131s\u0131.", "The organization that this signatory belongs to, as it should appear on certificates.": "Bu imza sahibine ait olan organizasyon, sertifikalarda g\u00f6r\u00fcnmeli.", "The page \"{route}\" could not be found.": "\"{route}\" sayfas\u0131 bulunamad\u0131.", - "The photo of your face matches the photo on your ID.": "Foto\u011fraf\u0131n\u0131z, kimlik kart\u0131n\u0131zdaki ile uygun olmal\u0131.", "The post you selected has been deleted.": "Se\u00e7ti\u011finiz ileti silindi.", "The raw error message is:": "\u0130\u015flenmemi\u015f hata mesaj\u0131:", "The refund deadline for this course has passed,so you will not receive a refund.": "Bu ders i\u00e7in iadenin son g\u00fcn\u00fc ge\u00e7ti, bu y\u00fczden iade alamayacaks\u0131n\u0131z.", @@ -1768,6 +1792,8 @@ "This post could not be reopened. Refresh the page and try again.": "Bu g\u00f6nderi yeniden a\u00e7\u0131lamaz. Sayfay\u0131 yenileyin ve tekrar deneyin.", "This post could not be unflagged for abuse. Refresh the page and try again.": "Bu g\u00f6nderinin taciz i\u015faretlemesi kald\u0131r\u0131lamaz. Sayfay\u0131 yenileyin ve tekrar deneyin.", "This post could not be unpinned. Refresh the page and try again.": "Bu g\u00f6nderi sabitlenmesi kald\u0131r\u0131lamad\u0131. Sayfay\u0131 yeniden y\u00fckleyin ve tekrar deneyin.", + "This post is visible to everyone.": "Bu g\u00f6nderi herkese a\u00e7\u0131kt\u0131r", + "This post will be visible to everyone.": "Bu ileti herkese g\u00f6r\u00fcn\u00fcr olacak.", "This problem could not be saved.": "Bu problem kaydedilemedi.", "This problem has already been released. Any changes will apply only to future assessments.": "Bu problem \u015fu anda yay\u0131mlanm\u0131\u015f bulunuyor. Bu durumda herhangi bir de\u011fi\u015fiklik sadece ileriki de\u011ferlendirmelerde uygulanacakt\u0131r.", "This problem has been reset.": "Bu problem s\u0131f\u0131rland\u0131.", @@ -1784,6 +1810,7 @@ "This short name for the assignment type (for example, HW or Midterm) appears next to assignments on a learner's Progress page.": "Bu g\u00f6rev t\u00fcr\u00fc i\u00e7in belirlenen k\u0131saisim (\u00f6rne\u011fin, \u00d6dev veya ARSNV gibi) \u00f6\u011frencinin \u0130lerleme sayfas\u0131nda, g\u00f6revin hemen yan\u0131nda g\u00f6z\u00fck\u00fcr.", "This team does not have any members.": "Bu tak\u0131mda hi\u00e7 \u00fcye yok.", "This team is full.": "Bu tak\u0131m dolu.", + "This thread is closed.": "Bu ileti dizisi kapand\u0131.", "This unit has validation issues.": "Bu \u00fcnitenin do\u011frulama sorunu var.", "This vote could not be processed. Refresh the page and try again.": "Bu oy i\u015flenemedi. Sayfay\u0131 yeniden y\u00fckleyin ve tekrar deneyin.", "Thumbnail": "K\u00fc\u00e7\u00fck resim", @@ -1809,7 +1836,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "T\u00fcm \u00f6\u011frencilerin videoya eri\u015febildi\u011finden emin olmak i\u00e7in, videonuzun .mp4 ve .webm s\u00fcr\u00fcmlerini sa\u011flaman\u0131z\u0131 \u00f6neririz. Ba\u015fka bir s\u00fcr\u00fcm i\u00e7in URL eklemek \u00fczere a\u015fa\u011f\u0131ya t\u0131klay\u0131n. Bu URL'ler YouTube URL'si olamaz. \u00d6\u011frencilerin bilgisayarlar\u0131yla uyumlu olan ilk listelenen video oynayacakt\u0131r.", "To complete the program, you must earn a verified certificate for each course.": "Program\u0131 tamamlamak i\u00e7in, t\u00fcm derslerde onayl\u0131 sertifikaya hak kazanmal\u0131s\u0131n\u0131z.", "To continue learning with this account, sign in below.": "Bu hesap ile \u00f6\u011frenmeye devam etmek i\u00e7in, a\u015fa\u011f\u0131dan giri\u015f yap.", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "Ders kredisini sonland\u0131rmak i\u00e7in, %(display_name)s, kredi talebini y\u00fcklemek i\u00e7in %(platform_name)s \u00f6\u011frencilerini gerektirir.", "To invalidate a certificate for a particular learner, add the username or email address below.": "Belli bir \u00f6\u011frencinin sertifikas\u0131n\u0131 ge\u00e7ersizle\u015ftirmek i\u00e7in, kullan\u0131c\u0131 ad\u0131 veya e-posta adresini a\u015fa\u011f\u0131ya girin.", "To pass this exam, you must complete the problems in the time allowed.": "Bu s\u0131navdan ge\u00e7mek i\u00e7in, problemleri size tan\u0131nan s\u00fcrede \u00e7\u00f6zmelisiniz.", "To receive a certificate, you must also verify your identity before {date}.": "Sertifika almak i\u00e7in {date} tarihinden \u00f6nce kimli\u011finizi do\u011frulamal\u0131s\u0131n\u0131z.", @@ -1824,6 +1850,7 @@ "Tools": "Ara\u00e7lar", "Top": "\u00dcst", "Topic": "Konu", + "Topic area": "Ba\u015fl\u0131k alan\u0131", "Topics": "Konular", "Total": "Toplam", "Total Number": "Toplam Say\u0131", @@ -1845,6 +1872,7 @@ "Type into this box to filter down the list of available %s.": "Mevcut %s listesini s\u00fczmek i\u00e7in bu kutu i\u00e7ine yaz\u0131n.", "URL": "URL", "Unable to delete account": "Hesap silinemedi", + "Unable to determine whether we should give you a refund because of System Error. Please try again later.": "\u015eu anda Sistem Hatas\u0131ndan dolay\u0131 geri \u00f6deme verip veremeyece\u011fimizi saptayam\u0131yoruz. L\u00fctfen daha sonra tekrar deneyiniz.", "Unable to load": "Y\u00fcklenemedi", "Unable to submit application": "Ba\u015fvuru g\u00f6nderilemedi", "Underline": "Alt \u00e7izgi", @@ -1853,7 +1881,9 @@ "Undo Changes": "De\u011fi\u015fiklikleri Geri Al", "Undo move": "Ta\u015f\u0131may\u0131 geri al", "Undo moving": "Ta\u015f\u0131may\u0131 geri al", + "Unendorse": "Destekleme", "Unexpected server error.": "Beklenmeyen sunucu hatas\u0131.", + "Unfollow": "Takibi b\u0131rak", "Ungraded": "Puanlanmam\u0131\u015f", "Ungraded Practice Exam": "Puanlanmam\u0131\u015f Al\u0131\u015ft\u0131rma S\u0131nav\u0131", "Unit": "\u00dcnite", @@ -1866,14 +1896,20 @@ "Unlink This Account": "Hesab\u0131n Ba\u011flant\u0131s\u0131n\u0131 Kald\u0131r", "Unlink your {accountName} account": "{accountName} hesab\u0131n\u0131z\u0131n ba\u011flant\u0131s\u0131n\u0131 kald\u0131r\u0131n", "Unlinking": "Ba\u011flant\u0131 kald\u0131rma", + "Unmark as Answer": "Cevap i\u015faretini Kald\u0131r", "Unmute": "Ses", "Unnamed Option": "Adland\u0131r\u0131lmam\u0131\u015f Se\u00e7enek", + "Unpin": "\u0130\u015fareti kald\u0131r", "Unpublished changes to content that will release in the future": "\u0130\u00e7eri\u011fin yay\u0131mlanmam\u0131\u015f de\u011fi\u015fiklikleri ilerde yay\u0131nlanacakt\u0131r.", "Unpublished changes to live content": "Canl\u0131 yay\u0131n i\u00e7eri\u011findeki yay\u0131mlanmam\u0131\u015f de\u011fi\u015fiklikler", "Unpublished units will not be released": "Yay\u0131mlanmam\u0131\u015f birimler yay\u0131nlanmayacakt\u0131r", + "Unreport": "Bildirme", "Unscheduled": "Planlanmam\u0131\u015f", "Update": "G\u00fcncelle", "Update Settings": "Ayarlar\u0131 G\u00fcncelle", + "Update comment": "Yorumu g\u00fcncelle", + "Update post": "\u0130leti g\u00fcncelle", + "Update response": "Cevab\u0131 g\u00fcncelle", "Update team.": "Tak\u0131m\u0131 g\u00fcncelle.", "Updating Tags": "Etiketler G\u00fcncelleniyor", "Updating with latest library content": "Son k\u00fct\u00fcphane i\u00e7eri\u011fiyle g\u00fcncelleniyor", @@ -1893,7 +1929,6 @@ "Upload Videos": "Videolar\u0131 Y\u00fckle", "Upload a CSV file": "CSV dosyas\u0131 y\u00fckle", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u0130stisna hakk\u0131 verilen \u00f6\u011frencilerin kullan\u0131c\u0131 adlar\u0131n\u0131 ve e-posta adreslerini i\u00e7eren ve virg\u00fclle ayr\u0131lan de\u011ferler (.csv) dosyas\u0131n\u0131 y\u00fckleyin. Virg\u00fclle ayr\u0131lm\u0131\u015f ilk alana kullan\u0131c\u0131 ad\u0131 ya da e-posta adreslerini ekleyin. \u0130kinci virg\u00fclle ayr\u0131lm\u0131\u015f alana istisna tan\u0131ma nedenini belirten, iste\u011fe ba\u011fl\u0131 bir not ekleyebilirsiniz.", - "Upload a new PDF to \u201c<%= name %>\u201d": " \u015eu konuma \u201c<%= name %>\u201d yeni bir PDF dosyas\u0131 y\u00fckle", "Upload an image": "G\u00f6rsel y\u00fckle", "Upload an image or capture one with your web or phone camera.": "Resim y\u00fckle veya Web kameran\u0131z veya telefonunuzun kameras\u0131yla \u00e7ekiniz.", "Upload completed": "Y\u00fckleme tamamland\u0131", @@ -1923,7 +1958,6 @@ "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "Tart\u0131\u015fmalar\u0131 b\u00f6lmek i\u00e7in kay\u0131tlanma yollar\u0131n\u0131 kullan. Kay\u0131tlanma yollar\u0131na ba\u011fl\u0131 olmaks\u0131z\u0131n t\u00fcm \u00f6\u011frenciler ayn\u0131 tart\u0131\u015fma ba\u015fl\u0131klar\u0131n\u0131 g\u00f6r\u00fcr; b\u00f6l\u00fcnm\u00fc\u015f ba\u015fl\u0131klarda ise sadece ayn\u0131 ayn\u0131 kay\u0131tlanma yolundaki \u00f6\u011frenciler birbirini g\u00f6r\u00fcp, bir di\u011ferine cevap verebilir.", "Use my institution/campus credentials": "Benim kurum / kamp\u00fcs kimlik bilgilerimi kullan\u0131n", "Use the All Topics menu to find specific topics.": "\u00d6zel konular\u0131 bulmak i\u00e7in T\u00fcm Konular men\u00fcs\u00fcn\u00fc kullan", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "Kimli\u011finizin foto\u011fraf\u0131n\u0131 \u00e7ekmek i\u00e7in web kameran\u0131z\u0131 kullan\u0131n. Biz bu foto\u011fraf\u0131n\u0131z\u0131 kimli\u011finiz \u00fczerindeki foto\u011fraf ile e\u015fle\u015ftirece\u011fiz.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "Y\u00fcz\u00fcn\u00fcz\u00fcn foto\u011fraf\u0131n\u0131 \u00e7ekmek i\u00e7in web kameran\u0131z\u0131 kullan\u0131n. Biz bu foto\u011fraf\u0131n\u0131z\u0131 kimli\u011finiz \u00fczerindeki foto\u011fraf ile e\u015fle\u015ftirece\u011fiz.", "Used": "Kullan\u0131ld\u0131", "User Email": "Kullan\u0131c\u0131 E-posta", @@ -1943,7 +1977,6 @@ "Verified Certificate upgrade": "Onayl\u0131 Sertifikay\u0131 G\u00fcncelle", "Verified Status": "Onaylanm\u0131\u015f Durum", "Verified mode price": "Onaylanm\u0131\u015f \u00fccret", - "Verify Now": "\u015eimdi Do\u011frula", "Version": "S\u00fcr\u00fcm", "Vertical space": "Dikey a\u00e7\u0131kl\u0131k", "Very loud": "\u00c7ok y\u00fcksek sesli", @@ -1968,12 +2001,15 @@ "View Program Record": "Program Kayd\u0131n\u0131 G\u00f6ster", "View Teams in the {topic_name} Topic": "{topic_name} Ba\u015fl\u0131\u011f\u0131 Alt\u0131ndaki Tak\u0131mlar\u0131 G\u00f6r\u00fcnt\u00fcle ", "View all errors": "T\u00fcm hatalar\u0131 g\u00f6r", + "View discussion": "Tart\u0131\u015fmay\u0131 g\u00f6r\u00fcnt\u00fcle", "View my exam": "S\u0131nav\u0131m\u0131 g\u00f6r\u00fcnt\u00fcle", "Visibility": "G\u00f6r\u00fcn\u00fcrl\u00fck", + "Visible to": "G\u00f6r\u00fcnecek ki\u015filer", "Visible to Staff Only": "Sadece Personele G\u00f6r\u00fcn\u00fcr", "Visual aids": "G\u00f6rsel yard\u0131mlar", "Volume": "Ses \u015eiddeti", "Vote for good posts and responses": "\u0130yi g\u00f6nderi ve yan\u0131tlar\u0131 oyla", + "Vote for this post,": "Bu ileti i\u00e7in oyla,", "Waiting": "Bekleniyor", "Want to confirm your identity later?": "Kimli\u011finizi daha sonra m\u0131 do\u011frulamak istersiniz?", "Warning": "Uyar\u0131", @@ -1983,7 +2019,6 @@ "We couldn't find any results for \"%s\".": "\"%s\" i\u00e7in hi\u00e7bir sonu\u00e7 bulunamad\u0131.", "We couldn't sign you in.": "Oturumunuzu a\u00e7amad\u0131k.", "We have encountered an error. Refresh your browser and then try again.": "Bir hatayla kar\u015f\u0131la\u015ft\u0131k. Taray\u0131c\u0131n\u0131z\u0131 yenileyin ve sonra tekrar deneyin.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Bilgilerinizi ald\u0131k ve kimli\u011finizi do\u011fruluyoruz. Do\u011frulama s\u00fcreci tamaland\u0131\u011f\u0131nda (genelde 1-2 g\u00fcn i\u00e7erisinde tamamlan\u0131r) ana panelinize mesaj gelecektir. Bu s\u00fcre i\u00e7inde mevcut olan ders i\u00e7eriklerine ula\u015fabilirsiniz.", "We just need a little more information before you start learning with %(platformName)s.": "%(platformName)s ile \u00f6\u011frenmeye ba\u015flamadan \u00f6nce biraz daha bilgiye ihtiyac\u0131m\u0131z var.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Foto\u011fraf\u0131n\u0131z\u0131 \u015fifrelemek ve inceleme i\u00e7in yetkilendirme hizmetimize g\u00f6ndermek i\u00e7in uygun olan en y\u00fcksek seviyede g\u00fcvenli\u011fi kullan\u0131yoruz. Foto\u011fraf\u0131n\u0131z ve bilgileriniz kaydedilmez ve do\u011frulama s\u00fcreci tamamland\u0131ktan sonra %(platformName)s \u00fczerinde hi\u00e7bir yerde g\u00f6r\u00fclmez.", "We're sorry to see you go! Your account will be deleted shortly.": "Gitti\u011finizi g\u00f6rmek bizi \u00fcz\u00fcyor! Hesab\u0131n\u0131z yak\u0131nda silinecek.", @@ -2080,13 +2115,10 @@ "You must specify a name": "\u0130sim belirtmelisiniz", "You must specify a name for the cohort": "Topluluk i\u00e7in bir isim belirtmelisiniz", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "T\u00fcm profilinizi payla\u015fmadan \u00f6nce do\u011fum y\u0131l\u0131n\u0131z\u0131 belirlemek zorundas\u0131n\u0131z. Do\u011fum y\u0131l\u0131n\u0131z\u0131 belirlemek i\u00e7in, {account_settings_page_link} gidin", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "Ad\u0131n\u0131z\u0131 ve foto\u011fraf\u0131n\u0131z\u0131 i\u00e7eren bir ehliyet, pasaport veya di\u011fer devlet taraf\u0131ndan verilen kimli\u011fe ihtiyac\u0131n\u0131z var.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "Ad\u0131n\u0131z\u0131 ve foto\u011fraf\u0131n\u0131z\u0131 i\u00e7eren bir kimli\u011fe ihtiyac\u0131n\u0131z vard\u0131r. Bir ehliyet, pasaport veya di\u011fer h\u00fck\u00fcmet taraf\u0131ndan verilen kimlikler t\u00fcm kabul edilebilir.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "Derse kay\u0131t olmadan \u00f6nce hesab\u0131n\u0131z\u0131 aktive edin. Etkinle\u015ftirme e-posta i\u00e7in gelen kutunuzu kontrol edin.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "Derse kay\u0131t olmadan \u00f6nce hesab\u0131n\u0131z\u0131 aktive edin. Etkinle\u015ftirme e-posta i\u00e7in gelen kutunuzu kontrol edin. Etkinle\u015ftirmeyi tamamlad\u0131ktan sonra bu sayfaya d\u00f6nebilir ve yenileyebilirsiniz.", "You receive messages from {platform_name} and course teams at this address.": "{platform_name} platformundan ve ders tak\u0131mlar\u0131ndan iletileri bu adrese alacaks\u0131n\u0131z.", "You reserve all rights for your work": "Eserinizin t\u00fcm haklar\u0131 sizde sakl\u0131d\u0131r", - "You still need to visit the %(display_name)s website to complete the credit process.": "Sizin hala daha kredi i\u015flemini tamamlamak i\u00e7in %(display_name)s websitesine ziyaret etmeniz gerekmektedir.", "You submitted {filename}; only {allowedFiles} are allowed.": "{filename} dosyas\u0131n\u0131 g\u00f6nderdiniz; sadece {allowedFiles} dosyalar\u0131na izin veriliyor.", "You waive some rights for your work, such that others can use it too": "Eserinizdeki baz\u0131 haklar\u0131n\u0131zdan feragat edebilirsiniz, b\u00f6ylece ba\u015fkalar\u0131 da onu kolayca kullanabilir", "You will be refunded the amount you paid.": "\u00d6dedi\u011finiz tutar size iade edilecektir.", @@ -2156,6 +2188,7 @@ "and others": "ve di\u011ferleri", "anonymous": "anonim", "answer": "cevap", + "answered question": "soru cevapland\u0131", "asset_path is required": "asset_path gerekli", "bytes": "byte", "certificate": "sertifika", @@ -2169,6 +2202,7 @@ "delete chapter": "b\u00f6l\u00fcm sil", "delete group": "grubu sil", "details about the failure": "ba\u015far\u0131s\u0131zl\u0131\u011fa dair ayr\u0131nt\u0131lar", + "discussion": "tart\u0131\u015fma", "dragging": "s\u00fcr\u00fckleme", "dragging out of slider": "Kayd\u0131r\u0131c\u0131n\u0131n d\u0131\u015f\u0131na s\u00fcr\u00fckleme", "dropped in slider": "kayd\u0131r\u0131c\u0131ya b\u0131rak\u0131ld\u0131", @@ -2180,8 +2214,8 @@ "emphasized text": "vurgulu metin", "enter code here": "kodu buraya girin", "enter link description here": "ba\u011flant\u0131 tan\u0131m\u0131n\u0131 buraya girin", + "follow this post": "bu iletiyi takip et", "for": "i\u00e7in", - "for {courseName}": "{courseName} i\u00e7in", "group configuration": "grup ayar\u0131", "image omitted": "g\u00f6rsel atland\u0131", "incorrect": "yanl\u0131\u015f", @@ -2205,6 +2239,8 @@ "or create a new one here": "ya da burada yeni bir tane olu\u015fturunuz", "or sign in with": "veya oturum a\u00e7\u0131n", "pending": "beklemede", + "post anonymously": "isimsiz olarak ileti yolla", + "posted %(time_ago)s by %(author)s": "%(author)s taraf\u0131ndan %(time_ago)s \u00f6nce g\u00f6nderildi", "practice": "al\u0131\u015ft\u0131rma", "price": "\u00fccret", "proctored": "g\u00f6zetmenli", @@ -2221,6 +2257,7 @@ "subsection": "altb\u00f6l\u00fcm", "team count": "tak\u0131m say\u0131s\u0131", "timed": "zamanlanm\u0131\u015f", + "unanswered question": "cevaplanmayan soru", "unit": "\u00fcnite", "unsatisfactory": "yetersiz", "unsubmitted": "g\u00f6nderilmedi", @@ -2303,6 +2340,7 @@ "{totalItems} total": "toplam {totalItems}", "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}": "{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}", "{type} Progress": "{type} \u0130lerleme", + "{unread_comments_count} new": "{unread_comments_count} yeni", "\u2026": "..." }; for (var key in newcatalog) { @@ -2325,7 +2363,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2378,9 +2416,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "d F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d M Y H:i", "SHORT_DATE_FORMAT": "d M Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/uk/djangojs.js b/lms/static/js/i18n/uk/djangojs.js index 592be1dc0d1a4d63f55f878a034aab81cd97931a..6c37475b2786402f8c4701cf9d84b8d3774c4b65 100644 --- a/lms/static/js/i18n/uk/djangojs.js +++ b/lms/static/js/i18n/uk/djangojs.js @@ -42,6 +42,7 @@ "%(field)s must have at least %(count)d characters.": "%(field)s \u043f\u043e\u0432\u0438\u043d\u043d\u043e \u0431\u0443\u0442\u0438 \u043d\u0435 \u043c\u0435\u043d\u0448\u0435 %(count)d \u0441\u0438\u043c\u0432\u043e\u043b\u0456\u0432.", "%(programName)s Home Page.": "%(programName)s \u0414\u043e\u043c\u0430\u0448\u043d\u044f \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0430 ", "%(sel)s of %(cnt)s selected": [ + "\u041e\u0431\u0440\u0430\u043d\u043e %(sel)s \u0437 %(cnt)s", "\u041e\u0431\u0440\u0430\u043d\u043e %(sel)s \u0437 %(cnt)s", "\u041e\u0431\u0440\u0430\u043d\u043e %(sel)s \u0437 %(cnt)s", "\u041e\u0431\u0440\u0430\u043d\u043e %(sel)s \u0437 %(cnt)s" @@ -388,7 +389,6 @@ "Default": "\u041e\u0441\u043d\u043e\u0432\u043d\u0438\u0439", "Default (Local Time Zone)": "\u0417\u0430 \u0437\u0430\u043c\u043e\u0432\u0447\u0430\u043d\u043d\u044f\u043c (\u043c\u0456\u0441\u0446\u0435\u0432\u0438\u0439 \u0447\u0430\u0441\u043e\u0432\u0438\u0439 \u043f\u043e\u044f\u0441)", "Delete": "\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \"<%= signatoryName %>\" \u0437\u0456 \u0441\u043f\u0438\u0441\u043a\u0443 \u043f\u043e\u043b\u0456\u0432?", "Delete File Confirmation": "\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u0432\u0438\u0434\u0430\u043b\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b\u0443. ", "Delete My Account": "\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u043c\u0456\u0439 \u043e\u0431\u043b\u0456\u043a\u043e\u0432\u0438\u0439 \u0437\u0430\u043f\u0438\u0441", "Delete Page Confirmation": "\u041f\u0456\u0434\u0442\u0432\u0435\u0440\u0434\u0436\u0435\u043d\u043d\u044f \u0432\u0438\u0434\u0430\u043b\u0435\u043d\u043d\u044f \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438", @@ -778,11 +778,13 @@ "Note: You are %s hour ahead of server time.": [ "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d\u0443 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d\u0438 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", + "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443." ], "Note: You are %s hour behind server time.": [ "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d\u0443 \u043f\u043e\u0437\u0430\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d\u0438 \u043f\u043e\u0437\u0430\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", + "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d \u043f\u043e\u0437\u0430\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443.", "\u041f\u0440\u0438\u043c\u0456\u0442\u043a\u0430: \u0412\u0438 \u043d\u0430 %s \u0433\u043e\u0434\u0438\u043d \u043f\u043e\u0437\u0430\u0434\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443." ], "Notes hidden": "\u041d\u043e\u0442\u0430\u0442\u043a\u0438 \u043f\u0440\u0438\u0445\u043e\u0432\u0430\u043d\u0456", @@ -800,7 +802,6 @@ "October": "\u0436\u043e\u0432\u0442\u043d\u044f", "Ok": "\u0414\u043e\u0431\u0440\u0435", "One or more rescheduling tasks failed.": "\u041e\u0434\u043d\u0430 \u0430\u0431\u043e \u043a\u0456\u043b\u044c\u043a\u0430 \u0437\u0430\u0434\u0430\u0447 \u043f\u0435\u0440\u0435\u043f\u043b\u0430\u043d\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u043b\u0430\u0441\u044f.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u041b\u0438\u0448\u0435 \u0444\u0430\u0439\u043b\u0438 \u0442\u0438\u043f\u0456\u0432 <%= fileTypes %> \u043c\u043e\u0436\u0443\u0442\u044c \u0431\u0443\u0442\u0438 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u0456. \u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u043e\u0431\u0435\u0440\u0456\u0442\u044c \u0434\u043b\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0444\u0430\u0439\u043b \u0437 \u0440\u043e\u0437\u0448\u0438\u0440\u0435\u043d\u043d\u044f\u043c <%= fileExtensions %>.", "Only properly formatted .csv files will be accepted.": "\u0414\u043e\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u044c\u0441\u044f \u0442\u0456\u043b\u044c\u043a\u0438 .csv \u0444\u0430\u0439\u043b\u0438 \u0437 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u0438\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c.", "Open Calculator": "\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440", "Open language menu": "\u0412\u0438\u0431\u0456\u0440 \u043c\u043e\u0432\u0438", @@ -1103,8 +1104,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u0421\u0435\u0440\u0442\u0438\u0444\u0456\u043a\u0430\u0442 \u0434\u043b\u044f \u0434\u0430\u043d\u043e\u0433\u043e \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u0430 \u0432\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439, \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e \u043f\u0435\u0440\u0435\u0440\u0430\u0445\u0443\u043d\u043e\u043a \u043e\u0446\u0456\u043d\u043a\u0438.", "The cohort cannot be added": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0434\u043e\u0434\u0430\u0442\u0438 \u043a\u043e\u0433\u043e\u0440\u0442\u0443", "The cohort cannot be saved": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0437\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u043a\u043e\u0433\u043e\u0440\u0442\u0443", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u0421\u0443\u043a\u0443\u043f\u043d\u0430 \u0434\u043e\u0432\u0436\u0438\u043d\u0430 \u043d\u0430\u0437\u0432\u0438 \u043e\u0440\u0433\u0430\u043d\u0456\u0437\u0430\u0446\u0456\u0457 \u0442\u0430 \u043a\u043e\u0434\u0443 \u0431\u0456\u0431\u043b\u0456\u043e\u0442\u0435\u043a\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435 \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0443\u0432\u0430\u0442\u0438 <%=limit%> \u0441\u0438\u043c\u0432\u043e\u043b\u0456\u0432.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u0421\u0443\u043a\u0443\u043f\u043d\u0430 \u0434\u043e\u0432\u0436\u0438\u043d\u0430 \u043d\u0430\u0437\u0432\u0438 \u043e\u0440\u0433\u0430\u043d\u0456\u0437\u0430\u0446\u0456\u0457, \u043d\u043e\u043c\u0435\u0440\u0430 \u043a\u0443\u0440\u0441\u0443 \u0442\u0430 \u043d\u0430\u0432\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u043e\u043a\u0443 \u043d\u0435 \u043c\u043e\u0436\u0435 \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0443\u0432\u0430\u0442\u0438 <%=limit%> \u0441\u0438\u043c\u0432\u043e\u043b\u0456\u0432.", "The country or region where you live.": "\u041a\u0440\u0430\u0457\u043d\u0430 \u0430\u0431\u043e \u0440\u0435\u0433\u0456\u043e\u043d, \u0434\u0435 \u0412\u0438 \u043f\u0440\u043e\u0436\u0438\u0432\u0430\u0454\u0442\u0435.", "The country that team members primarily identify with.": "\u041a\u0440\u0430\u0457\u043d\u0430, \u0434\u043e \u044f\u043a\u043e\u0457 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432\u0456\u0434\u043d\u043e\u0441\u0438\u0442\u044c \u0441\u0435\u0431\u0435.", "The display of ungraded and checked out responses could not be loaded.": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0435\u043a\u0440\u0430\u043d \u043d\u0435\u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0438\u0445 \u0442\u0430 \u043f\u0435\u0440\u0435\u0432\u0456\u0440\u0435\u043d\u0438\u0445 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0435\u0439.", @@ -1285,7 +1284,6 @@ "Upload Videos": "\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0412\u0456\u0434\u0435\u043e", "Upload a CSV file": "\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 CSV \u0444\u0430\u0439\u043b", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0442\u0435 \u0444\u0430\u0439\u043b \u0437\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f\u043c\u0438, \u0440\u043e\u0437\u0434\u0456\u043b\u0435\u043d\u0438\u043c\u0438 \u043a\u043e\u043c\u0430\u043c\u0438 (.csv), \u044f\u043a\u0438\u0439 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0456\u043c\u0435\u043d\u0430 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456\u0432 \u0430\u0431\u043e \u0430\u0434\u0440\u0435\u0441\u0438 \u0435\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0457 \u043f\u043e\u0448\u0442\u0438 \u0442\u0438\u0445 \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u0456\u0432, \u044f\u043a\u0438\u043c \u043d\u0430\u0434\u0430\u043d\u043e \u0432\u0438\u043d\u044f\u0442\u043e\u043a. \u041f\u0435\u0440\u0448\u0438\u043c \u0432\u0432\u0435\u0434\u0456\u0442\u044c \u0456\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0430\u0431\u043e \u0430\u0434\u0440\u0435\u0441\u0443 \u0435\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0457 \u043f\u043e\u0448\u0442\u0438 \u0442\u0430 \u0432\u0456\u0434\u043e\u043a\u0440\u0435\u043c\u0442\u0435 \u043a\u043e\u043c\u043e\u044e. \u0417\u0430 \u0431\u0430\u0436\u0430\u043d\u043d\u044f\u043c \u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0434\u0430\u0442\u0438 \u043f\u0440\u0438\u043c\u0456\u0442\u043a\u0443, \u044f\u043a\u0430 \u0431 \u043e\u043f\u0438\u0441\u0443\u0432\u0430\u043b\u0430 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u0432\u0438\u043d\u044f\u0442\u043a\u0443. \u0412\u043e\u043d\u0430 \u0431\u0443\u0434\u0435 \u0432\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u0438\u0441\u044f \u0443 \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u043f\u043e\u043b\u0456.", - "Upload a new PDF to \u201c<%= name %>\u201d": "\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u043d\u043e\u0432\u0438\u0439 PDF \u0432 \u201c<%= name %>\u201d", "Upload an image": "\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f", "Upload completed": "\u0412\u0438\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e", "Upload completed for video {fileName}": "\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0432\u0456\u0434\u0435\u043e {fileName}", @@ -1616,7 +1614,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1672,9 +1670,9 @@ "%Y-%m-%d" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "1", + "FIRST_DAY_OF_WEEK": 1, "MONTH_DAY_FORMAT": "d F", - "NUMBER_GROUPING": "3", + "NUMBER_GROUPING": 3, "SHORT_DATETIME_FORMAT": "d.m.Y H:i", "SHORT_DATE_FORMAT": "d.m.Y", "THOUSAND_SEPARATOR": "\u00a0", diff --git a/lms/static/js/i18n/ur/djangojs.js b/lms/static/js/i18n/ur/djangojs.js index af088af299a6dfec3655ea926e048d4a8e0a37c7..63d4b562ff70ad4ff54810fa71a1e6bc640473eb 100644 --- a/lms/static/js/i18n/ur/djangojs.js +++ b/lms/static/js/i18n/ur/djangojs.js @@ -64,7 +64,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -128,9 +128,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/uz/djangojs.js b/lms/static/js/i18n/uz/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/lms/static/js/i18n/uz/djangojs.js +++ b/lms/static/js/i18n/uz/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/vi/djangojs.js b/lms/static/js/i18n/vi/djangojs.js index 46ea6adac3ceef46f780460186e244b6ade7b7d4..b307df4fab4b253039cbaa3c00cd236ea22f318e 100644 --- a/lms/static/js/i18n/vi/djangojs.js +++ b/lms/static/js/i18n/vi/djangojs.js @@ -419,7 +419,6 @@ "Default (Local Time Zone)": "M\u1eb7c \u0111\u1ecbnh (M\u00fai gi\u1edd \u0111\u1ecba ph\u01b0\u01a1ng)", "Default Timed Transcript": "M\u1eb7c \u0111\u1ecbnh Timed Transcript", "Delete": "X\u00f3a", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "Xo\u00e1 \"<%= signatoryName %>\" t\u1eeb danh s\u00e1ch k\u00fd t\u00ean?", "Delete File Confirmation": "X\u00e1c Nh\u1eadn X\u00f3a File", "Delete My Account": "X\u00f3a t\u00e0i kho\u1ea3n", "Delete Page Confirmation": "X\u00e1c Nh\u1eadn X\u00f3a Trang", @@ -456,7 +455,6 @@ "Do you want to allow this student ('{student_id}') to skip the entrance exam?": "B\u1ea1n c\u00f3 mu\u1ed1n cho ph\u00e9p sinh vi\u00ean n\u00e0y ('{student_id}') \u0111\u01b0\u1ee3c ph\u00e9p b\u1ecf qua b\u00e0i ki\u1ec3m tra \u0111\u1ea7u v\u00e0o?", "Do you want to replace the edX transcript with the YouTube transcript?": "B\u1ea1n c\u00f3 mu\u1ed1n thay th\u1ebf b\u1ea3n d\u1ecbch edX b\u1eb1ng b\u1ea3n d\u1ecbch c\u1ee7a YouTube kh\u00f4ng?", "Document properties": "\u0110\u1eb7c t\u00ednh t\u00e0i li\u1ec7u", - "Does the photo of you match your ID photo?": "H\u00ecnh c\u1ee7a b\u1ea1n c\u00f3 gi\u1ed1ng v\u1edbi h\u00ecnh tr\u00ean ch\u1ee9ng minh nh\u00e2n d\u00e2n kh\u00f4ng?", "Does the photo of you show your whole face?": "H\u00ecnh c\u1ee7a b\u1ea1n c\u00f3 hi\u1ec3n th\u1ecb to\u00e0n b\u1ed9 khu\u00f4n m\u1eb7t kh\u00f4ng?", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "Kh\u00f4ng nh\u00ecn th\u1ea5y h\u00ecnh \u1ea3nh c\u1ee7a b\u1ea1n? H\u00e3y ch\u1eafc ch\u1eafn \u0111\u1ec3 cho ph\u00e9p tr\u00ecnh duy\u1ec7t c\u1ee7a b\u1ea1n \u0111\u1ec3 s\u1eed d\u1ee5ng m\u00e1y \u1ea3nh c\u1ee7a b\u1ea1n khi n\u00f3 y\u00eau c\u1ea7u s\u1ef1 cho ph\u00e9p.", "Donate": "Quy\u00ean g\u00f3p", @@ -612,7 +610,6 @@ "Gender": "Gi\u1edbi t\u00ednh", "General": "Chung", "General Proctored Exam Rules": "Quy t\u1eafc Chung v\u1ec1 Thi C\u00f3 gi\u00e1m s\u00e1t", - "Get Credit": "L\u1ea5y t\u00edn ch\u1ec9", "Go to Dashboard": "\u0110i \u0111\u1ebfn b\u1ea3ng \u0111i\u1ec1u khi\u1ec3n", "Go to my Dashboard": "Chuy\u1ec3n \u0111\u1ebfn b\u1ea3ng th\u00f4ng tin c\u1ee7a t\u00f4i", "Go to {platform} Home": "Chuy\u1ec3n \u0111\u1ebfn Trang ch\u1ee7 {platform}", @@ -904,7 +901,6 @@ "ORDER PLACED": "\u0110\u00c3 \u0110\u1eb6T H\u00c0NG", "Ok": "Ok", "One or more rescheduling tasks failed.": "M\u1ed9t ho\u1eb7c nhi\u1ec1u t\u00e1c v\u1ee5 \u0111i\u1ec1u ch\u1ec9nh l\u1ecbch h\u1ecdc \u0111\u00e3 th\u1ea5t b\u1ea1i.", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "Ch\u1ec9 t\u1eadp tin d\u1ea1ng <%= fileTypes %> c\u00f3 th\u1ec3 \u0111\u01b0\u1ee3c t\u1ea3i l\u00ean. Xin vui l\u00f2ng ch\u1ecdn m\u1ed9t t\u1eadp tin k\u1ebft th\u00fac b\u1eb1ng <%= fileExtensions %> \u0111\u1ec3 t\u1ea3i l\u00ean.", "Only properly formatted .csv files will be accepted.": "Ch\u1ec9 nh\u1eefng t\u1ec7p tin theo \u0111\u1ecbnh d\u1ea1ng .csv chu\u1ea9n \u0111\u01b0\u1ee3c ch\u1ea5p nh\u1eadn.", "Open Calculator": "M\u1edf m\u00e1y t\u00ednh ", "Open language menu": "M\u1edf menu ng\u00f4n ng\u1eef", @@ -1215,7 +1211,7 @@ "Subject": "Ch\u1ee7 \u0111\u1ec1", "Subject:": "Ch\u1ee7 \u0111\u1ec1:", "Submission aborted! Sorry, your browser does not support file uploads. If you can, please use Chrome or Safari which have been verified to support file uploads.": "G\u1eedi b\u1ecb h\u1ee7y b\u1ecf! Xin l\u1ed7i, tr\u00ecnh duy\u1ec7t c\u1ee7a b\u1ea1n kh\u00f4ng h\u1ed7 tr\u1ee3 t\u1ea3i l\u00ean t\u1ec7p. N\u1ebfu c\u00f3 th\u1ec3, vui l\u00f2ng s\u1eed d\u1ee5ng Chrome ho\u1eb7c Safari \u0111\u00e3 \u0111\u01b0\u1ee3c x\u00e1c nh\u1eadn h\u1ed7 tr\u1ee3 t\u1ea3i l\u00ean t\u1ec7p tin.", - "Submit": "G\u1eedi", + "Submit": "N\u1ed9p", "Submitted": "\u0110\u00e3 g\u1eedi", "Subscript": "Subscript", "Subsection": "Ti\u1ec3u m\u1ee5c", @@ -1288,8 +1284,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "Gi\u1ea5y ch\u1ee9ng nh\u1eadn cho h\u1ecdc vi\u00ean n\u00e0y \u0111\u00e3 \u0111\u01b0\u1ee3c x\u00e1c nh\u1eadn l\u1ea1i v\u00e0 h\u1ec7 th\u1ed1ng \u0111ang x\u1eed l\u00fd c\u1ea5p ph\u00e1t l\u1ea1i cho h\u1ecdc vi\u00ean n\u00e0y n\u00e0y.", "The cohort cannot be added": "Kh\u00f4ng th\u00eam \u0111\u01b0\u1ee3c nh\u00f3m h\u1ecdc vi\u00ean n\u00e0y", "The cohort cannot be saved": "Kh\u00f4ng l\u01b0u \u0111\u01b0\u1ee3c nh\u00f3m h\u1ecdc vi\u00ean n\u00e0y", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "Chi\u1ec1u d\u00e0i k\u1ebft h\u1ee3p c\u1ee7a tr\u01b0\u1eddng t\u1ed5 ch\u1ee9c v\u00e0 m\u00e3 m\u00e3 th\u01b0 vi\u1ec7n kh\u00f4ng \u0111\u01b0\u1ee3c nhi\u1ec1u h\u01a1n <%=limit%> k\u00fd t\u1ef1.", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "Chi\u1ec1u d\u00e0i k\u1ebft h\u1ee3p c\u1ee7a c\u00e1c tr\u01b0\u1eddng t\u1ed5 ch\u1ee9c, s\u1ed1 hi\u1ec7u kho\u00e1 h\u1ecdc, h\u1ecdc k\u1ef3 kh\u00f4ng \u0111\u01b0\u1ee3c nhi\u1ec1u h\u01a1n <%=limit%> k\u00fd t\u1ef1.", "The country or region where you live.": "Qu\u1ed1c gia ho\u1eb7c n\u01a1i b\u1ea1n sinh s\u1ed1ng.", "The country that team members primarily identify with.": "Qu\u1ed1c gia ch\u00ednh c\u1ee7a c\u00e1c th\u00e0nh vi\u00ean nh\u00f3m.", "The course end date must be later than the course start date.": "Ng\u00e0y k\u1ebft th\u00fac c\u1ee7a kh\u00f3a h\u1ecdc ph\u1ea3i sau ng\u00e0y b\u1eaft \u0111\u1ea7u c\u1ee7a kh\u00f3a h\u1ecdc.", @@ -1319,7 +1313,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "S\u1ed1 ph\u1ea7n con trong kh\u00f3a h\u1ecdc ch\u1ee9a c\u00e1c c\u00e2u h\u1ecfi c\u1ee7a lo\u1ea1i b\u00e0i t\u1eadp n\u00e0y.", "The organization that this signatory belongs to, as it should appear on certificates.": "T\u1ed5 ch\u1ee9c m\u00e0 ng\u01b0\u1eddi k\u00fd t\u00ean n\u00e0y thu\u1ed9c v\u1ec1, nh\u01b0 n\u00f3 s\u1ebd xu\u1ea5t hi\u1ec7n tr\u00ean gi\u1ea5y ch\u1ee9ng nh\u1eadn.", "The page \"{route}\" could not be found.": "Kh\u00f4ng th\u1ea5y trang \"{route}\".", - "The photo of your face matches the photo on your ID.": "Nh\u1eefng h\u00ecnh \u1ea3nh c\u1ee7a khu\u00f4n m\u1eb7t c\u1ee7a b\u1ea1n ph\u00f9 h\u1ee3p v\u1edbi h\u00ecnh \u1ea3nh tr\u00ean ID c\u1ee7a b\u1ea1n.", "The post you selected has been deleted.": "B\u00e0i b\u1ea1n ch\u1ecdn \u0111\u00e3 b\u1ecb x\u00f3a.", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "Phi\u00ean b\u1ea3n nh\u00e1nh \u0111\u00e3 xu\u1ea5t b\u1ea3n, {published}, \u0111\u00e3 \u0111\u01b0\u1ee3c \u0111\u1eb7t l\u1ea1i th\u00e0nh phi\u00ean b\u1ea3n nh\u00e1nh d\u1ef1 th\u1ea3o, {draft}.", "The raw error message is:": "Th\u00f4ng b\u00e1o l\u1ed7i ban \u0111\u1ea7u l\u00e0:", @@ -1507,7 +1500,6 @@ "Upload Photo": "T\u1ea3i \u1ea2nh l\u00ean", "Upload Signature Image": "T\u1ea3i l\u00ean H\u00ecnh \u1ea3nh Ch\u1eef k\u00fd", "Upload Videos": "T\u1ea3i l\u00ean Video", - "Upload a new PDF to \u201c<%= name %>\u201d": "T\u1ea3i l\u00ean m\u1ed9t file PDF m\u1edbi l\u00ean \u201c<%= name %>\u201d", "Upload an image": "T\u1ea3i l\u00ean h\u00ecnh \u1ea3nh", "Upload an image or capture one with your web or phone camera.": "T\u1ea3i l\u00ean m\u1ed9t h\u00ecnh \u1ea3nh ho\u1eb7c ch\u1ee5p m\u1ed9t v\u1edbi web c\u1ee7a b\u1ea1n ho\u1eb7c camera \u0111i\u1ec7n tho\u1ea1i.", "Upload completed": "T\u1ea3i l\u00ean ho\u00e0n t\u1ea5t", @@ -1534,7 +1526,6 @@ "Use as a Prerequisite": "S\u1eed d\u1ee5ng nh\u01b0 y\u00eau c\u1ea7u b\u0103t bu\u1ed9c", "Use cohorts as the basis for dividing discussions. All learners, regardless of cohort, see the same discussion topics, but within divided topics, only members of the same cohort see and respond to each others\u2019 posts. ": "S\u1eed d\u1ee5ng c\u00e1c nh\u00f3m l\u00e0m c\u01a1 s\u1edf \u0111\u1ec3 chia s\u1ebb c\u00e1c cu\u1ed9c th\u1ea3o lu\u1eadn. T\u1ea5t c\u1ea3 ng\u01b0\u1eddi h\u1ecdc, kh\u00f4ng ph\u00e2n bi\u1ec7t nh\u00f3m, xem c\u00e1c ch\u1ee7 \u0111\u1ec1 th\u1ea3o lu\u1eadn gi\u1ed1ng nhau, nh\u01b0ng trong c\u00e1c ch\u1ee7 \u0111\u1ec1 chia s\u1ebb, ch\u1ec9 nh\u1eefng th\u00e0nh vi\u00ean c\u1ee7a c\u00f9ng m\u1ed9t nh\u00f3m m\u1edbi th\u1ea5y v\u00e0 tr\u1ea3 l\u1eddi c\u00e1c b\u00e0i \u0111\u0103ng c\u1ee7a nhau.", "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "S\u1eed d\u1ee5ng c\u00e1c ki\u1ec3u \u0111\u0103ng k\u00fd l\u00e0m c\u01a1 s\u1edf \u0111\u1ec3 ph\u00e2n chia c\u00e1c cu\u1ed9c th\u1ea3o lu\u1eadn. T\u1ea5t c\u1ea3 h\u1ecdc vi\u00ean, b\u1ea5t k\u1ec3 ki\u1ec3u \u0111\u0103ng k\u00fd c\u1ee7a h\u1ecd, xem c\u00e1c ch\u1ee7 \u0111\u1ec1 th\u1ea3o lu\u1eadn gi\u1ed1ng nhau, nh\u01b0ng trong c\u00e1c ch\u1ee7 \u0111\u1ec1 \u0111\u00e3 ph\u00e2n chia, ch\u1ec9 nh\u1eefng h\u1ecdc vi\u00ean trong c\u00f9ng m\u1ed9t ki\u1ec3u \u0111\u0103ng k\u00fd m\u1edbi nh\u00ecn th\u1ea5y v\u00e0 tr\u1ea3 l\u1eddi c\u00e1c b\u00e0i vi\u1ebft c\u1ee7a nhau.", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "S\u1eed d\u1ee5ng webcam c\u1ee7a b\u1ea1n \u0111\u1ec3 c\u00f3 m\u1ed9t b\u1ee9c \u1ea3nh c\u1ee7a ID c\u1ee7a b\u1ea1n. Ch\u00fang t\u00f4i s\u1ebd \u0111\u1ed1i b\u1ee9c \u1ea3nh n\u00e0y v\u1edbi h\u00ecnh \u1ea3nh c\u1ee7a khu\u00f4n m\u1eb7t c\u1ee7a b\u1ea1n v\u00e0 t\u00ean t\u00e0i kho\u1ea3n c\u1ee7a b\u1ea1n.", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "S\u1eed d\u1ee5ng webcam c\u1ee7a b\u1ea1n \u0111\u1ec3 c\u00f3 m\u1ed9t h\u00ecnh \u1ea3nh c\u1ee7a khu\u00f4n m\u1eb7t c\u1ee7a b\u1ea1n \u0111\u1ec3 ch\u00fang t\u00f4i c\u00f3 th\u1ec3 k\u1ebft h\u1ee3p n\u00f3 v\u1edbi h\u00ecnh \u1ea3nh tr\u00ean ID c\u1ee7a b\u1ea1n.", "Used": "\u0110\u01b0\u1ee3c s\u1eed d\u1ee5ng", "Used in {count} location": [ @@ -1550,7 +1541,6 @@ "Verification checkpoint to be completed": "Ki\u1ec3m tra \u0111\u1ec3 ho\u00e0n th\u00e0nh x\u00e1c minh", "Verified Certificate": "Ch\u1ee9ng ch\u1ec9 c\u00f3 x\u00e1c nh\u1eadn", "Verified Certificate upgrade": "N\u00e2ng c\u1ea5p l\u00ean ch\u1ee9ng ch\u1ec9 c\u00f3 x\u00e1c nh\u1eadn", - "Verify Now": "X\u00e1c nh\u1eadn ngay b\u00e2y gi\u1edd", "Version": "Phi\u00ean b\u1ea3n", "Vertical space": "Vertical space", "Very loud": "R\u1ea5t to", @@ -1585,7 +1575,6 @@ "We couldn't find any results for \"%s\".": "Kh\u00f4ng th\u1ec3 t\u00ecm th\u1ea5y k\u1ebft qu\u1ea3 cho \"%s\".", "We couldn't sign you in.": "Ch\u00fang t\u00f4i kh\u00f4ng th\u1ec3 \u0111\u0103ng nh\u1eadp cho b\u1ea1n.", "We have encountered an error. Refresh your browser and then try again.": "\u0110\u00e3 ph\u00e1t hi\u1ec7n l\u1ed7i. L\u00e0m m\u1edbi l\u1ea1i tr\u00ecnh duy\u1ec7t c\u1ee7a b\u1ea1n r\u1ed3i th\u1eed l\u1ea1i.", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "Ch\u00fang t\u00f4i \u0111\u00e3 nh\u1eadn \u0111\u01b0\u1ee3c th\u00f4ng tin c\u1ee7a b\u1ea1n v\u00e0 \u0111ang ti\u1ebfn x\u00e1c nh\u1eadn danh t\u00ednh c\u1ee7a b\u1ea1n. B\u1ea1n s\u1ebd th\u1ea5y m\u1ed9t tin nh\u1eafn tr\u00ean b\u1ea3ng \u0111i\u1ec1u khi\u1ec3n khi qu\u00e1 tr\u00ecnh x\u00e1c nh\u1eadn ho\u00e0n t\u1ea5t (th\u00f4ng th\u01b0\u1eddng trong v\u00f2ng 1-2 ng\u00e0y). Trong th\u1eddi gian ch\u1edd \u0111\u1ee3i, b\u1ea1n v\u00e3n c\u00f3 th\u1ec3 truy c\u1eadp n\u1ed9i dung c\u00e1c kho\u00e1 h\u1ecdc c\u00f3 s\u1eb5n.", "We just need a little more information before you start learning with %(platformName)s.": "Ch\u00fang t\u00f4i ch\u1ec9 c\u1ea7n th\u00eam m\u1ed9t ch\u00fat th\u00f4ng tin tr\u01b0\u1edbc khi b\u1ea1n b\u1eaft \u0111\u1ea7u h\u1ecdc v\u1edbi %(platformName)s.", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "Ch\u00fang t\u00f4i s\u1eed d\u1ee5ng c\u00e1c m\u1ee9c b\u1ea3o m\u1eadt cao nh\u1ea5t c\u00f3 s\u1eb5n \u0111\u1ec3 m\u00e3 h\u00f3a h\u00ecnh \u1ea3nh c\u1ee7a b\u1ea1n v\u00e0 g\u1eedi n\u00f3 \u0111\u1ebfn d\u1ecbch v\u1ee5 \u1ee7y quy\u1ec1n c\u1ee7a ch\u00fang t\u00f4i \u0111\u1ec3 xem x\u00e9t. \u1ea2nh v\u00e0 th\u00f4ng tin c\u1ee7a b\u1ea1n s\u1ebd kh\u00f4ng \u0111\u01b0\u1ee3c l\u01b0u hay b\u1ea5t c\u1ee9 n\u01a1i n\u00e0o c\u00f3 th\u1ec3 nh\u00ecn th\u1ea5y tr\u00ean %(platformName)s sau khi qu\u00e1 tr\u00ecnh x\u00e1c minh ho\u00e0n t\u1ea5t.", "We're sorry to see you go! Your account will be deleted shortly.": "Ch\u00fang t\u00f4i r\u1ea5t ti\u1ebfc khi th\u1ea5y b\u1ea1n ra \u0111i! T\u00e0i kho\u1ea3n c\u1ee7a b\u1ea1n s\u1ebd \u0111\u01b0\u1ee3c x\u00f3a ngay.", @@ -1659,12 +1648,9 @@ "You must specify a name": "B\u1ea1n ph\u1ea3i x\u00e1c \u0111\u1ecbnh m\u1ed9t t\u00ean", "You must specify a name for the cohort": "B\u1ea1n ph\u1ea3i \u0111\u1eb7t t\u00ean cho nh\u00f3m.", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "B\u1ea1n ph\u1ea3i nh\u1eadp v\u00e0o n\u0103m sinh tr\u01b0\u1edbc khi b\u1ea1n c\u00f3 th\u1ec3 chia s\u1ebb to\u00e0n b\u1ed9 h\u1ed3 s\u01a1 c\u1ee7a b\u1ea1n. \u0110\u1ec3 nh\u1eadp v\u00e0o n\u0103m sinh, nh\u1ea5p v\u00e0o {account_settings_page_link}", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "B\u1ea1n c\u1ea7n c\u00f3 b\u1eb1ng l\u00e1i xe, h\u1ed9 chi\u1ebfu, ho\u1eb7c ID ch\u00ednh ph\u1ee7 ph\u00e1t h\u00e0nh c\u00f3 t\u00ean v\u00e0 \u1ea3nh c\u1ee7a b\u1ea1n.", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "B\u1ea1n c\u1ea7n m\u1ed9t ID c\u00f3 t\u00ean v\u00e0 \u1ea3nh c\u1ee7a b\u1ea1n. Gi\u1ea5y ph\u00e9p, h\u1ed9 chi\u1ebfu, ho\u1eb7c ID ch\u00ednh ph\u1ee7 ph\u00e1t h\u00e0nh c\u1ee7a m\u1ed9t tr\u00ecnh \u0111i\u1ec1u khi\u1ec3n \u0111\u01b0\u1ee3c t\u1ea5t c\u1ea3 ch\u1ea5p nh\u1eadn \u0111\u01b0\u1ee3c.", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "B\u1ea1n c\u1ea7n k\u00edch ho\u1ea1t t\u00e0i kho\u1ea3n tr\u01b0\u1edbc khi ghi danh v\u00e0o kho\u00e1 h\u1ecdc. Ki\u1ec3m tra h\u1ed9p th\u01b0 \u0111\u1ebfn cho email c\u1ea7n k\u00edch ho\u1ea1t.", "You receive messages from {platform_name} and course teams at this address.": "B\u1ea1n nh\u1eadn \u0111\u01b0\u1ee3c tin nh\u1eafn t\u1eeb {platform_name} t\u1ea1i \u0111\u1ecba ch\u1ec9 n\u00e0y.", "You reserve all rights for your work": "B\u1ea1n d\u00e0nh t\u1ea5t c\u1ea3 c\u00e1c quy\u1ec1n cho t\u00e1c ph\u1ea9m c\u1ee7a b\u1ea1n", - "You still need to visit the %(display_name)s website to complete the credit process.": "B\u1ea1n v\u1eabn c\u1ea7n ph\u1ea3i truy c\u1eadp v\u00e0o c\u00e1c trang web %(display_name)s \u0111\u1ec3 ho\u00e0n t\u1ea5t qu\u00e1 tr\u00ecnh t\u00edn ch\u1ec9.", "You submitted {filename}; only {allowedFiles} are allowed.": "B\u1ea1n \u0111\u00e3 g\u1eedi {filename}; ch\u1ec9 cho ph\u00e9p {allowedFiles}.", "You waive some rights for your work, such that others can use it too": "B\u1ea1n t\u1eeb b\u1ecf m\u1ed9t s\u1ed1 quy\u1ec1n \u0111\u1ed1i v\u1edbi t\u00e1c ph\u1ea9m c\u1ee7a b\u1ea1n, nh\u01b0 v\u1eady nh\u1eefng ng\u01b0\u1eddi kh\u00e1c c\u00f3 th\u1ec3 s\u1eed d\u1ee5ng l\u1ea1i", "You will be refunded the amount you paid.": "B\u1ea1n s\u1ebd \u0111\u01b0\u1ee3c ho\u00e0n tr\u1ea3 s\u1ed1 ti\u1ec1n \u0111\u00e3 thanh to\u00e1n.", @@ -1846,7 +1832,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1910,9 +1896,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ",", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "j F", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "H:i d-m-Y", "SHORT_DATE_FORMAT": "d-m-Y", "THOUSAND_SEPARATOR": ".", diff --git a/lms/static/js/i18n/zh-cn/djangojs.js b/lms/static/js/i18n/zh-cn/djangojs.js index f2382776846935e785d953bc48fc6ec9804f6cb3..c252c047cf253a12d545755f636fe4ee1820729e 100644 --- a/lms/static/js/i18n/zh-cn/djangojs.js +++ b/lms/static/js/i18n/zh-cn/djangojs.js @@ -580,7 +580,6 @@ "Default (Local Time Zone)": "\u9ed8\u8ba4 (\u672c\u5730\u65f6\u533a)", "Default Timed Transcript": "\u9ed8\u8ba4\u5b57\u5e55", "Delete": "\u5220\u9664", - "Delete \"<%= signatoryName %>\" from the list of signatories?": "\u786e\u5b9a\u8981\u4ece\u7b7e\u7f72\u8005\u5217\u8868\u4e2d\u5220\u9664 \"<%= signatoryName %>\" \u5417\uff1f", "Delete File Confirmation": "\u5220\u9664\u6587\u4ef6\u786e\u8ba4", "Delete My Account": "\u5220\u9664\u6211\u7684\u8d26\u53f7", "Delete Page Confirmation": "\u786e\u8ba4\u5220\u9664\u9875\u9762", @@ -623,7 +622,6 @@ "Do you want to upload your file before submitting?": "\u60a8\u786e\u5b9a\u5728\u63d0\u4ea4\u4e4b\u524d\u4e0a\u4f20\u60a8\u7684\u6587\u4ef6\u5417\uff1f", "Document properties": "\u6587\u6863\u5c5e\u6027", "Does the name on your ID match your account name: %(fullName)s?": "\u60a8\u8eab\u4efd\u8bc1\u4ef6\u4e0a\u7684\u59d3\u540d\u548c\u60a8\u5728\u8d26\u53f7\u4e2d\u586b\u5199\u7684\u59d3\u540d\u201c%(fullName)s\u201d\u76f8\u7b26\u5417\uff1f", - "Does the photo of you match your ID photo?": "\u8fd9\u5f20\u7167\u7247\u548c\u60a8\u8eab\u4efd\u8bc1\u4ef6\u4e0a\u7684\u7167\u7247\u76f8\u5339\u914d\u5417\uff1f", "Does the photo of you show your whole face?": "\u8fd9\u5f20\u7167\u7247\u4e2d\u6709\u60a8\u7684\u6574\u5f20\u8138\u5417\uff1f", "Doing so means that you are no longer eligible for academic credit.": "\u5173\u95ed\u76d1\u8003\u529f\u80fd\u610f\u5473\u7740\u60a8\u5c06\u5931\u53bb\u5b66\u5206\u8d44\u683c\u3002", "Don't see your picture? Make sure to allow your browser to use your camera when it asks for permission.": "\u6ca1\u6709\u770b\u5230\u60a8\u81ea\u5df1\uff1f\u8bf7\u786e\u8ba4\u5f53\u6d4f\u89c8\u5668\u8bf7\u6c42\u4f7f\u7528\u6444\u50cf\u5934\u6743\u9650\u7684\u65f6\u5019\u60a8\u9009\u62e9\u4e86\u5141\u8bb8\u3002", @@ -789,7 +787,6 @@ "Files that you upload must be smaller than 5MB in size.": "\u4e0a\u4f20\u7684\u6587\u4ef6\u4e0d\u5f97\u8d85\u8fc75MB\u3002", "Fill browser": "\u5168\u5c4f", "Filter and sort topics": "\u8fc7\u6ee4\u548c\u6574\u7406\u8bdd\u9898", - "Final Grade": "\u6700\u7ec8\u6210\u7ee9", "Final Grade Received": "\u6700\u7ec8\u6536\u83b7\u5f97\u5206", "Financial Assistance": "\u7ecf\u6d4e\u8865\u52a9", "Financial Assistance Application": "\u7ecf\u6d4e\u63f4\u52a9\u7533\u8bf7", @@ -821,7 +818,6 @@ "Generate": "\u751f\u6210", "Generate Exception Certificates": "\u751f\u6210\u7279\u4f8b\u8bc1\u4e66", "Generate the user's certificate": "\u751f\u6210\u7528\u6237\u8bc1\u4e66", - "Get Credit": "\u83b7\u5f97\u5b66\u5206", "Go Back": "\u8fd4\u56de", "Go to Dashboard": "\u524d\u5f80\u8bfe\u7a0b\u9762\u677f", "Go to my Dashboard": "\u524d\u5f80\u6211\u7684\u8bfe\u7a0b\u9762\u677f", @@ -900,10 +896,8 @@ "If the subsection does not have a due date, learners always see their scores when they submit answers to assessments.": "\u5982\u679c\u8282\u4e0d\u8bbe\u6709\u622a\u6b62\u65e5\u671f\uff0c\u90a3\u4e48\u53ea\u8981\u5b66\u5458\u63d0\u4ea4\u7b54\u6848\u81f3\u8bc4\u5206\uff0c\u5c31\u53ef\u4ee5\u67e5\u770b\u81ea\u5df1\u7684\u5f97\u5206\u3002", "If the unit was previously published and released to learners, any changes you made to the unit when it was hidden will now be visible to learners.": "\u5982\u679c\u6b64\u5355\u5143\u5148\u524d\u5df2\u88ab\u53d1\u5e03\u4e14\u5411\u5b66\u751f\u516c\u5f00\uff0c\u4efb\u4f55\u5728\u8be5\u5355\u5143\u5904\u4e8e\u9690\u85cf\u65f6\u7684\u6539\u52a8\u90fd\u5c06\u5bf9\u5b66\u751f\u53ef\u89c1\u3002", "If the unit was previously published and released to students, any changes you made to the unit when it was hidden will now be visible to students. Do you want to proceed?": "\u82e5\u6b64\u5355\u5143\u5148\u524d\u5df2\u53d1\u8868\u4e14\u5411\u5b66\u751f\u516c\u5f00\uff0c\u4efb\u4f55\u5728\u8be5\u5355\u5143\u5904\u4e8e\u9690\u85cf\u72b6\u6001\u65f6\u6240\u4f5c\u51fa\u7684\u6539\u52a8\u90fd\u5c06\u5bf9\u5b66\u751f\u53ef\u89c1\u3002\u662f\u5426\u7ee7\u7eed\uff1f", - "If you are unable to access your account contact us via email using {email}.": "\u5982\u679c\u60a8\u65e0\u6cd5\u8bbf\u95ee\u8d26\u53f7\uff0c\u8bf7\u901a\u8fc7\u7535\u5b50\u90ae\u4ef6\u8054\u7cfb\u6211\u4eec{email}\u3002", "If you do not yet have an account, use the button below to register.": "\u5982\u679c\u60a8\u5c1a\u65e0\u8d26\u53f7\uff0c\u8bf7\u4f7f\u7528\u4ee5\u4e0b\u6309\u94ae\u8fdb\u884c\u6ce8\u518c\u3002", "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity.": "\u5982\u679c\u60a8\u73b0\u5728\u4e0d\u9a8c\u8bc1\u60a8\u7684\u8eab\u4efd\uff0c\u60a8\u4ecd\u53ef\u4ee5\u901a\u8fc7\u63a7\u5236\u9762\u677f\u6d4f\u89c8\u8bfe\u7a0b\u3002\u4f46\u60a8\u4f1a\u5b9a\u671f\u4ece%(platformName)s\u6536\u5230\u8eab\u4efd\u9a8c\u8bc1\u63d0\u9192\u3002", - "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity.": "\u5982\u679c\u60a8\u73b0\u5728\u4e0d\u9a8c\u8bc1\u8eab\u4efd\uff0c\u60a8\u4ecd\u53ef\u4ee5\u901a\u8fc7\u8bfe\u7a0b\u9762\u677f\u6d4f\u89c8\u8bfe\u7a0b\u3002\u4f46\u60a8\u4f1a\u5b9a\u671f\u4ece {platformName} \u6536\u5230\u8eab\u4efd\u9a8c\u8bc1\u63d0\u9192\u3002", "If you leave this page without saving or submitting your response, you will lose any work you have done on the response.": "\u5982\u679c\u60a8\u4e0d\u4fdd\u5b58\u6216\u8005\u63d0\u4ea4\u7b54\u6848\u5c31\u79bb\u5f00\uff0c\u60a8\u53ef\u80fd\u4f1a\u4e22\u5931\u6389\u5199\u5b8c\u7684\u4e00\u5207\u3002", "If you leave this page without submitting your peer assessment, you will lose any work you have done.": "\u5982\u679c\u60a8\u79bb\u5f00\u672c\u9875\u65f6\u6ca1\u6709\u63d0\u4ea4\u60a8\u7684\u540c\u5b66\u4e92\u8bc4\uff0c\u60a8\u5c06\u4e22\u5931\u60a8\u6240\u505a\u7684\u4e00\u5207\u3002", "If you leave this page without submitting your self assessment, you will lose any work you have done.": "\u5982\u679c\u60a8\u672a\u63d0\u4ea4\u60a8\u7684\u81ea\u6211\u8bc4\u4f30\u5c31\u79bb\u5f00\u6b64\u9875\u9762\uff0c\u60a8\u5c06\u4e22\u5931\u6240\u505a\u7684\u4e00\u5207\u3002", @@ -1090,7 +1084,6 @@ "Name of the signatory": "\u7b7e\u53d1\u8005\u59d3\u540d", "Name or short description of the configuration": "\u8be5\u914d\u7f6e\u7684\u540d\u79f0\u6216\u7b80\u77ed\u63cf\u8ff0", "Navigate up": "\u5411\u4e0a\u5bfc\u822a", - "Need help logging in?": "\u767b\u5f55\u65f6\u9700\u8981\u5e2e\u52a9\uff1f", "Needs verified certificate ": "\u9700\u8981\u5df2\u8ba4\u8bc1\u8bc1\u4e66", "Never published": "\u4ece\u672a\u53d1\u5e03\u8fc7", "Never show assessment results": "\u4e00\u76f4\u9690\u85cf\u8bc4\u5206\u7ed3\u679c", @@ -1156,7 +1149,6 @@ "Onboarding Exam": "\u5165\u804c\u8003\u8bd5", "Once you complete one of the program requirements you have a program record. This record is marked complete once you meet all program requirements. A program record can be used to continue your learning journey and demonstrate your learning to others.": "\u5b8c\u6210\u5176\u4e2d\u4e00\u4e2a\u8bfe\u7a0b\u8981\u6c42\u540e\uff0c\u60a8\u5c06\u62e5\u6709\u4e00\u4e2a\u8bfe\u7a0b\u8bb0\u5f55\u3002\u4e00\u65e6\u6ee1\u8db3\u6240\u6709\u8bfe\u7a0b\u8981\u6c42\uff0c\u6b64\u8bb0\u5f55\u5c31\u4f1a\u6807\u8bb0\u4e3a\u5df2\u5b8c\u6210\u3002\u8bfe\u7a0b\u8bb0\u5f55\u53ef\u7528\u4e8e\u7ee7\u7eed\u60a8\u7684\u5b66\u4e60\u4e4b\u65c5\uff0c\u5e76\u5411\u5176\u4ed6\u4eba\u5c55\u793a\u60a8\u7684\u5b66\u4e60\u7ecf\u5386\u3002", "One or more rescheduling tasks failed.": "\u4e00\u9879\u6216\u51e0\u9879\u6539\u671f\u4efb\u52a1\u5931\u8d25\u4e86\u3002", - "Only <%= fileTypes %> files can be uploaded. Please select a file ending in <%= fileExtensions %> to upload.": "\u53ea\u6709 <%= fileTypes %> \u683c\u5f0f\u7684\u6587\u4ef6\u53ef\u4ee5\u4e0a\u4f20\u3002\u8bf7\u9009\u62e9\u6269\u5c55\u540d\u4e3a <%= fileExtensions %> \u7684\u6587\u4ef6\u4e0a\u4f20\u3002", "Only properly formatted .csv files will be accepted.": "\u53ea\u6709\u6807\u51c6\u7684CSV\u683c\u5f0f\u6587\u4ef6\u4f1a\u88ab\u63a5\u53d7\u3002", "Only the parent course staff of a CCX can create content groups.": "\u53ea\u6709CCX\u8bfe\u7a0b\u7684\u4e3b\u6559\u5458\u624d\u53ef\u521b\u5efa\u5185\u5bb9\u7ec4\u3002", "Open Calculator": "\u5f00\u542f\u8ba1\u7b97\u5668", @@ -1623,9 +1615,7 @@ "Textbook Name": "\u8bfe\u672c\u540d\u79f0", "Textbook information": "\u8bfe\u672c\u4fe1\u606f", "Textbook name is required": "\u6559\u6750\u540d\u79f0\u5fc5\u586b", - "Thank you %(full_name)s! We have received your payment for %(course_name)s.": "\u8c22\u8c22\u60a8\uff0c%(full_name)s\uff01\u6211\u4eec\u5df2\u7ecf\u6536\u5230\u4e86\u60a8\u4e3a%(course_name)s\u7684\u4ed8\u6b3e\u3002", "Thank you for setting your course goal to {goal}!": "\u611f\u8c22\u60a8\u5c06\u8bfe\u7a0b\u76ee\u6807\u5b9a\u4e3a{goal}\uff01", - "Thank you for submitting a request! We will contact you within 24 hours.": "\u611f\u8c22\u60a8\u63d0\u4ea4\u7684\u7533\u8bf7\uff01\u6211\u4eec\u4f1a\u572824\u5c0f\u65f6\u5185\u8054\u7cfb\u60a8\u3002", "Thank you for submitting your financial assistance application for {course_name}! You can expect a response in 2-4 business days.": "\u611f\u8c22\u60a8\u63d0\u4ea4 {course_name} \u7684\u7ecf\u6d4e\u63f4\u52a9\u7533\u8bf7\uff01\u60a8\u5c06\u5728 2 \u81f3 4 \u4e2a\u5de5\u4f5c\u65e5\u5185\u5f97\u5230\u56de\u590d\u3002", "Thank you for submitting your photos. We will review them shortly. You can now sign up for any %(platformName)s course that offers verified certificates. Verification is good for one year. After one year, you must submit photos for verification again.": "\u611f\u8c22\u63d0\u4ea4\u60a8\u7684\u7167\u7247\uff0c\u6211\u4eec\u7a0d\u540e\u5c06\u8fdb\u884c\u5ba1\u6838\u3002\u60a8\u73b0\u5728\u5c31\u53ef\u4ee5\u53bb\u52a0\u5165%(platformName)s\u4e0a\u4efb\u4f55\u63d0\u4f9b\u8ba4\u8bc1\u8bc1\u4e66\u7684\u8bfe\u7a0b\u3002\u8ba4\u8bc1\u6709\u6548\u671f\u4e3a\u4e00\u5e74\u3002\u4e00\u5e74\u540e\uff0c\u60a8\u9700\u8981\u91cd\u65b0\u63d0\u4ea4\u7167\u7247\u8fdb\u884c\u8ba4\u8bc1\u3002", "Thank you! We have received your payment for {courseName}.": "\u8c22\u8c22\uff01\u6211\u4eec\u5df2\u7ecf\u6536\u5230\u60a8\u7684 {courseName} \u4ed8\u6b3e\u3002", @@ -1637,8 +1627,6 @@ "The certificate for this learner has been re-validated and the system is re-running the grade for this learner.": "\u8fd9\u540d\u5b66\u751f\u7684\u8bc1\u4e66\u5df2\u7ecf\u91cd\u65b0\u9a8c\u8bc1\u53ca\u7cfb\u7edf\u91cd\u65b0\u8ba1\u7b97\u8be5\u540d\u5b66\u751f\u7684\u6210\u7ee9\u3002", "The cohort cannot be added": "\u8be5\u7fa4\u7ec4\u4e0d\u80fd\u6dfb\u52a0", "The cohort cannot be saved": "\u8be5\u7fa4\u7ec4\u4e0d\u80fd\u4fdd\u5b58", - "The combined length of the organization and library code fields cannot be more than <%=limit%> characters.": "\u673a\u6784\u548c\u77e5\u8bc6\u5e93\u7f16\u53f7\u5b57\u6bb5\u5408\u5728\u4e00\u8d77\u4e0d\u80fd\u8d85\u8fc7 <%=limit%> \u4e2a\u5b57\u7b26", - "The combined length of the organization, course number, and course run fields cannot be more than <%=limit%> characters.": "\u673a\u6784\u3001\u8bfe\u7a0b\u7f16\u53f7\u548c\u5f00\u8bfe\u65f6\u95f4\u5b57\u6bb5\u5408\u5728\u4e00\u8d77\u4e0d\u80fd\u8d85\u8fc7 <%=limit%> \u4e2a\u5b57\u7b26\u3002", "The country or region where you live.": "\u60a8\u6240\u5c45\u4f4f\u7684\u56fd\u5bb6\u6216\u5730\u533a\u3002", "The country that team members primarily identify with.": "\u591a\u6570\u56e2\u961f\u6210\u5458\u6765\u81ea\u7684\u56fd\u5bb6", "The course end date must be later than the course start date.": "\u8bfe\u7a0b\u7ed3\u675f\u65e5\u671f\u5fc5\u987b\u665a\u4e8e\u8bfe\u7a0b\u5f00\u59cb\u65e5\u671f\u3002", @@ -1654,7 +1642,6 @@ "The following email addresses and/or usernames are invalid:": "\u4ee5\u4e0b\u90ae\u7bb1/\u7528\u6237\u540d\u65e0\u6548\uff1a", "The following errors were generated:": "\u51fa\u73b0\u4ee5\u4e0b\u9519\u8bef\uff1a", "The following file types are not allowed: ": "\u4e0b\u5217\u6587\u4ef6\u7c7b\u578b\u4e0d\u53ef\u7528\uff1a", - "The following information is already a part of your {platform} profile. We\\'ve included it here for your application.": "\u4ee5\u4e0b\u4fe1\u606f\u5df2\u7ecf\u662f\u60a8\u7684 {platform} \u7b80\u8ff0\u7684\u4e00\u90e8\u5206\u3002\u6211\u4eec\u5df2\u5c06\u5176\u5217\u5165\u60a8\u7684\u7533\u8bf7\u4e2d\u3002", "The following message will be displayed at the bottom of the courseware pages within your course:": "\u4ee5\u4e0b\u4fe1\u606f\u5c06\u4f1a\u5728\u60a8\u8bfe\u7a0b\u7684\u8bfe\u4ef6\u9875\u9762\u5e95\u90e8\u663e\u793a\uff1a", "The following options are available for the {license_name} license.": "\u4ee5\u4e0b\u4e3a {license_name}\u8bb8\u53ef\u7684\u53ef\u7528\u9009\u9879", "The following users are no longer enrolled in the course:": "\u4ee5\u4e0b\u7528\u6237\u5df2\u4e0d\u518d\u9009\u4fee\u672c\u8bfe\u7a0b\uff1a", @@ -1666,7 +1653,6 @@ "The minimum completion percentage must be a whole number between 0 and 100.": "\u6700\u4f4e\u5b8c\u6210\u7387\u5fc5\u987b\u4e3a0-100\u7684\u6574\u6570\u3002", "The minimum grade for course credit is not set.": "\u5c1a\u672a\u8bbe\u7f6e\u80fd\u83b7\u53d6\u8bfe\u7a0b\u5b66\u5206\u7684\u6700\u4f4e\u5206\u503c\u3002", "The minimum score percentage must be a whole number between 0 and 100.": "\u5206\u6570\u767e\u5206\u6bd4\u7684\u6700\u5c0f\u503c\u5fc5\u987b\u662f\u57280\u5230100\u4e4b\u95f4\u7684\u6574\u6570\u3002", - "The more you tell us, the more quickly and helpfully we can respond!": "\u60a8\u63d0\u4f9b\u7684\u4fe1\u606f\u8d8a\u8be6\u7ec6\uff0c\u6211\u4eec\u8d8a\u80fd\u5feb\u901f\u5e76\u6709\u6548\u5730\u5e2e\u52a9\u5230\u60a8\uff01", "The name of this signatory as it should appear on certificates.": "\u7b7e\u53d1\u8005\u5728\u8bc1\u4e66\u4e0a\u663e\u793a\u7684\u540d\u5b57", "The name that identifies you on {platform_name}. You cannot change your username.": "\u60a8\u5728{platform_name}\u4e0a\u7684\u540d\u5b57\uff0c\u7528\u6237\u540d\u65e0\u6cd5\u66f4\u6539\u3002", "The name that is used for ID verification and that appears on your certificates.": "\u7528\u4e8e\u8eab\u4efd\u8ba4\u8bc1\u548c\u663e\u793a\u5728\u8bc1\u4e66\u4e0a\u7684\u59d3\u540d\u3002", @@ -1674,7 +1660,6 @@ "The number of subsections in the course that contain problems of this assignment type.": "\u8bfe\u7a0b\u4e2d\u6240\u6709\u5305\u542b\u6b64\u4efb\u52a1\u7c7b\u578b\u7684\u8282\u6570\u3002", "The organization that this signatory belongs to, as it should appear on certificates.": "\u6b64\u7b7e\u7f72\u4eba\u6240\u5c5e\u7684\u7ec4\u7ec7\uff0c\u5e94\u663e\u793a\u5728\u8bc1\u4e66\u4e0a\u3002", "The page \"{route}\" could not be found.": "\u65e0\u6cd5\u627e\u5230\"{route}\"\u9875\u9762\u3002", - "The photo of your face matches the photo on your ID.": "\u60a8\u7684\u9762\u90e8\u7167\u7247\u4e0e\u60a8\u8eab\u4efd\u8bc1\u4ef6\u4e0a\u7684\u7167\u7247\u76f8\u7b26\u3002", "The post you selected has been deleted.": "\u60a8\u6240\u9009\u62e9\u7684\u5e16\u5b50\u5df2\u88ab\u5220\u9664\u3002", "The published branch version, {published}, was reset to the draft branch version, {draft}.": "\u5df2\u53d1\u5e03\u5206\u652f\u7248\u672c{published}\u88ab\u91cd\u7f6e\u4e3a\u521d\u7a3f\u5206\u652f\u7248\u672c{draft}\u3002", "The raw error message is:": "\u539f\u59cb\u7684\u9519\u8bef\u4fe1\u606f\u662f\uff1a", @@ -1810,7 +1795,6 @@ "To be sure all students can access the video, we recommend providing both an .mp4 and a .webm version of your video. Click below to add a URL for another version. These URLs cannot be YouTube URLs. The first listed video that's compatible with the student's computer will play.": "\u8981\u786e\u4fdd\u6240\u6709\u5b66\u751f\u90fd\u80fd\u770b\u5230\u89c6\u9891\uff0c\u6211\u4eec\u5efa\u8bae\u60a8\u540c\u65f6\u63d0\u4f9b.mp4\u7248\u672c\u548c.webm\u7248\u672c\u7684\u89c6\u9891\u3002\u70b9\u51fb\u4e0b\u65b9\u6309\u94ae\u6dfb\u52a0\u53e6\u4e00\u4e2a\u7248\u672c\u7684URL\uff08\u8bf7\u52ff\u4f7f\u7528YouTube\u7684URL\uff09\uff0c\u5b66\u751f\u5c06\u4f1a\u770b\u5230\u5217\u8868\u4e2d\u7b2c\u4e00\u4e2a\u4e0e\u5176\u8ba1\u7b97\u673a\u517c\u5bb9\u7684\u89c6\u9891\u3002", "To complete the program, you must earn a verified certificate for each course.": "\u60a8\u5fc5\u987b\u6bcf\u95e8\u8bfe\u7a0b\u90fd\u83b7\u5f97\u8bc1\u4e66\uff0c\u624d\u53ef\u4ee5\u5b8c\u6210\u6b64\u8bfe\u7a0b\u65b9\u6848\u3002", "To continue learning with this account, sign in below.": "\u5982\u9700\u7ee7\u7eed\u4f7f\u7528\u6b64\u8d26\u53f7\u5b66\u4e60\uff0c\u8bf7\u70b9\u51fb\u4ee5\u4e0b\u6309\u94ae\u767b\u5f55\u3002", - "To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request.": "\u8981\u5b8c\u6210\u8bfe\u7a0b\u5b66\u5206\uff0c%(display_name)s \u8981\u6c42 %(platform_name)s \u5b66\u5458\u63d0\u4ea4\u4e00\u4efd\u5b66\u5206\u7533\u8bf7\u3002", "To invalidate a certificate for a particular learner, add the username or email address below.": "\u8981\u8bbe\u5b9a\u67d0\u4e2a\u7279\u5b9a\u5b66\u5458\u7684\u8bc1\u4e66\u65e0\u6548\uff0c\u8bf7\u5728\u4e0b\u9762\u6dfb\u52a0\u76f8\u5e94\u7684\u7528\u6237\u540d\u6216\u90ae\u7bb1\u3002", "To pass this exam, you must complete the problems in the time allowed.": "\u60a8\u5fc5\u987b\u5728\u65f6\u9650\u5185\u5b8c\u6210\u9898\u76ee\u624d\u53ef\u4ee5\u901a\u8fc7\u8003\u8bd5\u3002", "To receive a certificate, you must also verify your identity before {date}.": "\u8981\u83b7\u5f97\u8bc1\u4e66\uff0c\u60a8\u5fc5\u987b\u5728 {date} \u4e4b\u524d\u9a8c\u8bc1\u60a8\u7684\u8eab\u4efd\u3002", @@ -1895,7 +1879,6 @@ "Upload Videos": "\u4e0a\u4f20\u89c6\u9891", "Upload a CSV file": "\u4e0a\u4f20 CSV \u6587\u4ef6", "Upload a comma separated values (.csv) file that contains the usernames or email addresses of learners who have been given exceptions. Include the username or email address in the first comma separated field. You can include an optional note describing the reason for the exception in the second comma separated field.": "\u4e0a\u4f20\u4e00\u4e2a\u7528\u9017\u53f7\u9694\u5f00\u7684\u503c (.csv) \u6587\u4ef6\uff0c\u6587\u4ef6\u8981\u5305\u542b\u83b7\u5f97\u7279\u4f8b\u7684\u5b66\u5458\u7684\u7528\u6237\u540d\u6216\u90ae\u7bb1\u3002\u5c06\u7528\u6237\u540d\u6216\u90ae\u7bb1\u5217\u5165\u7b2c\u4e00\u4e2a\u9017\u53f7\u9694\u5f00\u7684\u5b57\u6bb5\u4e2d\u3002\u60a8\u53ef\u4ee5\u5728\u7b2c\u4e8c\u4e2a\u7528\u9017\u53f7\u9694\u5f00\u7684\u5b57\u6bb5\u4e2d\u8f93\u5165\u7279\u6b8a\u5904\u7406\u7684\u539f\u56e0\u63cf\u8ff0\u3002", - "Upload a new PDF to \u201c<%= name %>\u201d": "\u4e0a\u4f20\u65b0\u7684PDF\u6587\u4ef6\u81f3\u201c<%= name %>\u201d", "Upload an image": "\u4e0a\u4f20\u56fe\u7247", "Upload an image or capture one with your web or phone camera.": "\u4e0a\u4f20\u7167\u7247\u6216\u901a\u8fc7\u4f7f\u7528\u60a8\u7684\u7f51\u7edc\uff0f\u624b\u673a\u6444\u50cf\u5934\u62cd\u7167\u4e0a\u4f20\u3002", "Upload completed": "\u4e0a\u4f20\u5b8c\u6210", @@ -1926,7 +1909,6 @@ "Use enrollment tracks as the basis for dividing discussions. All learners, regardless of their enrollment track, see the same discussion topics, but within divided topics, only learners who are in the same enrollment track see and respond to each others\u2019 posts.": "\u5c06\u9009\u8bfe\u901a\u9053\u4f5c\u4e3a\u5212\u5206\u8ba8\u8bba\u7ec4\u7684\u57fa\u7840\u3002\u6240\u6709\u7684\u5b66\u5458\uff0c\u4e0d\u7ba1\u4ed6\u4eec\u7684\u9009\u8bfe\u901a\u9053\u662f\u4ec0\u4e48\uff0c\u90fd\u53ef\u4ee5\u770b\u5230\u76f8\u540c\u7684\u8ba8\u8bba\u4e3b\u9898\uff0c\u4f46\u662f\u5728\u4e0d\u540c\u7684\u4e3b\u9898\u4e2d\uff0c\u53ea\u6709\u5728\u540c\u4e00\u9009\u8bfe\u901a\u9053\u4e0a\u7684\u5b66\u5458\u624d\u80fd\u770b\u5230\u548c\u56de\u590d\u5f7c\u6b64\u7684\u5e16\u5b50\u3002", "Use my institution/campus credentials": "\u4f7f\u7528\u6211\u7684\u673a\u6784/\u6821\u56ed\u8d26\u53f7", "Use the All Topics menu to find specific topics.": "\u4f7f\u7528\u201c\u6240\u6709\u4e3b\u9898\u201d\u83dc\u5355\u627e\u5230\u7279\u5b9a\u8bdd\u9898", - "Use your webcam to take a photo of your ID. We will match this photo with the photo of your face and the name on your account.": "\u8bf7\u7528\u6444\u50cf\u5934\u62cd\u6444\u4e00\u5f20\u60a8\u8eab\u4efd\u8bc1\u4ef6\u7684\u7167\u7247\uff0c\u6211\u4eec\u5c06\u67e5\u770b\u8be5\u7167\u7247\u662f\u5426\u4e0e\u60a8\u7684\u9762\u90e8\u7167\u7247\u53ca\u60a8\u5728\u8d26\u53f7\u4e2d\u586b\u5199\u7684\u59d3\u540d\u5339\u914d\u3002", "Use your webcam to take a photo of your face. We will match this photo with the photo on your ID.": "\u8bf7\u7528\u6444\u50cf\u5934\u62cd\u6444\u4e00\u5f20\u60a8\u7684\u9762\u90e8\u7167\u7247\uff0c\u6211\u4eec\u5c06\u5bf9\u6bd4\u8be5\u7167\u7247\u4e0e\u60a8\u8eab\u4efd\u8bc1\u4ef6\u4e0a\u7684\u7167\u7247\u3002", "Used": "\u5df2\u4f7f\u7528", "Used in {count} location": [ @@ -1949,7 +1931,6 @@ "Verified Certificate upgrade": "\u8ba4\u8bc1\u8bc1\u4e66\u5347\u7ea7", "Verified Status": "\u9a8c\u8bc1\u72b6\u6001", "Verified mode price": "\u901a\u8fc7\u9a8c\u8bc1\u7684\u6a21\u5f0f\u4ef7\u683c", - "Verify Now": "\u73b0\u5728\u8ba4\u8bc1", "Version": "\u7248\u672c", "Vertical space": "\u5782\u76f4\u95f4\u8ddd", "Very loud": "\u97f3\u91cf\u6700\u5927", @@ -1992,7 +1973,6 @@ "We couldn't find any results for \"%s\".": "\u6211\u4eec\u627e\u4e0d\u5230\u6709\u5173\u201c%s\u201d\u7684\u4efb\u4f55\u7ed3\u679c\u3002", "We couldn't sign you in.": "\u767b\u5f55\u5931\u8d25\u3002", "We have encountered an error. Refresh your browser and then try again.": "\u53d1\u751f\u9519\u8bef\uff0c\u8bf7\u5237\u65b0\u60a8\u7684\u6d4f\u89c8\u5668\u5e76\u91cd\u8bd5\u3002", - "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content.": "\u6211\u4eec\u5df2\u7ecf\u6536\u5230\u60a8\u7684\u4fe1\u606f\u5e76\u6b63\u5728\u9a8c\u8bc1\u60a8\u7684\u8eab\u4efd\u3002\u9a8c\u8bc1\u6d41\u7a0b\u7ed3\u675f\u540e(\u4e00\u822c\u5728 1-2 \u5929\u5185)\uff0c\u60a8\u5c06\u5728\u60a8\u7684\u63a7\u5236\u9762\u677f\u4e0a\u6536\u5230\u4e00\u6761\u6d88\u606f\u3002\u4e0e\u6b64\u540c\u65f6\uff0c\u60a8\u4ecd\u7136\u53ef\u4ee5\u8bbf\u95ee\u6240\u6709\u7684\u8bfe\u7a0b\u5185\u5bb9\u3002", "We just need a little more information before you start learning with %(platformName)s.": "\u60a8\u53ea\u9700\u518d\u591a\u63d0\u4f9b\u4e00\u70b9\u4fe1\u606f\u5c31\u53ef\u4ee5\u5f00\u59cb\u5728%(platformName)s\u5b66\u4e60\u4e86\u3002", "We use the highest levels of security available to encrypt your photo and send it to our authorization service for review. Your photo and information are not saved or visible anywhere on %(platformName)s after the verification process is complete.": "\u6211\u4eec\u4f1a\u91c7\u7528\u6700\u9ad8\u7ea7\u522b\u7684\u5b89\u5168\u6280\u672f\u6765\u52a0\u5bc6\u60a8\u7684\u7167\u7247\u5e76\u53d1\u9001\u5230\u6211\u4eec\u7684\u6388\u6743\u670d\u52a1\u7528\u4e8e\u5ba1\u6838\u76ee\u7684\uff1b\u4e00\u65e6\u5b8c\u6210\u4e86\u8ba4\u8bc1\u8fc7\u7a0b\uff0c%(platformName)s\u4e0d\u4f1a\u7ee7\u7eed\u4fdd\u5b58\u8fd9\u4e9b\u7167\u7247\u548c\u4fe1\u606f\u3002", "We're sorry to see you go! Your account will be deleted shortly.": "\u5f88\u9057\u61be\u60a8\u8981\u79bb\u5f00\uff01\u60a8\u7684\u8d26\u53f7\u5c06\u5f88\u5feb\u88ab\u5220\u9664\u3002", @@ -2087,13 +2067,10 @@ "You must specify a name": "\u60a8\u5fc5\u987b\u6307\u5b9a\u4e00\u4e2a\u540d\u79f0", "You must specify a name for the cohort": "\u60a8\u5fc5\u987b\u4e3a\u8be5\u7fa4\u7ec4\u547d\u540d\u3002", "You must specify your birth year before you can share your full profile. To specify your birth year, go to the {account_settings_page_link}": "\u60a8\u5fc5\u987b\u586b\u5199\u51fa\u751f\u5e74\u4efd\u624d\u80fd\u5206\u4eab\u5b8c\u6574\u8d44\u6599\u3002\u70b9\u51fb {account_settings_page_link} \u586b\u5199", - "You need a driver's license, passport, or other government-issued ID that has your name and photo.": "\u60a8\u9700\u8981\u9a7e\u7167\u3001\u62a4\u7167\u6216\u8005\u5176\u4ed6\u7531\u653f\u5e9c\u7b7e\u53d1\u7684\u5e26\u6709\u60a8\u59d3\u540d\u548c\u7167\u7247\u7684\u8eab\u4efd\u8bc1\u4ef6\u3002", - "You need an ID with your name and photo. A driver's license, passport, or other government-issued IDs are all acceptable.": "\u60a8\u9700\u8981\u4e00\u4efd\u5e26\u6709\u60a8\u59d3\u540d\u548c\u7167\u7247\u7684\u8eab\u4efd\u8bc1\u4ef6\uff0c\u6211\u4eec\u53ef\u4ee5\u63a5\u53d7\u9a7e\u7167\u3001\u62a4\u7167\u4ee5\u53ca\u5176\u4ed6\u7531\u653f\u5e9c\u7b7e\u53d1\u7684\u8eab\u4efd\u8bc1\u4ef6\u3002", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email.": "\u5728\u9009\u8bfe\u4e4b\u524d\u60a8\u9700\u8981\u5148\u6fc0\u6d3b\u60a8\u7684\u8d26\u53f7\uff0c\u8bf7\u68c0\u67e5\u6536\u4ef6\u7bb1\u4e2d\u7684\u6fc0\u6d3b\u90ae\u4ef6\u3002", "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page.": "\u5728\u9009\u8bfe\u4e4b\u524d\u60a8\u9700\u8981\u5148\u6fc0\u6d3b\u60a8\u7684\u8d26\u53f7\uff0c\u8bf7\u68c0\u67e5\u6536\u4ef6\u7bb1\u4e2d\u7684\u6fc0\u6d3b\u90ae\u4ef6\u3002\u5f53\u60a8\u5b8c\u6210\u6fc0\u6d3b\u540e\uff0c\u60a8\u53ef\u4ee5\u8fd4\u56de\u5e76\u5237\u65b0\u672c\u9875\u9762\u3002", "You receive messages from {platform_name} and course teams at this address.": "\u6b64\u90ae\u7bb1\u7528\u4e8e\u63a5\u6536\u6765\u81ea{platform_name}\u548c\u8bfe\u7a0b\u56e2\u961f\u7684\u4fe1\u606f\u3002", "You reserve all rights for your work": "\u60a8\u5bf9\u60a8\u6240\u4f5c\u51fa\u7684\u8d21\u732e\u4fdd\u7559\u6240\u6709\u6743\u5229", - "You still need to visit the %(display_name)s website to complete the credit process.": "\u60a8\u4ecd\u7136\u9700\u8981\u8bbf\u95ee %(display_name)s \u7f51\u7ad9\u5b8c\u6210\u5b66\u5206\u9886\u53d6\u6d41\u7a0b\u3002", "You submitted {filename}; only {allowedFiles} are allowed.": "\u60a8\u63d0\u4ea4\u4e86 {filename}\uff1b\u4ec5\u652f\u6301\u63d0\u4ea4 {allowedFiles} \u683c\u5f0f\u7684\u6587\u4ef6\u3002", "You waive some rights for your work, such that others can use it too": "\u60a8\u9700\u8981\u5bf9\u60a8\u6240\u505a\u7684\u8d21\u732e\u653e\u5f03\u90e8\u5206\u6743\u5229\uff0c\u4f8b\u5982\u4ed6\u4eba\u4e5f\u53ef\u4ee5\u4f7f\u7528\u60a8\u7684\u6210\u679c", "You will be refunded the amount you paid.": "\u60a8\u5c06\u4f1a\u6536\u5230\u5168\u989d\u9000\u6b3e\u3002", @@ -2187,7 +2164,6 @@ "enter code here": "\u6b64\u5904\u8f93\u5165\u4ee3\u7801", "enter link description here": "\u6b64\u5904\u8f93\u5165\u94fe\u63a5\u7684\u63cf\u8ff0", "for": "\u7684", - "for {courseName}": "\u4e3a{courseName}\u8bfe\u7a0b", "group configuration": "\u7ec4\u914d\u7f6e", "image omitted": "\u7701\u7565\u7684\u56fe\u7247", "incorrect": "\u4e0d\u6b63\u786e", @@ -2316,7 +2292,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -2380,9 +2356,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/zh-hk/djangojs.js b/lms/static/js/i18n/zh-hk/djangojs.js index bef1a8a228f5bf2ce42a713133cb8576159e3a4e..5e1878aa25edd2d80a3e487c4b434e5705ecfb42 100644 --- a/lms/static/js/i18n/zh-hk/djangojs.js +++ b/lms/static/js/i18n/zh-hk/djangojs.js @@ -28,7 +28,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -92,9 +92,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/i18n/zh-tw/djangojs.js b/lms/static/js/i18n/zh-tw/djangojs.js index adff90275f2768d736bbe8d219a4fe93d49f3e1d..ddccbb9507950767a4d6b9d779ec3a4d162a344f 100644 --- a/lms/static/js/i18n/zh-tw/djangojs.js +++ b/lms/static/js/i18n/zh-tw/djangojs.js @@ -969,7 +969,7 @@ if (typeof(value) == 'undefined') { return (count == 1) ? singular : plural; } else { - return value[django.pluralidx(count)]; + return value.constructor === Array ? value[django.pluralidx(count)] : value; } }; @@ -1033,9 +1033,9 @@ "%d %B, %Y" ], "DECIMAL_SEPARATOR": ".", - "FIRST_DAY_OF_WEEK": "0", + "FIRST_DAY_OF_WEEK": 0, "MONTH_DAY_FORMAT": "F j", - "NUMBER_GROUPING": "0", + "NUMBER_GROUPING": 0, "SHORT_DATETIME_FORMAT": "m/d/Y P", "SHORT_DATE_FORMAT": "m/d/Y", "THOUSAND_SEPARATOR": ",", diff --git a/lms/static/js/learner_dashboard/EnterpriseLearnerPortalBanner.jsx b/lms/static/js/learner_dashboard/EnterpriseLearnerPortalBanner.jsx deleted file mode 100644 index 3ee56f856a578bdffc8a9458d86bf589e68af3e7..0000000000000000000000000000000000000000 --- a/lms/static/js/learner_dashboard/EnterpriseLearnerPortalBanner.jsx +++ /dev/null @@ -1,80 +0,0 @@ -import React, { Component } from 'react'; -import { getAuthenticatedUser } from '@edx/frontend-auth'; -import { getLearnerPortalLinks } from '@edx/frontend-enterprise'; -import { StatusAlert } from '@edx/paragon'; - -import apiClient from '../apiClient'; - -const LOCAL_STORAGE_KEY = 'has-viewed-enterprise-learner-portal-banner'; - -function getAlertHtml(learnerPortalLinks) { - let html = ''; - for (let i = 0; i < learnerPortalLinks.length; i += 1) { - const link = learnerPortalLinks[i]; - html += `<div class="copy-content"> - ${link.title} has a dedicated page where you can see all of your sponsored courses. - Go to <a href="${link.url}">your learner portal</a>. - </div>`; - } - return html; -} - -function setViewedBanner() { - window.localStorage.setItem(LOCAL_STORAGE_KEY, true); -} - -function hasViewedBanner() { - return window.localStorage.getItem(LOCAL_STORAGE_KEY) != null; -} - -class EnterpriseLearnerPortalBanner extends Component { - constructor(props) { - super(props); - - this.onClose = this.onClose.bind(this); - - this.state = { - open: false, - alertHtml: '', - }; - } - - componentDidMount() { - if (!hasViewedBanner()) { - const authenticatedUser = getAuthenticatedUser(); - getLearnerPortalLinks(apiClient, authenticatedUser).then((learnerPortalLinks) => { - this.setState({ - open: true, - alertHtml: getAlertHtml(learnerPortalLinks), - }); - }); - } - } - - onClose() { - this.setState({ open: false }); - setViewedBanner(); - } - - render() { - const { alertHtml, open } = this.state; - - if (open && alertHtml) { - return ( - <div className="edx-enterprise-learner-portal-banner-wrapper"> - <StatusAlert - className={['edx-enterprise-learner-portal-banner']} - open={open} - // eslint-disable-next-line react/no-danger - dialog={(<span dangerouslySetInnerHTML={{ __html: alertHtml }} />)} - onClose={this.onClose} - /> - </div> - ); - } - - return null; - } -} - -export { EnterpriseLearnerPortalBanner }; // eslint-disable-line import/prefer-default-export diff --git a/lms/static/js/learner_dashboard/models/course_card_model.js b/lms/static/js/learner_dashboard/models/course_card_model.js index 6deb5131454a728d49f147a27eedbc2621355eb4..9a0d38bade8fe0c3989300be22a0beba58cf6520 100644 --- a/lms/static/js/learner_dashboard/models/course_card_model.js +++ b/lms/static/js/learner_dashboard/models/course_card_model.js @@ -38,23 +38,6 @@ class CourseCardModel extends Backbone.Model { return desiredCourseRun; } - getCourseRunWithHighestGrade(grades) { - const allEnrolledCourseRuns = this.context.course_runs.filter(run => run.is_enrolled); - if (allEnrolledCourseRuns.length <= 1) { - return null; - } - - allEnrolledCourseRuns.sort((a, b) => (grades[a.key] || 0) - (grades[b.key] || 0)); - return allEnrolledCourseRuns[allEnrolledCourseRuns.length - 1]; - } - - updateCourseRunWithHighestGrade(grades) { - const courseRunWithHighestGrade = this.getCourseRunWithHighestGrade(grades); - if (courseRunWithHighestGrade) { - this.setActiveCourseRun(courseRunWithHighestGrade, this.context.user_preferences); - } - } - isEnrolledInSession() { // Returns true if the user is currently enrolled in a session of the course return this.context.course_runs.find(run => run.is_enrolled) !== undefined; diff --git a/lms/static/js/learner_dashboard/spec/course_card_view_spec.js b/lms/static/js/learner_dashboard/spec/course_card_view_spec.js index 726dc2b70b067916b0ef5dd0bbd046f9411686f0..b63c91f78532eb089a405afa1bece2eb799de137 100644 --- a/lms/static/js/learner_dashboard/spec/course_card_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/course_card_view_spec.js @@ -13,11 +13,7 @@ describe('Course Card View', () => { const setupView = (data, isEnrolled, collectionCourseStatus) => { const programData = $.extend({}, data); const context = { - courseData: { - grades: { - 'course-v1:WageningenX+FFESx+1T2017': 0.8, - }, - }, + courseData: {}, collectionCourseStatus, }; @@ -88,18 +84,6 @@ describe('Course Card View', () => { expect(view).toBeDefined(); }); - it('should render final grade if course is completed', () => { - view.remove(); - setupView(course, true); - expect(view.$('.grade-display').text()).toEqual('80%'); - }); - - it('should not render final grade if course has not been completed', () => { - view.remove(); - setupView(course, true, 'in_progress'); - expect(view.$('.final-grade').length).toEqual(0); - }); - it('should render the course card based on the data not enrolled', () => { view.remove(); setupView(course, false); diff --git a/lms/static/js/learner_dashboard/spec/program_details_view_spec.js b/lms/static/js/learner_dashboard/spec/program_details_view_spec.js index 055cb9d90b780fb47f5a6c106338ae2acfa8b0a6..e85d5a88eee66a692d883d3e2ba990a887871f3a 100644 --- a/lms/static/js/learner_dashboard/spec/program_details_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/program_details_view_spec.js @@ -461,9 +461,6 @@ describe('Program Details Header View', () => { ], }, ], - grades: { - 'course-v1:Testx+DOGx002+1T2016': 0.9, - }, }, urls: { program_listing_url: '/dashboard/programs/', diff --git a/lms/static/js/learner_dashboard/views/course_card_view.js b/lms/static/js/learner_dashboard/views/course_card_view.js index f5516932f177ba539e24a77ffcf200244770f8c5..96cfec4157c9931a3bdae7e46a1af0df178f292d 100644 --- a/lms/static/js/learner_dashboard/views/course_card_view.js +++ b/lms/static/js/learner_dashboard/views/course_card_view.js @@ -27,11 +27,6 @@ class CourseCardView extends Backbone.View { this.enrollModel.urlRoot = this.urlModel.get('commerce_api_url'); } this.context = options.context || {}; - if (this.context.collectionCourseStatus === 'completed') { - this.model.updateCourseRunWithHighestGrade(this.context.courseData.grades); - } - this.grade = this.context.courseData.grades[this.model.get('course_run_key')]; - this.grade = Math.round(this.grade * 100); this.collectionCourseStatus = this.context.collectionCourseStatus || ''; this.entitlement = this.model.get('user_entitlement'); @@ -58,7 +53,6 @@ class CourseCardView extends Backbone.View { this.enrollView = new CourseEnrollView({ $parentEl: this.$('.course-actions'), model: this.model, - grade: this.grade, collectionCourseStatus: this.collectionCourseStatus, urlModel: this.urlModel, enrollModel: this.enrollModel, diff --git a/lms/static/js/learner_dashboard/views/course_enroll_view.js b/lms/static/js/learner_dashboard/views/course_enroll_view.js index c8e7cb65b04e4cfacd9598116bfe08aaa3a33077..cfe96cf7f6bcdf3c572c5cf864a636e58a8fa2ed 100644 --- a/lms/static/js/learner_dashboard/views/course_enroll_view.js +++ b/lms/static/js/learner_dashboard/views/course_enroll_view.js @@ -21,7 +21,6 @@ class CourseEnrollView extends Backbone.View { this.$parentEl = options.$parentEl; this.enrollModel = options.enrollModel; this.urlModel = options.urlModel; - this.grade = options.grade; this.collectionCourseStatus = options.collectionCourseStatus; this.render(); } @@ -30,7 +29,6 @@ class CourseEnrollView extends Backbone.View { let filledTemplate; const context = this.model.toJSON(); if (this.$parentEl && this.enrollModel) { - context.grade = this.grade; context.collectionCourseStatus = this.collectionCourseStatus; filledTemplate = this.tpl(context); HtmlUtils.setHtml(this.$el, filledTemplate); diff --git a/lms/static/js/spec/commerce/receipt_view_spec.js b/lms/static/js/spec/commerce/receipt_view_spec.js deleted file mode 100644 index ea00ed44fde716f1268aeebf9a5e0b462be5304c..0000000000000000000000000000000000000000 --- a/lms/static/js/spec/commerce/receipt_view_spec.js +++ /dev/null @@ -1,338 +0,0 @@ -define([ - 'jquery', - 'jquery.ajax-retry', - 'js/commerce/views/receipt_view', - 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers' -], - function($, AjaxRetry, ReceiptView, AjaxHelpers) { - 'use strict'; - describe('edx.commerce.ReceiptView', function() { - var data, courseResponseData, providerResponseData, mockRequests, mockRender, createReceiptView, - createProduct, createLine, createOrderResponse, doCheckVerification, doCheckVerificationNagRendered, - userResponseData; - - createReceiptView = function() { - return new ReceiptView({el: $('#receipt-container')}); - }; - - mockRequests = function(requests, method, apiUrl, responseData) { - AjaxHelpers.expectRequest(requests, method, apiUrl); - AjaxHelpers.respondWithJson(requests, responseData); - }; - - mockRender = function(useEcommerceOrderNumber, isVerified, requestInThemedSite) { - var requests, view, orderUrlFormat, - actualRequestInThemedSite = requestInThemedSite; - if (typeof actualRequestInThemedSite === 'undefined') { - actualRequestInThemedSite = 'False'; - } - requests = AjaxHelpers.requests(this); - $('#receipt-container').data({ - verified: isVerified, - 'is-request-in-themed-site': actualRequestInThemedSite - }); - view = createReceiptView(); - view.useEcommerceApi = true; - if (useEcommerceOrderNumber) { - view.ecommerceOrderNumber = 'EDX-123456'; - orderUrlFormat = '/api/commerce/v1/orders/EDX-123456/'; - } else { - view.ecommerceBasketId = 'EDX-123456'; - orderUrlFormat = '/api/commerce/v0/baskets/EDX-123456/order/'; - } - view.render(); - mockRequests(requests, 'GET', orderUrlFormat, data); - - mockRequests( - requests, 'GET', '/commerce/checkout/verification_status/?course_id=' + - encodeURIComponent('course-v1:edx+dummy+2015_T3'), {is_verification_required: true} - ); - - mockRequests( - requests, 'GET', '/api/courses/v1/courses/course-v1:edx+dummy+2015_T3/', courseResponseData - ); - - mockRequests( - requests, 'GET', '/api/user/v1/accounts/user-1', userResponseData - ); - - mockRequests(requests, 'GET', '/api/credit/v1/providers/edx/', providerResponseData); - return view; - }; - - createProduct = function(attributes) { - var actualAttributes = attributes; - if (typeof actualAttributes === 'undefined') { - actualAttributes = [ - { - name: 'certificate_type', - value: 'verified' - }, - { - name: 'course_key', - code: 'course_key', - value: 'course-v1:edx+dummy+2015_T3' - }, - { - name: 'credit_provider', - value: 'edx' - } - ]; - } - - return { - attribute_values: actualAttributes, - stockrecords: [ - { - price_currency: 'USD', - product: 123, - partner_sku: '1234ABC', - partner: 1, - price_excl_tax: '10.00', - id: 123 - } - ], - product_class: 'Seat', - title: 'Dummy title', - url: 'https://ecom.edx.org/api/v2/products/123/', - price: '10.00', - expires: null, - is_available_to_buy: true, - id: 123, - structure: 'child' - }; - }; - - createLine = function(product) { - var actualProduct = product; - if (typeof actualProduct === 'undefined') { - actualProduct = createProduct(); - } - return { - status: 'Open', - unit_price_excl_tax: '10.00', - product: actualProduct, - line_price_excl_tax: '10.00', - description: 'dummy description', - title: 'dummy title', - quantity: 1 - }; - }; - - createOrderResponse = function(lines) { - var actualLines = lines; - if (typeof actualLines === 'undefined') { - actualLines = [createLine()]; - } - return { - status: 'Open', - billed_to: { - city: 'dummy city', - first_name: 'john', - last_name: 'doe', - country: 'AL', - line2: 'line2', - line1: 'line1', - state: '', - postcode: '12345' - }, - lines: actualLines, - number: 'EDX-123456', - date_placed: '2016-01-01T01:01:01Z', - currency: 'USD', - total_excl_tax: '10.00' - }; - }; - - doCheckVerification = function(attributes, expected) { - var view = createReceiptView(), - product = createProduct(attributes); - expect(view.requiresVerification(product)).toBe(expected); - }; - - doCheckVerificationNagRendered = function(attributes, userVerified, expected, requestInThemedSite) { - var view; - data = createOrderResponse([createLine(createProduct(attributes))]); - view = mockRender(true, userVerified, requestInThemedSite); - if (expected) { - expect(view.$('.nav-wizard.is-ready').text()).toContain('Want to confirm your identity later'); - } else { - expect(view.$('.nav-wizard.is-ready').text()).toContain('Go to Dashboard'); - } - }; - - beforeEach(function() { - var receiptFixture, providerFixture; - // Stub analytics tracking - window.analytics = jasmine.createSpyObj('analytics', ['page', 'track', 'trackLink']); - - loadFixtures('js/fixtures/commerce/checkout_receipt.html'); - - receiptFixture = readFixtures('templates/commerce/receipt.underscore'); - providerFixture = readFixtures('templates/commerce/provider.underscore'); - appendSetFixtures( - '<script id="receipt-tpl" type="text/template" >' + receiptFixture + '</script>' + - '<script id="provider-tpl" type="text/template" >' + providerFixture + '</script>' - ); - - data = createOrderResponse(); - - providerResponseData = { - id: 'edx', - display_name: 'edX', - url: 'http://www.edx.org', - status_url: 'http://www.edx.org/status', - description: 'Nothing', - enable_integration: false, - fulfillment_instructions: '', - thumbnail_url: 'http://edx.org/thumbnail.png' - }; - - courseResponseData = { - id: 'course-v1:edx+dummy+2015_T3', - name: 'receipt test', - category: 'course', - org: 'edx', - run: '2015_T2', - course: 'CS420', - uri: 'http://test.com/api/courses/v1/courses/course-v1:edx+dummy+2015_T3/', - image_url: '/test.jpg', - start: '2030-01-01T00:00:00Z', - end: null - }; - userResponseData = { - username: 'user-1', - name: 'full name' - }; - }); - - it('sends analytic event when verified receipt is rendered', function() { - mockRender(true, 'True'); - expect(window.analytics.track).toHaveBeenCalledWith( - 'Completed Purchase', - { - orderId: 'EDX-123456', - total: '10.00', - currency: 'USD' - } - ); - }); - - it('sends analytic event when non verified receipt is rendered', function() { - mockRender(true, 'False'); - expect(window.analytics.track).toHaveBeenCalledWith( - 'Completed Purchase', - { - orderId: 'EDX-123456', - total: '10.00', - currency: 'USD' - } - ); - }); - - it('renders a receipt correctly with Ecommerce Order Number', function() { - var view; - - view = mockRender(true, 'True'); - expect(view.$('.course_name_placeholder').text()).toContain('receipt test'); - }); - - it('renders a receipt correctly with Ecommerce Basket Id', function() { - var view; - - view = mockRender(false, 'True'); - expect(view.$('.course_name_placeholder').text()).toContain('receipt test'); - }); - - it('requiresVerification returns true if product requires verification', function() { - var expected = true, - attributes = [ - {name: 'certificate_type', value: 'professional'}, - {name: 'course_key', value: 'course-v1:OC+OC+2'}, - {name: 'id_verification_required', value: true} - ]; - doCheckVerification(attributes, expected, 'False'); - }); - - it('requiresVerification returns true if product requires verification, different order', function() { - var expected = true, - attributes = [ - {name: 'certificate_type', value: 'professional'}, - {name: 'id_verification_required', value: true}, - {name: 'course_key', value: 'course-v1:OC+OC+2'} - ]; - doCheckVerification(attributes, expected, 'False'); - }); - - it('requiresVerification defaults to true', function() { - var expected = true, - attributes = [ - {name: 'certificate_type', value: 'professional'}, - {name: 'course_key', value: 'course-v1:OC+OC+2'} - ]; - doCheckVerification(attributes, expected, 'False'); - }); - - it('requiresVerification returns false for courses not requiring verification', function() { - var expected = false, - attributes = [ - {name: 'certificate_type', value: 'professional'}, - {name: 'id_verification_required', value: false}, - {name: 'course_key', value: 'course-v1:OC+OC+2'} - ]; - doCheckVerification(attributes, expected, 'False'); - }); - - it('receipt view verification nag for not verified users in a verified course', function() { - var attributes = [ - {name: 'certificate_type', value: 'professional'}, - {name: 'id_verification_required', value: true}, - {name: 'course_key', value: 'course-v1:edx+dummy+2015_T3'}, - {name: 'credit_provider', value: 'edx'} - ]; - doCheckVerificationNagRendered(attributes, 'False', true, 'False'); - }); - - it("receipt view doesn't show verification nag for a verified user in a verified course", function() { - var attributes = [ - {name: 'certificate_type', value: 'professional'}, - {name: 'id_verification_required', value: true}, - {name: 'course_key', value: 'course-v1:edx+dummy+2015_T3'}, - {name: 'credit_provider', value: 'edx'} - ]; - doCheckVerificationNagRendered(attributes, 'True', false, 'False'); - }); - - it("receipt view doesn't show verification for a unverified user in a not verified course", function() { - var attributes = [ - {name: 'certificate_type', value: 'professional'}, - {name: 'id_verification_required', value: false}, - {name: 'course_key', value: 'course-v1:edx+dummy+2015_T3'}, - {name: 'credit_provider', value: 'edx'} - ]; - doCheckVerificationNagRendered(attributes, 'False', false, 'False'); - }); - - it("receipt view doesn't show verification nag for a verified user in a not verified course", function() { - var attributes = [ - {name: 'certificate_type', value: 'professional'}, - {name: 'id_verification_required', value: false}, - {name: 'course_key', value: 'course-v1:edx+dummy+2015_T3'}, - {name: 'credit_provider', value: 'edx'} - ]; - doCheckVerificationNagRendered(attributes, 'True', false, 'False'); - }); - - it("receipt view doesn't show verification nag for a not verified user in a verified" + - ' course on themed site', function() { - var attributes = [ - {name: 'certificate_type', value: 'professional'}, - {name: 'id_verification_required', value: true}, - {name: 'course_key', value: 'course-v1:edx+dummy+2015_T3'}, - {name: 'credit_provider', value: 'edx'} - ]; - doCheckVerificationNagRendered(attributes, 'False', false, 'True'); - }); - }); - } -); diff --git a/lms/static/js/spec/student_account/access_spec.js b/lms/static/js/spec/student_account/access_spec.js index b592a79ade850b905b8ebb1c00d4f9a276caf6b8..5fd2a1b6318c85efaa029dc4087a0f00b0d2c2e4 100644 --- a/lms/static/js/spec/student_account/access_spec.js +++ b/lms/static/js/spec/student_account/access_spec.js @@ -179,8 +179,8 @@ // Simulate a click on the reset password link view.resetPassword(); - // Verify that the login-anchor is hidden - expect($('#login-anchor')).toHaveClass('hidden'); + // Verify that the login-form is hidden + expect($('#login-form')).toHaveClass('hidden'); // Verify that the password reset form is not hidden expect($('#password-reset-form')).not.toHaveClass('hidden'); diff --git a/lms/static/js/spec/student_account/login_spec.js b/lms/static/js/spec/student_account/login_spec.js index e162dc125d3de7e59290a2ebd5956198b47d4a18..a2aa534c8ff0afa4bb143c203827dce0e9ee1acf 100644 --- a/lms/static/js/spec/student_account/login_spec.js +++ b/lms/static/js/spec/student_account/login_spec.js @@ -18,6 +18,7 @@ requests = null, authComplete = false, PLATFORM_NAME = 'edX', + ENTERPRISE_SLUG_LOGIN_URL = 'enterprise/login', USER_DATA = { email: 'xsy@edx.org', password: 'xsyisawesome', @@ -88,7 +89,8 @@ model: model, resetModel: resetModel, thirdPartyAuth: THIRD_PARTY_AUTH, - platformName: PLATFORM_NAME + platformName: PLATFORM_NAME, + enterpriseSlugLoginURL: ENTERPRISE_SLUG_LOGIN_URL }); // Spy on AJAX requests @@ -191,11 +193,18 @@ expect($('.button-oa2-facebook')).toBeVisible(); }); - it('displays a link to the password reset form', function() { + it('displays a link to the signin help', function() { createLoginView(this); - // Verify that the password reset link is displayed - expect($('.forgot-password')).toBeVisible(); + // Verify that the Signin help link is displayed + expect($('.login-help')).toBeVisible(); + }); + + it('displays a link to the enterprise slug login', function() { + createLoginView(this); + + // Verify that the enterprise login link is displayed + expect($('.enterprise-login')).toBeVisible(); }); it('displays password reset success message after password reset request', function() { diff --git a/lms/static/js/spec/student_account/password_reset_spec.js b/lms/static/js/spec/student_account/password_reset_spec.js index 8846655312c350fef8da3294bb0857b1edd04aa7..20c1d92ed74ad2d974f8d36c363664cbc3c406dc 100644 --- a/lms/static/js/spec/student_account/password_reset_spec.js +++ b/lms/static/js/spec/student_account/password_reset_spec.js @@ -105,6 +105,13 @@ expect($(view.el).html().length).toEqual(0); }); + it('displays a link to the password reset help', function() { + createPasswordResetView(this); + + // Verify that the password reset help link is displayed + expect($('.reset-help')).toBeVisible(); + }); + it('validates the email field', function() { createPasswordResetView(this); diff --git a/lms/static/js/student_account/AccountsClient.js b/lms/static/js/student_account/AccountsClient.js index 4f5e933ee07263703fc893ab6a54dd434784458d..d2b14e3509765ae8ff9455d33c2d1abcc32fdea6 100644 --- a/lms/static/js/student_account/AccountsClient.js +++ b/lms/static/js/student_account/AccountsClient.js @@ -15,7 +15,7 @@ const deactivate = (password) => fetch('/api/user/v1/accounts/deactivate_logout/ return response; } - throw new Error(response); + throw new Error(response.status); }); export { diff --git a/lms/static/js/student_account/components/StudentAccountDeletionModal.jsx b/lms/static/js/student_account/components/StudentAccountDeletionModal.jsx index 0267831a427f14ce45923723d7b9a368809eaca1..9c6c68b2359cf674a93510964c8f1ff339b36656 100644 --- a/lms/static/js/student_account/components/StudentAccountDeletionModal.jsx +++ b/lms/static/js/student_account/components/StudentAccountDeletionModal.jsx @@ -52,9 +52,8 @@ class StudentAccountDeletionConfirmationModal extends React.Component { } failedSubmission(error) { - const { status } = error; - const title = status === 403 ? gettext('Password is incorrect') : gettext('Unable to delete account'); - const body = status === 403 ? gettext('Please re-enter your password.') : gettext('Sorry, there was an error trying to process your request. Please try again later.'); + const title = error.message === '403' ? gettext('Password is incorrect') : gettext('Unable to delete account'); + const body = error.message === '403' ? gettext('Please re-enter your password.') : gettext('Sorry, there was an error trying to process your request. Please try again later.'); this.setState({ passwordSubmitted: false, diff --git a/lms/static/js/student_account/views/AccessView.js b/lms/static/js/student_account/views/AccessView.js index cb1f50c4003d2630deff1f7694e6fc2872a1292c..9d547d363995f3e3dbbaf3eed961698a9219ff15 100644 --- a/lms/static/js/student_account/views/AccessView.js +++ b/lms/static/js/student_account/views/AccessView.js @@ -78,6 +78,7 @@ this.hideAuthWarnings = options.hide_auth_warnings || false; this.pipelineUserDetails = options.third_party_auth.pipeline_user_details; this.enterpriseName = options.enterprise_name || ''; + this.enterpriseSlugLoginURL = options.enterprise_slug_login_url || ''; this.isAccountRecoveryFeatureEnabled = options.is_account_recovery_feature_enabled || false; this.isMultipleUserEnterprisesFeatureEnabled = options.is_multiple_user_enterprises_feature_enabled || false; @@ -128,7 +129,12 @@ }, loadForm: function(type) { - var loadFunc = _.bind(this.load[type], this); + var loadFunc; + if (type === 'reset') { + loadFunc = _.bind(this.load.login, this); + loadFunc(this.formDescriptions.login); + } + loadFunc = _.bind(this.load[type], this); loadFunc(this.formDescriptions[type]); }, @@ -155,7 +161,8 @@ createAccountOption: this.createAccountOption, hideAuthWarnings: this.hideAuthWarnings, pipelineUserDetails: this.pipelineUserDetails, - enterpriseName: this.enterpriseName + enterpriseName: this.enterpriseName, + enterpriseSlugLoginURL: this.enterpriseSlugLoginURL }); // Listen for 'password-help' event to toggle sub-views @@ -225,7 +232,7 @@ }, passwordEmailSent: function() { - var $loginAnchorElement = $('#login-anchor'); + var $loginAnchorElement = $('#login-form'); this.element.hide($(this.el).find('#password-reset-anchor')); this.element.show($loginAnchorElement); this.element.scrollTop($loginAnchorElement); @@ -236,7 +243,7 @@ category: 'user-engagement' }); - this.element.hide($(this.el).find('#login-anchor')); + this.element.hide($(this.el).find('#login-form')); this.loadForm('reset'); this.element.scrollTop($('#password-reset-anchor')); }, @@ -257,6 +264,12 @@ // Load the form. Institution login is always refreshed since it changes based on the previous form. if (!this.form.isLoaded($form) || type == 'institution_login') { + + // We need a special case for loading reset form as there is mismatch of form id + // value ie 'password-reset' vs load function name ie 'reset' + if (type === 'password-reset') { + type = 'reset'; + } this.loadForm(type); } this.activeForm = type; diff --git a/lms/static/js/student_account/views/FormView.js b/lms/static/js/student_account/views/FormView.js index dd136da3227f777ef6dbb5f47d0d180add696f97..676816b763f8eac2ffca0a00258fea3e2f059117 100644 --- a/lms/static/js/student_account/views/FormView.js +++ b/lms/static/js/student_account/views/FormView.js @@ -144,12 +144,16 @@ $form = this.$form, elements = $form[0].elements, i, + $n, + tpl, len = elements.length, $el, $label, key = '', errors = [], - validation = {}; + validation = {}, + $desc, + $validationNode; for (i = 0; i < len; i++) { $el = $(elements[i]); @@ -163,12 +167,29 @@ } if (key) { + if (this.interesting_fields($el)) { + this.remove_validation_error($el, $form); + } validation = this.validate(elements[i]); if (validation.isValid) { obj[key] = $el.attr('type') === 'checkbox' ? $el.is(':checked') : $el.val(); $el.removeClass('error'); $label.removeClass('error'); } else { + if (this.interesting_fields($el)) { + $validationNode = this.get_error_validation_node($el, $form); + if ($validationNode) { + $n = $.parseHTML(validation.message); + tpl = HtmlUtils.template('<i class="fa fa-exclamation-triangle"></i>'); + + HtmlUtils.prepend($n, tpl()); + HtmlUtils.append($validationNode, HtmlUtils.HTML($n)); + } + + $desc = $form.find('#' + $el.attr('id') + '-desc'); + $desc.remove(); + } + errors.push(validation.message); $el.addClass('error'); $label.addClass('error'); @@ -180,6 +201,34 @@ return obj; }, + remove_validation_error: function($el, $form) { + var $validationNode = this.get_error_validation_node($el, $form); + if ($validationNode && $validationNode.find('li').length > 0) { + $validationNode.empty(); + } + }, + + get_error_validation_node: function($el, $form) { + var $node = $form.find('#' + $el.attr('id') + '-validation-error-msg'); + return $node.find('ul'); + }, + + interesting_fields: function($el) { + return ($el.attr('name') === 'email' || $el.attr('name') === 'password'); + }, + + toggleHelp: function(event, $help) { + var $el = $(event.currentTarget); + var $i = $el.find('i'); + + if ($help.css('display') === 'block') { + $help.css('display', 'none'); + $i.addClass('fa-caret-right').removeClass('fa-caret-down'); + } else { + $help.css('display', 'block'); + $i.addClass('fa-caret-down').removeClass('fa-caret-right'); + } + }, saveError: function(error) { this.errors = [ diff --git a/lms/static/js/student_account/views/LoginView.js b/lms/static/js/student_account/views/LoginView.js index 9997817636b9fff62e8b4c9788b522f2c9181fba..3b0fa997851a17ac53ae1485692418a98e58d289 100644 --- a/lms/static/js/student_account/views/LoginView.js +++ b/lms/static/js/student_account/views/LoginView.js @@ -23,7 +23,9 @@ events: { 'click .js-login': 'submitForm', 'click .forgot-password': 'forgotPassword', - 'click .login-provider': 'thirdPartyAuth' + 'click .login-provider': 'thirdPartyAuth', + 'click .enterprise-login': 'enterpriseSlugLogin', + 'click .login-help': 'toggleLoginHelp' }, formType: 'login', requiredStr: '', @@ -54,6 +56,7 @@ this.hideAuthWarnings = data.hideAuthWarnings; this.pipelineUserDetails = data.pipelineUserDetails; this.enterpriseName = data.enterpriseName; + this.enterpriseSlugLoginURL = data.enterpriseSlugLoginURL; this.listenTo(this.model, 'sync', this.saveSuccess); this.listenTo(this.resetModel, 'sync', this.resetEmail); @@ -137,6 +140,20 @@ this.clearPasswordResetSuccess(); }, + toggleLoginHelp: function(event) { + var $help; + event.preventDefault(); + $help = $('#login-help'); + this.toggleHelp(event, $help); + }, + + enterpriseSlugLogin: function(event) { + event.preventDefault(); + if (this.enterpriseSlugLoginURL) { + window.location.href = this.enterpriseSlugLoginURL; + } + }, + postFormSubmission: function() { this.clearPasswordResetSuccess(); }, diff --git a/lms/static/js/student_account/views/PasswordResetView.js b/lms/static/js/student_account/views/PasswordResetView.js index 46007ce31197d905a5d6029932b2ac4c84e3129c..4dc6142d57edfeed33f4366fa5e71a5b10583f63 100644 --- a/lms/static/js/student_account/views/PasswordResetView.js +++ b/lms/static/js/student_account/views/PasswordResetView.js @@ -11,7 +11,8 @@ tpl: '#password_reset-tpl', events: { - 'click .js-reset': 'submitForm' + 'click .js-reset': 'submitForm', + 'click .reset-help': 'toggleResetHelp' }, formType: 'password-reset', @@ -27,6 +28,13 @@ this.listenTo(this.model, 'sync', this.saveSuccess); }, + toggleResetHelp: function(event) { + var $help; + event.preventDefault(); + $help = $('#reset-help'); + this.toggleHelp(event, $help); + }, + saveSuccess: function() { this.trigger('password-email-sent'); diff --git a/lms/static/js/student_account/views/RegisterView.js b/lms/static/js/student_account/views/RegisterView.js index c0ae569e8f07c1a2cc5b21eeb42584d59eeb25eb..7bd7e5aef396e99d9a46886e6cc9aa5bb988907f 100644 --- a/lms/static/js/student_account/views/RegisterView.js +++ b/lms/static/js/student_account/views/RegisterView.js @@ -274,6 +274,9 @@ handleInputBehavior($input); } }); + $('#register-confirm_email').bind('cut copy paste', function(e) { + e.preventDefault(); + }); setTimeout(handleAutocomplete, 1000); }, diff --git a/lms/static/lms/js/spec/main.js b/lms/static/lms/js/spec/main.js index 8de036f33a2ce4c57149c3c532ce5e4fc706aeaa..7c0cdb2c12666e10854634ef85d87123324bd877 100644 --- a/lms/static/lms/js/spec/main.js +++ b/lms/static/lms/js/spec/main.js @@ -79,7 +79,6 @@ // Manually specify LMS files that are not converted to RequireJS 'history': 'js/vendor/history', - 'js/commerce/views/receipt_view': 'js/commerce/views/receipt_view', 'js/staff_debug_actions': 'js/staff_debug_actions', 'js/vendor/jquery.qubit': 'js/vendor/jquery.qubit', 'js/utils/navigation': 'js/utils/navigation', @@ -347,10 +346,6 @@ exports: 'js/ccx/schedule', deps: ['jquery', 'underscore', 'backbone', 'gettext', 'moment'] }, - 'js/commerce/views/receipt_view': { - exports: 'edx.commerce.ReceiptView', - deps: ['jquery', 'jquery.url', 'backbone', 'underscore', 'string_utils'] - }, // Backbone classes loaded explicitly until they are converted to use RequireJS 'js/instructor_dashboard/ecommerce': { @@ -714,7 +709,6 @@ 'js/learner_dashboard/spec/unenroll_view_spec.js', 'js/spec/api_admin/catalog_preview_spec.js', 'js/spec/ccx/schedule_spec.js', - 'js/spec/commerce/receipt_view_spec.js', 'js/spec/components/card/card_spec.js', 'js/spec/components/header/header_spec.js', 'js/spec/course_sharing/course_sharing_events_spec.js', diff --git a/lms/static/sass/_build-learner-dashboard.scss b/lms/static/sass/_build-learner-dashboard.scss index 5b1a1ad16e4a3b65e921212a88d1f03ae5fa60f3..16962bcd69632962a611e7478f2c0372c700f6a3 100644 --- a/lms/static/sass/_build-learner-dashboard.scss +++ b/lms/static/sass/_build-learner-dashboard.scss @@ -10,8 +10,3 @@ @import 'elements/program-card'; @import 'elements-v2/icons'; @import 'elements/progress-circle'; - -// Various View Styling -@import 'views/course-entitlements'; -@import 'views/program-details'; -@import 'views/program-list'; diff --git a/lms/static/sass/_build-lms-v1.scss b/lms/static/sass/_build-lms-v1.scss index 566228e9860864fe955d02c396a3c49cb903f9aa..cfac8d84f6692f1ddd159e6d9e05ac743244bc20 100644 --- a/lms/static/sass/_build-lms-v1.scss +++ b/lms/static/sass/_build-lms-v1.scss @@ -73,7 +73,6 @@ @import 'features/_unsupported-browser-alert'; @import 'features/content-type-gating'; @import 'features/course-duration-limits'; -@import 'features/enterprise-learner-portal-banner'; @import 'features/first-purchase-banner'; @import 'features/next-up-banner'; diff --git a/lms/static/sass/_build-lms-v2.scss b/lms/static/sass/_build-lms-v2.scss index 1dc6e8ed4b7fff5c8cd38116f77d4734df12bc5b..124f3a85444a618160eb46c047e32f449f746ed9 100644 --- a/lms/static/sass/_build-lms-v2.scss +++ b/lms/static/sass/_build-lms-v2.scss @@ -33,7 +33,6 @@ @import 'features/course-sock'; @import 'features/course-upgrade-message'; @import 'features/content-type-gating'; -@import 'features/enterprise-learner-portal-banner'; // Responsive Design diff --git a/lms/static/sass/_developer.scss b/lms/static/sass/_developer.scss index a6ed3f1a69bd100a6b61820af76d511f06cb837a..4049474508a5ec4a093f0a00b2c892ad86c9962b 100644 --- a/lms/static/sass/_developer.scss +++ b/lms/static/sass/_developer.scss @@ -74,7 +74,9 @@ float: left; padding: ($baseline*0.5) 0; - .product-info, .product-name, .price { + .product-info, + .product-name, + .price { @extend %t-ultrastrong; color: $m-blue-d3; diff --git a/lms/static/sass/_experiments.scss b/lms/static/sass/_experiments.scss index 7fdaf08427ce3883663e48851f7a26359233fc98..b177a38a2ae979082a10f4525d8d035ec5749292 100644 --- a/lms/static/sass/_experiments.scss +++ b/lms/static/sass/_experiments.scss @@ -48,7 +48,8 @@ /* modal-specific */ -#upsell-modal, #portfolio-experiment-upsell-modal { +#upsell-modal, +#portfolio-experiment-upsell-modal { display: none; /* slick modal from https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css */ @@ -505,7 +506,7 @@ padding-bottom: 15px; } - @media only screen and (max-width: 600px){ + @media only screen and (max-width: 600px) { .slick-slide.carousel-item { min-width: 0; } diff --git a/lms/static/sass/_header.scss b/lms/static/sass/_header.scss index f3f15e5367b32a7b2df415c47abf4dc1b33fbcc4..aa4236fd744b157620469a1a4b7d92cb4a5c75a0 100644 --- a/lms/static/sass/_header.scss +++ b/lms/static/sass/_header.scss @@ -209,7 +209,9 @@ position: absolute; background-color: theme-color("inverse"); color: theme-color("secondary"); + @include right(30px); + top: 55px; z-index: 10; diff --git a/lms/static/sass/_shame.scss b/lms/static/sass/_shame.scss index 5203469ce4745ec45a69440916d2f54d73e411c8..997e46db5f6919c73b06bd461a86f7bdd016ec58 100644 --- a/lms/static/sass/_shame.scss +++ b/lms/static/sass/_shame.scss @@ -7,18 +7,16 @@ // extends btn %m-btn { - @include box-sizing(border-box); + box-sizing: border-box; + @include transition(color $tmg-f2 ease-in-out, background $tmg-f2 ease-in-out, box-shadow $tmg-f2 ease-in-out); display: inline-block; cursor: pointer; text-decoration: none; - &:hover, &:active { - - } - - &.disabled, &[disabled] { + &.disabled, + &[disabled] { cursor: default; pointer-events: none; } @@ -42,16 +40,19 @@ @extend %m-btn-edged; border: none; - padding:($baseline/2) ($baseline); + padding: ($baseline/2) ($baseline); text-align: center; text-shadow: none; font-weight: 500; letter-spacing: 0; - &.disabled, &[disabled], &.is-disabled { + &.disabled, + &[disabled], + &.is-disabled { background: $action-primary-disabled-bg; - &:hover, &:focus { + &:hover, + &:focus { background: $action-primary-disabled-bg !important; // needed for IE currently } } @@ -65,7 +66,9 @@ background: $action-primary-bg; color: $action-primary-fg; - &:hover, &:active, &:focus { + &:hover, + &:active, + &:focus { background: $action-primary-focused-bg; } @@ -73,18 +76,22 @@ box-shadow: 0 0 6px 0 $action-primary-active-focused-shadow; } - &.current, &.active { + &.current, + &.active { box-shadow: inset 0 2px 1px 1px $action-primary-active-shadow; background: $action-primary-active-bg; color: $action-primary-active-fg; - &:hover, &:active, &:focus { + &:hover, + &:active, + &:focus { box-shadow: inset 0 2px 1px 1px $action-primary-active-focused-shadow; color: $action-primary-active-focused-fg; } } - &.disabled, &[disabled] { + &.disabled, + &[disabled] { box-shadow: none; background: $action-primary-disabled-bg; // needed for IE currently } @@ -98,7 +105,9 @@ background: $action-secondary-bg; color: $action-secondary-fg; - &:hover, &:active, &:focus { + &:hover, + &:active, + &:focus { background: $action-secondary-focused-bg; } @@ -106,18 +115,22 @@ box-shadow: 0 0 6px 0 $action-primary-active-focused-shadow; } - &.current, &.active { + &.current, + &.active { box-shadow: inset 0 2px 1px 1px $action-secondary-active-shadow; background: $action-secondary-active-bg; color: $action-secondary-active-fg; - &:hover, &:active, &:focus { + &:hover, + &:active, + &:focus { box-shadow: inset 0 2px 1px 1px $action-secondary-active-focused-shadow; color: $action-secondary-active-focused-fg; } } - &.disabled, &[disabled] { + &.disabled, + &[disabled] { box-shadow: none; background: $action-secondary-disabled-bg; // needed for IE currently } @@ -127,7 +140,10 @@ // ==================== // edx.org marketing site - needed, but bad overrides with importants -.view-register, .view-login, .view-passwordreset, .view-survey { +.view-register, +.view-login, +.view-passwordreset, +.view-survey { .form-actions button[type="submit"] { text-transform: none; vertical-align: middle; @@ -145,13 +161,17 @@ //overriding reset link style for nav/header .header-global { - .logo a:hover, .logo:active, .logo a:focus { + .logo a:hover, + .logo:active, + .logo a:focus { border: none; text-decoration: none; padding-bottom: 0; } - .nav-global a:hover, .nav-global a:active, .nav-global a:focus { + .nav-global a:hover, + .nav-global a:active, + .nav-global a:focus { border: none; } } @@ -179,7 +199,8 @@ footer .references { // ==================== // modal semantic button resetting - overriding the poorly scoped button mixin styling -.close-modal, button.close-modal { +.close-modal, +button.close-modal { @extend %ui-reset-button; &:focus { diff --git a/lms/static/sass/base/_animations.scss b/lms/static/sass/base/_animations.scss index bace488eb1b4f7e9e6ee07ad3f206602eed8300d..09f949f7f8afb85dd343a892abede9b1783cc6f9 100644 --- a/lms/static/sass/base/_animations.scss +++ b/lms/static/sass/base/_animations.scss @@ -1,6 +1,8 @@ // home-header-pop-up animation //************************************************************************// +/* stylelint-disable */ + .animation-home-header-pop-up { @include animation(home-header-pop-up 1.15s ease-in-out); @include animation-fill-mode(both); diff --git a/lms/static/sass/base/_base.scss b/lms/static/sass/base/_base.scss index 255490b27bd459df7f9bdf822304bb74ebddd366..e572f7c5f17620a272047e8011b2e65e7b39904e 100644 --- a/lms/static/sass/base/_base.scss +++ b/lms/static/sass/base/_base.scss @@ -145,7 +145,8 @@ a:visited:not(.btn) { .container { @include clearfix(); - @include box-sizing(border-box); + + box-sizing: border-box; @include media-breakpoint-up(md) { margin: 0 auto; @@ -305,29 +306,37 @@ mark { } } -div.reset-deadlines-banner { - background-color: theme-color("primary"); - display: none; - flex-wrap: wrap; - padding: 15px 20px; - margin-top: 5px; - - div.reset-deadlines-text { - color: theme-color("inverse"); - margin: 10px 10px 10px 0; - flex: 0 1 auto; +.dates-banner { + border-radius: 4px; + border: solid 1px #9cd2e6; + background-color: #eff8fa; + margin-top: 20px; + margin-bottom: 20px; + padding: 24px; + display: flex; + flex-wrap: wrap; + justify-content: space-between; + max-width: $text-width-readability-max; + + .dates-banner-text { + font-size: 16px; + line-height: 24px; + color: #414141; + + a.mobile-dates-link { + color: #0075b4; + } + } - a { - color: #FFFFFF; - text-decoration: underline; + &.has-button { + .dates-banner-text { + flex: 1 1 20em; + max-width: 70%; + } } - } - form { - button { - color: #0075b4; - background-color: theme-color("inverse"); - cursor: pointer; + &.on-mobile { + margin-left: 20px; + margin-right: 20px; } - } } diff --git a/lms/static/sass/base/_build.scss b/lms/static/sass/base/_build.scss index a36bffce87028edf1cea8926a93125ac70b4a6e2..3aa8501618dfc9ac4683dfe23780cf99365505f2 100644 --- a/lms/static/sass/base/_build.scss +++ b/lms/static/sass/base/_build.scss @@ -7,10 +7,20 @@ @import 'bootstrap/variables'; @import 'bootstrap/scss/functions'; @import 'bootstrap/scss/variables'; +@import 'bootstrap/scss/mixins/background-variant'; @import 'bootstrap/scss/mixins/box-shadow'; @import 'bootstrap/scss/mixins/breakpoints'; +@import 'bootstrap/scss/mixins/float'; @import 'bootstrap/scss/mixins/grid'; +@import 'bootstrap/scss/mixins/hover'; @import 'bootstrap/scss/mixins/reset-text'; +@import 'bootstrap/scss/mixins/screen-reader'; +@import 'bootstrap/scss/mixins/text-truncate'; +@import 'bootstrap/scss/mixins/text-emphasis'; +@import 'bootstrap/scss/mixins/text-hide'; +@import 'bootstrap/scss/mixins/visibility'; +@import 'bootstrap/scss/utilities'; + // Bootstrap components @import 'bootstrap/scss/popover'; diff --git a/lms/static/sass/base/_extends.scss b/lms/static/sass/base/_extends.scss index d7aeb41287f78eff6967848f31c06beaae52da72..43317328de5297e18df38122c6b829f55ec0d56d 100644 --- a/lms/static/sass/base/_extends.scss +++ b/lms/static/sass/base/_extends.scss @@ -100,21 +100,17 @@ // ==================== // needed utility extend for resetting poor basic <button> elem styling -%ui-reset-button { +%ui-reset-button { border: none !important; box-shadow: none !important; background: transparent !important; text-shadow: none !important; letter-spacing: 0 !important; text-transform: none !important; - - &:focus { - // outline: thin dotted !important; - } } // light button reset -%ui-clear-button { +%ui-clear-button { background: none; border-radius: ($baseline/4); box-shadow: none; @@ -154,8 +150,7 @@ // extends - content - text overflow by ellipsis %cont-truncated { - @include box-sizing(border-box); - + box-sizing: border-box; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; @@ -164,6 +159,6 @@ // Adds a simple extend that indicates that this user interface element should not print %ui-print-excluded { @media print { - display:none; + display: none; } } diff --git a/lms/static/sass/base/_grid-settings.scss b/lms/static/sass/base/_grid-settings.scss index 9cc73f7d652d2ac93068c1567a68f033d83ae8d7..088fbcc6eda14e61723d2ccc7a312167d4aacf0a 100644 --- a/lms/static/sass/base/_grid-settings.scss +++ b/lms/static/sass/base/_grid-settings.scss @@ -27,7 +27,7 @@ $edx-bp-huge: new-breakpoint(min-width 980px 12); @mixin grid-container() { display: flex; flex-direction: row; - flex-wrap: wrap; + flex-wrap: wrap; /* stylelint-disable-line */ justify-content: flex-start; align-items: flex-start; box-sizing: border-box; diff --git a/lms/static/sass/base/_mixins.scss b/lms/static/sass/base/_mixins.scss index fa9e5b6c9764be658b3c602ef73d83ae15127351..a88f7654b12e37c7ed742592f3ecf1d5990b83b5 100644 --- a/lms/static/sass/base/_mixins.scss +++ b/lms/static/sass/base/_mixins.scss @@ -53,17 +53,17 @@ // ==================== // theme mixin styles -@mixin login_register_h1_style {} +@mixin login_register_h1_style {} /* stylelint-disable-line */ -@mixin footer_references_style {} +@mixin footer_references_style {} /* stylelint-disable-line */ // ==================== // extends - UI - used for page/view-level wrappers (for centering/grids) %ui-wrapper { @include clearfix(); - @include box-sizing(border-box); + box-sizing: border-box; width: 100%; } @@ -151,7 +151,9 @@ padding: 0; text-indent: 0; - li, dt, dd { + li, + dt, + dd { margin: 0; padding: 0; } @@ -166,7 +168,7 @@ // extends - text - wrapping %text-wrap { - text-wrap: wrap; + text-wrap: wrap; /* stylelint-disable-line */ white-space: pre-wrap; white-space: -moz-pre-wrap; word-wrap: break-word; @@ -174,8 +176,7 @@ // extends - text - text overflow by ellipsis %text-truncated { - @include box-sizing(border-box); - + box-sizing: border-box; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; @@ -207,7 +208,8 @@ %shame-link-base { color: $link-color; - &:hover, &:focus { + &:hover, + &:focus { color: saturate($link-color, 50%); } } @@ -215,7 +217,8 @@ %shame-link-text { @extend %shame-link-base; - &:hover, &:focus { + &:hover, + &:focus { text-decoration: underline !important; } } diff --git a/lms/static/sass/bootstrap/_components.scss b/lms/static/sass/bootstrap/_components.scss index 7122d12efb4a63452e7ecb57a2cf2aa9002bd386..64282e83fc4e428183bd16054f3a8fd9e6f47462 100644 --- a/lms/static/sass/bootstrap/_components.scss +++ b/lms/static/sass/bootstrap/_components.scss @@ -21,10 +21,8 @@ .alert.alert-warning .message-content .enroll-btn.btn-link { color: #004368; } - } - } - + } } // Alerts @@ -47,3 +45,57 @@ text-decoration: underline; font-weight: bold; } + +.alert-error { + box-shadow: inset 0 0 0 4px $palette-error-back; + + .alert-copy:last-child { + margin-bottom: 0; + } +} + +.alert-error .alert-icon { + align-self: center; + color: $white; + background-color: $palette-error-accent; + display: none; + border-radius: 50%; + padding: 0.625rem; + + @include media-breakpoint-up(md) { + display: block; + } +} + +.alert-message-with-action { + @include media-breakpoint-up(md) { + width: 80%; + padding: 1.25rem; + padding-top: 0; + padding-bottom: 0; + } + + .alert-copy { + display: inline-block; + vertical-align: sub; + } +} + +// Discussion +.discussion { + .btn-link { + border-color: transparent + } + + .breadcrumbs { + font-size: 0.875rem; + + .all-topics { + border: none; + } + } + + .field-label-text { + font-size: 1rem + } +} diff --git a/lms/static/sass/bootstrap/_footer.scss b/lms/static/sass/bootstrap/_footer.scss index 278bddd1ac4a3223119eb97a45300753710f2e4d..40cc3bd4a1ae91e31fccad6a7344c1aea25f7f95 100644 --- a/lms/static/sass/bootstrap/_footer.scss +++ b/lms/static/sass/bootstrap/_footer.scss @@ -40,7 +40,7 @@ text-decoration: none; padding: 0; margin-right: $baseline/4; - font-size: .8em; + font-size: 0.8em; } } @@ -57,7 +57,7 @@ @include text-align(left); margin: -2px 0 8px; - font-size: .8em; + font-size: 0.8em; color: $gray; } diff --git a/lms/static/sass/bootstrap/_legacy.scss b/lms/static/sass/bootstrap/_legacy.scss index eb6077a13199c6782cc457f3af50cd686df70ebe..5db46a64ed1f7db5bfd1421cc17207595dc81ebf 100644 --- a/lms/static/sass/bootstrap/_legacy.scss +++ b/lms/static/sass/bootstrap/_legacy.scss @@ -40,8 +40,7 @@ $grid-breakpoints-lg: 992px !default; // Wrap grids with grid-container. @mixin grid-container() { display: flex; - flex-direction: row; - flex-wrap: wrap; + flex-flow: row wrap; justify-content: flex-start; align-items: flex-start; box-sizing: border-box; @@ -109,3 +108,45 @@ $shadow-l1: rgba(0, 0, 0, 0.1) !default; $shadow-l2: rgba(0, 0, 0, 0.05) !default; $shadow-d1: rgba(0, 0, 0, 0.4) !default; $shadow-d2: rgba($black, 0.6) !default; + +$primary-dark: rgba(6, 86, 131, 100) !default; +$primary-dark1: mix($black, $blue, 20%) !default; +$primary-dark2: desaturate($blue, 15%) !default; +$primary-base: rgba(0, 117, 180, 100) !default; +$primary-accent: rgba(41, 145, 195, 100) !default; + +$gray-dark: rgba(17, 17, 17, 100) !default; +$gray-base: rgba(65, 65, 65, 100) !default; +$gray-light1: rgb(252, 252, 252) !default; +$gray-light2: mix($white, $gray, 60%) !default; +$gray-light3: mix($white, $gray, 80%) !default; +$gray-light4: mix($white, $gray, 95%) !default; + +// ---------------------------- +// #COLORS- Bootstrap-style +// ---------------------------- + +$state-success-text: $black !default; +$state-success-bg: #dff0d8 !default; +$state-success-border: darken($state-success-bg, 5%) !default; + +$state-info-text: #31708f !default; +$state-info-text-link: #245269 !default; +$state-info-bg: #d9edf7 !default; +$state-info-border: darken($state-info-bg, 7%) !default; + +$state-warning-text: $black !default; +$state-warning-bg: #fcf8e3 !default; +$state-warning-border: darken($state-warning-bg, 5%) !default; + +$state-danger-text: $black !default; +$state-danger-bg: #f2dede !default; +$state-danger-border: darken($state-danger-bg, 5%) !default; + +$palette-error-accent: #cb0712; +$palette-error-back: #feeced; + +// logo colors +$micromasters-color: #005585 !default; +$zebra-stripe-color: rgb(249, 250, 252) !default; +$divider-color: rgb(226, 231, 236) !default; diff --git a/lms/static/sass/bootstrap/elements/_banners.scss b/lms/static/sass/bootstrap/elements/_banners.scss new file mode 100644 index 0000000000000000000000000000000000000000..86f6d6a8ca0d5542f0472556229bae2bdb90efe8 --- /dev/null +++ b/lms/static/sass/bootstrap/elements/_banners.scss @@ -0,0 +1,127 @@ +$full-width-banner-img-height: 260px !default; +$full-width-banner-img-width: 1140px !default; +$full-width-banner-margin: 20px; + +.full-width-banner { + position: relative; + + .banner-background-wrapper { + height: $full-width-banner-img-height; + width: 100%; + overflow: hidden; + position: relative; + background: $black; + + &::before { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: $black; + opacity: 0.65; + + @include media-breakpoint-up(md) { + opacity: 0.4; + } + } + } + + .banner-background-image { + height: $full-width-banner-img-height; + + @include media-breakpoint-up($full-width-banner-img-width) { + height: auto; + width: 100%; + } + } + + .banner-content { + position: absolute; + top: 0; + left: $full-width-banner-margin; + right: $full-width-banner-margin; + } +} + +.page-banner { + max-width: map-get($grid-breakpoints, xl); + margin: 0 auto; + + .user-messages { + padding-top: $baseline; + + // Hack: force override the global important rule + // that courseware links don't have an underline. + a:hover { + color: $link-color; + text-decoration: underline !important; + } + + .user-messages-ul { + list-style: none; + padding: 0; + margin: 0; + + li { + margin: 5px 0; + } + } + } + + .alert { + display: flex; + padding: $baseline; + border: 1px solid; + + &:not(:last-child) { + margin-bottom: $baseline / 2; + } + + .icon-alert { + @include margin-right($baseline); + } + + .message-actions { + @include margin-left($baseline); + } + + &.alert-info { + color: $state-info-text; + background-color: $state-info-bg; + border-color: $state-info-border; + box-shadow: none; + line-height: initial; + + a, + a:visited, + .btn-link { + color: $state-info-text-link; + font-weight: bold; + border-color: transparent; + } + } + + &.alert-success { + color: $state-success-text; + background-color: $state-success-bg; + border-color: $state-success-border; + box-shadow: none; + } + + &.alert-warning { + color: $state-warning-text; + background-color: $state-warning-bg; + border-color: $state-warning-border; + box-shadow: none; + } + + &.alert-danger { + color: $state-danger-text; + background-color: $state-danger-bg; + border-color: $state-danger-border; + box-shadow: none; + } + } +} diff --git a/lms/static/sass/bootstrap/elements/_program-card.scss b/lms/static/sass/bootstrap/elements/_program-card.scss new file mode 100644 index 0000000000000000000000000000000000000000..33b8e85021677a4b391a4bdd69c2ae1d4cd27ff1 --- /dev/null +++ b/lms/static/sass/bootstrap/elements/_program-card.scss @@ -0,0 +1,211 @@ +%hide-until-focus { + @include left(0); + + display: inline-block; + position: absolute; + top: -999999px; + overflow: hidden; +} + +.program-card { + flex: 0 0 98%; + max-width: 98%; + border: 1px solid $gray-500; + border-bottom: none; + margin-bottom: $baseline; + position: relative; + + @include margin-right(8px); + @include margin-left(8px); + + @include media-breakpoint-up(md) { + flex: 0 0 47%; + max-width: 47%; + + &:nth-child(2n+1) { + @include margin-left(0); + } + } + + @include media-breakpoint-up(lg) { + flex: 0 0 48%; + max-width: 48%; + } + + .card-link { + @include left(0); + @include right(0); + + position: absolute; + top: 0; + bottom: 0; + border: 0; + z-index: 1; + opacity: 0.8; + + &:active, + &:hover, + &:focus { + opacity: 1; + } + + .banner-image-container { + position: relative; + overflow: hidden; + height: 166px; + + @include media-breakpoint-up(sm) { height: 242px; } + + @include media-breakpoint-up(md) { height: 116px; } + + @include media-breakpoint-up(lg) { height: 145px; } + + .banner-image { + @include left(50%); + + position: absolute; + top: 0; + z-index: 0; + transform: translate(-50%, 0); + min-height: 100%; + } + } + } + + .text-section { + padding: 40px $baseline $baseline; + position: relative; + margin-top: 156px; + + @include media-breakpoint-up(sm) { margin-top: 232px; } + + @include media-breakpoint-up(md) { margin-top: 106px; } + + @include media-breakpoint-up(lg) { margin-top: 135px; } + } + + .meta-info { + font-size: 0.75rem; + color: $gray-dark; + position: absolute; + top: $baseline; + width: calc(100% - 40px); + display: flex; + } + + .organization { + @include make-col(6); + + white-space: nowrap; + overflow: hidden; + padding: 0; + } + + .category { + @include make-col(6); + @include text-align(right); + + padding: 0; + + .category-text { + @include float(right); + } + + .category-icon { + @include float(right); + @include margin-right($baseline*0.25); + + background-color: transparent; + background-size: 100%; + width: ($baseline*0.7); + height: ($baseline*0.7); + } + } + + .hd-3 { + font: -apple-system-short-headline !important; + color: $gray-dark; + min-height: ($baseline*3); + line-height: 1.15; + margin-bottom: 0.625rem; + font-size: 1.5rem; + } + + .status-text { + display: flex; + margin-bottom: 5px; + + .number-status { + font: -apple-system-short-caption1 !important; + text-align: center; + width: 100%; + float: left; + padding: { + left: 5px; + right: 5px; + bottom: 8px; + } + + margin-top: -8px; + font-size: 0.9375em; + font-family: $font-family-sans-serif; + } + + .number-circle { + padding-top: 1px; + border-radius: 50%; + margin-left: auto; + margin-right: auto; + width: 23px; + height: 23px; + color: white; + text-align: center; + font-size: 0.9375em; + font-family: $font-family-sans-serif; + font-weight: bold; + } + + .completed { + background: $blue; + } + + .enrolled { + background: $green; + } + + .not-enrolled { + background: $gray-dark; + } + } + + .progress-container { + .progress-bar { + height: 5px; + display: flex; + width: 100%; + background-color: $white; + + .item { + width: 100%; + margin-right: 2px; + height: 5px; + + &.completed { + background: $blue; + } + + &.enrolled { + background: $green; + } + + &.not-enrolled { + background: lightgray; + } + + &.not-enrolled:last-of-type { + margin-right: 0; + } + } + } + } +} diff --git a/lms/static/sass/bootstrap/elements/_progress-circle.scss b/lms/static/sass/bootstrap/elements/_progress-circle.scss new file mode 100644 index 0000000000000000000000000000000000000000..fc3329a10ebe0c80f0843abc2ba841dd8a6877c6 --- /dev/null +++ b/lms/static/sass/bootstrap/elements/_progress-circle.scss @@ -0,0 +1,67 @@ +$progress-title-color: $primary-dark1 !default; +$progress-complete-color: $primary-dark2 !default; +$progress-incomplete-color: $gray-light2 !default; +$progress-complete-number-color: $primary-dark1 !default; +$progress-incomplete-number-color: $gray-600 !default; +$progress-number-label-color: $gray-base !default; + +.program-progress { + width: 300px; + margin: 0 auto 30px; + + @include media-breakpoint-up(md) { + margin-left: 0; + } +} + +.progress-heading { + color: $progress-title-color; + text-align: center; + margin-bottom: 0; + font: { + size: 1.1em; + weight: 700; + } +} + +.progress-circle-wrapper { + position: relative; + margin-top: -20px; + width: 300px; + height: 300px; + + .progress-label { + position: absolute; + width: 100%; + top: 92px; + text-align: center; + } + + .numbers { + font-size: 3em; + color: $progress-incomplete-number-color; + + .complete { + color: $progress-complete-number-color; + } + } + + .label { + font: { + size: 1.1em; + weight: 600; + } + + color: $progress-number-label-color; + } +} + +.progress-circle { + .complete { + stroke: $progress-complete-color; + } + + .incomplete { + stroke: $progress-incomplete-color; + } +} diff --git a/lms/static/sass/bootstrap/lms-main.scss b/lms/static/sass/bootstrap/lms-main.scss index 404aba2d2a88194bd92aa953945fa1919433dde7..a1a11a1496e5746f5bc06bb9f09b83abafee0dc6 100644 --- a/lms/static/sass/bootstrap/lms-main.scss +++ b/lms/static/sass/bootstrap/lms-main.scss @@ -15,9 +15,13 @@ $static-path: '../..'; @import 'layouts'; @import 'components'; @import 'course/layout/courseware_preview'; -@import 'course/layout/reset_deadlines'; +@import 'course/layout/dates_banner'; @import 'shared/modal'; @import 'shared/help-tab'; +@import './elements/banners'; +@import './elements/progress-circle'; +@import './elements/program-card'; +@import 'elements/icons'; // Features @import 'features/bookmarks'; @@ -26,13 +30,15 @@ $static-path: '../..'; @import 'features/course-sock'; @import 'features/course-upgrade-message'; @import 'features/course-duration-limits'; -@import 'features/enterprise-learner-portal-banner'; @import 'features/first-purchase-banner'; @import 'features/next-up-banner'; // Individual Pages @import "views/program-marketing-page"; @import "views/entitlement-support-page"; +@import "views/course-entitlements"; +@import "views/program-details"; +@import 'views/program-list'; // Responsive Design @import '../header'; diff --git a/lms/static/sass/course/_dates.scss b/lms/static/sass/course/_dates.scss index 169d50072b60c4bd4091fe15b2b72ee98ae1720a..0a9de0ab274613506aeb42da549e84bf0caedc8c 100644 --- a/lms/static/sass/course/_dates.scss +++ b/lms/static/sass/course/_dates.scss @@ -5,10 +5,43 @@ .date-title { color: #414141; - font-weight: 500; + font-size: 24px; border-bottom: 0; } + .dates-banner { + border-radius: 4px; + border: solid 1px #9cd2e6; + background-color: #eff8fa; + margin-top: 20px; + margin-bottom: 20px; + padding: 24px; + display: flex; + flex-wrap: wrap; + justify-content: space-between; + max-width: $text-width-readability-max; + + .dates-banner-text { + font-size: 16px; + line-height: 24px; + color: #414141; + } + + .banner-has-button { + flex: 1 1 20em; + max-width: 70%; + } + + .upgrade-button { + align-self: start; + flex: none; + + button { + @include white-button-flat-outline; + } + } + } + .timeline-item { border-left: solid 1px #2d323e; color: #2d323e; @@ -30,15 +63,25 @@ width: 7px; height: 7px; position: absolute; - left: -4px; + left: -5px; background-color: #2d323e; border-radius: 50%; + border-style: solid; + border-width: thin; - &.active { - width: 14px; - height: 14px; - left: -7px; - background-color: #2d323e; + &.past-date { + background-color: #f5f5f5; + + &.past-due { + background-color: #d1d2d4; + } + } + + &.todays-date { + width: 13px; + height: 13px; + left: -8px; + background-color: #ffdb87; } } @@ -50,11 +93,18 @@ flex: 100%; line-height: 1.25; - &.active { + &.todays-date { top: -3px; } } + .no-access { + // This is too low-contrast for a11y purposes. But since it only applies to pieces of the page that are + // inaccessible to users, and we have a banner explaining the parts that are inaccessible at the top, + // we're OK from an accessibility point of view. + color: #d1d2d4; + } + .timeline-date-content { @include font-size(16); @@ -63,6 +113,10 @@ font-weight: bold; margin-bottom: 8px; align-items: center; + + &.not-released { + color: #767676; + } } .timeline-title { @@ -78,6 +132,10 @@ color: #2d323e; text-decoration: underline; } + + &.not-released { + color: #d1d2d4; + } } .timeline-description { @@ -96,14 +154,36 @@ .pill { @include font-size(12); - padding: 2px 8px 2px 8px; + padding: 2px 8px; border-radius: 5px; margin-left: 8px; font-style: italic; font-weight: bold; vertical-align: top; - &.due { + &.completed { + background-color: #f3f3f4; + color: #2d323e; + } + + &.due-next { + background-color: #686b73; + color: $white; + } + + &.not-released { + background-color: $white; + border-color: #d1d2d4; + border-style: solid; + border-width: thin; + color: #767676; + } + + &.past-due { + background-color: #d1d2d4; + } + + &.today { background-color: #ffdb87; color: #2d323e; } diff --git a/lms/static/sass/course/_gradebook.scss b/lms/static/sass/course/_gradebook.scss index f91e6f68ba273c3fef50e81bc0fd1d4c99cf2952..86baef30683000bece5e553d18883f9c3b936061 100644 --- a/lms/static/sass/course/_gradebook.scss +++ b/lms/static/sass/course/_gradebook.scss @@ -27,9 +27,7 @@ div.gradebook-wrapper { width: 100%; height: 27px; padding: 0 ($baseline*0.75) 0 35px; - - @include box-sizing(border-box); - + box-sizing: border-box; border-radius: 13px; border: 1px solid $table-border-color; background: url('#{$static-path}/images/search-icon.png') no-repeat 9px center $gray-l6; diff --git a/lms/static/sass/course/_info.scss b/lms/static/sass/course/_info.scss index 800313868c03e0ca1ed8e293f52bc30600f88b39..ab6f6a4f17ca0137da36df57d5a3e9adaa712127 100644 --- a/lms/static/sass/course/_info.scss +++ b/lms/static/sass/course/_info.scss @@ -2,9 +2,9 @@ // Upgrade $notification-highlight-border-color: $uxpl-green-base !default; -$notification-background: rgb(255, 255, 255) !default +$notification-background: rgb(255, 255, 255) !default; - .home{ +.home { @include clearfix(); max-width: map-get($container-max-widths, xl); @@ -58,7 +58,7 @@ div.info-wrapper { width: 100%; display: block; - div.upgrade-banner { + div.dates-banner { // This banner uses the Pattern Library's defined variables @include border-left(0); @@ -114,15 +114,17 @@ div.info-wrapper { margin-bottom: lh(); } - > ol,section,div { + > ol, + section, + div { list-style: none; margin-bottom: lh(); padding-left: 0; .updates-article { - border-radius:3px; + border-radius: 3px; background-color: $white; - border:1px solid transparent; + border: 1px solid transparent; &:hover { border: 1px solid $gray-l3; @@ -142,14 +144,16 @@ div.info-wrapper { cursor: pointer; background: none; - &:hover, &:focus { + &:hover, + &:focus { background-color: unset; color: $m-blue-d3; border: 1px solid black; } } - > li,article { + > li, + article { @extend .clearfix; padding: $baseline; @@ -157,8 +161,10 @@ div.info-wrapper { margin-bottom: lh(1.5); background-color: $white; - ol, ul { - ol,ul { + ol, + ul { + ol, + ul { list-style-type: disc; } } @@ -173,7 +179,7 @@ div.info-wrapper { @include padding-left($baseline); @include float(left); } - + .toggle-visibility-button { @extend %t-title9; @@ -189,8 +195,8 @@ div.info-wrapper { } .toggle-visibility-element { - content:''; - display:block; + content: ''; + display: block; clear: both; } diff --git a/lms/static/sass/course/_profile.scss b/lms/static/sass/course/_profile.scss index 6b3ac29aa50f997db033b4c4fc28891e9697a17d..76fece68f72aacb0ba27b74450658cf33ec0a18c 100644 --- a/lms/static/sass/course/_profile.scss +++ b/lms/static/sass/course/_profile.scss @@ -50,8 +50,7 @@ input { &[type="text"] { - @include box-sizing(border-box); - + box-sizing: border-box; margin: lh(0.5) 0; width: 100%; } @@ -160,8 +159,8 @@ > a { @include button(simple, $button-color); - @include box-sizing(border-box); + box-sizing: border-box; border-radius: 3px; font: normal 15px/1.6rem $font-family-sans-serif; letter-spacing: 0; @@ -278,8 +277,8 @@ .hd { @include border-right(1px dashed #ddd); - @include box-sizing(border-box); + box-sizing: border-box; display: table-cell; letter-spacing: 0; margin: 0; diff --git a/lms/static/sass/course/_student-notes.scss b/lms/static/sass/course/_student-notes.scss index 91b5264a77e5c72555745770db7b139564e860a1..4cc3fe1f4009a1648e779279853725bd460de834 100644 --- a/lms/static/sass/course/_student-notes.scss +++ b/lms/static/sass/course/_student-notes.scss @@ -316,7 +316,6 @@ $divider-visual-tertiary: ($baseline/20) solid $gray-l4; .note-comment { color: $gray-d2; - } } } @@ -478,7 +477,8 @@ $divider-visual-tertiary: ($baseline/20) solid $gray-l4; } } - p, ul { + p, + ul { margin-bottom: $baseline; } } diff --git a/lms/static/sass/course/_syllabus.scss b/lms/static/sass/course/_syllabus.scss index 46ec08eafe28a4486fad7ad3ea2274adafbe26c2..4fb063b83bc285b99a18ef5198db9a93b3fa3a72 100644 --- a/lms/static/sass/course/_syllabus.scss +++ b/lms/static/sass/course/_syllabus.scss @@ -3,7 +3,7 @@ div.syllabus { text-align: center; h1 { - @extend .top-header + @extend .top-header; } .notes { @@ -33,7 +33,10 @@ div.syllabus { font-size: 1em !important; line-height: auto; - &.day, &.due, &.slides, &.assignment { + &.day, + &.due, + &.slides, + &.assignment { white-space: nowrap !important; } diff --git a/lms/static/sass/course/_tabs.scss b/lms/static/sass/course/_tabs.scss index a76bc36924b1ff691b3fa066d57523ce67864e29..4e58e2a6739a2590584b4dc202a82723065481b5 100644 --- a/lms/static/sass/course/_tabs.scss +++ b/lms/static/sass/course/_tabs.scss @@ -1,10 +1,9 @@ div.static_tab_wrapper { - @include box-sizing(border-box); - + box-sizing: border-box; padding: 2em 2.5em; h1 { - @extend .top-header + @extend .top-header; } section { diff --git a/lms/static/sass/course/_textbook.scss b/lms/static/sass/course/_textbook.scss index 54d347bbe41323bab5d3bc326480d0c937cf37b4..888db22b25eb8694b74798b56e024ab405f998b3 100755 --- a/lms/static/sass/course/_textbook.scss +++ b/lms/static/sass/course/_textbook.scss @@ -3,8 +3,6 @@ div.book-wrapper { margin: 0 auto; width: 100%; - /*background-color: $white;*/ - #open_close_accordion { display: none; } @@ -22,8 +20,7 @@ div.book-wrapper { @extend .sidebar; @extend .tran; - @include box-sizing(border-box); - + box-sizing: border-box; padding: ($baseline/2) 0; border-radius: 3px 0 0 3px; border: 1px solid $gray-l3; @@ -61,7 +58,8 @@ div.book-wrapper { padding: 0; color: theme-color("primary"); - &:hover, &:focus { + &:hover, + &:focus { background-color: transparent; color: $uxpl-blue-hover-active; @@ -76,7 +74,8 @@ div.book-wrapper { position: relative; top: 4px; - &:hover, &:focus { + &:hover, + &:focus { filter: alpha(opacity=60); opacity: 0.6; } @@ -104,7 +103,7 @@ div.book-wrapper { @extend .content; padding: 0; - width:76%; + width: 76%; nav { @extend .clearfix; @@ -128,9 +127,7 @@ div.book-wrapper { background-color: rgba(#000, 0.7); background-position: center; background-repeat: no-repeat; - - @include box-sizing(border-box); - + box-sizing: border-box; display: table; height: 100%; opacity: 0; @@ -142,12 +139,13 @@ div.book-wrapper { vertical-align: middle; width: 100%; - &:hover, &:focus { + &:hover, + &:focus { opacity: 1; } &.is-disabled { - display:none; + display: none; } } @@ -166,7 +164,6 @@ div.book-wrapper { background-image: url('#{$static-path}/images/textbook/textbook-right.png'); } } - } } @@ -197,7 +194,8 @@ div.book-wrapper { line-height: 1.6em; margin: ($baseline/4); - .Paragraph, h2 { + .Paragraph, + h2 { margin-top: ($baseline/2); } } diff --git a/lms/static/sass/course/base/_base.scss b/lms/static/sass/course/base/_base.scss index 37d7bea74e59dac145bdf30c10991b07922c788f..c017cd145f419be726f52ddc01f26b5414afd7f3 100644 --- a/lms/static/sass/course/base/_base.scss +++ b/lms/static/sass/course/base/_base.scss @@ -41,7 +41,15 @@ body { background-color: $course-bg-color; } -body, h1, h2, h3, h4, h5, h6, p, label { +body, +h1, +h2, +h3, +h4, +h5, +h6, +p, +label { @include text-align(left); font-family: $font-family-sans-serif; @@ -101,9 +109,7 @@ input[type="password"] { border: 1px solid $border-color-2; border-radius: 0; box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.6), inset 0 0 3px 0 $shadow-l1; - - @include box-sizing(border-box); - + box-sizing: border-box; font: normal 1em $font-family-sans-serif; height: 35px; padding: ($baseline/4) 12px; @@ -200,7 +206,8 @@ img { opacity: 0; -webkit-transition: all 0.2s; - p, span { + p, + span { color: $white; } diff --git a/lms/static/sass/course/base/_extends.scss b/lms/static/sass/course/base/_extends.scss index 091ba0e00b434d22d62f07e678af8173de155524..b1f3f96c3b6eeafca0189826d02217b0e8545da7 100644 --- a/lms/static/sass/course/base/_extends.scss +++ b/lms/static/sass/course/base/_extends.scss @@ -77,7 +77,10 @@ a.light-button, // only used in askbot as classes width: flex-grid(3); background: $sidebar-color; - h1, h2, h3, h4 { + h1, + h2, + h3, + h4 { font-weight: bold; letter-spacing: 0; text-transform: none; @@ -116,7 +119,8 @@ a.light-button, // only used in askbot as classes display: none; } - ul, ol { + ul, + ol { margin: 0; padding-left: 0; diff --git a/lms/static/sass/course/base/_mixins.scss b/lms/static/sass/course/base/_mixins.scss index ac9156c82bd42aec216850b097689cb23b719439..d8fab175eb194483ca66c8e5c8a9edf0de966782 100644 --- a/lms/static/sass/course/base/_mixins.scss +++ b/lms/static/sass/course/base/_mixins.scss @@ -45,6 +45,23 @@ } } +@mixin white-button-flat-outline { + display: block; + border-radius: 2px; + border: solid 1px #0175b4; + background: white; + color: #2d323e; + font-size: 14px; + font-weight: bold; + line-height: 24px; + + &:hover, + &:focus, + &:active { + box-shadow: 0 2px 1px $shadow; + } +} + @mixin dark-grey-button { display: block; height: 35px; diff --git a/lms/static/sass/course/ccx_coach/_dashboard.scss b/lms/static/sass/course/ccx_coach/_dashboard.scss index 302c98be248faa4430f1de95166e5a257537ec9d..729da74acd335b9070d9e6340bb67d1ec0bc3202 100644 --- a/lms/static/sass/course/ccx_coach/_dashboard.scss +++ b/lms/static/sass/course/ccx_coach/_dashboard.scss @@ -18,7 +18,8 @@ table.ccx-schedule { width: 18%; } - th, td { + th, + td { padding: 10px; } diff --git a/lms/static/sass/course/courseware/_amplifier.scss b/lms/static/sass/course/courseware/_amplifier.scss index af2a38f3f02e71884fb6037a677952fe88b984fc..ac14587ed270ff30db8178838b8a53188ad564ce 100644 --- a/lms/static/sass/course/courseware/_amplifier.scss +++ b/lms/static/sass/course/courseware/_amplifier.scss @@ -12,9 +12,7 @@ section.tool-wrapper { div#graph-container { background: none; - - @include box-sizing(border-box); - + box-sizing: border-box; display: table-cell; padding: lh(); vertical-align: top; @@ -81,9 +79,7 @@ section.tool-wrapper { background: darken(#073642, 2%); border-right: 1px solid darken(#002b36, 6%); box-shadow: 1px 0 0 lighten(#002b36, 6%), inset 0 0 0 4px darken(#094959, 6%); - - @include box-sizing(border-box); - + box-sizing: border-box; display: table-cell; padding: lh(); vertical-align: top; @@ -132,7 +128,6 @@ section.tool-wrapper { @include clearfix(); - margin-bottom: lh(); margin-bottom: lh(); padding: 0 0 lh(); } @@ -179,25 +174,30 @@ section.tool-wrapper { } //MOSFET AMPLIFIER - label[for="vinCheckbox"], label[for="vinRadioButton"]{ + label[for="vinCheckbox"], + label[for="vinRadioButton"] { color: desaturate(#00bfff, 50%); } - label[for="voutCheckbox"], label[for="voutRadioButton"]{ + label[for="voutCheckbox"], + label[for="voutRadioButton"] { color: darken(#ffcf48, 20%); } - label[for="vrCheckbox"], label[for="vrRadioButton"]{ + label[for="vrCheckbox"], + label[for="vrRadioButton"] { color: desaturate(#1df914, 40%); } //RC Filters - label[for="vcCheckbox"], label[for="vcRadioButton"]{ + label[for="vcCheckbox"], + label[for="vcRadioButton"] { color: darken(#ffcf48, 20%); } //RLC Series - label[for="vlCheckbox"], label[for="vlRadioButton"]{ + label[for="vlCheckbox"], + label[for="vlRadioButton"] { color: desaturate(#d33682, 40%); } @@ -249,7 +249,9 @@ section.tool-wrapper { box-shadow: inset 0 1px 0 lighten(#586e75, 20%); margin-top: -0.3em; - &:hover, &:active, &:focus { + &:hover, + &:active, + &:focus { background-color: lighten(#586e75, 10%); } } diff --git a/lms/static/sass/course/courseware/_courseware.scss b/lms/static/sass/course/courseware/_courseware.scss index f8aef346775d48e2d76fc05ea7d3b4c82953c8f3..ab6b3376394801aedb507aa7f8f5cba7c2f2cbc1 100644 --- a/lms/static/sass/course/courseware/_courseware.scss +++ b/lms/static/sass/course/courseware/_courseware.scss @@ -205,7 +205,7 @@ html.video-fullscreen { } .proctored-exam-code { - margin: 5px 0px; + margin: 5px 0; font-size: 1.3em; } @@ -228,11 +228,11 @@ html.video-fullscreen { } .copy-exam-code-button { - margin: 5px 0px; + margin: 5px 0; padding: 7.5px 20px; margin-left: -5px; - border-top-left-radius: 0px; - border-bottom-left-radius: 0px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } .exam-action-button { @@ -523,6 +523,33 @@ html.video-fullscreen { } } + .vert-due-date { + color: #686b73; + display: flex; + font-size: 16px; + + .pill { + font-size: 12px; + + padding: 2px 8px; + border-radius: 5px; + margin-left: 8px; + font-style: italic; + font-weight: bold; + vertical-align: top; + + &.completed { + background-color: #f3f3f4; + color: #2d323e; + } + + &.past-due { + background-color: #d1d2d4; + color: black; + } + } + } + .vert-mod { padding: 0; margin: 0; diff --git a/lms/static/sass/course/courseware/_sidebar.scss b/lms/static/sass/course/courseware/_sidebar.scss index 2a492a1bc22c1fa8ac5d8510fdd72b79dd6716aa..b0c948933482f9ae666d43035c475cab7668ebf3 100644 --- a/lms/static/sass/course/courseware/_sidebar.scss +++ b/lms/static/sass/course/courseware/_sidebar.scss @@ -6,7 +6,8 @@ display: table-cell; // needed to extend the sidebar the full height of the area // provides sufficient contrast for all screen reader-only elements - .sr, .sr-only { + .sr, + .sr-only { color: $black; background: $white; } @@ -23,7 +24,9 @@ .course-navigation { .button-chapter { @include transition(all $tmg-s3 ease-in-out); - @include box-sizing(border-box); + + box-sizing: border-box; + @include linear-gradient(top, $sidebar-chapter-bg-top, $sidebar-chapter-bg-bottom); @include transition(background-color 0.1s linear 0s); diff --git a/lms/static/sass/course/instructor/_instructor_2.scss b/lms/static/sass/course/instructor/_instructor_2.scss index 4f3ff209ae408aff095203283d42266a2307ecd9..f6e10574f386ffe454ee552a29a58a79a6070fde 100644 --- a/lms/static/sass/course/instructor/_instructor_2.scss +++ b/lms/static/sass/course/instructor/_instructor_2.scss @@ -251,7 +251,7 @@ @include margin-left(1px); @include font-size(14); - font-family: verdana,arial,sans-serif; + font-family: verdana, arial, sans-serif; color: #333; .slick-cell { @@ -557,7 +557,7 @@ input[name="send_to"]:disabled + label { font-weight: lighter; - background-color: $light-gray3 + background-color: $light-gray3; } .email-targets-primary { @@ -647,7 +647,7 @@ } } - .batch-enrollment-ccx{ + .batch-enrollment-ccx { @extend .batch-enrollment; float: left; @@ -674,7 +674,9 @@ display: block; position: absolute; top: ($baseline/2); + @include left(-9999em); + padding: ($baseline/2); width: 50%; background-color: $light-gray3; @@ -734,7 +736,8 @@ .member-list-widget { .header { - @include box-sizing(border-box); + box-sizing: border-box; + @include border-top-radius(3); position: relative; @@ -756,8 +759,7 @@ } .info { - @include box-sizing(border-box); - + box-sizing: border-box; padding: ($baseline/2); border: 1px solid $light-gray; color: $lighter-base-font-color; @@ -766,7 +768,7 @@ } .member-list { - @include box-sizing(border-box); + box-sizing: border-box; table { width: 100%; @@ -795,7 +797,8 @@ } .bottom-bar { - @include box-sizing(border-box); + box-sizing: border-box; + @include border-bottom-radius(3); position: relative; @@ -1568,7 +1571,8 @@ margin-top: 25px; - .metrics-left, .metrics-left-header { + .metrics-left, + .metrics-left-header { position: relative; width: 30%; @@ -1717,7 +1721,7 @@ } input[name="subject"] { - width:600px; + width: 600px; } .enrollment-wrapper { @@ -1779,7 +1783,6 @@ input[name="subject"] { @include float(right); } } - } #e-commerce { @@ -1813,7 +1816,7 @@ input[name="subject"] { .error-msgs { background: #ffeef5; - color:#b72667; + color: #b72667; text-align: center; padding: ($baseline/2) 0; font-family: $font-family-sans-serif; @@ -2034,7 +2037,7 @@ input[name="subject"] { white-space: normal; } - input[name="generate-registration-codes-csv"]{ + input[name="generate-registration-codes-csv"] { @include button(simple, $primary); @extend .button-reset; @@ -2134,7 +2137,8 @@ input[name="subject"] { min-height: 45px !important; } - li#generate-registration-modal-field-city, li#generate-registration-modal-field-state, + li#generate-registration-modal-field-city, + li#generate-registration-modal-field-state, li#generate-registration-modal-field-zipcode { width: 205px; } @@ -2336,7 +2340,6 @@ input[name="subject"] { .example-certificate-status-wrapper { width: 75%; } - } input[name="subject"] { @@ -2395,7 +2398,7 @@ input[name="subject"] { @include float(right); line-height: 14px; - font-size: 0.7em; + font-size: 0.7em; /* stylelint-disable-line */ } } @@ -2786,7 +2789,8 @@ input[name="subject"] { } } - .white-listed-students, .invalidation-history { + .white-listed-students, + .invalidation-history { margin-top: 10px; padding-top: 5px; @@ -2819,7 +2823,6 @@ input[name="subject"] { &.action { width: 150px; } - } td { @@ -2890,7 +2893,6 @@ input[name="subject"] { margin: 2px; border-top-style: none; } - } .arrow { diff --git a/lms/static/sass/course/layout/_courseware_header.scss b/lms/static/sass/course/layout/_courseware_header.scss index 2a28fa2f1574a6d33f23f5325142766972b36bac..5c04f2388d74ed11a715e6f7f3f1320663f33fc3 100644 --- a/lms/static/sass/course/layout/_courseware_header.scss +++ b/lms/static/sass/course/layout/_courseware_header.scss @@ -1,6 +1,7 @@ .wrapper-course-material { @include clearfix(); - @include box-sizing(border-box); + + box-sizing: border-box; @extend %ui-print-excluded; @@ -103,9 +104,7 @@ border: 1px solid transparent; border-color: theme-color("primary"); border-radius: 3px; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.6); color: theme-color("inverse"); display: inline-block; diff --git a/lms/static/sass/course/layout/_courseware_preview.scss b/lms/static/sass/course/layout/_courseware_preview.scss index f72b6c8b166fd056097bfebdc854812d26c9dff0..2c2626a8b61f428bb6cd39e14c5edab55937a5df 100644 --- a/lms/static/sass/course/layout/_courseware_preview.scss +++ b/lms/static/sass/course/layout/_courseware_preview.scss @@ -1,4 +1,5 @@ $proctoring-banner-text-size: 14px; + .wrapper-preview-menu { @include clearfix(); @@ -15,6 +16,10 @@ $proctoring-banner-text-size: 14px; @extend %inner-wrapper; width: auto; + + a.btn { + margin: 5px 0 5px 5px; + } } .preview-actions { @@ -192,6 +197,7 @@ $proctoring-banner-text-size: 14px; border-top-left-radius: 0; margin-right: 0; } + h3 { display: inline; font-size: $proctoring-banner-text-size; diff --git a/lms/static/sass/course/layout/_dates_banner.scss b/lms/static/sass/course/layout/_dates_banner.scss new file mode 100644 index 0000000000000000000000000000000000000000..813d87fb02e1494495afef8977d353ad597209f0 --- /dev/null +++ b/lms/static/sass/course/layout/_dates_banner.scss @@ -0,0 +1,53 @@ +.dates-banner { + border-radius: 4px; + border: solid 1px #9cd2e6; + background-color: #eff8fa; + margin-top: 20px; + margin-bottom: 20px; + padding: 24px; + display: flex; + flex-wrap: wrap; + justify-content: space-between; + max-width: $text-width-readability-max; + + .dates-banner-text { + font-size: 16px; + line-height: 24px; + color: #414141; + } + + &.has-button { + .dates-banner-text { + flex: 1 1 20em; + max-width: 70%; + } + } + + .upgrade-button { + align-self: start; + flex: none; + + a { + text-decoration: none; + } + + button { + display: block; + border-radius: 2px; + border: solid 1px #0175b4; + background: white; + color: #2d323e; + font-size: 14px; + font-weight: bold; + line-height: 24px; + padding: 7px 18px; + + &:hover, + &:focus, + &:active { + cursor: pointer; + box-shadow: 0 2px 1px $shadow; + } + } + } +} diff --git a/lms/static/sass/course/layout/_reset_deadlines.scss b/lms/static/sass/course/layout/_reset_deadlines.scss deleted file mode 100644 index 34b7b66978ff11f36014408be5767b270c136f3a..0000000000000000000000000000000000000000 --- a/lms/static/sass/course/layout/_reset_deadlines.scss +++ /dev/null @@ -1,23 +0,0 @@ -div.reset-deadlines-banner { - background-color: theme-color("primary"); - display: none; - flex-wrap: wrap; - padding: 15px 20px; - margin-top: 5px; - - div, - button { - flex: 0 1 auto; - - &.reset-deadlines-text { - color: theme-color("inverse"); - margin: 10px 10px 10px 0; - } - - &.reset-deadlines-button { - color: #0075b4; - background-color: theme-color("inverse"); - cursor: pointer; - } - } -} diff --git a/lms/static/sass/course/modules/_calculator.scss b/lms/static/sass/course/modules/_calculator.scss index 02af5e584adfb9ee0e1c88cbca9cb76353d3c2cc..000180afcc28a1398b7074161525bcf1446a3ac0 100644 --- a/lms/static/sass/course/modules/_calculator.scss +++ b/lms/static/sass/course/modules/_calculator.scss @@ -29,7 +29,8 @@ background: $black-t1; color: $white; - &:hover, &:focus { + &:hover, + &:focus { background: $gray-d1; } @@ -56,7 +57,8 @@ .calculator-input-help-table { margin: ($baseline/2) 0; - tr th, tr td { + tr th, + tr td { vertical-align: top; border: 1px solid $gray-l4; padding: ($baseline/2); @@ -66,8 +68,7 @@ form { @extend .clearfix; - @include box-sizing(border-box); - + box-sizing: border-box; padding: lh(); .calc-output-label { @@ -79,9 +80,7 @@ border: 1px solid $white; border-radius: 0; box-shadow: none; - - @include box-sizing(border-box); - + box-sizing: border-box; color: $black; float: left; font-size: 30px; @@ -93,7 +92,8 @@ -webkit-appearance: none; width: flex-grid(0.5) + flex-gutter(); - &:hover, &:focus { + &:hover, + &:focus { background: $blue-d2; color: $white; } @@ -109,9 +109,7 @@ background: $white; border: 1px solid $white; box-shadow: none; - - @include box-sizing(border-box); - + box-sizing: border-box; color: $black; float: left; font-size: 16px; @@ -120,7 +118,7 @@ padding: 10px; -webkit-appearance: none; width: flex-grid(4); - + &.has-result { border: 1px solid $green-d1; box-shadow: inset 0 0 ($baseline/3) $green-d1; @@ -144,9 +142,7 @@ direction: ltr; // Almost all of the real-world calculators are LTR border: none; box-shadow: none; - - @include box-sizing(border-box); - + box-sizing: border-box; font-size: 16px; padding: 10px; -webkit-appearance: none; @@ -215,14 +211,16 @@ font-weight: bold; } - p, p+p { + p, + p + p { margin: 0; } .calc-postfixes { margin: 10px auto; - td, th { + td, + th { padding: 2px 15px; } } diff --git a/lms/static/sass/course/modules/_student-notes.scss b/lms/static/sass/course/modules/_student-notes.scss index 12b1618cde2303f34f6a087157561fc0843216da..d54a1de7073f87a285c305aba31534d2531e72c0 100644 --- a/lms/static/sass/course/modules/_student-notes.scss +++ b/lms/static/sass/course/modules/_student-notes.scss @@ -37,7 +37,7 @@ // -------------------- $notes-annotator-background-light: rgb(251, 251, 251); // taken from annotatorJS base colors $notes-annotator-background-med: rgb(214, 214, 214); // taken from annotatorJS base colors -$notes-annotator-background-dark: rgba(122,122,122,0.6); // taken from annotatorJS base colors +$notes-annotator-background-dark: rgba(122, 122, 122, 0.6); // taken from annotatorJS base colors %notes-reset-background { background-image: none !important; @@ -219,7 +219,8 @@ $notes-annotator-background-dark: rgba(122,122,122,0.6); // taken from annotator font-family: $font-family-sans-serif !important; // actions - .annotator-save, .annotator-cancel { + .annotator-save, + .annotator-cancel { @extend %notes-reset-background; padding: ($baseline/4) ($baseline/2) !important; @@ -256,7 +257,8 @@ $notes-annotator-background-dark: rgba(122,122,122,0.6); // taken from annotator background: $notes-annotator-background-light !important; //matches annotator JS editing bubble triangle color // STATE: hover/focus - &:hover, &:focus { + &:hover, + &:focus { background: $notes-annotator-background-light; } } @@ -275,12 +277,14 @@ $notes-annotator-background-dark: rgba(122,122,122,0.6); // taken from annotator color: $link-color; // STATE: hover/focus - &:hover, &:focus { + &:hover, + &:focus { text-decoration: underline; } // STATE: disabled - &:disabled, &.is-disabled { + &:disabled, + &.is-disabled { @extend %ui-disabled; opacity: 0.5; @@ -294,7 +298,8 @@ $notes-annotator-background-dark: rgba(122,122,122,0.6); // taken from annotator color: $link-color; // STATE: hover/focus - &:hover, &:focus { + &:hover, + &:focus { text-decoration: underline; } } @@ -326,7 +331,9 @@ $notes-annotator-background-dark: rgba(122,122,122,0.6); // taken from annotator @include float(right); @include padding-left($baseline/4); - .annotator-edit, .annotator-delete, .annotator-close { + .annotator-edit, + .annotator-delete, + .annotator-close { position: relative; display: inline-block; vertical-align: middle; diff --git a/lms/static/sass/course/wiki/_create.scss b/lms/static/sass/course/wiki/_create.scss index 664ce93bb848ef30e22c8a10101b69eb0b644b8e..43a598dd0179d9e76fc808526da1606dfaecbb3b 100644 --- a/lms/static/sass/course/wiki/_create.scss +++ b/lms/static/sass/course/wiki/_create.scss @@ -16,15 +16,13 @@ form#wiki_revision { .CodeMirror { @extend textarea; - @include box-sizing(border-box); - + box-sizing: border-box; font-family: monospace; margin-bottom: $baseline; } textarea { - @include box-sizing(border-box); - + box-sizing: border-box; margin-bottom: $baseline; min-height: 450px; width: 100%; diff --git a/lms/static/sass/course/wiki/_sidebar.scss b/lms/static/sass/course/wiki/_sidebar.scss index c33eed53350474d8dc1d51a9011119fe01d30837..32952697a5f429ca80e5b9afd5c7a209b8f3449f 100644 --- a/lms/static/sass/course/wiki/_sidebar.scss +++ b/lms/static/sass/course/wiki/_sidebar.scss @@ -26,8 +26,7 @@ div#wiki_panel { } input[type="text"] { - @include box-sizing(border-box); - + box-sizing: border-box; display: block; width: 100%; margin-bottom: lh(0.5); diff --git a/lms/static/sass/course/wiki/_table.scss b/lms/static/sass/course/wiki/_table.scss index 26e83108f060807596e0b0dfd5ed4d8aeb6518f2..3c3bfcc7dac3351d09cc6a045780251e7ca8a998 100644 --- a/lms/static/sass/course/wiki/_table.scss +++ b/lms/static/sass/course/wiki/_table.scss @@ -23,7 +23,7 @@ table.wiki-history { } &#modified { - width:20%; + width: 20%; } } } diff --git a/lms/static/sass/course/wiki/_wiki.scss b/lms/static/sass/course/wiki/_wiki.scss index d0aa4e4a474fd3f93d3f5fe5904a55f3bafde5e0..b3023af1d7bbb22ccc16044526ea339e8d22d285 100644 --- a/lms/static/sass/course/wiki/_wiki.scss +++ b/lms/static/sass/course/wiki/_wiki.scss @@ -7,7 +7,7 @@ float: right; } - .form-search .input-prepend>label { + .form-search .input-prepend > label { display: inline-block; vertical-align: bottom; } @@ -23,11 +23,11 @@ } - /*----------------- + // ----------------- - Breadcrumbs + // Breadcrumbs - -----------------*/ + // ----------------- .breadcrumb { list-style: none; @@ -43,7 +43,6 @@ float: left; display: block; overflow: hidden; - height: 30px; line-height: 31px; max-width: 200px; height: 100%; @@ -69,11 +68,11 @@ - /*----------------- + // ----------------- - Global Functions + // Global Functions - -----------------*/ + // ----------------- .global-functions { display: block; @@ -89,7 +88,8 @@ font-size: 0.72em; font-weight: 600; - &:hover, &:focus { + &:hover, + &:focus { text-decoration: none; } } @@ -122,11 +122,11 @@ - /*----------------- + // ----------------- - Article + // Article - -----------------*/ + // ----------------- h1 { font-weight: bold; @@ -150,8 +150,7 @@ width: flex-grid(9); padding: 40px 0 40px 40px; color: $body-color; - - @include box-sizing(border-box); + box-sizing: border-box; } &.view .main-article { @@ -228,18 +227,17 @@ - /*----------------- + // ----------------- - Sidebar + // Sidebar - -----------------*/ + // ----------------- .article-functions { float: left; width: flex-grid(3); padding: 40px; - - @include box-sizing(border-box); + box-sizing: border-box; .timestamp { margin-top: ($baseline*0.75); @@ -254,7 +252,6 @@ .date { font-size: 0.9em; } - } .see-children { @@ -269,7 +266,8 @@ font-size: 0.9em; line-height: 25px; - &:hover, &:focus { + &:hover, + &:focus { color: $uxpl-blue-hover-active; font-weight: bold; } @@ -289,7 +287,7 @@ font-weight: bold; background-color: $light-gray1; border-color: $uxpl-blue-hover-active; - border-left: 4px solid + border-left: 4px solid; } } } @@ -311,7 +309,8 @@ padding-right: ($baseline/4); } - &:hover, &:focus { + &:hover, + &:focus { color: $uxpl-blue-hover-active; font-weight: bold; } @@ -321,11 +320,11 @@ - /*----------------- + // ----------------- - Edit + // Edit - -----------------*/ + // ----------------- label { font-family: $font-family-sans-serif; @@ -362,7 +361,7 @@ top: 10px; right: 0%; font-size: 12px; - text-align:right; + text-align: right; } .CodeMirror { @@ -428,7 +427,8 @@ text-transform: none !important; letter-spacing: 0 !important; - &:hover, &:focus { + &:hover, + &:focus { color: $body-color; text-decoration: none; } @@ -507,7 +507,8 @@ padding: ($baseline/2) ($baseline/2) 0 ($baseline/2); margin-bottom: ($baseline/2); - h1, p { + h1, + p { color: $body-color; } @@ -601,11 +602,11 @@ font-size: 12px; } - /*----------------- + // ----------------- - Changes + // Changes - -----------------*/ + // ----------------- &.history { .accordion { @@ -615,7 +616,8 @@ background: #f9f9f9; border-radius: 5px; - a:hover, a:focus { + a:hover, + a:focus { text-decoration: none; } } @@ -663,11 +665,11 @@ - /*----------------- + // ----------------- - Settings + // Settings - -----------------*/ + // ----------------- #settings_form { .well { @@ -699,11 +701,11 @@ - /*----------------- + // ----------------- - New + // New - -----------------*/ + // ----------------- .new-article { margin: auto; @@ -744,11 +746,11 @@ - /*----------------- + // ----------------- - Directory + // Directory - -----------------*/ + // ----------------- .directory-toolbar { background-color: $sidebar-color; padding: 9px; @@ -779,7 +781,8 @@ width: 100%; margin-top: $baseline; - th, td { + th, + td { border-bottom: 1px solid $light-gray; padding: 8px; overflow: hidden; @@ -790,7 +793,8 @@ } a { - &:hover, &:focus { + &:hover, + &:focus { font-weight: bold; } } @@ -803,11 +807,11 @@ - /*----------------- + // ----------------- - Attachments + // Attachments - -----------------*/ + // ----------------- .attachment-options { height: 40px; @@ -873,11 +877,11 @@ - /*----------------- + // ----------------- - Delete + // Delete - -----------------*/ + // ----------------- #div_id_confirm { position: relative; @@ -904,11 +908,11 @@ - /*----------------- + // ----------------- - Alerts + // Alerts - -----------------*/ + // ----------------- .alert { position: relative; @@ -964,7 +968,8 @@ text-align: center; -webkit-font-smoothing: antialiased; - &:hover, &:focus { + &:hover, + &:focus { background: darken($pink, 12%); } } diff --git a/lms/static/sass/discussion/_discussion-v1.scss b/lms/static/sass/discussion/_discussion-v1.scss index 6f19dae68c4bd227ea5e86f14498376f7fbc0d1f..0a6a26d6c181fe0ae268775296f11e47c33aa198 100644 --- a/lms/static/sass/discussion/_discussion-v1.scss +++ b/lms/static/sass/discussion/_discussion-v1.scss @@ -8,8 +8,8 @@ color 0.125s ease-in-out 0s, border-color 0.125s ease-in-out 0s, background 0.125s ease-in-out 0s, - box-shadow 0.125s ease-in-out 0s - ); + box-shadow 0.125s ease-in-out 0s + ); display: inline-block; border: 1px solid $forum-color-active-thread; @@ -54,7 +54,8 @@ } // Use pattern library buttons for discussion components -.discussion-module, .wmd-prompt-dialog { +.discussion-module, +.wmd-prompt-dialog { .btn { @extend %pattern-library-btn; diff --git a/lms/static/sass/discussion/_mixins.scss b/lms/static/sass/discussion/_mixins.scss index 26e938ca42692c996a9a815bc0f5a63eddf700f2..abe967621b06a6595d09ede813d9bc0c761e776f 100644 --- a/lms/static/sass/discussion/_mixins.scss +++ b/lms/static/sass/discussion/_mixins.scss @@ -22,7 +22,8 @@ background-color: $white; color: theme-color("gray-dark"); - &:hover, &:focus { + &:hover, + &:focus { background-color: $white; } } @@ -71,7 +72,8 @@ width: auto; background-color: $forum-color-background-light; - ol, ul { // Fix up the RTL-only _reset.scss, but only in specific places + ol, + ul { // Fix up the RTL-only _reset.scss, but only in specific places @include padding-left($baseline*2); @include padding-right(0); } diff --git a/lms/static/sass/discussion/elements/_actions.scss b/lms/static/sass/discussion/elements/_actions.scss index fd62c13195be6660cc62ae792166590e49736033..91b6ee7ec2b9b95a600f429f9c0214ebcdedf811 100644 --- a/lms/static/sass/discussion/elements/_actions.scss +++ b/lms/static/sass/discussion/elements/_actions.scss @@ -155,7 +155,8 @@ padding: 2px 8px; } - &:hover, &:focus { + &:hover, + &:focus { .action-label { display: inline-block; } @@ -171,7 +172,9 @@ color: theme-color("primary"); } - &.is-checked, &:hover, &:focus { + &.is-checked, + &:hover, + &:focus { .action-icon { background-color: $forum-color-following; border: 1px solid theme-color("primary"); @@ -179,7 +182,8 @@ } } - &:hover, &:focus { + &:hover, + &:focus { border-color: $forum-color-following; } } @@ -189,7 +193,9 @@ opacity: 1; } - &.is-checked, &:hover, &:focus { + &.is-checked, + &:hover, + &:focus { .action-icon { background-color: $green; border: 1px solid $green; @@ -197,7 +203,8 @@ } } - &:hover, &:focus { + &:hover, + &:focus { border-color: $green; .action-label { @@ -207,7 +214,9 @@ } &.action-endorse { - &.is-checked, &:hover, &:focus { + &.is-checked, + &:hover, + &:focus { .action-icon { background-color: theme-color("primary"); border: 1px solid theme-color("primary"); @@ -215,7 +224,8 @@ } } - &:hover, &:focus { + &:hover, + &:focus { border-color: theme-color("primary"); background-color: $forum-color-background; @@ -226,7 +236,9 @@ } &.action-answer { - &.is-checked, &:hover, &:focus { + &.is-checked, + &:hover, + &:focus { .action-icon { border: 1px solid $green; background-color: $green; @@ -234,7 +246,8 @@ } } - &:hover, &:focus { + &:hover, + &:focus { border-color: $green; background-color: $forum-color-background; @@ -248,7 +261,8 @@ &.action-more { position: relative; - &:hover, &:focus { + &:hover, + &:focus { border-color: theme-color("dark"); background-color: $forum-color-background; @@ -282,7 +296,8 @@ white-space: nowrap; color: theme-color("secondary"); - &:hover, &:focus { + &:hover, + &:focus { color: $link-color; } @@ -312,14 +327,16 @@ } // CASE: hover for any action - &:hover, &:focus { + &:hover, + &:focus { color: $link-color; } } } } - .action-button, .action-list-item { + .action-button, + .action-list-item { .action-label { @include float(left); @@ -339,9 +356,10 @@ } } - .btn-primary, .btn-outline-primary{ - &:focus{ - box-shadow: 0 0 0 2px rgb(0,120,180); + .btn-primary, + .btn-outline-primary { + &:focus { + box-shadow: 0 0 0 2px rgb(0, 120, 180); } } } diff --git a/lms/static/sass/discussion/elements/_editor.scss b/lms/static/sass/discussion/elements/_editor.scss index a907d3b94f17a6ef3992b1f137978c006f58d0dd..750b0ad9a2b4e8246e67ca0ad73bb7c8c62d936c 100644 --- a/lms/static/sass/discussion/elements/_editor.scss +++ b/lms/static/sass/discussion/elements/_editor.scss @@ -41,7 +41,7 @@ background: none; } -.wmd-button-bar { +.wmd-button-bar { width: 100%; } diff --git a/lms/static/sass/discussion/elements/_labels.scss b/lms/static/sass/discussion/elements/_labels.scss index 38bffa2ac0049ee387d102a4de56682e18662da7..2609889c2a6c0a02727cf69943a700bb17e28935 100644 --- a/lms/static/sass/discussion/elements/_labels.scss +++ b/lms/static/sass/discussion/elements/_labels.scss @@ -50,7 +50,6 @@ font-size: $forum-small-font-size; white-space: nowrap; } - } // Make post labels tighter when shown inside the left nav diff --git a/lms/static/sass/discussion/elements/_navigation.scss b/lms/static/sass/discussion/elements/_navigation.scss index f440915d36cb57aecc14cb7cae6d3125a9c73e11..ad5daead77e0d7238b273c2daa3f7e47b5941fe5 100644 --- a/lms/static/sass/discussion/elements/_navigation.scss +++ b/lms/static/sass/discussion/elements/_navigation.scss @@ -79,7 +79,7 @@ // need to override button styles background-image: none !important; box-shadow: none !important; - background: $forum-color-background !important; + background: $forum-color-background !important; /* stylelint-disable-line */ } } @@ -132,7 +132,8 @@ width: 50%; } -.forum-nav-filter-cohort, .forum-nav-sort { +.forum-nav-filter-cohort, +.forum-nav-sort { @include text-align(right); box-sizing: border-box; diff --git a/lms/static/sass/discussion/lms-discussion-main-rtl.scss b/lms/static/sass/discussion/lms-discussion-main-rtl.scss deleted file mode 100644 index c1585c0a7bc0d5a54fcfb71f6d7bcf187969be68..0000000000000000000000000000000000000000 --- a/lms/static/sass/discussion/lms-discussion-main-rtl.scss +++ /dev/null @@ -1,16 +0,0 @@ -// ------------------------------ -// LMS discussion main styling -// -// NOTE: This is the right-to-left (RTL) configured style compile. -// It should mirror lms-discussion-main w/ the exception of bi-app references. - -// Load the RTL version of the edX Pattern Library -$pattern-library-path: '../../edx-pattern-library' !default; - -@import 'edx-pattern-library/pattern-library/sass/edx-pattern-library-rtl'; - -// Configure RTL variables -@import 'base/variables-rtl'; - -// Load the shared build -@import 'build'; diff --git a/lms/static/sass/discussion/lms-discussion-main.scss b/lms/static/sass/discussion/lms-discussion-main.scss deleted file mode 100644 index 32b16a7b7fbab44c17a29df8db49392b094452a8..0000000000000000000000000000000000000000 --- a/lms/static/sass/discussion/lms-discussion-main.scss +++ /dev/null @@ -1,16 +0,0 @@ -// ------------------------------ -// LMS discussion main styling -// -// NOTE: This is the left-to-right (LTR) configured style compile. -// It should mirror lms-discussion-main-rtl w/ the exception of bi-app references. - -// Load the LTR version of the edX Pattern Library -$pattern-library-path: '../../edx-pattern-library' !default; - -@import 'edx-pattern-library/pattern-library/sass/edx-pattern-library-ltr'; - -// Configure LTR variables -@import 'base/variables-ltr'; - -// Load the shared build -@import 'build'; diff --git a/lms/static/sass/discussion/utilities/_developer.scss b/lms/static/sass/discussion/utilities/_developer.scss index ab27d508838ae1ac144ccf5a84e20e7eb9a790a8..9a5b2270af23a52df42baab7dc09b63c84fcb13c 100644 --- a/lms/static/sass/discussion/utilities/_developer.scss +++ b/lms/static/sass/discussion/utilities/_developer.scss @@ -19,12 +19,6 @@ // -------------------- .forum-nav { - - // wrapper for multiple alerts - .search-alerts { - - } - // a single alert, which can be independently displayed / dismissed .search-alert { @include transition(none); @@ -33,7 +27,8 @@ background-color: $black; } - .search-alert-content, .search-alert-controls { + .search-alert-content, + .search-alert-controls { display: inline-block; vertical-align: middle; } @@ -78,7 +73,8 @@ font-size: $forum-base-font-size; // reseting poorly globally scoped hover/focus state for this control - &:hover, &:focus { + &:hover, + &:focus { color: $white; text-decoration: none; } diff --git a/lms/static/sass/discussion/utilities/_shame.scss b/lms/static/sass/discussion/utilities/_shame.scss index 9bba9b0edf2b579f03c39d88ea29687b815b8ce5..b1cdb031f9b7b981c4e409aee7a59551def343e6 100644 --- a/lms/static/sass/discussion/utilities/_shame.scss +++ b/lms/static/sass/discussion/utilities/_shame.scss @@ -43,14 +43,18 @@ // -------------------------------- // Override global label rules -.forum-nav-filter-main, .forum-nav-filter-cohort, .forum-nav-sort { +.forum-nav-filter-main, +.forum-nav-filter-cohort, +.forum-nav-sort { font: inherit; line-height: 1em; margin-bottom: 0; } // Override global select rules -.forum-nav-filter-main-control, .forum-nav-filter-cohort-control, .forum-nav-sort-control { +.forum-nav-filter-main-control, +.forum-nav-filter-cohort-control, +.forum-nav-sort-control { font: inherit; } @@ -68,7 +72,8 @@ li[class*=forum-nav-thread-label-] { } // Override clearfix stuff in .sidebar ul li rules - &::before, &::after { + &::before, + &::after { display: none !important; } } @@ -80,12 +85,15 @@ li[class*=forum-nav-thread-label-] { .discussion { // Override courseware - .post-actions-list, .response-actions-list, .comment-actions-list { + .post-actions-list, + .response-actions-list, + .comment-actions-list { @extend %t-copy-sub2; } // Override global span - .action-label span, .action-icon span { + .action-label span, + .action-icon span { color: inherit; } } diff --git a/lms/static/sass/discussion/utilities/_v1-compatibility.scss b/lms/static/sass/discussion/utilities/_v1-compatibility.scss index 787a4fcd448e7b021af20c90269acf5c2c524f7f..982a8ff3a3797ad95977b858bac4a4b12f6dc7b9 100644 --- a/lms/static/sass/discussion/utilities/_v1-compatibility.scss +++ b/lms/static/sass/discussion/utilities/_v1-compatibility.scss @@ -84,7 +84,9 @@ padding: 0; text-indent: 0; - li, dt, dd { + li, + dt, + dd { margin: 0; padding: 0; } diff --git a/lms/static/sass/discussion/views/_create-edit-post.scss b/lms/static/sass/discussion/views/_create-edit-post.scss index d73edb0d3d9fe741c529660bb6171a4e7c118b1c..5813cbd8758f51cdf457452fe430c33fdec3fd81 100644 --- a/lms/static/sass/discussion/views/_create-edit-post.scss +++ b/lms/static/sass/discussion/views/_create-edit-post.scss @@ -118,7 +118,8 @@ margin-top: ($baseline/2); - &:hover, &:focus { + &:hover, + &:focus { border-color: #222; } } diff --git a/lms/static/sass/discussion/views/_home.scss b/lms/static/sass/discussion/views/_home.scss index 72f16a6def9cc6f4439bdffd2a3795b012af7212..6df353907fffebcbda4f847537575b0fe8fdac9b 100644 --- a/lms/static/sass/discussion/views/_home.scss +++ b/lms/static/sass/discussion/views/_home.scss @@ -100,7 +100,8 @@ font-size: $forum-small-font-size; } - .row-item-full, .row-item { + .row-item-full, + .row-item { font-size: $forum-small-font-size; padding: 0 ($baseline/2); width: 26%; @@ -155,25 +156,46 @@ .row-description { display: inline-block; - width:80%; + width: 80%; } } } .helpgrid-row-navigation { - .fa-bars {color: theme-color("light");} - .fa-search {color: $gray-300;} - .fa-sort {color: $gray-300;} + .fa-bars { + color: theme-color("light"); + } + + .fa-search { + color: $gray-300; + } + + .fa-sort { + color: $gray-300; + } } .helpgrid-row-participation { - .fa-plus {color: $green;} - .fa-flag {color: $pink;} - .fa-star {color: $blue;} + .fa-plus { + color: $green; + } + + .fa-flag { + color: $pink; + } + + .fa-star { + color: $blue; + } } .helpgrid-row-notification { - .fa-square {color: $green;} - .fa-envelope {color: $gray-300;} + .fa-square { + color: $green; + } + + .fa-envelope { + color: $gray-300; + } } } diff --git a/lms/static/sass/discussion/views/_inline.scss b/lms/static/sass/discussion/views/_inline.scss index 0b92f3dea614cafc2c29c28000c6e78c0f0fe37e..44bd787c2c9bbf6848ba9f82764b37eef8e480d2 100644 --- a/lms/static/sass/discussion/views/_inline.scss +++ b/lms/static/sass/discussion/views/_inline.scss @@ -53,5 +53,4 @@ } } } - } diff --git a/lms/static/sass/discussion/views/_response.scss b/lms/static/sass/discussion/views/_response.scss index 05ac6d415321a5a2eceacfa9813af1bcdb8cbc5a..5cd9bfd56f379ede66b07109e2aedbe1f6be7a82 100644 --- a/lms/static/sass/discussion/views/_response.scss +++ b/lms/static/sass/discussion/views/_response.scss @@ -37,7 +37,7 @@ padding: $baseline; background-color: $forum-color-background; } - + .posted-by { @extend %t-ultrastrong; } @@ -47,7 +47,7 @@ .discussion-response { .response-header-content { - // CASE: larger username for responses + // CASE: larger username for responses .username { @extend %t-weight5; @@ -56,7 +56,8 @@ } // rtl resets for response list elements - .response-body ol, .response-body ul { // Fix up the RTL-only _reset.scss, but only in specific places + .response-body ol, + .response-body ul { // Fix up the RTL-only _reset.scss, but only in specific places @include padding-left($baseline*2); @include padding-right(0); } @@ -80,7 +81,7 @@ } // +response - labels and banners -// NOTE - these styles seem to no longer be in use. They have been isolated here, but should be ideally removed or fixed. +// NOTE - these styles seem to no longer be in use. They have been isolated here, but should be ideally removed or fixed. .discussion .responses .forum-response { // CASE: label - staff response diff --git a/lms/static/sass/discussion/views/_search.scss b/lms/static/sass/discussion/views/_search.scss index 65660bc34d3928a937ac9693614cc7650ee4e59a..aa836067237a8c5d6a5aabfd047086240d02c375 100644 --- a/lms/static/sass/discussion/views/_search.scss +++ b/lms/static/sass/discussion/views/_search.scss @@ -21,10 +21,9 @@ position: absolute; display: block; color: #495057; - transition: all .1s ease-in-out; + transition: all 0.1s ease-in-out; padding-left: 10px; padding-top: 10px; - } input::placeholder { @@ -33,10 +32,9 @@ input:not(:placeholder-shown) { & ~ label { - padding-top: .15rem; + padding-top: 0.15rem; font-size: 10px; } - } } diff --git a/lms/static/sass/discussion/views/_thread.scss b/lms/static/sass/discussion/views/_thread.scss index c4d07547583619ff545b9ff65451ce84c7b4b988..baa81109474a722e421a45dd96e78deb6e199053 100644 --- a/lms/static/sass/discussion/views/_thread.scss +++ b/lms/static/sass/discussion/views/_thread.scss @@ -33,7 +33,8 @@ display: inline; } - .timeago, .top-post-status { + .timeago, + .top-post-status { color: inherit; } } @@ -59,7 +60,7 @@ .response-header-content { display: inline-block; vertical-align: top; - width: flex-grid(11,12); + width: flex-grid(11, 12); } .response-header-actions { @@ -80,6 +81,7 @@ .discussion-comment { .response-body { @extend %t-copy-sub2; + @include padding(($baseline / 2), ($baseline * 1.5), 0, 0); display: inline-block; @@ -108,7 +110,9 @@ } // +thread - elements - shared styles -.discussion-post, .discussion-response, .discussion-comment { +.discussion-post, +.discussion-response, +.discussion-comment { @include clearfix(); // thread - images diff --git a/lms/static/sass/elements/_banners.scss b/lms/static/sass/elements/_banners.scss index 52b59592b0a2e146d5490dcbd478d492e412ca5c..90147ec1c95022d3ee0d77885b59ee2a5991614a 100644 --- a/lms/static/sass/elements/_banners.scss +++ b/lms/static/sass/elements/_banners.scss @@ -59,18 +59,17 @@ $full-width-banner-margin: 20px; text-decoration: underline !important; } - .user-messages-ul { - list-style: none; - padding: 0; - margin: 0; + .user-messages-ul { + list-style: none; + padding: 0; + margin: 0; - li { - margin: 5px 0; + li { + margin: 5px 0; + } } } - } - .alert { display: flex; padding: $baseline; diff --git a/lms/static/sass/elements/_controls.scss b/lms/static/sass/elements/_controls.scss index 4d1e4d9d9c7a262a9208054822395432f5bb9a6c..8f89339805b3a1d70527414c232015f4fc357c6d 100644 --- a/lms/static/sass/elements/_controls.scss +++ b/lms/static/sass/elements/_controls.scss @@ -2,7 +2,8 @@ // ==================== %btn { - @include box-sizing(border-box); + box-sizing: border-box; + @include transition(color $tmg-f2 ease-in-out, background $tmg-f2 ease-in-out, box-shadow $tmg-f2 ease-in-out); display: inline-block; @@ -266,7 +267,6 @@ color: $white-t3; pointer-events: none; cursor: default; - pointer-events: none; box-shadow: none; &:hover, @@ -337,7 +337,7 @@ // imitating the pattern library // starts with overrides %btn-pl-default-base { - @include box-sizing(border-box); + box-sizing: border-box; @extend %t-copy-base; @@ -364,7 +364,7 @@ %btn-pl-primary-base { @extend %btn-pl-default-base; - background-color: darken($action-primary-bg,10%); + background-color: darken($action-primary-bg, 10%); color: $action-primary-fg; } diff --git a/lms/static/sass/elements/_creative-commons.scss b/lms/static/sass/elements/_creative-commons.scss index 0acb91cdda9c40e4824704b5c4ea77e675d920d6..2fde86fb9b4ddfb121b782897398ec871ea54a3f 100644 --- a/lms/static/sass/elements/_creative-commons.scss +++ b/lms/static/sass/elements/_creative-commons.scss @@ -1,7 +1,8 @@ @font-face { font-family: 'CreativeCommons'; src: url('#{$static-path}/fonts/CreativeCommons/cc.eot'); - src: url('#{$static-path}/fonts/CreativeCommons/cc.eot#iefix') format('embedded-opentype'), + src: + url('#{$static-path}/fonts/CreativeCommons/cc.eot#iefix') format('embedded-opentype'), url('#{$static-path}/fonts/CreativeCommons/cc.woff') format('woff'), url('#{$static-path}/fonts/CreativeCommons/cc.ttf') format('truetype'), url('#{$static-path}/fonts/CreativeCommons/cc.svg#CreativeCommons') format('svg'); @@ -9,7 +10,8 @@ font-style: normal; } -[class^="icon-cc"]::before, [class*=" icon-cc"]::before { +[class^="icon-cc"]::before, +[class*=" icon-cc"]::before { font-family: "CreativeCommons"; } diff --git a/lms/static/sass/elements/_navigation.scss b/lms/static/sass/elements/_navigation.scss index 86e17636b1cfd60463ed0a523e55f60517f79dcc..0bf6d9a223248ba7fd5e9c066b8acf296777c7cc 100644 --- a/lms/static/sass/elements/_navigation.scss +++ b/lms/static/sass/elements/_navigation.scss @@ -21,7 +21,9 @@ @extend %text-sr; } -.nav-contents, .nav-skip, .transcript-skip { +.nav-contents, +.nav-skip, +.transcript-skip { @extend %nav-skip; } @@ -55,7 +57,8 @@ color: $white; // STATE: hover/active - &:hover, &:active { + &:hover, + &:active { background: $gray-d1; } @@ -76,7 +79,9 @@ border-radius: 0; // STATE: hover/active - &:hover, &:active, &:focus { + &:hover, + &:active, + &:focus { border: none; box-shadow: none; } @@ -161,12 +166,6 @@ // +tabs - styles for tabs and tabpanels (teams and learner profile, currently) // -------------------- -.page-content-nav { - .tab { - - } -} - .page-content-main { .tabs { .tabpanel { diff --git a/lms/static/sass/elements/_program-card.scss b/lms/static/sass/elements/_program-card.scss index c3fa9b806bf79a3863866407489cebf02d1423aa..4aeb539494a05b814e92e8fc2ec105c7ae054bac 100644 --- a/lms/static/sass/elements/_program-card.scss +++ b/lms/static/sass/elements/_program-card.scss @@ -168,8 +168,6 @@ } .progress-container { - max-width: inherit; - .progress-bar { height: 5px; display: flex; @@ -198,5 +196,4 @@ } } } - } diff --git a/lms/static/sass/elements/_progress-circle.scss b/lms/static/sass/elements/_progress-circle.scss index ff4fa8327d1916a70fdd10b25a5bfcc0e09704de..52b905e429d2e3b3b7ddebf44405ca84f6b9b9bb 100644 --- a/lms/static/sass/elements/_progress-circle.scss +++ b/lms/static/sass/elements/_progress-circle.scss @@ -45,7 +45,7 @@ $progress-number-label-color: palette(grayscale, base) !default; color: $progress-complete-number-color; } } - + .label { font: { size: 1.1em; diff --git a/lms/static/sass/elements/_system-feedback.scss b/lms/static/sass/elements/_system-feedback.scss index 71e035c4f61a36b95c5ae61a7cb9ad63a3bd4519..27602c9460cd747fcb72bdfe4b6502ff66ad3aa6 100644 --- a/lms/static/sass/elements/_system-feedback.scss +++ b/lms/static/sass/elements/_system-feedback.scss @@ -52,12 +52,12 @@ .has-actions { .msg-content { - width: flex-grid(10,12); + width: flex-grid(10, 12); } .nav-actions, .msg-actions { - width: flex-grid(2,12); + width: flex-grid(2, 12); display: inline-block; vertical-align: middle; text-align: right; @@ -70,11 +70,11 @@ .is-dismissable { .msg-content { - width: flex-grid(11,12); + width: flex-grid(11, 12); } .action-dismiss { - width: flex-grid(1,12); + width: flex-grid(1, 12); display: inline-block; vertical-align: top; text-align: right; @@ -88,7 +88,8 @@ text-shadow: none; color: inherit; - &:hover, &:focus { + &:hover, + &:focus { color: $action-primary-bg; } } @@ -115,16 +116,18 @@ &.recovery-email-alert { &#banner-msg { - background: $state-info-bg ; + background: $state-info-bg; box-shadow: none; border-top: 1px solid #579cc5; padding: 20px 20px 20px 40px; - margin: -16px 0 5px 0 + margin: -16px 0 10px 0; } + .fa-close { position: relative; float: right; } + .fa-close:hover { cursor: pointer; } @@ -133,6 +136,7 @@ &.urgency-low { background: $notify-banner-bg-3; box-shadow: 0 1px 2px $shadow; + .msg { color: $black; } @@ -203,7 +207,8 @@ .message-status { @include border-top-radius(2px); - @include box-sizing(border-box); + + box-sizing: border-box; @extend %t-strong; @@ -240,15 +245,19 @@ // ==================== // shared -.wrapper-notification, .wrapper-alert, .prompt { - @include box-sizing(border-box); +.wrapper-notification, +.wrapper-alert, +.prompt { + box-sizing: border-box; .copy { @extend %t-copy-sub1; } } -.wrapper-notification, .wrapper-alert, .prompt { +.wrapper-notification, +.wrapper-alert, +.prompt { background: $gray-d3; .copy { @@ -266,7 +275,9 @@ } } -.alert, .notification, .prompt { +.alert, +.notification, +.prompt { // types - confirm &.confirm { @@ -534,14 +545,16 @@ padding: ($baseline/2) $baseline; .notification { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); width: 100%; max-width: none; min-width: none; - .feedback-symbol, .copy { + .feedback-symbol, + .copy { float: none; display: inline-block; vertical-align: middle; @@ -553,10 +566,6 @@ margin-right: ($baseline/4); line-height: 3rem; } - - .copy { - - } } } @@ -571,7 +580,8 @@ padding: $baseline; .notification { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); width: 100%; @@ -595,7 +605,8 @@ } .notification { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); margin: 0 auto; @@ -606,7 +617,8 @@ @extend %t-strong; } - .feedback-symbol, .copy { + .feedback-symbol, + .copy { float: left; display: inline-block; vertical-align: middle; @@ -724,8 +736,7 @@ .wrapper-alert { @extend %ui-depth2; - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 1px $white, inset 0 2px 2px $shadow-d1, inset 0 -4px 1px $blue; position: relative; overflow: hidden; @@ -785,7 +796,8 @@ // adopted alerts .alert:not(.pattern-library-shim) { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); margin: 0 auto; @@ -797,7 +809,8 @@ @extend %t-strong; } - .feedback-symbol, .copy { + .feedback-symbol, + .copy { float: left; } @@ -905,10 +918,11 @@ // Making this optional wouldn't cause any issue for confirmation dialog at-least. @extend %btn-secondary-white !optional; - padding:($baseline/4) ($baseline/2); + padding: ($baseline/4) ($baseline/2); } - .icon,.button-copy { + .icon, + .button-copy { display: inline-block; vertical-align: middle; } @@ -934,10 +948,6 @@ .wrapper-prompt { visibility: hidden; pointer-events: none; - - .prompt { - - } } // prompt showing @@ -961,9 +971,6 @@ } } - // alert showing/hiding done by jQuery - .wrapper-alert { } - // notification showing/hiding .wrapper-notification { bottom: -($ui-notification-height); @@ -1050,9 +1057,9 @@ // temporary body.uxdesign.alerts { - .content-primary, .content-supplementary { - @include box-sizing(border-box); - + .content-primary, + .content-supplementary { + box-sizing: border-box; float: left; } @@ -1111,9 +1118,8 @@ body.uxdesign.alerts { margin-bottom: ($baseline*1.5); border-radius: 3px; border: 1px solid #edbd3c; - border-radius: 3px; background: #fbf6e1; - // background: #edbd3c; + @include clearfix(); .alert-message { diff --git a/lms/static/sass/features/_bookmarks-v1.scss b/lms/static/sass/features/_bookmarks-v1.scss index d6d206bc532fb9e802722191ce974606d2a2d383..525f8414dc526fc44d846d8208c27c2a4ced72a2 100644 --- a/lms/static/sass/features/_bookmarks-v1.scss +++ b/lms/static/sass/features/_bookmarks-v1.scss @@ -7,8 +7,7 @@ $bookmarked-icon: "\f02e"; // .fa-bookmark padding: ($baseline/4); > div { - @include box-sizing(border-box); - + box-sizing: border-box; display: inline-block; } } diff --git a/lms/static/sass/features/_content-type-gating.scss b/lms/static/sass/features/_content-type-gating.scss index 5ac07efd43f92c006d87f644cca1a974ec567128..33ed1c9b98c903c3f3b5c9d1d8744727c8259856 100644 --- a/lms/static/sass/features/_content-type-gating.scss +++ b/lms/static/sass/features/_content-type-gating.scss @@ -1,42 +1,41 @@ .content-paywall { - margin-top: 10px; - border-radius: 5px 5px 5px 5px; - display: flex; - justify-content: space-between; - border: lightgrey 1px solid; - padding: 15px 20px; + margin-top: 10px; + border-radius: 5px; + display: flex; + justify-content: space-between; + border: lightgrey 1px solid; + padding: 15px 20px; - h3 { - font-weight: 600; - margin-bottom: 10px; - } + h3 { + font-weight: 600; + margin-bottom: 10px; + } - .fa-lock { - color: black; - margin-right: 10px; - font-size: 24px; - margin-left: 5px; - } + .fa-lock { + color: black; + margin-right: 10px; + font-size: 24px; + margin-left: 5px; + } - .certDIV_1 { - color: rgb(25, 125, 29); - height: 20px; - width: 300px; - font: normal normal 600 normal 14px / 20px 'Helvetica Neue', Helvetica, Arial, sans-serif; - } + .certDIV_1 { + color: rgb(25, 125, 29); + height: 20px; + width: 300px; + font: normal normal 600 normal 14px / 20px 'Helvetica Neue', Helvetica, Arial, sans-serif; + } - .certA_1 { - text-decoration: underline !important; - color: rgb(0, 117, 180); - font: normal normal 400 normal 16px / 25.6px 'Open Sans'; - } + .certA_1 { + text-decoration: underline !important; + color: rgb(0, 117, 180); + font: normal normal 400 normal 16px / 25.6px 'Open Sans'; + } - .certSPAN_1 { - padding: 10px 0; - } - - img { - height: 60px; - } + .certSPAN_1 { + padding: 10px 0; + } + img { + height: 60px; + } } diff --git a/lms/static/sass/features/_course-duration-limits.scss b/lms/static/sass/features/_course-duration-limits.scss index c199eb5a7069555a7eb5c573d404608fc033017f..503f96cf78ecbaa0ed2ced0ccee8beff12e57b22 100644 --- a/lms/static/sass/features/_course-duration-limits.scss +++ b/lms/static/sass/features/_course-duration-limits.scss @@ -3,37 +3,39 @@ body.view-in-mfe { display: none; } } + .course-expiration-message { - background-color: #D8EDF8; - color: #393f43; - font-size: 16px; - border: 1px solid #BBDFF2; - border-radius: 4px; - box-sizing: border-box; - line-height: 1.5; - margin: $baseline auto; - padding: 20px; + background-color: #d8edf8; + color: #393f43; + font-size: 16px; + border: 1px solid #bbdff2; + border-radius: 4px; + box-sizing: border-box; + line-height: 1.5; + margin: $baseline auto; + padding: 20px; - a:not(.btn) { - font-weight: bold; - text-decoration: underline; - color: #006ea9; + a:not(.btn) { + font-weight: bold; + text-decoration: underline; + color: #006ea9; - &:hover{ - color: darken(#006ea9, 15%); - text-decoration: underline; - } + &:hover { + color: darken(#006ea9, 15%); + text-decoration: underline; } + } - & + .page-content { - margin-top: 0; - padding-top: 0; - } + & + .page-content { + margin-top: 0; + padding-top: 0; + } } -.course-content .course-expiration-message{ - max-width: $text-width-readability-max; + +.course-content .course-expiration-message { + max-width: $text-width-readability-max; } -#discussion-container .course-expiration-message { - margin: $baseline 40px; +#discussion-container .course-expiration-message { + margin: $baseline 40px; } diff --git a/lms/static/sass/features/_course-experience.scss b/lms/static/sass/features/_course-experience.scss index 620441245e33353000ea4b386dd75a89f21c34d0..3179044a42cd621db62c5c72d5cbd0c01ac374bc 100644 --- a/lms/static/sass/features/_course-experience.scss +++ b/lms/static/sass/features/_course-experience.scss @@ -181,9 +181,9 @@ h1, h2, h3 { - font-size: font-size(large); font-weight: $font-bold; color: $black; + margin-bottom: $baseline; } img { @@ -197,8 +197,9 @@ @include float(right); .btn-link { - color: palette(grayscale, base); + color: $gray-800; border-color: transparent; + cursor: pointer; } } @@ -388,7 +389,6 @@ margin: 0 0 0 35px; .subsection-title { - display: inline-block; margin: 0; font-weight: $font-regular; display: inline; @@ -409,6 +409,16 @@ } } } + + .fa-chevron-right { + transform: rotateY(0deg) #{"/*rtl: rotateY(180deg)*/"}; + font-size: inherit; + + &.fa-rotate-90 { + transform: rotate(90deg) #{"/*rtl: rotate(90deg)*/"}; + font-size: inherit; + } + } } #expand-collapse-outline-all-button { @@ -487,6 +497,14 @@ } } +.dates-tab-link { + padding: 16px 0 0 24px; + + a { + font-weight: bold; + } +} + // Course Updates Page .course-updates { .all-updates { @@ -498,7 +516,7 @@ border-bottom: 1px solid $border-color; .date { - font-size: font-size(small); + font-size: 0.875rem; font-weight: $font-light; float: none; padding-bottom: ($baseline/4); @@ -513,6 +531,26 @@ max-width: 100%; } } + + .well { + box-shadow: inset 0 1px 2px 1px $shadow; + padding: 1.25rem; + background: $gray-100; + } + } + + .breadcrumbs { + font-size: 0.875rem; + + .nav-item { + @include margin-left($baseline/4); + } + + .fa-angle-right { + transform: rotateY(0deg) #{"/*rtl: rotateY(180deg)*/"}; + + @include margin-left($baseline/4); + } } } diff --git a/lms/static/sass/features/_course-upgrade-message.scss b/lms/static/sass/features/_course-upgrade-message.scss index 7ad6abdc68f76afecaa9844fb06eb215a73b4b8b..ab93eaea46e97ac28a33c932af7e58c98c47cf64 100644 --- a/lms/static/sass/features/_course-upgrade-message.scss +++ b/lms/static/sass/features/_course-upgrade-message.scss @@ -38,7 +38,7 @@ Search for the courseware_verified_certificate_upsell promotion ID. text-align: center; } -@media only screen and (max-width: 991px) and (min-width: 768px) { +@media only screen and (max-width: 991px) and (min-width: 768px) { .section-upgrade .upgrade-container { float: none; } diff --git a/lms/static/sass/features/_enterprise-learner-portal-banner.scss b/lms/static/sass/features/_enterprise-learner-portal-banner.scss deleted file mode 100644 index 19f8067f57d5d04aa3321ec1b341c93be815cdb6..0000000000000000000000000000000000000000 --- a/lms/static/sass/features/_enterprise-learner-portal-banner.scss +++ /dev/null @@ -1,102 +0,0 @@ -$enterprise-learner-portal-banner-background-color: #d9edf7 !default; -$enterprise-learner-portal-banner-text-color: #000000 !default; -$enterprise-learner-portal-banner-cta-base: #0075b4 !default; -$enterprise-learner-portal-banner-cta-hover: #075683 !default; -$enterprise-learner-portal-banner-btn-color: #000000 !default; - -.edx-enterprise-learner-portal-banner-wrapper { - background: $enterprise-learner-portal-banner-background-color; - box-sizing: border-box; - - /** Base Styles - start **/ - text-align: left; - line-height: 1.5; - margin-bottom: 5px; - font: { - family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; - size: 1rem; - weight: 400; - } - - .alert { - position: relative; - padding: 0.75rem 1.25rem; - } - - .alert-dismissible { - .close { - position: absolute; - top: 0; - right: 0; - padding: 0.75rem 1.25rem; - background: transparent; - border: 0; - text-shadow: 0 1px 0 #fff; - opacity: 1; - float: right; - line-height: 1; - font: { - size: 1.5rem; - weight: 700; - } - } - - .btn { - display: inline-block; - text-align: center; - white-space: nowrap; - vertical-align: middle; - box-shadow: none; - } - } - /** Base Styles - end **/ - - - .edx-enterprise-learner-portal-banner { - box-sizing: border-box; - display: flex; - justify-content: space-between; - max-width: none !important; - min-width: 0; - margin: 0 auto; - background: inherit; - border: none; - padding: 20px 20px 20px 40px; - - .policy-link { - color: $enterprise-learner-portal-banner-cta-base; - text-decoration: underline; - - &:focus, - &:hover { - color: $enterprise-learner-portal-banner-cta-hover; - border: none; - } - } - - .copy-content { - font-size: 0.875rem; - line-height: 1.4; - color: $enterprise-learner-portal-banner-text-color; - } - - .alert-dialog { - margin-right: 30px; - color: $enterprise-learner-portal-banner-text-color; - max-width: 1180px; - margin: 0 auto; - width: 100%; - } - - .btn.close { - color: $enterprise-learner-portal-banner-btn-color; - text-shadow: 0 0 1px $enterprise-learner-portal-banner-btn-color; - bottom: 0; - - &:focus, - &:hover { - cursor: pointer; - } - } - } -} diff --git a/lms/static/sass/features/_first-purchase-banner.scss b/lms/static/sass/features/_first-purchase-banner.scss index 60bfe282141026d70929635c367ca228650d0298..2e9d9f1b450ab78278fdaee70e57f7d746902e2d 100644 --- a/lms/static/sass/features/_first-purchase-banner.scss +++ b/lms/static/sass/features/_first-purchase-banner.scss @@ -1,6 +1,6 @@ // First purchase offer banner .first-purchase-offer-banner { - background-color: #DEE3F1; + background-color: #dee3f1; font-size: 16px; border-radius: 7px; padding: 20px; @@ -9,19 +9,22 @@ line-height: 1.5; .first-purchase-offer-banner-bold { - font-weight: bold; - color: #393f43; + font-weight: bold; + color: #393f43; } a { - color: #23419F !important; + color: #23419f !important; text-decoration: underline !important; font-weight: bold !important; border-bottom: none; } - } #seq_content .first-purchase-offer-banner { max-width: $text-width-readability-max; } + +body.view-in-mfe .first-purchase-offer-banner { + display: none; +} diff --git a/lms/static/sass/features/_learner-profile.scss b/lms/static/sass/features/_learner-profile.scss index 1613fbe0c6b6f6082ee0d59783b0063e3ef50df7..8d35a7eccc67755e9f08cc5eb3f54b2330e717b8 100644 --- a/lms/static/sass/features/_learner-profile.scss +++ b/lms/static/sass/features/_learner-profile.scss @@ -262,8 +262,8 @@ .profile-self { .wrapper-profile-field-account-privacy { @include clearfix(); - @include box-sizing(border-box); + box-sizing: border-box; width: 100%; margin: 0 auto; border-bottom: 1px solid $gray-l3; diff --git a/lms/static/sass/multicourse/_about_pages.scss b/lms/static/sass/multicourse/_about_pages.scss index 3185341ef7109414d7563dec842f69b05a6fce54..086bb10c8bc8fec0eb625b41b1f0986b087277df 100644 --- a/lms/static/sass/multicourse/_about_pages.scss +++ b/lms/static/sass/multicourse/_about_pages.scss @@ -52,7 +52,9 @@ .logo { @include border-right(1px solid rgb(200, 200, 200)); - @include box-sizing(border-box); + + box-sizing: border-box; + @include float(left); height: 115px; @@ -70,7 +72,8 @@ } h2.mission-quote { - @include box-sizing(border-box); + box-sizing: border-box; + @include float(right); font-style: italic; @@ -107,8 +110,7 @@ } .photo { - @include box-sizing(border-box); - + box-sizing: border-box; background: rgb(255, 255, 255); border: 1px solid rgb(210, 210, 210); margin-top: 37px; @@ -123,7 +125,8 @@ } > article { - @include box-sizing(border-box); + box-sizing: border-box; + @include float(left); @include padding-left($baseline); @@ -170,8 +173,8 @@ nav.categories { border: 1px solid rgb(220, 220, 220); + box-sizing: border-box; - @include box-sizing(border-box); @include float(left); @include margin-left(flex-gutter()); @@ -244,8 +247,8 @@ .article-cover { background: rgb(255, 255, 255); border: 1px solid rgb(120, 120, 120); + box-sizing: border-box; - @include box-sizing(border-box); @include float(left); height: 140px; @@ -292,8 +295,7 @@ margin: 0 auto; .photo { - @include box-sizing(border-box); - + box-sizing: border-box; background: rgb(255, 255, 255); border: 1px solid rgb(210, 210, 210); padding: 1px; @@ -308,7 +310,8 @@ } .contacts { - @include box-sizing(border-box); + box-sizing: border-box; + @include float(left); @include padding-left(40px); diff --git a/lms/static/sass/multicourse/_account.scss b/lms/static/sass/multicourse/_account.scss index e418ec72d67c6caca6438a953349913c814effb9..a9e6595a986259a2cf95de67d5f3da9611823afa 100644 --- a/lms/static/sass/multicourse/_account.scss +++ b/lms/static/sass/multicourse/_account.scss @@ -109,7 +109,8 @@ .container, .introduction { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); margin: 0 auto; @@ -231,8 +232,7 @@ // basic layout .content, aside { - @include box-sizing(border-box); - + box-sizing: border-box; margin: $baseline 0 0 0; } @@ -625,8 +625,7 @@ // forms - messages/status .status { - @include box-sizing(border-box); - + box-sizing: border-box; margin: 0 0 $baseline 0; border-bottom: 3px solid shade($yellow, 10%); padding: $baseline $baseline; @@ -812,9 +811,7 @@ @extend %body-text; box-shadow: inset 0 -1px 2px 0 tint($red, 85%); - - @include box-sizing(border-box); - + box-sizing: border-box; margin: $baseline 0 ($baseline/2) 0 !important; padding: $baseline; border: none; diff --git a/lms/static/sass/multicourse/_course_about.scss b/lms/static/sass/multicourse/_course_about.scss index 9eebb401706112ceb3a31e8d3692887f4af98683..33df96922c6021ff52ad90816ba3515cdf2fe8c3 100644 --- a/lms/static/sass/multicourse/_course_about.scss +++ b/lms/static/sass/multicourse/_course_about.scss @@ -16,7 +16,6 @@ background: $course-profile-bg; background-image: $homepage-bg-image; background-size: cover; - box-shadow: 0 1px 80px 0 rgba(0, 0, 0, 0.5); border-bottom: 1px solid $border-color-3; box-shadow: inset 0 1px 5px 0 $shadow-l1; height: 100%; @@ -28,8 +27,8 @@ background: $course-header-bg; border: 1px solid $border-color-3; box-shadow: 0 4px 25px 0 rgba(0, 0, 0, 0.5); + box-sizing: border-box; - @include box-sizing(border-box); @include clearfix(); margin: 0 auto; @@ -48,7 +47,8 @@ } .intro { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); display: table-cell; @@ -88,7 +88,8 @@ color: $body-color !important; letter-spacing: 0 !important; - &:hover, &:focus { + &:hover, + &:focus { color: $link-color; } } @@ -105,7 +106,8 @@ text-shadow: 0 1px rgba(255, 255, 255, 0.6); text-transform: none; - &:hover, &:focus { + &:hover, + &:focus { color: $link-color; } } @@ -120,10 +122,12 @@ width: flex-grid(12); - > a.find-courses, a.register, a.add-to-cart { + > a.find-courses, + a.register, + a.add-to-cart { @include button(shiny, $button-color); - @include box-sizing(border-box); + box-sizing: border-box; border-radius: 3px; display: block; font: normal 1.2rem/1.6rem $font-family-sans-serif; @@ -132,7 +136,8 @@ text-align: center; width: flex-grid(6); - &:hover, &:focus { + &:hover, + &:focus { color: rgb(255, 255, 255); } @@ -142,15 +147,17 @@ } a { - &:hover, &:visited, &:focus { + &:hover, + &:visited, + &:focus { text-decoration: none; } } strong { @include button(shiny, $button-color); - @include box-sizing(border-box); + box-sizing: border-box; border-radius: 3px; display: block; @@ -162,17 +169,17 @@ text-align: center; width: flex-grid(3, 8); - &:hover, &:focus { + &:hover, + &:focus { color: rgb(255, 255, 255); } } - span.register, span.add-to-cart { + span.register, + span.add-to-cart { background: $button-archive-color; border: 1px solid darken($button-archive-color, 50%); - - @include box-sizing(border-box); - + box-sizing: border-box; color: darken($button-archive-color, 50%); display: block; letter-spacing: 1px; @@ -199,9 +206,7 @@ .media { background: transparent; - - @include box-sizing(border-box); - + box-sizing: border-box; display: table-cell; padding: 20px; position: relative; @@ -254,7 +259,8 @@ } } - &:hover, &:focus { + &:hover, + &:focus { text-decoration: none; .play-intro { @@ -367,7 +373,8 @@ } } - .prerequisites, .syllabus { + .prerequisites, + .syllabus { ul { li { font: normal 1em/1.6em $serif; @@ -401,7 +408,8 @@ .course-sidebar { @include media-breakpoint-up(dm) { - @include box-sizing(border-box); + box-sizing: border-box; + @include float(left); width: flex-grid(4); @@ -481,13 +489,15 @@ @include margin-right($baseline*0.75); @include padding-right(15px); - &:hover, &:focus { + &:hover, + &:focus { color: $lighter-base-font-color; } } .social-sharing { - @include box-sizing(border-box); + box-sizing: border-box; + @include float(left); height: 44px; @@ -497,7 +507,8 @@ z-index: 2; float: none; - &:hover, &:focus { + &:hover, + &:focus { .sharing-message { opacity: 1; top: 56px; @@ -511,9 +522,7 @@ border: 1px solid rgba(0, 0, 0, 0.5); border-radius: 4px; box-shadow: 0 4px 25px 0 rgba(0, 0, 0, 0.5); - - @include box-sizing(border-box); - + box-sizing: border-box; color: rgb(255, 255, 255); @include float(right); @@ -535,7 +544,8 @@ top: 65px; width: 220px; - &:hover, &:focus { + &:hover, + &:focus { opacity: 0; } } @@ -555,7 +565,8 @@ @include transition(all 0.15s linear 0s); - &:hover, &:focus { + &:hover, + &:focus { opacity: 1; } @@ -585,7 +596,8 @@ margin-bottom: $baseline; padding-bottom: ($baseline/2); - &:hover, &:focus { + &:hover, + &:focus { .icon { opacity: 1; } diff --git a/lms/static/sass/multicourse/_courses.scss b/lms/static/sass/multicourse/_courses.scss index 5a49dc77d7f5db0c449adad3a7ef3f0984e283ef..9da6d4b7e164409f32e8709aac772fc900f870d5 100644 --- a/lms/static/sass/multicourse/_courses.scss +++ b/lms/static/sass/multicourse/_courses.scss @@ -416,7 +416,8 @@ $facet-background-color: #007db8; .search-facets { @include fill-parent(); @include omega(); - @include box-sizing(border-box); + + box-sizing: border-box; @extend %ui-depth1; @@ -521,7 +522,9 @@ $facet-background-color: #007db8; .count { @include right($baseline*0.6); @include text-align(right); - @include box-sizing(border-box); + + box-sizing: border-box; + @include transition(all 0.2s ease-out); position: absolute; diff --git a/lms/static/sass/multicourse/_dashboard.scss b/lms/static/sass/multicourse/_dashboard.scss index f849d2427228f512ad489d9c120dd05a0c30fe84..de7cc4ada3c3b9b8b6c8462685b668972319adc1 100644 --- a/lms/static/sass/multicourse/_dashboard.scss +++ b/lms/static/sass/multicourse/_dashboard.scss @@ -55,7 +55,8 @@ // UI: individual course item .course { - @include box-sizing(box); + box-sizing: box; + @include transition(all 0.15s linear 0s); @include clearfix(); @@ -73,7 +74,8 @@ overflow: hidden; .cover { - @include box-sizing(border-box); + box-sizing: border-box; + @include transition(all 0.15s linear 0s); @include float(left); @@ -135,8 +137,10 @@ flex-basis: 100%; padding-top: $baseline/2; - a, span { + a, + span { font: -apple-system-short-headline !important; + @extend %t-title3; @extend %t-regular; @@ -164,8 +168,9 @@ .info-date-block-container { display: block; - .info-date-block{ + .info-date-block { font: -apple-system-short-subheadline !important; + @extend %t-title7; color: $gray; // WCAG 2.0 AA compliant @@ -224,7 +229,8 @@ // UI: course item actions .action { - @include box-sizing(border-box); + box-sizing: border-box; + @include margin-right($baseline/2); @include float(right); @@ -235,7 +241,8 @@ border: 1px solid $white; text-align: center; - &:hover, &:focus { + &:hover, + &:focus { color: $gray-d3; border: 1px solid $gray-l4; } @@ -295,8 +302,7 @@ .actions-dropdown-list { @extend %ui-no-list; - @include box-sizing(border-box); - + box-sizing: border-box; display: table; box-shadow: 0 1px 1px $shadow-l1; position: relative; @@ -372,7 +378,8 @@ width: flex-grid(8); @include float(left); - @include box-sizing(border-box); + + box-sizing: border-box; p { color: $lighter-base-font-color; @@ -397,6 +404,7 @@ .enter-course { font: -apple-system-short-subheadline !important; + @extend %btn-pl-white-base; @include float(right); @@ -517,6 +525,8 @@ order: 2; .wrapper-find-courses { + margin-bottom: $baseline * 0.5; + .course-advertise { @include clearfix(); @@ -568,31 +578,9 @@ } } - .wrapper-coaching { - border: 1px solid $border-color-l3; - margin: 20px 0; - - .coaching-signup { - padding: 20px; - - .coaching-prompt { - font-size: 20px; - line-height: 28px; - font-weight: bold; - } - - .coaching-link .btn-neutral { - display: block; - text-align: center; - margin: 20px 20px 0 20px; - border-radius: 20px; - padding: 10px; - border: 1px solid theme-color('primary'); - } - } - } - .profile-sidebar { + margin-bottom: $baseline * 0.5; + ul { padding: 0; border: 1px solid theme-color("light"); @@ -601,7 +589,6 @@ // Responsive behavior @include media-breakpoint-down(md) { - margin: 0 $baseline $baseline*2; padding: 0; max-width: 100%; } @@ -817,7 +804,8 @@ color: $white; // nasty but needed override for poor <span> styling } - .copy, .copy-sub { + .copy, + .copy-sub { display: inline-block; vertical-align: middle; } @@ -869,7 +857,7 @@ @include float(right); @include margin-right(5px); - background-image: none ; + background-image: none; text-shadow: none; box-shadow: none; text-transform: none; @@ -886,7 +874,8 @@ } .btn { - @include box-sizing(border-box); + box-sizing: border-box; + @include float(left); border-radius: 3px; @@ -898,7 +887,8 @@ &.disabled { cursor: default !important; - &:hover, &:focus { + &:hover, + &:focus { @include background-image(linear-gradient(top, #EEE 0%, #C2C2C2 50%, #ABABAB 50%, #B0B0B0 100%)); background: #eee; @@ -958,7 +948,8 @@ font-weight: bold; letter-spacing: 0; - &:hover, &:focus { + &:hover, + &:focus { text-decoration: none; } } @@ -999,8 +990,7 @@ .action-certificate .btn { @extend %btn-inherited-primary; - @include box-sizing(border-box); - + box-sizing: border-box; padding: 7px $baseline*0.75; float: none; border-radius: 3px; @@ -1136,7 +1126,7 @@ color: $lighter-base-font-color; margin-bottom: $baseline; - text-shadow: 0 1px rgba(255,255,255, 0.6); + text-shadow: 0 1px rgba(255, 255, 255, 0.6); } p.custom-message { @@ -1149,9 +1139,7 @@ background-color: theme-color('primary'); border: 1px solid theme-color('primary'); box-shadow: 0 1px 8px 0 $shadow-l1; - - @include box-sizing(border-box); - + box-sizing: border-box; color: $white; font-family: $font-family-sans-serif; display: inline-block; @@ -1160,8 +1148,9 @@ margin-left: ($baseline/4); padding: $baseline*0.75 $baseline; - &:hover, &:focus { - background: theme-color('primary')-l2; + &:hover, + &:focus { + background: theme-color('primary')-l2; /* stylelint-disable-line */ text-decoration: none; } } @@ -1286,6 +1275,7 @@ .btn-reverify { margin-top: ($baseline/2); } + .deco-arrow { @include triangle(($baseline/2), $verified-color-lvl4, up); } @@ -1328,7 +1318,6 @@ color: #fff; background-color: #0079bc; } - } } @@ -1379,11 +1368,11 @@ p.course-block { padding: ($baseline/4); border-width: 1px; background: #fdfbe4; - } .enter-course-blocked { - @include box-sizing(border-box); + box-sizing: border-box; + @include float(right); display: block; @@ -1404,7 +1393,8 @@ p.course-block { font: normal 15px/1.6rem $font-family-sans-serif; padding: 6px 32px 7px; - &:hover, &:focus { + &:hover, + &:focus { text-decoration: none; } } @@ -1628,7 +1618,9 @@ a.fade-cover { color: theme-color("inverse"); } - .survey_button:visited, .survey_button:hover, .survey_button:focus { + .survey_button:visited, + .survey_button:hover, + .survey_button:focus { color: theme-color("inverse"); text-decoration: none; } diff --git a/lms/static/sass/multicourse/_entitlement_dashboard.scss b/lms/static/sass/multicourse/_entitlement_dashboard.scss index d67e07425edfd3f68bbcb550700d573bf2346a32..dd6ef3e93dccf5ee5002fe75c87791eb34071309 100644 --- a/lms/static/sass/multicourse/_entitlement_dashboard.scss +++ b/lms/static/sass/multicourse/_entitlement_dashboard.scss @@ -31,7 +31,7 @@ @extend .inner-wrapper; height: 98%; - overflow-y: scroll; + overflow-y: scroll; .entitlement-unenrollment-modal-close-btn { @extend .close-modal; diff --git a/lms/static/sass/multicourse/_error-pages.scss b/lms/static/sass/multicourse/_error-pages.scss index 710790b639f4a757cc1162402b83a52014a8c1ec..c0c43a42257a466aba8c42d918f0f363e9af43ae 100644 --- a/lms/static/sass/multicourse/_error-pages.scss +++ b/lms/static/sass/multicourse/_error-pages.scss @@ -12,7 +12,9 @@ section.outside-app { text-align: center; } - p, ul, form { + p, + ul, + form { max-width: 600px; margin: 0 auto; font: normal 1em/1.6em $serif; diff --git a/lms/static/sass/multicourse/_help.scss b/lms/static/sass/multicourse/_help.scss index bbcf0a97649c1fb7ab44f0097cf15db95ff147b4..3d7c3606672187a9e0a3b84dd3385c4646dd6fc5 100644 --- a/lms/static/sass/multicourse/_help.scss +++ b/lms/static/sass/multicourse/_help.scss @@ -4,8 +4,8 @@ nav.categories { border: 1px solid rgb(220, 220, 220); + box-sizing: border-box; - @include box-sizing(border-box); @include float(left); @include margin-left(flex-gutter()); diff --git a/lms/static/sass/multicourse/_home.scss b/lms/static/sass/multicourse/_home.scss index a1f9a0c138b7220f6b86f7894a2a7cdc77425946..3ca7761fc7226c25fb686911fa84475ad6d8fdcb 100644 --- a/lms/static/sass/multicourse/_home.scss +++ b/lms/static/sass/multicourse/_home.scss @@ -9,8 +9,7 @@ $course-search-input-height: ($button-size); padding: 0; > .container { - @include box-sizing(border-box); - + box-sizing: border-box; width: flex-grid(12); } @@ -43,7 +42,9 @@ $course-search-input-height: ($button-size); .title { @include span-columns(8); @include shift(2); - @include box-sizing(border-box); + + box-sizing: border-box; + @include transition(all 0.2s linear 0s); position: relative; @@ -81,7 +82,9 @@ $course-search-input-height: ($button-size); > .heading-group { @include left(0); - @include box-sizing(border-box); + + box-sizing: border-box; + @include transition(all 0.2s linear 0s); @include text-align(left); @@ -171,7 +174,8 @@ $course-search-input-height: ($button-size); border: 1px solid $border-color-3; @include border-left(0); - @include box-sizing(border-box); + + box-sizing: border-box; // box-shadow: 0 4px 25px 0 rgba(0, 0, 0, 0.5); height: 120px; @@ -200,9 +204,7 @@ $course-search-input-height: ($button-size); border-radius: 4px; box-shadow: 0 1px 12px 0 $shadow-d1; - - @include box-sizing(border-box); - + box-sizing: border-box; border: 2px solid rgba(255, 255, 255, 0.8); height: 60px; @@ -260,8 +262,7 @@ $course-search-input-height: ($button-size); } .highlighted-courses { - @include box-sizing(border-box); - + box-sizing: border-box; margin-bottom: ($baseline*2); position: relative; width: flex-grid(12); @@ -456,20 +457,19 @@ $course-search-input-height: ($button-size); } &.university-partners2x6 { - @include box-sizing(border-box); - + box-sizing: border-box; width: flex-grid(12, 12); .partners { - @include box-sizing(border-box); + box-sizing: border-box; + @include clearfix(); @include margin-left(60px); padding: 12px 0; .partner { - @include box-sizing(border-box); - + box-sizing: border-box; width: flex-grid(2, 12); display: block; @@ -550,8 +550,7 @@ $course-search-input-height: ($button-size); } .news { - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: inset 0 0 3px 0 rgba(0, 0, 0, 0.15); padding: 20px; width: flex-grid(12); @@ -566,8 +565,8 @@ $course-search-input-height: ($button-size); > article { border: 1px dotted transparent; border-color: $border-color-2; + box-sizing: border-box; - @include box-sizing(border-box); @include clearfix(); @include float(left); @include margin-right(flex-gutter()); @@ -591,9 +590,7 @@ $course-search-input-height: ($button-size); .post-graphics { border: 1px solid $border-color-1; - - @include box-sizing(border-box); - + box-sizing: border-box; display: block; @include float(left); diff --git a/lms/static/sass/multicourse/_jobs.scss b/lms/static/sass/multicourse/_jobs.scss index 6b446697da2ed164656dfbe871f1734b5ac688fa..67c3b56fb995fb45944c8d51237eb08319c99fa0 100644 --- a/lms/static/sass/multicourse/_jobs.scss +++ b/lms/static/sass/multicourse/_jobs.scss @@ -36,7 +36,7 @@ width: flex-grid(4); img { - background: rgb(245,245,245); + background: rgb(245, 245, 245); display: block; max-width: 100%; } @@ -89,9 +89,8 @@ } .jobs-sidebar { - @include box-sizing(border-box); - - border: 1px solid rgb(220,220,220); + box-sizing: border-box; + border: 1px solid rgb(220, 220, 220); @include float(left); @@ -109,8 +108,9 @@ @include padding(12px, 0, 12px, 20px); @include text-align(left); - &:hover, &:focus { - background: rgb(245,245,245); + &:hover, + &:focus { + background: rgb(245, 245, 245); text-decoration: none; } } @@ -128,7 +128,7 @@ width: flex-grid(9); .job { - border-bottom: 1px solid rgb(220,220,220); + border-bottom: 1px solid rgb(220, 220, 220); padding: 40px 0; &:first-child { @@ -140,9 +140,6 @@ padding-bottom: 0; } - .inner-wrapper { - } - h3 { font-family: $font-family-sans-serif; font-weight: 700; diff --git a/lms/static/sass/multicourse/_media-kit.scss b/lms/static/sass/multicourse/_media-kit.scss index 4527cc432297f5bd696d0a2320cdca9d9b5be389..8c9e05f9c882bd62aeb22e0043161c6e9c0e838f 100644 --- a/lms/static/sass/multicourse/_media-kit.scss +++ b/lms/static/sass/multicourse/_media-kit.scss @@ -3,17 +3,14 @@ $baseline: 20px; $white: rgb(255, 255, 255); .mediakit { - @include box-sizing(border-box); - + box-sizing: border-box; margin: 0 auto; padding: ($baseline*3) 0; width: 980px; .wrapper-mediakit { border-radius: 4px; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 10px 0 $shadow-l1; margin: ($baseline*3) 0 0 0; border: 1px solid $border-color; @@ -25,10 +22,6 @@ $white: rgb(255, 255, 255); &:last-child { margin-bottom: 0; } - - header { - - } } } @@ -86,7 +79,8 @@ $white: rgb(255, 255, 255); } } - &:hover, &:focus { + &:hover, + &:focus { .note { color: shade($blue, 25%); } @@ -114,8 +108,7 @@ $white: rgb(255, 255, 255); } article { - @include box-sizing(border-box); - + box-sizing: border-box; width: 500px; @include margin-right($baseline); @@ -124,9 +117,7 @@ $white: rgb(255, 255, 255); aside { border-radius: 2px; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 4px 0 $shadow; width: 330px; @@ -159,8 +150,7 @@ $white: rgb(255, 255, 255); } figure { - @include box-sizing(border-box); - + box-sizing: border-box; background: $white; width: 100%; @@ -185,13 +175,11 @@ $white: rgb(255, 255, 255); // library section .library { border-radius: 2px; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 4px 0 $shadow; - border: 3px solid tint($light-gray,50%); + border: 3px solid tint($light-gray, 50%); padding: 0; - background: tint($light-gray,50%); + background: tint($light-gray, 50%); header { padding: ($baseline*0.75) $baseline; @@ -222,8 +210,7 @@ $white: rgb(255, 255, 255); list-style: none; li { - @include box-sizing(border-box); - + box-sizing: border-box; overflow-y: auto; @include float(left); @@ -240,23 +227,22 @@ $white: rgb(255, 255, 255); figure { a { border-radius: 2px; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 2px 0 $shadow-l1; display: block; min-height: 380px; - border: 2px solid tint($light-gray,75%); + border: 2px solid tint($light-gray, 75%); padding: $baseline; - &:hover, &:focus { + &:hover, + &:focus { border-color: $blue; } } img { display: block; - border: 2px solid tint($light-gray,80%); + border: 2px solid tint($light-gray, 80%); margin: 0 auto ($baseline*0.75); } @@ -273,9 +259,4 @@ $white: rgb(255, 255, 255); } } } - - // share - .share { - - } } diff --git a/lms/static/sass/multicourse/_press_release.scss b/lms/static/sass/multicourse/_press_release.scss index 8e4b404c4adcc379e9909f963f851fc10754acf9..495555fa7ae4e1295d86200033a1b6247f800c20 100644 --- a/lms/static/sass/multicourse/_press_release.scss +++ b/lms/static/sass/multicourse/_press_release.scss @@ -1,5 +1,5 @@ .pressrelease { - background: rgb(250,250,250); + background: rgb(250, 250, 250); .container { padding: ($baseline*3) 0 ($baseline*6); @@ -34,11 +34,9 @@ } > article { - border: 1px solid rgb(220,220,220); + border: 1px solid rgb(220, 220, 220); border-radius: 10px; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 2px 16px 0 $shadow-l1; margin: 0 auto; padding: 80px 80px 40px; diff --git a/lms/static/sass/multicourse/_survey-page.scss b/lms/static/sass/multicourse/_survey-page.scss index 346b36c0dc1ad5c7bb3ad636c4bd8f111123f4d6..5af944a499fa813c7a68a4bcdf075846cd08d59d 100644 --- a/lms/static/sass/multicourse/_survey-page.scss +++ b/lms/static/sass/multicourse/_survey-page.scss @@ -56,7 +56,8 @@ // reset nasty LMS default styles form { - h1, h2 { + h1, + h2 { text-align: inherit; letter-spacing: inherit; text-transform: inherit; @@ -77,7 +78,7 @@ @include padding(($baseline), ($baseline*1.5), ($baseline*1.5), ($baseline*1.5)); - background-color: tint($error-color,85%); + background-color: tint($error-color, 85%); .message-title { @extend %t-title5; @@ -153,7 +154,10 @@ } // override basic form input styles - button, input, select, textarea { + button, + input, + select, + textarea { @extend %t-copy-sub1; } diff --git a/lms/static/sass/partials/lms/theme/_variables-v1.scss b/lms/static/sass/partials/lms/theme/_variables-v1.scss index 971b1951009e54de4caa648d46eeae25b01e6108..b00ef42a00d0e0b593a42ada884207a305ff7507 100644 --- a/lms/static/sass/partials/lms/theme/_variables-v1.scss +++ b/lms/static/sass/partials/lms/theme/_variables-v1.scss @@ -481,7 +481,7 @@ $shadow-color: $blue !default; $modal-bg-color: rgb(245, 245, 245) !default; // courseware elements -$courseware-header-image: linear-gradient(top, rgb(255, 255, 255), rgb(238, 238, 238)) !default; +$courseware-header-image: linear-gradient(top, rgb(255, 255, 255), rgb(238, 238, 238)) !default; /* stylelint-disable-line */ $courseware-header-bg: transparent !default; $courseware-footer-border: none !default; $courseware-footer-shadow: none !default; @@ -541,7 +541,7 @@ $result-highlight-color-base: rgba($highlight-color, 0.25) !default; $sidebar-chapter-bg-top: rgba(255, 255, 255, 0.5) !default; $sidebar-chapter-bg-bottom: rgba(255, 255, 255, 0) !default; $sidebar-chapter-bg: rgb(246, 246, 246) !default; -$sidebar-active-image: linear-gradient(top, rgb(230, 230, 230), rgb(214, 214, 214)) !default; +$sidebar-active-image: linear-gradient(top, rgb(230, 230, 230), rgb(214, 214, 214)) !default; /* stylelint-disable-line */ // student notes diff --git a/lms/static/sass/search/_search.scss b/lms/static/sass/search/_search.scss index b8a7b7aa8c22670d534f1a5ca1e1a6b47360e748..0e1abd63e3a2266a68bd1586b8d53011b9227a41 100644 --- a/lms/static/sass/search/_search.scss +++ b/lms/static/sass/search/_search.scss @@ -1,6 +1,5 @@ .search-bar { - @include box-sizing(border-box); - + box-sizing: border-box; position: relative; .search-field-wrapper { @@ -10,8 +9,7 @@ .search-field { @extend %t-weight2; - @include box-sizing(border-box); - + box-sizing: border-box; top: 5px; width: 100%; border-radius: 4px; @@ -24,7 +22,8 @@ .cancel-button:hover { @extend %t-regular; - @include box-sizing(border-box); + box-sizing: border-box; + @include right(0); display: block; @@ -44,7 +43,7 @@ line-height: 33px; text-shadow: none; text-transform: none; - + &:hover, &:focus, &:active { @@ -57,7 +56,6 @@ .cancel-button { display: none; } - } .search-results { diff --git a/lms/static/sass/shared-v2/_components.scss b/lms/static/sass/shared-v2/_components.scss index afab8dca34a2582591a0110148d74da388df0877..8f800990aa53297bf3bba2c09df7616d707ebb54 100644 --- a/lms/static/sass/shared-v2/_components.scss +++ b/lms/static/sass/shared-v2/_components.scss @@ -145,8 +145,8 @@ .wrapper-preview-menu { @include clearfix(); - @include box-sizing(border-box); + box-sizing: border-box; margin: 0 auto; padding: ($baseline*0.75) 20px; background-color: theme-color("primary"); diff --git a/lms/static/sass/shared-v2/_footer.scss b/lms/static/sass/shared-v2/_footer.scss index 6f9a066c37dde2fdaed83ecdc9eedb4f4617a90a..85abdae1c3418f782a8ccc4e28ccfa5e470365e3 100644 --- a/lms/static/sass/shared-v2/_footer.scss +++ b/lms/static/sass/shared-v2/_footer.scss @@ -17,7 +17,9 @@ box-sizing: border-box; margin: 0 auto; - p, ol, ul { + p, + ol, + ul { font-family: $font-family-sans-serif; // override needed for poorly scoped font-family styling on p a:link {} diff --git a/lms/static/sass/shared-v2/_help-tab.scss b/lms/static/sass/shared-v2/_help-tab.scss index 474db59fe849e4f4550ff607f99060a534b10ed3..b915c022582c27d8da08eff64bbcaadea88aa70b 100644 --- a/lms/static/sass/shared-v2/_help-tab.scss +++ b/lms/static/sass/shared-v2/_help-tab.scss @@ -12,7 +12,6 @@ width: 700px !important; margin-left: -350px !important; } - } .help-tab { diff --git a/lms/static/sass/shared-v2/_modal.scss b/lms/static/sass/shared-v2/_modal.scss index 326703ae8fd17a6a8b657b5972c9c0cdb6f433aa..a45936efad06ce79d0066c4aa7f2df0941cec424 100644 --- a/lms/static/sass/shared-v2/_modal.scss +++ b/lms/static/sass/shared-v2/_modal.scss @@ -2,11 +2,11 @@ @include background-image(radial-gradient(circle at 50% 30%, $shadow-d1, $shadow-d2)); display: none; - height:100%; + height: 100%; left: 0; position: fixed; top: 0; - width:100%; + width: 100%; z-index: 100; } @@ -59,9 +59,9 @@ radial-gradient( 50% 50%, circle closest-side, $white-opacity-80 0%, - $white-transparent 100% - ) - ); + $white-transparent 100% + ) + ); content: ''; display: block; @@ -79,10 +79,10 @@ linear-gradient( 180deg, $white-transparent 0%, - $white-opacity-80 50%, - $white-transparent - ) - ); + $white-opacity-80 50%, + $white-transparent + ) + ); height: 1px; width: 100%; @@ -96,10 +96,10 @@ linear-gradient( 180deg, $light-grey-transparent 0%, - $light-grey-solid 50%, - $light-grey-transparent - ) - ); + $light-grey-solid 50%, + $light-grey-transparent + ) + ); height: 1px; width: 100%; @@ -144,7 +144,8 @@ padding: 12px; } - .activation-message, .message { + .activation-message, + .message { padding: 0 ($baseline*2) ($baseline/2); p { diff --git a/lms/static/sass/shared/_activation_messages.scss b/lms/static/sass/shared/_activation_messages.scss index 88fa0b7f4c7a8e7c00ab28d0c2a39099f8064638..f42804ef15eb719350afb1217ea881161cb0ef29 100644 --- a/lms/static/sass/shared/_activation_messages.scss +++ b/lms/static/sass/shared/_activation_messages.scss @@ -19,8 +19,8 @@ } .message { - background: rgb(252,252,252); - border: 1px solid rgb(200,200,200); + background: rgb(252, 252, 252); + border: 1px solid rgb(200, 200, 200); box-shadow: 0 3px 20px 0 $shadow; border-radius: 4px; margin: 0 auto; diff --git a/lms/static/sass/shared/_alerts_pattern_library_shim.scss b/lms/static/sass/shared/_alerts_pattern_library_shim.scss index 63b1cd15473c7786f560cca780e8b7f26561b85f..e22217d6396054ca9884791d9183bad6b2966a98 100644 --- a/lms/static/sass/shared/_alerts_pattern_library_shim.scss +++ b/lms/static/sass/shared/_alerts_pattern_library_shim.scss @@ -148,7 +148,6 @@ $bp-screen-md: 768px !default; // shift the section up to make the alert more compact margin-top: - $spacing-vertical-x-small; } - } .alert-copy { diff --git a/lms/static/sass/shared/_course_filter.scss b/lms/static/sass/shared/_course_filter.scss index 2b92cc2b11e99f5802cc0d983ab2e1b1683b1187..e6e5be1acc228ce4c57901502b35a0815e45ecbd 100644 --- a/lms/static/sass/shared/_course_filter.scss +++ b/lms/static/sass/shared/_course_filter.scss @@ -2,14 +2,12 @@ height: 60px; nav { - @include background-image(linear-gradient(-90deg, rgb(250,250,250), rgb(230,230,230))); + @include background-image(linear-gradient(-90deg, rgb(250, 250, 250), rgb(230, 230, 230))); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.4), inset 0 0 0 -1px rgba(255, 255, 255, 0.4); - - @include box-sizing(border-box); - - border: 1px solid rgb(190,190,190); - border-bottom-color: rgb(200,200,200); + box-sizing: border-box; + border: 1px solid rgb(190, 190, 190); + border-bottom-color: rgb(200, 200, 200); border-top: none; @include border-bottom-radius(4px); @@ -37,11 +35,9 @@ @include background-image(linear-gradient(-90deg, rgb(250,250,250) 0%, rgb(245,245,245) 50%, rgb(235,235,235) 50%, rgb(230,230,230) 100%)); border-radius: 4px; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.4), inset 0 1px 0 0 rgba(255, 255, 255, 0.6); - border: 1px solid rgb(200,200,200); + border: 1px solid rgb(200, 200, 200); color: $body-color; cursor: pointer; height: 36px; @@ -56,7 +52,7 @@ ul { background: rgb(255, 255, 255); border-radius: 0 4px 4px; - border: 1px solid rgb(200,200,200); + border: 1px solid rgb(200, 200, 200); box-shadow: 0 2px 15px 0 $shadow; padding: 20px 0 5px 20px; position: absolute; @@ -70,14 +66,15 @@ } } - &:hover, &:focus { + &:hover, + &:focus { .filter-heading { background: rgb(255, 255, 255); - @include background-image(linear-gradient(-90deg, rgb(250,250,250), rgb(255, 255, 255))); + @include background-image(linear-gradient(-90deg, rgb(250, 250, 250), rgb(255, 255, 255))); border-radius: 4px 4px 0 0; - border-bottom: 1px dotted rgb(200,200,200); + border-bottom: 1px dotted rgb(200, 200, 200); box-shadow: 0 2px 0 -1px rgb(255, 255, 255); color: $body-color; height: 40px; diff --git a/lms/static/sass/shared/_course_object.scss b/lms/static/sass/shared/_course_object.scss index 5d77a47aa0b7e02e59729c46ddf2d2afec153c22..82ec1d9c98c6dc0da4a61a5dac75c71f48ec5fa9 100644 --- a/lms/static/sass/shared/_course_object.scss +++ b/lms/static/sass/shared/_course_object.scss @@ -1,8 +1,9 @@ -.highlighted-courses, .find-courses { +.highlighted-courses, +.find-courses { .courses { @include clearfix(); - padding: ($baseline*2) 0 ($baseline*0.75) ; + padding: ($baseline*2) 0 ($baseline*0.75); .university-column { width: flex-grid(4); @@ -20,9 +21,7 @@ background: $body-bg; border: 1px solid $border-color-1; border-radius: 2px; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 10px 0 rgba(0, 0, 0, 0.15), inset 0 0 0 1px rgba(255, 255, 255, 0.9); margin-bottom: ($baseline*1.5); position: relative; @@ -60,7 +59,8 @@ display: block; } - a:hover, a:focus { + a:hover, + a:focus { text-decoration: none; } @@ -103,15 +103,15 @@ width: 100%; z-index: 3; - // > a { @include background-image(linear-gradient(-90deg, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0.85))); box-shadow: inset 0 -1px 0 0 rgba(255, 255, 255, 0.2); - border-bottom: 1px solid rgba(150,150,150, 0.7); + border-bottom: 1px solid rgba(150, 150, 150, 0.7); display: block; height: 50px; - &:hover, &:focus { + &:hover, + &:focus { @include background-image(linear-gradient(-90deg, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0.8))); text-decoration: none; @@ -156,10 +156,8 @@ } .info-link { - border-left: 1px solid rgba(150,150,150, 0.5); - - @include box-sizing(border-box); - + border-left: 1px solid rgba(150, 150, 150, 0.5); + box-sizing: border-box; color: $body-color; display: inline-block; font: bold 1.6em/1.2em $font-family-sans-serif; @@ -174,9 +172,7 @@ width: 60px; vertical-align: middle; } - } - // } .info { background: $body-bg; @@ -203,8 +199,7 @@ } .desc { - @include box-sizing(border-box); - + box-sizing: border-box; height: 120px; overflow: hidden; padding: 10px 10px 12px; @@ -222,8 +217,7 @@ } .bottom { - @include box-sizing(border-box); - + box-sizing: border-box; padding: 0 10px 10px; width: 100%; @@ -232,7 +226,7 @@ letter-spacing: 1px; } - .start-date { + .start-date { border-left: 1px solid $border-color-2; margin-left: ($baseline/4); padding-left: ($baseline/2); @@ -242,7 +236,8 @@ } } - &:hover, &:focus { + &:hover, + &:focus { background: $course-profile-bg; border-color: $border-color-1; box-shadow: 0 1px 4px 0 rgba($shadow-color, 0.4); diff --git a/lms/static/sass/shared/_fields.scss b/lms/static/sass/shared/_fields.scss index 344d0a4f533d1674a967a10e1e93c19cc14b27e4..34536fd7c05fa5883eb6c49d74f78c3cb3df5834 100644 --- a/lms/static/sass/shared/_fields.scss +++ b/lms/static/sass/shared/_fields.scss @@ -32,7 +32,6 @@ display: inline-block; color: $link-color; } - } &.mode-hidden { @@ -41,7 +40,7 @@ i { color: $gray-l2; - vertical-align:text-bottom; + vertical-align: text-bottom; @include margin-right(5px); } @@ -90,7 +89,8 @@ margin-bottom: 0; -webkit-font-smoothing: antialiased; - label, span { + label, + span { @include margin-left($baseline/2); } } @@ -100,7 +100,8 @@ display: inline-block; vertical-align: top; - select, input { + select, + input { width: 100%; } } @@ -126,11 +127,15 @@ } .u-field-dropdown { - &.mode-display select, &.mode-placeholder select { + &.mode-display select, + &.mode-placeholder select { display: none; } - button.u-field-value-display, button.u-field-value-display:active, button.u-field-value-display:focus, button.u-field-value-display:hover { + button.u-field-value-display, + button.u-field-value-display:active, + button.u-field-value-display:focus, + button.u-field-value-display:hover { border-color: transparent; background: transparent; padding: 0; diff --git a/lms/static/sass/shared/_footer-edx.scss b/lms/static/sass/shared/_footer-edx.scss index 62d7ee00198e8507370fbbe10ddcda82c7567795..6a7fe943ad26247b76fab901164191d2ca001f4f 100644 --- a/lms/static/sass/shared/_footer-edx.scss +++ b/lms/static/sass/shared/_footer-edx.scss @@ -167,7 +167,8 @@ footer#footer-edx-v3 { .footer-content-wrapper { @include outer-container; - @include box-sizing(border-box); + + box-sizing: border-box; } p { @@ -183,6 +184,7 @@ footer#footer-edx-v3 { a { text-decoration: underline !important; } + @include margin-left(8px); @include font-size(16); @include line-height(24px); @@ -855,10 +857,10 @@ footer#footer-edx-v3 { &:hover, &:active, &:focus { - background: $m-blue-d3 !important; - color: white !important; + background: $m-blue-d3 !important; + color: white !important; } -} + } @extend %ui-print-excluded; diff --git a/lms/static/sass/shared/_footer.scss b/lms/static/sass/shared/_footer.scss index e29332d4936dac8bd4dfe6f0c89997ec0c9bcb24..18ef6d6a7dc823e08fa9c64ca5300220c6d03792 100644 --- a/lms/static/sass/shared/_footer.scss +++ b/lms/static/sass/shared/_footer.scss @@ -14,12 +14,16 @@ footer#footer-openedx { @include clearfix(); - @include box-sizing(border-box); + + box-sizing: border-box; + @include outer-container; margin: 0 auto; - p, ol, ul { + p, + ol, + ul { font-family: $font-family-sans-serif; // override needed for poorly scoped font-family styling on p a:link {} @@ -35,7 +39,9 @@ color: $link-color; text-decoration: none !important; - &:hover, &:focus, &:active { + &:hover, + &:focus, + &:active { border-bottom: 1px dotted $link-color; } } @@ -71,7 +77,9 @@ a { color: tint($black, 20%); - &:hover, &:focus, &:active { + &:hover, + &:focus, + &:active { color: $link-color; } } @@ -94,7 +102,7 @@ p { float: left; - width: flex-grid(6,8); + width: flex-grid(6, 8); margin-left: $baseline; padding-left: $baseline; font-size: em(13); @@ -106,7 +114,7 @@ // references .references { margin: -10px 0 0 0; - width: flex-grid(4,12); + width: flex-grid(4, 12); display: inline-block; } @@ -159,7 +167,9 @@ a { display: block; - &:hover, &:focus, &:active { + &:hover, + &:focus, + &:active { border: none; } } @@ -204,16 +214,16 @@ } .select-lang-button { - padding: 5px; - color: $m-blue-d3 !important; - height: 30px; - - &:hover, - &:active, - &:focus { - background: $m-blue-d3 !important; - color: white !important; - } + padding: 5px; + color: $m-blue-d3 !important; + height: 30px; + + &:hover, + &:active, + &:focus { + background: $m-blue-d3 !important; + color: white !important; + } } } @@ -232,7 +242,9 @@ } // marketing site design syncing -.view-register, .view-login, .view-passwordreset { +.view-register, +.view-login, +.view-passwordreset { .wrapper-footer footer { width: 960px; diff --git a/lms/static/sass/shared/_forms.scss b/lms/static/sass/shared/_forms.scss index 912fb8ce642c251559d1ec5d473881fae0278996..3dd8e52ec9ced009657ebc6363f92265b0c9b59a 100644 --- a/lms/static/sass/shared/_forms.scss +++ b/lms/static/sass/shared/_forms.scss @@ -33,9 +33,7 @@ input[type="tel"] { border: 1px solid $border-color-2; border-radius: 3px; box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.6), inset 0 0 3px 0 $shadow-l1; - - @include box-sizing(border-box); - + box-sizing: border-box; font: italic 300 1rem/1.6rem $serif; height: 35px; padding: ($baseline/4) 12px; diff --git a/lms/static/sass/shared/_header.scss b/lms/static/sass/shared/_header.scss index 297cc7d92d3bf2e869215fd85a2af3adc15bfeb4..898933685b26424e0a817b65b50a18a2ca7cf7a9 100644 --- a/lms/static/sass/shared/_header.scss +++ b/lms/static/sass/shared/_header.scss @@ -95,9 +95,7 @@ @include background-image($button-bg-image); background-color: $button-bg-color; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.6); color: $body-color; display: inline-block; @@ -264,9 +262,7 @@ > a { border: 1px solid transparent; border-radius: 3px; - - @include box-sizing(border-box); - + box-sizing: border-box; color: $link-color; cursor: pointer; display: block; @@ -401,8 +397,7 @@ @extend %ui-depth1; /* Temp. fix until applied globally */ - @include box-sizing(border-box); - + box-sizing: border-box; position: relative; width: 100%; border-bottom: 1px solid $gray-l1; @@ -411,8 +406,8 @@ .wrapper-header { @include clearfix(); - @include box-sizing(border-box); + box-sizing: border-box; height: 74px; margin: 0 auto; padding: 17px 0; @@ -519,9 +514,7 @@ @include background-image($button-bg-image); background-color: $button-bg-color; - - @include box-sizing(border-box); - + box-sizing: border-box; box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.6); color: $body-color; font-family: $header-sans-serif; @@ -679,9 +672,7 @@ > a { border: 1px solid transparent; border-radius: 3px; - - @include box-sizing(border-box); - + box-sizing: border-box; color: $link-color; cursor: pointer; display: block; diff --git a/lms/static/sass/shared/_help-tab.scss b/lms/static/sass/shared/_help-tab.scss index e08507029d9e607287761b54621357dc2bf38e32..ea48096d10f1cea5ca485c79fd088e8c12ae3812 100644 --- a/lms/static/sass/shared/_help-tab.scss +++ b/lms/static/sass/shared/_help-tab.scss @@ -68,7 +68,8 @@ } #feedback_form { - input, textarea { + input, + textarea { font: normal 1em/1.4em $font-family-sans-serif; } diff --git a/lms/static/sass/shared/_modal.scss b/lms/static/sass/shared/_modal.scss index 710f8e50f64833a8683affb42c7b0dbe9f2b6036..88eb6c354d535e94cacc3273b237e56ed19254a3 100644 --- a/lms/static/sass/shared/_modal.scss +++ b/lms/static/sass/shared/_modal.scss @@ -164,7 +164,8 @@ display: block; color: #8f0e0e; - + input, + textarea { + + input, + + textarea { border: 1px solid #ca1111; color: #8f0e0e; } @@ -349,7 +350,8 @@ .modal-settings-language { // general reset - .list-input, .list-actions { + .list-input, + .list-actions { @extend %ui-no-list; } diff --git a/lms/static/sass/shared/_tooltips.scss b/lms/static/sass/shared/_tooltips.scss index aec9772838f80f8e8451743990460b22dcfb7c15..5b75ab5b9bf2f09de8091ae307d697442767768d 100644 --- a/lms/static/sass/shared/_tooltips.scss +++ b/lms/static/sass/shared/_tooltips.scss @@ -57,7 +57,8 @@ } } - &:hover, &:focus { + &:hover, + &:focus { p { display: block; margin-top: $margin-top; diff --git a/lms/static/sass/shared/_unsubscribe.scss b/lms/static/sass/shared/_unsubscribe.scss index cc38e0beb2ccbd9838612888ade3630940094b7a..ed4bdce5a016be2793d42dafdc8a9e5972e98bae 100644 --- a/lms/static/sass/shared/_unsubscribe.scss +++ b/lms/static/sass/shared/_unsubscribe.scss @@ -13,8 +13,8 @@ } .message { - background: rgb(252,252,252); - border: 1px solid rgb(200,200,200); + background: rgb(252, 252, 252); + border: 1px solid rgb(200, 200, 200); box-shadow: 0 3px 20px 0 $shadow; border-radius: 4px; margin: 0 auto; diff --git a/lms/static/sass/views/_account-settings.scss b/lms/static/sass/views/_account-settings.scss index 4ccdf7609f002ceae45cb2791f0102681a86e8fe..a4e5ff76eab68ba99d077f19bdd9b29c17d10777 100644 --- a/lms/static/sass/views/_account-settings.scss +++ b/lms/static/sass/views/_account-settings.scss @@ -133,6 +133,7 @@ .account-settings-header-subtitle-warning { @extend .account-settings-header-subtitle; + color: $alert-color; } @@ -397,7 +398,8 @@ } .u-field { - &.u-field-dropdown, &.editable-never &.mode-display { + &.u-field-dropdown, + &.editable-never &.mode-display { .u-field-value { margin-bottom: ($baseline); @@ -642,7 +644,7 @@ } .account-settings-message { - margin-bottom: 0px; + margin-bottom: 0; .alert-message { padding: 10px; diff --git a/lms/static/sass/views/_api-access.scss b/lms/static/sass/views/_api-access.scss index afdeb3f564d24b16a9d38fef5ae68abb4b6e8c04..75c32fa52fa6e33f97adf51dccf186275d894de4 100644 --- a/lms/static/sass/views/_api-access.scss +++ b/lms/static/sass/views/_api-access.scss @@ -78,7 +78,8 @@ display: inline-block; } - input, textarea { + input, + textarea { @extend %t-copy-base; font-family: 'Open Sans'; @@ -117,7 +118,8 @@ } } - #api-access-submit, .preview-query { + #api-access-submit, + .preview-query { @extend %t-copy-base; border-radius: 3px; diff --git a/lms/static/sass/views/_course-entitlements.scss b/lms/static/sass/views/_course-entitlements.scss index 03a9e31df48ecf1154f5a13a05aaa6bdca7f832b..6eb3d85bc5ddbfcb54e93eb229ae9b3b74ce5216 100644 --- a/lms/static/sass/views/_course-entitlements.scss +++ b/lms/static/sass/views/_course-entitlements.scss @@ -120,9 +120,8 @@ padding-top: $baseline/2; .action-header, - .action-controls .session-select{ + .action-controls .session-select { font-size: $font-size-sm; - } } } diff --git a/lms/static/sass/views/_decoupled-verification.scss b/lms/static/sass/views/_decoupled-verification.scss index 210d50c7b9784487506e3161d4aa81aab9d0d66c..674cd903adf171150f2e7965e45c2653373e798b 100644 --- a/lms/static/sass/views/_decoupled-verification.scss +++ b/lms/static/sass/views/_decoupled-verification.scss @@ -1,6 +1,8 @@ // Updates for decoupled verification A/B test .verification-process { - .pay-and-verify, .incourse-reverify, .reverify { + .pay-and-verify, + .incourse-reverify, + .reverify { .review { .title.center-col { padding: 0 calc((100% - 750px) / 2) 10px; @@ -151,13 +153,14 @@ .retake-photos { color: $blue; - background:none!important; - border:0!important; - padding:0!important; + background: none !important; + border: 0 !important; + padding: 0 !important; box-shadow: none; cursor: pointer; - &:hover, &:focus { + &:hover, + &:focus { text-decoration: underline; } } diff --git a/lms/static/sass/views/_financial-assistance.scss b/lms/static/sass/views/_financial-assistance.scss index 9f16367c8599f0c2d7597c196fde3ee67aa6a120..20370aa617da946b30cd5e7aadc26679f05fc7b5 100644 --- a/lms/static/sass/views/_financial-assistance.scss +++ b/lms/static/sass/views/_financial-assistance.scss @@ -4,7 +4,7 @@ padding: ($baseline/2) 0; margin: 0; color: $m-gray-d2; -}; +} .financial-assistance-wrapper { margin: auto; diff --git a/lms/static/sass/views/_homepage.scss b/lms/static/sass/views/_homepage.scss index 6e96f6d92acb8a4f28e3f87f72e7f42613456fd0..bb7963fba6c389a322536e0a46b72a18dd355fd0 100644 --- a/lms/static/sass/views/_homepage.scss +++ b/lms/static/sass/views/_homepage.scss @@ -11,7 +11,7 @@ $learn-more-horizontal-position: calc(50% - 100px); // calculate the left positi @include row(); @include float(left); - width:100%; + width: 100%; .courses-listing { @extend %ui-no-list; @@ -23,7 +23,8 @@ $learn-more-horizontal-position: calc(50% - 100px); // calculate the left positi } .course { - @include box-sizing(border-box); + box-sizing: border-box; + @include transition(all $tmg-f3 linear 0s); position: relative; @@ -58,7 +59,8 @@ $learn-more-horizontal-position: calc(50% - 100px); // calculate the left positi .learn-more { @include left($learn-more-horizontal-position); - @include box-sizing(border-box); + + box-sizing: border-box; @extend %ui-depth2; @@ -86,13 +88,17 @@ $learn-more-horizontal-position: calc(50% - 100px); // calculate the left positi font-family: $font-family-sans-serif; } - .course-organization, .course-code, .course-date { + .course-organization, + .course-code, + .course-date { @extend %t-icon6; color: $gray-d2; } - .course-organization, .course-code, .course-title { + .course-organization, + .course-code, + .course-title { display: block; text-transform: none; } diff --git a/lms/static/sass/views/_login-register.scss b/lms/static/sass/views/_login-register.scss index ed1c19e6f8b795f9a426e40cdcc118baf3ddfd6f..42e23f098b1de8883985f4537f05931bf3c99f22 100644 --- a/lms/static/sass/views/_login-register.scss +++ b/lms/static/sass/views/_login-register.scss @@ -56,7 +56,8 @@ } .login-register-content { - @include box-sizing(border-box); + box-sizing: border-box; + @include outer-container; width: 100%; @@ -97,6 +98,16 @@ } } +#login-help, #reset-help { + padding-left: 8px; +} +ul.fa-ul{ + margin: 0 0 0 0; + i { + margin-right: 5px; + } +} + .login-register { $grid-columns: 12; @@ -116,13 +127,13 @@ /* Temp. fix until applied globally */ > { - @include box-sizing(border-box); + box-sizing: border-box; } /* Remove autocomplete yellow background */ input:-webkit-autofill { - -webkit-box-shadow:0 0 0 50px white inset; + -webkit-box-shadow: 0 0 0 50px white inset; -webkit-text-fill-color: #333; } @@ -141,7 +152,8 @@ overflow: hidden; .headline { - @include box-sizing(border-box); + box-sizing: border-box; + @include font-size(35); padding: 0 10px; @@ -153,7 +165,8 @@ } .tagline { - @include box-sizing(border-box); + box-sizing: border-box; + @include font-size(24); padding: 0 10px; @@ -215,8 +228,7 @@ .form-type, .toggle-form { - @include box-sizing(border-box); - + box-sizing: border-box; max-width: 600px; min-width: 250px; margin: 0 auto; @@ -371,8 +383,8 @@ @extend %t-copy-sub2; display: block; - margin-bottom: ($baseline/2); - margin-top: ($baseline/4); + margin-bottom: 5px; + margin-top: 5px; border: none; padding: 0; background: transparent; @@ -389,6 +401,11 @@ &:focus { text-decoration: underline; } + > i { + border: none; + padding: 0; + margin: 0 2px 0 0; + } } input, @@ -468,7 +485,8 @@ } } - .tip, .label-optional { + .tip, + .label-optional { @extend %t-copy-sub1; color: $uxpl-gray-base; @@ -632,7 +650,6 @@ color: $white; } } - } .button-secondary-login { @@ -647,18 +664,16 @@ &:hover { border-color: $m-blue-d3; box-shadow: none; - } } /** Error Container - from _account.scss **/ .status { - @include box-sizing(border-box); - + box-sizing: border-box; margin: 0 0 25px; border-bottom: 3px solid shade($yellow, 10%); padding: 25px; - background: tint($yellow,20%); + background: tint($yellow, 20%); .message-title { @extend %t-title5; @@ -706,18 +721,15 @@ } } - .submission-error, .system-error { + .submission-error, + .system-error { box-shadow: inset 0 -1px 2px 0 tint($red, 85%); border-bottom: 3px solid shade($red, 10%); - background: tint($red,95%); + background: tint($red, 95%); .message-title { color: shade($red, 10%) !important; } - - .message-copy { - - } } .submission-success { @@ -728,10 +740,6 @@ .message-title { color: shade($green, 10%) !important; } - - .message-copy { - - } } .institution-list { @@ -754,7 +762,8 @@ } .finish-auth { - @include box-sizing(border-box); + box-sizing: border-box; + @include outer-container; $grid-columns: 12; @@ -763,8 +772,7 @@ width: 100%; .finish-auth-inner { - @include box-sizing(border-box); - + box-sizing: border-box; max-width: 650px; margin: 1em auto; } diff --git a/lms/static/sass/views/_oauth2.scss b/lms/static/sass/views/_oauth2.scss index 885d9b6fcc5f27624a266b06a5cff0c219ca86b9..9849cc4c44468fb02e79641623982fc95e5092e4 100644 --- a/lms/static/sass/views/_oauth2.scss +++ b/lms/static/sass/views/_oauth2.scss @@ -10,7 +10,6 @@ float: unset !important; // fixes issues with oauth page and edx-theme footer line-height: 1.5em; padding: 50px 0; - } } diff --git a/lms/static/sass/views/_program-details.scss b/lms/static/sass/views/_program-details.scss index 880ea6f7b991d7a821f9a4e6826a1062b8b8fa22..6d786588f135f3804e150af6edcdc1ecafc5083b 100644 --- a/lms/static/sass/views/_program-details.scss +++ b/lms/static/sass/views/_program-details.scss @@ -4,7 +4,7 @@ // +local variables/utilities: // ---------------------- -$btn-color-primary: palette(primary, dark); +$btn-color-primary: $primary-dark; .program-details { .content-wrapper { @@ -44,7 +44,7 @@ $btn-color-primary: palette(primary, dark); .breadcrumb-wrapper { padding: $full-width-banner-margin; - @media (min-width: $bp-screen-xl) { + @include media-breakpoint-up(xl) { padding-left: 0; } } @@ -60,21 +60,21 @@ $btn-color-primary: palette(primary, dark); position: relative; font-size: font-size(x-small); line-height: line-height(x-small); - color: palette(grayscale, dark); + color: $gray-dark; &.active { - color: palette(grayscale, dark); + color: $gray-dark; } } .crumb-link { font-size: inherit; line-height: inherit; - color: palette(primary, base); + color: $primary-base; &:hover, &:focus { - color: palette(grayscale, black); + color: $gray-dark; text-decoration: underline; } } @@ -102,7 +102,7 @@ $btn-color-primary: palette(primary, dark); .program-details-wrapper { .program-details-header { - background-color: $light-gray4; + background-color: $gray-light1; display: flex; color: black; font-family: 'Open Sans'; @@ -110,7 +110,7 @@ $btn-color-primary: palette(primary, dark); flex-wrap: wrap; padding: 40px 10px 35px; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { padding: { left: 30px; right: 30px; @@ -127,7 +127,7 @@ $btn-color-primary: palette(primary, dark); .hd-1 { font-size: 1.5em; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { font-size: 2.375em; } } @@ -143,8 +143,10 @@ $btn-color-primary: palette(primary, dark); } /* IE11 CSS styles */ - @media (min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) { - height: 50px; + @include media-breakpoint-up(md) { + @media (-ms-high-contrast: none), (-ms-high-contrast: active) { + height: 50px; + } } } @@ -152,7 +154,7 @@ $btn-color-primary: palette(primary, dark); fill: $micromasters-color; width: 200px; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { width: 250px; } } @@ -161,7 +163,7 @@ $btn-color-primary: palette(primary, dark); fill: xseries-color; width: 150px; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { width: 200px; } } @@ -170,7 +172,7 @@ $btn-color-primary: palette(primary, dark); fill: $professional-certificate-color; width: 250px; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { width: 300px; } } @@ -179,11 +181,11 @@ $btn-color-primary: palette(primary, dark); margin: 0; display: block; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { width: 70%; } - @media (min-width: $bp-screen-lg) { + @include media-breakpoint-up(lg) { width: 75%; } @@ -197,24 +199,24 @@ $btn-color-primary: palette(primary, dark); text-align: center; display: flex; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { display: block; } .heading { font-family: $font-family-sans-serif; font-weight: bold; - color: palette(primary, dark); + color: $primary-dark; font-size: 0.9375em; margin-top: auto; margin-bottom: auto; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { @include margin-right(10px 0 0 0); } } - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { margin: initial; width: 30%; @@ -226,7 +228,7 @@ $btn-color-primary: palette(primary, dark); } } - @media (min-width: $bp-screen-lg) { + @include media-breakpoint-up(lg) { width: 25%; } } @@ -237,7 +239,7 @@ $btn-color-primary: palette(primary, dark); margin-bottom: 30px; padding: 30px 10px; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { @include float(left); padding: { left: 30px; @@ -248,7 +250,7 @@ $btn-color-primary: palette(primary, dark); position: relative; } - @media (min-width: $bp-screen-lg) { + @include media-breakpoint-up(lg) { width: calc(100% - 510px); max-width: 700px; } @@ -261,7 +263,7 @@ $btn-color-primary: palette(primary, dark); .course-list-heading { font-family: $font-family-sans-serif; font-weight: bold; - color: palette(primary, dark); + color: $primary-dark; font-size: 0.9375em; line-height: normal; padding-bottom: 5px; @@ -287,7 +289,7 @@ $btn-color-primary: palette(primary, dark); font-size: 0.9375em; width: 310px; - @media (min-width: $bp-screen-sm) { + @include media-breakpoint-up(sm) { width: auto; } @@ -312,7 +314,7 @@ $btn-color-primary: palette(primary, dark); font-family: $font-family-sans-serif; font-weight: 600; font-size: 1.3em; - color: palette(grayscale, base); + color: $gray-base; margin-bottom: 5px; line-height: normal; } @@ -326,6 +328,7 @@ $btn-color-primary: palette(primary, dark); .view-course-button { background: $btn-color-primary; border-color: $btn-color-primary; + color: $white; height: 37px; padding: 7px 18.5px 0; width: auto; @@ -335,11 +338,13 @@ $btn-color-primary: palette(primary, dark); margin-top: 5px; /* IE11 CSS styles */ - @media (min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) { - @include float(right); + @include media-breakpoint-up(lg) { + @media (-ms-high-contrast: none), (-ms-high-contrast: active) { + @include float(right); + } } - @media (min-width: $bp-screen-lg) { + @include media-breakpoint-up(lg) { margin-top: 0; } } @@ -347,20 +352,22 @@ $btn-color-primary: palette(primary, dark); .enroll-button { width: 100%; - @media (min-width: $bp-screen-sm) { + @include media-breakpoint-up(sm) { width: initial; margin-bottom: 0; margin-top: 17px; } - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { width: initial; margin-top: 0; margin-bottom: 0; } - button, .enroll-course-button { + button, + .enroll-course-button { background-color: $btn-color-primary; + color: $white; height: 37px; width: 128px; padding: 0; @@ -374,8 +381,10 @@ $btn-color-primary: palette(primary, dark); } /* IE11 CSS styles */ - @media (min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) { - @include float(right); + @include media-breakpoint-up(md) { + @media (-ms-high-contrast: none), (-ms-high-contrast: active) { + @include float(right); + } } } @@ -390,17 +399,17 @@ $btn-color-primary: palette(primary, dark); font-family: $font-family-sans-serif; font-weight: bold; font-size: 0.9375em; - color: palette(grayscale, base); + color: $gray-base; margin-top: 6px; display: block; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { display: inline; } } .run-select-container { - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { margin-top: 8px; display: flex; flex-wrap: wrap; @@ -415,23 +424,26 @@ $btn-color-primary: palette(primary, dark); } .upgrade-button { - background: palette(success, text); - border-color: palette(success, text); + background: theme-color("success"); + border-color: theme-color("success"); + color: $white; border-radius: 0; padding: 7px; text-align: center; font-size: 0.9375em; /* IE11 CSS styles */ - @media (min-width: $bp-screen-md) and (-ms-high-contrast: none), (-ms-high-contrast: active) { - @include float(right); + @include media-breakpoint-up(md) { + @media (-ms-high-contrast: none), (-ms-high-contrast: active) { + @include float(right); + } } &.complete-program { margin: 10px 15px 10px 5px; align-self: flex-start; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { align-self: flex-end; } @@ -446,7 +458,7 @@ $btn-color-primary: palette(primary, dark); width: 100%; padding: 15px; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { height: auto; } @@ -455,7 +467,7 @@ $btn-color-primary: palette(primary, dark); flex-direction: column; justify-content: space-between; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { flex-wrap: wrap; } } @@ -472,7 +484,7 @@ $btn-color-primary: palette(primary, dark); width: 100%; float: none; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { display: table-cell; vertical-align: top; float: left; @@ -484,25 +496,25 @@ $btn-color-primary: palette(primary, dark); margin: 0; .course-title-link, - .course-title-link:visited{ - color: palette(primary, base); + .course-title-link:visited { + color: $primary-base; text-decoration: underline; } } .run-period, .info-expires-at { - color: palette(grayscale, base); + color: $gray-base; font-size: 0.9375em; } .course-text .enrolled { - color: palette(grayscale, base); + color: $gray-base; } } .course-meta-container { - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { display: table; width: 100%; } @@ -513,14 +525,14 @@ $btn-color-primary: palette(primary, dark); } .course-actions { - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { width: 100%; text-align: right; float: right; } .course-enroll-view { - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { text-align: right; } } @@ -533,14 +545,14 @@ $btn-color-primary: palette(primary, dark); .final-grade { .grade-header { - color: palette(grayscale, base); + color: $gray-base; font-weight: bold; } .grade-display { padding-right: 15px; font-size: 1.5em; - color: palette(primary, accent); + color: $primary-accent; } } @@ -551,7 +563,7 @@ $btn-color-primary: palette(primary, dark); width: 100%; margin: 5px 0; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { margin-left: auto; width: initial; } @@ -561,11 +573,11 @@ $btn-color-primary: palette(primary, dark); padding-top: 0; width: initial; - @media (min-width: $bp-screen-sm) { + @include media-breakpoint-up(sm) { width: 300px; } - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { width: initial; } @@ -573,36 +585,35 @@ $btn-color-primary: palette(primary, dark); font-family: $font-family-sans-serif; font-weight: bold; font-size: 0.9375em; - color: palette(grayscale, base); + color: $gray-base; display: block; - @media (min-width: $bp-screen-sm) { + @include media-breakpoint-up(sm) { display: inline; } } .price { - color: palette(success, text); + color: theme-color("success"); font-weight: bold; } } - } .certificate-status { .fa-check-circle { - color: palette(success, text); + color: theme-color("success"); } .card-msg { font-family: $font-family-sans-serif; font-weight: bold; font-size: 0.9375em; - color: palette(grayscale, base); + color: $gray-base; } .certificate-status-msg { - color: palette(grayscale, base); + color: $gray-base; font-size: 0.9375em; } } @@ -612,12 +623,12 @@ $btn-color-primary: palette(primary, dark); padding-top: 5px; width: 300px; - @media (min-width: $bp-screen-sm) { + @include media-breakpoint-up(sm) { padding-top: 10px; width: 500px; } - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { width: initial; } } @@ -625,7 +636,7 @@ $btn-color-primary: palette(primary, dark); .expired-icon { @include float(left); - color: palette(primary, dark); + color: $primary-dark; } .expired-text { @@ -650,7 +661,7 @@ $btn-color-primary: palette(primary, dark); font-size: 0.9375em; width: $baseline*15.5; - @media (min-width: $bp-screen-sm) { + @include media-breakpoint-up(sm) { width: auto; } @@ -662,7 +673,7 @@ $btn-color-primary: palette(primary, dark); .divider-heading { font-family: $font-family-sans-serif; font-weight: bold; - color: palette(primary, dark); + color: $primary-dark; font-size: 0.9375em; line-height: normal; padding-bottom: $baseline*0.25; @@ -686,11 +697,12 @@ $btn-color-primary: palette(primary, dark); @include margin-left($baseline*0.75); width: $baseline*15.5; - border-bottom: 1px solid $gray-l4; + border-bottom: 1px solid $gray-light3; - @media (min-width: $bp-screen-sm) { - width: auto; + @include media-breakpoint-up(sm) { + width: auto; } + .pathway-info { margin: 15px 0; font-size: 0.9375em; @@ -707,7 +719,7 @@ $btn-color-primary: palette(primary, dark); border-bottom: none; } - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { @include float(right); width: $baseline*15; @@ -715,7 +727,7 @@ $btn-color-primary: palette(primary, dark); position: relative; } - @media (min-width: $bp-screen-lg) { + @include media-breakpoint-up(lg) { width: $baseline*22.5; .program-progress { @@ -731,11 +743,11 @@ $btn-color-primary: palette(primary, dark); .certificate-heading { margin-bottom: 10px; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { @include margin-right(30px); } - @media (min-width: $bp-screen-lg) { + @include media-breakpoint-up(lg) { @include margin-left(10px); @include margin-right(0); } @@ -748,7 +760,7 @@ $btn-color-primary: palette(primary, dark); &:focus, &:hover { .program-cert { - border-color: $blue-d1; + border-color: $primary-dark1; } } } @@ -757,11 +769,11 @@ $btn-color-primary: palette(primary, dark); width: 100%; border: 1px solid $divider-color; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { width: calc(100% - 30px); } - @media (min-width: $bp-screen-lg) { + @include media-breakpoint-up(lg) { width: 100%; } } @@ -779,7 +791,7 @@ $btn-color-primary: palette(primary, dark); .image-link { flex: 0 0 100px; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { flex: 0 0 120px; } } @@ -794,11 +806,11 @@ $btn-color-primary: palette(primary, dark); weight: 600; } - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { font-size: 0.9em; } - @media (min-width: $bp-screen-lg) { + @include media-breakpoint-up(lg) { font-size: 1.1em; } @@ -806,21 +818,21 @@ $btn-color-primary: palette(primary, dark); &:focus, &:hover { .sample-cert { - border-color: $blue-d1; + border-color: $primary-dark1; } } } .sample-cert { width: 120px; - border: 3px solid $gray-l3; + border: 3px solid $gray-light2; border-radius: 5px; - @media (min-width: $bp-screen-md) { + @include media-breakpoint-up(md) { width: 100px; } - @media (min-width: $bp-screen-lg) { + @include media-breakpoint-up(lg) { width: 120px; } } diff --git a/lms/static/sass/views/_program-list.scss b/lms/static/sass/views/_program-list.scss index 89f27dc85c10e0621fe016388e67d53c7e442533..3cc8a5b9080b5a4f03890df82aa7463e2f47c2c3 100644 --- a/lms/static/sass/views/_program-list.scss +++ b/lms/static/sass/views/_program-list.scss @@ -1,4 +1,9 @@ .program-list-wrapper { + @include make-row(); + + max-width: 73.125rem; + margin: 0 auto; + @include media-breakpoint-up(sm) { padding: $baseline; } @@ -6,28 +11,31 @@ .program-cards-container { @include grid-container(); - @include span(12); + @include make-col(12); + + padding: 0 8px; @include media-breakpoint-up(sm) { - @include span(9); + @include make-col(9); } } .sidebar { - @include span(12); + @include make-col(12); @include float(right); margin-bottom: $baseline; + padding: 0 8px; @include media-breakpoint-up(sm) { - @include span(3); + @include make-col(3); } .aside { padding: $baseline; margin-bottom: $baseline; box-sizing: border-box; - border: 1px solid $border-color-l3; + border: 1px solid $gray-500; } .program-advertise { @@ -37,22 +45,32 @@ width: 100%; text-align: center; padding: 10px; + white-space: normal; + border-color: theme-color("primary"); + color: theme-color("primary"); + font-weight: 600; + &:hover, + &:active, + &:focus { + background: theme-color("primary"); + color: $white; + } } .advertise-message { - font-size: font-size(x-small); - color: palette(grayscale, black); + font-size: 0.75rem; + color: $gray-dark; margin-bottom: $baseline; } } } .empty-programs-message { - @include span(12); + @include make-col(12); - border: 3px solid $gray-l4; - background: $gray-l6; + background: $gray-light4; + border: 3px solid $gray-light3; padding: ($baseline*2) 0; text-align: center; margin-bottom: 20px; diff --git a/lms/static/sass/views/_shoppingcart.scss b/lms/static/sass/views/_shoppingcart.scss index e28d615de840db8bcac0980565ccd8f50a69edd2..bcf6c3aef8952fca5d586e9dae522431d5bb44fe 100644 --- a/lms/static/sass/views/_shoppingcart.scss +++ b/lms/static/sass/views/_shoppingcart.scss @@ -205,7 +205,9 @@ $light-border: 1px solid $gray-l5; position: relative; } - input[type="text"], input[type="email"], select { + input[type="text"], + input[type="email"], + select { @extend %t-action2; @extend %t-strong; @@ -324,7 +326,8 @@ $light-border: 1px solid $gray-l5; width: calc(100% - #{$data-input-width-difference}); - h3, h3 span { + h3, + h3 span { @extend %t-title6; padding: 0; @@ -1050,7 +1053,7 @@ $light-border: 1px solid $gray-l5; border-bottom: 1px solid $light-gray1; // CASE: has last child - &:last-child { + &:last-child { border-bottom: none; } @@ -1111,7 +1114,8 @@ $light-border: 1px solid $gray-l5; } } -.course-image, .image { +.course-image, +.image { .item-image { width: 100%; height: 100%; @@ -1174,7 +1178,10 @@ $light-border: 1px solid $gray-l5; content: none !important; } - .steps, .blue.pull-right, .bordered-bar .pull-right, .left.nav-global.authenticated { + .steps, + .blue.pull-right, + .bordered-bar .pull-right, + .left.nav-global.authenticated { display: none; } @@ -1211,7 +1218,7 @@ $light-border: 1px solid $gray-l5; .redemption-url { &::before { display: inline-block; - content:" " attr(data-base-url) " "; + content: " " attr(data-base-url) " "; } } diff --git a/lms/static/sass/views/_support.scss b/lms/static/sass/views/_support.scss index 74d88982c3fd9c5cd6b0ad73c0e4294728690bef..ca6f632768d695647e4aa7d362ceff3ade5e1896 100644 --- a/lms/static/sass/views/_support.scss +++ b/lms/static/sass/views/_support.scss @@ -16,7 +16,7 @@ } } -.manage-user-search{ +.manage-user-search { margin: 40px 0; input[name="query"] { @@ -164,7 +164,7 @@ text-align: center; } - td{ + td { padding: 0 23px; } @@ -181,7 +181,7 @@ } } -.manage-user-content{ +.manage-user-content { text-align: center; } @@ -196,16 +196,16 @@ text-align: center; } - td{ + td { padding: 0 23px; } } -.fb-enrollments-content{ +.fb-enrollments-content { text-align: center; } -.fb-enrollments-search{ +.fb-enrollments-search { margin: 40px 0; input[name="course_key"] { @@ -213,8 +213,8 @@ } } -.fb-enrollments-gating-col{ - background-color: #eee; +.fb-enrollments-gating-col { + background-color: #eee; } .contact-us-wrapper { @@ -241,7 +241,7 @@ font-weight: $font-regular; } - .help-button { + .help-button, .btn-secondary { margin-bottom: $baseline; height: $baseline * 2; font-weight: $font-regular; @@ -292,6 +292,10 @@ background-color: $m-blue-d6; border-color: $m-blue-d6; } + + &[disabled] { + color: $white; + } } .file-loading, diff --git a/lms/static/sass/views/_teams.scss b/lms/static/sass/views/_teams.scss index 5b48b13d4bb50f6a6349c605cf89bf3c68086c3e..e17e6b5f0d8640f94e7d8611e7d153cca9f87794 100644 --- a/lms/static/sass/views/_teams.scss +++ b/lms/static/sass/views/_teams.scss @@ -179,7 +179,8 @@ // STATE: hover, active, and focus &:hover, &:active, - &:focus { + &:focus, + &:focus-within { box-shadow: 0 0 5px 1px $m-blue-t1; .card-description { @@ -744,6 +745,11 @@ } } + .teams-paging-header .listing-sort-select.input-select, + .topics-paging-header .listing-sort-select.input-select { + border: 1px solid $gray-l2; + } + .create-team.wrapper-msg { margin: 0 0 $baseline 0; } diff --git a/lms/static/sass/views/_text-me-the-app.scss b/lms/static/sass/views/_text-me-the-app.scss index 877b691fc64b86b5390714cfb992d59e58bc97d0..9dd1aeb2817506962bdef748090574dd67a797dd 100644 --- a/lms/static/sass/views/_text-me-the-app.scss +++ b/lms/static/sass/views/_text-me-the-app.scss @@ -1,5 +1,6 @@ .text-me-content { - @include box-sizing(border-box); + box-sizing: border-box; + @include outer-container; width: 100%; @@ -15,10 +16,7 @@ background: $white; min-height: 100%; - padding-left: ($baseline/2); - padding-right: ($baseline/2); - padding-top: ($baseline*6); - padding-bottom: ($baseline*6); + padding: ($baseline*6) ($baseline/2); display: block; max-width: 350px; min-width: 250px; @@ -58,7 +56,8 @@ width: 100%; margin: ($baseline/2) 0 0 0; - label, input { + label, + input { width: 100%; height: auto; line-height: 1.5em; diff --git a/lms/static/sass/views/_verification.scss b/lms/static/sass/views/_verification.scss index 9a78893ec1a9a224f93a2b93b9758a4333eaf217..eb8686a5c8eac170c61d3fbc327a5af5577fa376 100644 --- a/lms/static/sass/views/_verification.scss +++ b/lms/static/sass/views/_verification.scss @@ -54,7 +54,7 @@ // reset: box-sizing (making things so right its scary) * { - @include box-sizing(border-box); + box-sizing: border-box; } // reset: typography @@ -734,7 +734,7 @@ .wrapper-task { @include clearfix(); - width: flex-grid(12,12); + width: flex-grid(12, 12); margin: $baseline 0; .wrapper-help { @@ -1374,7 +1374,8 @@ } .content-supplementary { - @include box-sizing(border-box); + box-sizing: border-box; + @include outer-container; @include span-columns(12); @@ -1556,7 +1557,8 @@ @include text-align(left); } - .action-select input, .action-select button { + .action-select input, + .action-select button { @extend %btn-verify-primary; } @@ -1789,7 +1791,6 @@ padding: $baseline; border-bottom: 1px solid $verified-color-lvl4; background: $verified-color-lvl5; - } .placeholder-art { @@ -2269,7 +2270,7 @@ } a { - color: #23419F; + color: #23419f; text-decoration: underline !important; font-weight: bold; border-bottom: none; @@ -2474,7 +2475,8 @@ .progress .progress-step { // STATE: is completed - &#progress-step1, &#progress-step2 { + &#progress-step1, + &#progress-step2 { border-bottom: ($baseline/5) solid $verified-color-lvl3; .wrapper-step-number { diff --git a/lms/templates/commerce/checkout_cancel.html b/lms/templates/commerce/checkout_cancel.html deleted file mode 100644 index 08566ddb3c19b48665ca534799feae1617eec133..0000000000000000000000000000000000000000 --- a/lms/templates/commerce/checkout_cancel.html +++ /dev/null @@ -1,15 +0,0 @@ -<%page expression_filter="h"/> -<%! from django.utils.translation import ugettext as _ -from openedx.core.djangolib.markup import HTML, Text -%> - -<%inherit file="../main.html" /> - -<%block name="pagetitle">${_("Checkout Cancelled")}</%block> - - -<section class="container"> - <h1>${_("Checkout Cancelled")}</h1> - ${ Text(_(u"Your transaction has been cancelled. If you feel an error has occurred, contact {email}.")).format( - email=HTML("<a href=\"mailto:{email}\">{email}</a>").format(email=payment_support_email)) } -</section> diff --git a/lms/templates/commerce/checkout_error.html b/lms/templates/commerce/checkout_error.html deleted file mode 100644 index ecc8dc596a7c00fe3767c2e5505434310ccc2baf..0000000000000000000000000000000000000000 --- a/lms/templates/commerce/checkout_error.html +++ /dev/null @@ -1,17 +0,0 @@ -<%page expression_filter="h"/> -<%! from django.utils.translation import ugettext as _ -from openedx.core.djangolib.markup import HTML, Text -%> - -<%inherit file="../main.html" /> - -<%block name="pagetitle">${_("Checkout Error")}</%block> - - -<section class="container"> - <h1>${_("Checkout Error")}</h1> - ${ Text(_(u"An error has occurred with your payment. {b_start}You have not been charged.{b_end} Please try to submit your payment again. If this problem persists, contact {email}.")).format( - b_start=HTML('<b>'), - b_end=HTML('</b>'), - email=HTML("<a href=\"mailto:{email}\">{email}</a>").format(email=payment_support_email)) } -</section> diff --git a/lms/templates/commerce/checkout_receipt.html b/lms/templates/commerce/checkout_receipt.html deleted file mode 100644 index 2b89d30100d7ac9f517bd6194a9eedb3bd27314f..0000000000000000000000000000000000000000 --- a/lms/templates/commerce/checkout_receipt.html +++ /dev/null @@ -1,62 +0,0 @@ -<%page expression_filter="h"/> -<%! -from django.utils.translation import ugettext as _ -%> -<%namespace name='static' file='../static_content.html'/> - -<%inherit file="../main.html" /> -<%block name="bodyclass">register verification-process step-requirements</%block> - -<%block name="pagetitle">${page_title}</%block> - -<%block name="header_extras"> -<script type="text/template" id="receipt-tpl"> - <%static:include path="commerce/receipt.underscore" /> -</script> -<script type="text/template" id="provider-tpl"> - <%static:include path="commerce/provider.underscore" /> -</script> - -</%block> -<%block name="js_extra"> -<script src="${static.url('js/vendor/jquery.ajax-retry.js')}"></script> -<script src="${static.url('js/src/tooltip_manager.js')}"></script> -<script src="${static.url('js/commerce/credit.js')}"></script> -<script src="${static.url('js/commerce/views/receipt_view.js')}"></script> -</%block> - -<%block name="content"> -<div id="error-container" class="hidden"> - <div id="error" class="wrapper-msg wrapper-msg-activate"> - <div class=" msg msg-activate"> - <span class="msg-icon icon fa fa-exclamation-triangle" aria-hidden="true"></span> - <div class="msg-content"> - <h3 class="title"> - <span class="sr">${error_summary}</span> - ${error_summary} - </h3> - %if error_text: - <div class="copy"> - <p>${error_text}</p> - <br/> - </div> - %endif - <div class="msg"> - <p>${for_help_text}</p> - </div> - </div> - </div> - </div> -</div> - -<div class="container"> - <section class="wrapper carousel"> - <div id="receipt-container" class="pay-and-verify hidden" data-is-payment-complete='${is_payment_complete}' - data-platform-name='${platform_name}' data-verified='${verified}' data-username='${username}' - data-is-request-in-themed-site='${is_request_in_themed_site}'> - <h1>${_("Loading Order Data...")}</h1> - <span>${ _("Please wait while we retrieve your order details.") }</span> - </div> - </section> -</div> -</%block> diff --git a/lms/templates/commerce/provider.underscore b/lms/templates/commerce/provider.underscore deleted file mode 100644 index 7f40e192ea460df6be5915c27f9c51a8bb73c197..0000000000000000000000000000000000000000 --- a/lms/templates/commerce/provider.underscore +++ /dev/null @@ -1,27 +0,0 @@ -<div class="provider-wrapper"> - <div class="provider-info"> - <%= interpolate( - gettext("You still need to visit the %(display_name)s website to complete the credit process."), - { display_name: display_name }, true - ) %> - </div> - <div class="provider-more-info"> - <%= interpolate( - gettext("To finalize course credit, %(display_name)s requires %(platform_name)s learners to submit a credit request."), - { display_name: display_name, platform_name: platformName }, true - ) %> - </div> - <div class="provider-instructions"> - <%= fulfillment_instructions %> - </div> -</div> - -<div class="provider-buttons-logos"> - <div class="provider-logo"> - <%= interpolate("<img src='%s' alt='%s'></image>", [thumbnail_url, display_name]) %> - </div> - <div class="complete-order"> - <%= interpolate('<button data-provider="%s" data-course-key="%s" data-username="%s" class="complete-course" onClick=completeOrder(this)>%s</button>', [id, course_key, username, - gettext( "Get Credit")]) %> - </div> -</div> diff --git a/lms/templates/commerce/receipt.underscore b/lms/templates/commerce/receipt.underscore deleted file mode 100644 index 9e676007d8d3afa93837c1041ef6b236e8133e6f..0000000000000000000000000000000000000000 --- a/lms/templates/commerce/receipt.underscore +++ /dev/null @@ -1,107 +0,0 @@ -<div class="wrapper-content-main payment-confirmation-step"> - <article class="content-main"> - <h3 class="title"> - <%= interpolate( - gettext( "Thank you %(full_name)s! We have received your payment for %(course_name)s."), - { course_name: "<span class='course_name_placeholder'></span>", - full_name: "<span class='full_name_placeholder'></span>"}, true - ) %> - </h3> - - <% if ( receipt ) { %> - <div class="list-info"> - <div class="info-item payment-info"> - <div class="copy"> - <p><%- gettext( "Please print this page for your records; it serves as your receipt. You will also receive an email with the same information." ) %></p> - </div> - - <div class="wrapper-report"> - <table class="report report-receipt"> - <thead> - <tr> - <th scope="col" ><%- gettext( "Order No." ) %></th> - <th scope="col" ><%- gettext( "Description" ) %></th> - <th scope="col" ><%- gettext( "Date" ) %></th> - <th scope="col" ><%- gettext( "Amount" ) %></th> - </tr> - </thead> - - <tbody> - <% for ( var i = 0; i < receipt.items.length; i++ ) { %> - <% if ( receipt.isRefunded ) { %> - <td><del><%- receipt.orderNum %></del></td> - <td><del><%- receipt.items[i].lineDescription %></del></td> - <td><del><%- receipt.purchasedDatetime %></del></td> - <td><del><%- receipt.items[i].cost %> (<%- receipt.currency.toUpperCase() %>)</del></td> - <% } else { %> - <tr> - <td><%- receipt.orderNum %></td> - <td><%- receipt.items[i].lineDescription %></td> - <td><%- receipt.purchasedDatetime %></td> - <td><%- receipt.items[i].cost %> (<%- receipt.currency.toUpperCase() %>)</td> - </tr> - <% } %> - <% } %> - </tbody> - - <tfoot> - <tr> - <th scope="row" class="total-label"><%- gettext( "Total" ) %></th> - <td colspan="2"></td> - <td class="total-value"> - <span class="value-amount"><%- receipt.totalCost %></span> - <span class="value-currency">(<%- receipt.currency.toUpperCase() %>)</span> - </td> - </tr> - </tfoot> - </table> - - <% if ( receipt.isRefunded ) { %> - <div class="msg msg-refunds"> - <h4 class="title sr"><%- gettext( "Please Note" ) %>: </h4> - <div class="copy"> - <p><%- gettext( "Crossed out items have been refunded." ) %></p> - </div> - </div> - <% } %> - </div> - - <% if ( receipt.billedTo ) { %> - <div class="copy"> - <p><%- gettext( "Billed to" ) %>: - <span class="name-first"><%- receipt.billedTo.firstName %></span> - <span class="name-last"><%- receipt.billedTo.lastName %></span> - (<span class="address-city"><%- receipt.billedTo.city %></span>, - <span class="address-state"><%- receipt.billedTo.state %></span> - <span class="address-postalcode"><%- receipt.billedTo.postalCode %></span> - <span class="address-country"><%- receipt.billedTo.country.toUpperCase() %></span>) - </p> - </div> - <% } %> - - <div class="report report-receipt report-receipt-provider hidden" id="receipt-provider"></div> - - </div> - </div> - <% } else { %> - <p class="no-content"><%- gettext( "No receipt available" ) %></p> - <% } %> - - <nav class="nav-wizard is-ready"> - <% if ( !is_verification_required || verified || is_request_in_themed_site) { %> - <a class="next action-primary right" href="/dashboard"><%- gettext( "Go to Dashboard" ) %></a> - <% } else { %> - <a id="verify_later_button" class="next action-secondary verify-later nav-link" href="/dashboard" data-tooltip="<%- edx.StringUtils.interpolate( gettext( "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from {platformName} to verify your identity." ), { platformName: platformName } ) %>"> - <%- gettext( "Want to confirm your identity later?" ) %> - </a> - - <a id="verify_now_button" - class="next action-primary right" - href="<%- edx.StringUtils.interpolate( '/verify_student/verify-now/{courseKey}/', { courseKey: courseKey } ) %>" - > - <%- gettext( "Verify Now" ) %> - </a> - <% } %> - </nav> - </article> -</div> diff --git a/lms/templates/components/header/header.underscore b/lms/templates/components/header/header.underscore index 1a400baad4e13d9ccbe759d50e17931b06509b1b..2bc93788f32b9aba0750d44c5e19572e4b0d0a1f 100644 --- a/lms/templates/components/header/header.underscore +++ b/lms/templates/components/header/header.underscore @@ -4,7 +4,7 @@ <% if (breadcrumbs !== null && breadcrumbs.length > 0) { %> <nav class="breadcrumbs" aria-label="<%- nav_aria_label %>"> <% _.each(breadcrumbs, function (breadcrumb) { %> - <a class="nav-item" href="<%= breadcrumb.url %>"><%- breadcrumb.title %></a> + <a class="nav-item" href="<%- breadcrumb.url %>"><%- breadcrumb.title %></a> <span class="icon fa-angle-right" aria-hidden="true"></span> <% }) %> </nav> diff --git a/lms/templates/courseware/course_about.html b/lms/templates/courseware/course_about.html index 293084de572adf8e2dea40822feed28fad14d343..8c1ebd83b7d44d2eed89e5313ab0e9d9ae9c7133 100644 --- a/lms/templates/courseware/course_about.html +++ b/lms/templates/courseware/course_about.html @@ -31,32 +31,6 @@ from six import string_types event.preventDefault(); }); - % if can_add_course_to_cart: - add_course_complete_handler = function(jqXHR, textStatus) { - if (jqXHR.status == 200) { - location.href = "${cart_link | n, js_escaped_string}"; - } - if (jqXHR.status == 400) { - $("#register_error") - .text(jqXHR.responseText ? jqXHR.responseText : "${_("An error occurred. Please try again later.") | n, js_escaped_string}") - .css("display", "block"); - } - else if (jqXHR.status == 403) { - location.href = "${reg_then_add_to_cart_link | n, js_escaped_string}"; - } - }; - - $("#add_to_cart_post").click(function(event){ - $.ajax({ - url: "${reverse('add_course_to_cart', args=[text_type(course.id)]) | n, js_escaped_string}", - type: "POST", - /* Using `complete` as promise.done did not work on this page */ - complete: add_course_complete_handler - }) - event.preventDefault(); - }); - % endif - $('#class_enroll_form').on('ajax:complete', function(event, xhr) { if (xhr.status == 200) { if (xhr.responseText == "") { @@ -112,13 +86,6 @@ from six import string_types </a> %endif - %elif in_cart: - <span class="add-to-cart"> - ${Text(_('This course is in your {start_cart_link}cart{end_cart_link}.')).format( - start_cart_link=HTML('<a href="{cart_link}">').format(cart_link=cart_link), - end_cart_link=HTML("</a>"), - )} - </span> % elif is_course_full: <span class="register disabled"> ${_("Course is full")} @@ -130,28 +97,6 @@ from six import string_types ## so that they can register and become a real user that can enroll. % elif not is_shib_course and not can_enroll: <span class="register disabled">${_("Enrollment is Closed")}</span> - %elif can_add_course_to_cart: - <% - if user.is_authenticated: - reg_href = "#" - reg_element_id = "add_to_cart_post" - else: - reg_href = reg_then_add_to_cart_link - reg_element_id = "reg_then_add_to_cart" - %> - <% if ecommerce_checkout: - reg_href = ecommerce_checkout_link - reg_element_id = "" - %> - <a href="${reg_href}" class="add-to-cart" id="${reg_element_id}"> - ${Text(_("Add {course_name} to Cart {start_span}({price} USD){end_span}")).format( - course_name=course.display_number_with_default, - price=course_price, - start_span=HTML("<span>"), - end_span=HTML("</span>"), - )} - </a> - <div id="register_error"></div> %elif allow_anonymous: %if show_courseware_link: <a href="${course_target}"> @@ -264,7 +209,7 @@ from six import string_types ##<li class="important-dates-item"><span class="icon fa fa-clock-o" aria-hidden="true"></span><p class="important-dates-item-title">${_('Course Length')}</p><span class="important-dates-item-text course-length">${_('{number} weeks').format(number=15)}</span></li> - %if course_price and (can_add_course_to_cart or is_cosmetic_price_enabled): + %if course_price and (is_cosmetic_price_enabled): <li class="important-dates-item"> <span class="icon fa fa-money" aria-hidden="true"></span> <p class="important-dates-item-title">${_("Price")}</p> diff --git a/lms/templates/courseware/courseware-chromeless.html b/lms/templates/courseware/courseware-chromeless.html index b0e021b37db45eede79aeb37dea494662abe133a..99825e950a0a12ead9f7a187f5f8a5f1ce9df600 100644 --- a/lms/templates/courseware/courseware-chromeless.html +++ b/lms/templates/courseware/courseware-chromeless.html @@ -11,13 +11,7 @@ from openedx.core.djangolib.js_utils import js_escaped_string <%def name="course_name()"> <% return _("{course_number} Courseware").format(course_number=course.display_number_with_default) %> </%def> - -% if display_reset_dates_banner: - <script type="text/javascript"> - $('.reset-deadlines-banner').css('display', 'flex'); - </script> -% endif - +<%include file="/dates_banner.html" /> <%block name="bodyclass">view-in-course view-courseware courseware ${course.css_class or ''}</%block> <%block name="title"><title> % if section_title: @@ -126,11 +120,14 @@ ${HTML(fragment.foot_html())} var lastWidth = window.offsetWidth; var contentElement = document.getElementById('content'); - function dispatchResizeMessage() { + function dispatchResizeMessage(event) { + // Note: event is actually an Array of MutationRecord objects + // when fired from the MutationObserver + var eventType = event.type || 'mutate'; var newHeight = contentElement.offsetHeight; var newWidth = contentElement.offsetWidth; - if (newWidth === lastWidth && newHeight === lastHeight) { + if (eventType !== 'load' && newWidth === lastWidth && newHeight === lastHeight) { return; } diff --git a/lms/templates/courseware/courseware-error.html b/lms/templates/courseware/courseware-error.html index 2d7babaf282de7ba792b9ed36c326515e5bcb4ba..403e4a35eb05dc097d6e5460b56a11355b5aa2cf 100644 --- a/lms/templates/courseware/courseware-error.html +++ b/lms/templates/courseware/courseware-error.html @@ -26,10 +26,7 @@ from openedx.core.djangolib.markup import HTML, Text )} </h1> <p> - ${Text(_("We're sorry, this module is temporarily unavailable. Our staff is working to fix " - "it as soon as possible. Please email us at {tech_support_email} to report any problems or downtime.")).format( - tech_support_email=HTML(u'<a href=\"mailto:{0}\">{0}</a>').format(static.get_tech_support_email_address()) - )} + ${Text(_("We're sorry, this module is temporarily unavailable. Our staff is working to fix it as soon as possible.")) } </p> </section> </section> diff --git a/lms/templates/courseware/dates.html b/lms/templates/courseware/dates.html index 2d0394fff53a7e4adc80d8c80be44adc5b5765af..f140089522739dd34aea9b83a11035cdecd44296 100644 --- a/lms/templates/courseware/dates.html +++ b/lms/templates/courseware/dates.html @@ -4,7 +4,7 @@ <%! from django.utils.translation import ugettext as _ -from lms.djangoapps.courseware.date_summary import CourseAssignmentDate, VerificationDeadlineDate, VerifiedUpgradeDeadlineDate +from lms.djangoapps.courseware.date_summary import CourseAssignmentDate, TodaysDate, VerificationDeadlineDate, VerifiedUpgradeDeadlineDate from openedx.core.djangolib.markup import HTML, Text %> @@ -26,44 +26,63 @@ from openedx.core.djangolib.markup import HTML, Text <h2 class="hd hd-2 date-title"> ${_("Important Dates")} </h2> + <%include file="/dates_banner.html" /> + <% due_next_set = False %> % for block in course_date_blocks: - <% active = 'active' if block.date and (block.date.strftime(block.date_format) == block.current_time.strftime(block.date_format)) else '' %> - <% block_is_verified = (hasattr(block, 'requires_full_access') and block.requires_full_access) or isinstance(block, VerificationDeadlineDate) %> + <% block_is_verified = (hasattr(block, 'contains_gated_content') and block.contains_gated_content) or isinstance(block, VerificationDeadlineDate) %> + <% learner_has_access = not block_is_verified or learner_is_full_access %> + <% access_class = '' if learner_has_access else 'no-access' %> <% is_assignment = isinstance(block, CourseAssignmentDate) %> - % if not (learner_is_verified and isinstance(block, VerifiedUpgradeDeadlineDate)): - <div class="timeline-item ${active}"> - <div class="date-circle ${active}"></div> - <div class="date-content ${active}"> - <div class="timeline-date-content"> - % if block.date: - <div class="timeline-date"> - <div class="course-date localized_datetime" aria-hidden="true" data-format="shortDate" data-datetime="${block.date}" data-language="${user_language}" data-timezone="${user_timezone}"></div> - </div> - % if active: - <div class="pill due">${_('Due Today')}</div> + <% assignment_type = is_assignment and block.assignment_type %> + <% todays_date = 'todays-date' if isinstance(block, TodaysDate) else '' %> + <% past_date = 'past-date' if block.date and block.date < block.current_time else '' %> + <% past_due = 'past-due' if learner_is_full_access and is_assignment and block.past_due else '' %> + <% due_in_future = True if learner_is_full_access and is_assignment and block.date and block.date >= block.current_time else False %> + <% not_released = 'not-released' if learner_is_full_access and is_assignment and not block.title_html else '' %> + % if not (learner_is_full_access and isinstance(block, VerifiedUpgradeDeadlineDate)): + <div class="timeline-item"> + <div class="date-circle ${todays_date} ${past_date} ${past_due}"></div> + <div class="date-content ${todays_date}"> + <div class="timeline-date-content ${not_released}"> + % if block.date: + <div class="timeline-date"> + <div class="course-date localized_datetime" aria-hidden="true" data-format="shortDate" data-datetime="${block.date}" data-language="${user_language}" data-timezone="${user_timezone}"></div> + </div> + % if todays_date: + <div class="pill today">${_('Today')}</div> + % endif + % if not learner_has_access: + <div class="pill verified"><span class="fa fa-lock verified-icon" aria-hidden="true"></span>${_('Verified Only')}</div> + % else: + % if is_assignment and block.complete: + <div class="pill completed">${_('Completed')}</div> + % elif is_assignment and block.past_due: + <div class="pill past-due">${_('Past Due')}</div> + % elif is_assignment and due_in_future and not due_next_set: + <div class="pill due-next">${_('Due Next')}</div> + <% due_next_set = True %> % endif - % if block_is_verified and not learner_is_verified: - <div class="pill verified"><span class="fa fa-lock verified-icon" aria-hidden="true"></span>${_('Verified Only')}</div> + % if not_released: + <div class="pill not-released">${_('Not yet released')}</div> % endif - % endif - </div> - <div class="timeline-title "> - % if block.title_html and is_assignment: - ${block.title_html} - % else: - ${block.title} - % endif - </div> - <div class="timeline-description"> - ${block.description} - % if block_is_verified and verified_upgrade_link and not learner_is_verified: - ${Text(_('{a_start}Upgrade{a_end}{space}to a Verified Certificate for full access.')).format( - a_start=HTML('<a href={link}>').format(link=verified_upgrade_link), - a_end=HTML('</a>'), - space=HTML(' '), - )} + %endif % endif </div> + % if not todays_date: + <div class="timeline-title ${access_class} ${not_released}"> + % if assignment_type: + ${assignment_type}: + % endif + % if block.title_html and is_assignment and learner_has_access: + ${block.title_html} + % else: + ${block.title} + % endif + </div> + <div class="timeline-description ${access_class} ${not_released}"> + ${block.description} + </div> + % endif </div> </div> % endif diff --git a/lms/templates/courseware/error-message.html b/lms/templates/courseware/error-message.html index dc7497448796b2aefcc893a112b796d52c869284..c3b0fe287a02b6e71e5a770c510467436bf33309 100644 --- a/lms/templates/courseware/error-message.html +++ b/lms/templates/courseware/error-message.html @@ -5,8 +5,6 @@ from django.utils.translation import ugettext as _ from openedx.core.djangolib.markup import HTML, Text %> -<% - tech_support_email=HTML('<a href=\"mailto:{tech_support_email}\">{tech_support_email}</a>').format(tech_support_email=static.get_tech_support_email_address()) -%> + <p>${Text(_("We're sorry, this module is temporarily unavailable. Our staff is working to fix it as soon as possible."))}</p> diff --git a/lms/templates/courseware/info.html b/lms/templates/courseware/info.html index 4fea8989a9cddb736929db54d09ce0cef8b0022a..022ef48669c00b81c79ceb88b1b01aa98d4af56c 100644 --- a/lms/templates/courseware/info.html +++ b/lms/templates/courseware/info.html @@ -9,7 +9,7 @@ from pytz import timezone, utc from django.urls import reverse from django.utils.translation import ugettext as _ -from lms.djangoapps.courseware.courses import get_course_info_section, get_course_date_blocks +from lms.djangoapps.courseware.courses import get_course_info_section from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration from openedx.core.djangolib.markup import HTML, Text %> diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html index 2353fb3f83adead7d4ae2d941dba33336811981b..30f036e0860dc94a3cdcf0215f30cd053d9594d9 100644 --- a/lms/templates/dashboard.html +++ b/lms/templates/dashboard.html @@ -183,7 +183,10 @@ from student.models import CourseEnrollment pseudo_session = unfulfilled_entitlement_pseudo_sessions[str(entitlement.uuid)] if not pseudo_session: continue - enrollment = CourseEnrollment(user=user, course=CourseOverview.get_from_id(pseudo_session['key']), mode=pseudo_session['type']) + pseudo_key = pseudo_session['key'] + if not isinstance(pseudo_key, CourseKey): + pseudo_key = CourseKey.from_string(pseudo_session['key']) + enrollment = CourseEnrollment(user=user, course=CourseOverview.get_from_id(pseudo_key), mode=pseudo_session['type']) # We only show email settings for entitlement cards if the entitlement has an associated enrollment show_email_settings = is_fulfilled_entitlement and (entitlement_session.course_id in show_email_settings_for) else: @@ -197,7 +200,6 @@ from student.models import CourseEnrollment credit_status = credit_statuses.get(session_id) course_mode_info = all_course_modes.get(session_id) is_paid_course = True if entitlement else (session_id in enrolled_courses_either_paid) - is_course_blocked = (session_id in block_courses) course_verification_status = verification_status_by_course.get(session_id, {}) course_requirements = courses_requirements_not_met.get(session_id) related_programs = inverted_programs.get(six.text_type(entitlement.course_uuid if is_unfulfilled_entitlement else session_id)) @@ -205,7 +207,7 @@ from student.models import CourseEnrollment course_overview = enrollment.course_overview resume_button_url = resume_button_urls[dashboard_index] %> - <%include file='dashboard/_dashboard_course_listing.html' args='course_overview=course_overview, course_card_index=dashboard_index, enrollment=enrollment, is_unfulfilled_entitlement=is_unfulfilled_entitlement, is_fulfilled_entitlement=is_fulfilled_entitlement, entitlement=entitlement, entitlement_session=entitlement_session, entitlement_available_sessions=entitlement_available_sessions, entitlement_expiration_date=entitlement_expiration_date, entitlement_expired_at=entitlement_expired_at, show_courseware_link=show_courseware_link, cert_status=cert_status, can_refund_entitlement=can_refund_entitlement, can_unenroll=can_unenroll, credit_status=credit_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, is_paid_course=is_paid_course, is_course_blocked=is_course_blocked, verification_status=course_verification_status, course_requirements=course_requirements, dashboard_index=dashboard_index, share_settings=share_settings, user=user, related_programs=related_programs, display_course_modes_on_dashboard=display_course_modes_on_dashboard, show_consent_link=show_consent_link, enterprise_customer_name=enterprise_customer_name, resume_button_url=resume_button_url' /> + <%include file='dashboard/_dashboard_course_listing.html' args='course_overview=course_overview, course_card_index=dashboard_index, enrollment=enrollment, is_unfulfilled_entitlement=is_unfulfilled_entitlement, is_fulfilled_entitlement=is_fulfilled_entitlement, entitlement=entitlement, entitlement_session=entitlement_session, entitlement_available_sessions=entitlement_available_sessions, entitlement_expiration_date=entitlement_expiration_date, entitlement_expired_at=entitlement_expired_at, show_courseware_link=show_courseware_link, cert_status=cert_status, can_refund_entitlement=can_refund_entitlement, can_unenroll=can_unenroll, credit_status=credit_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, is_paid_course=is_paid_course, verification_status=course_verification_status, course_requirements=course_requirements, dashboard_index=dashboard_index, share_settings=share_settings, user=user, related_programs=related_programs, display_course_modes_on_dashboard=display_course_modes_on_dashboard, show_consent_link=show_consent_link, enterprise_customer_name=enterprise_customer_name, resume_button_url=resume_button_url' /> % endfor % if show_load_all_courses_link: <br/> diff --git a/lms/templates/dashboard/_dashboard_course_listing.html b/lms/templates/dashboard/_dashboard_course_listing.html index 8ac9d1ced6dcc0cd1223b678aad92fce667e3624..1e93b6f018366282152dd99ecccf09ebcdefcc57 100644 --- a/lms/templates/dashboard/_dashboard_course_listing.html +++ b/lms/templates/dashboard/_dashboard_course_listing.html @@ -1,4 +1,4 @@ -<%page args="course_overview, enrollment, entitlement, entitlement_session, course_card_index, is_unfulfilled_entitlement, is_fulfilled_entitlement, entitlement_available_sessions, entitlement_expiration_date, entitlement_expired_at, show_courseware_link, cert_status, can_refund_entitlement, can_unenroll, credit_status, show_email_settings, course_mode_info, is_paid_course, is_course_blocked, verification_status, course_requirements, dashboard_index, share_settings, related_programs, display_course_modes_on_dashboard, show_consent_link, enterprise_customer_name, resume_button_url" expression_filter="h"/> +<%page args="course_overview, enrollment, entitlement, entitlement_session, course_card_index, is_unfulfilled_entitlement, is_fulfilled_entitlement, entitlement_available_sessions, entitlement_expiration_date, entitlement_expired_at, show_courseware_link, cert_status, can_refund_entitlement, can_unenroll, credit_status, show_email_settings, course_mode_info, is_paid_course, verification_status, course_requirements, dashboard_index, share_settings, related_programs, display_course_modes_on_dashboard, show_consent_link, enterprise_customer_name, resume_button_url" expression_filter="h"/> <%! import six @@ -68,7 +68,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ <h2 class="hd hd-2 sr" id="details-heading-${enrollment.course_id}">${_('Course details')}</h2> <div class="wrapper-course-image" aria-hidden="true"> % if show_courseware_link and not is_unfulfilled_entitlement: - % if not is_course_blocked and not is_course_expired: + % if not is_course_expired: <a href="${course_target}" data-course-key="${enrollment.course_id}" class="cover course-target-link" tabindex="-1"> <img src="${course_overview.image_urls['small']}" class="course-image" alt="${_('{course_number} {course_name} Home Page').format(course_number=course_overview.number, course_name=course_overview.display_name_with_default)}" /> </a> @@ -95,7 +95,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ <div class="wrapper-course-details"> <h3 class="course-title" id="course-title-${enrollment.course_id}"> % if show_courseware_link and not is_unfulfilled_entitlement: - % if not is_course_blocked and not is_course_expired: + % if not is_course_expired: <a data-course-key="${enrollment.course_id}" href="${course_target}" class="course-target-link">${course_overview.display_name_with_default}</a> % else: <a class="disable-look" data-course-key="${enrollment.course_id}">${course_overview.display_name_with_default}</a> @@ -108,6 +108,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ <span class="info-university">${course_overview.display_org_with_default} - </span> <span class="info-course-id">${course_overview.display_number_with_default}</span> <% + enrollment_date = course_overview.self_paced and enrollment and enrollment.created if course_overview.start_date_is_still_default: container_string = _("Coming Soon") course_date = None @@ -118,7 +119,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ course_date = course_overview.end elif course_overview.has_started(): container_string = _("Started - {date}") - course_date = course_overview.dashboard_start_display + course_date = enrollment_date or course_overview.dashboard_start_display elif course_overview.starts_within(days=5): container_string = _("Starts - {date}") course_date = course_overview.dashboard_start_display @@ -177,14 +178,12 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ <div class="course-actions"> % if (show_courseware_link or is_unfulfilled_entitlement) and not is_course_expired: % if course_overview.has_ended(): - % if is_course_blocked: - <a class="enter-course-blocked archived course-target-link" data-course-key="${enrollment.course_id}">${_('View Archived Course')}<span class="sr"> ${course_overview.display_name_with_default}</span></a> - % elif not is_unfulfilled_entitlement: + % if not is_unfulfilled_entitlement: <a href="${course_target}" class="enter-course archived course-target-link" data-course-key="${enrollment.course_id}">${_('View Archived Course')}<span class="sr"> ${course_overview.display_name_with_default}</span></a> % endif % else: - <%include file="_dashboard_course_resume.html" args="resume_button_url=resume_button_url, course_overview=course_overview, enrollment=enrollment, is_unfulfilled_entitlement=is_unfulfilled_entitlement, is_course_blocked=is_course_blocked, course_target=course_target, related_programs=related_programs"/> + <%include file="_dashboard_course_resume.html" args="resume_button_url=resume_button_url, course_overview=course_overview, enrollment=enrollment, is_unfulfilled_entitlement=is_unfulfilled_entitlement, course_target=course_target, related_programs=related_programs"/> % endif % endif @@ -263,7 +262,6 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ % if can_unenroll: <li class="actions-item" id="actions-item-unenroll-${dashboard_index}" role="menuitem"> <% course_refund_url = reverse('course_run_refund_status', args=[six.text_type(course_overview.id)]) %> - % if not is_course_blocked: <a href="#unenroll-modal" class="action action-unenroll" rel="leanModal" data-course-id="${course_overview.id}" data-course-number="${course_overview.number}" @@ -275,28 +273,11 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ data-course-enrollment-mode="${enrollment.mode}"> ${_('Unenroll')} </a> - % else: - <a class="action action-unenroll is-disabled" - data-course-id="${course_overview.id}" - data-course-number="${course_overview.number}" - data-course-name="${course_overview.display_name_with_default}" - data-dashboard-index="${dashboard_index}" - data-course-refund-url="${course_refund_url}" - data-course-is-paid-course="${is_paid_course}" - data-course-cert-name-long="${cert_name_long}" - data-course-enrollment-mode="${enrollment.mode}"> - ${_('Unenroll')} - </a> - % endif </li> % endif <li class="actions-item" id="actions-item-email-settings-${dashboard_index}" role="menuitem"> % if show_email_settings: - % if not is_course_blocked: <a href="#email-settings-modal" class="action action-email-settings" rel="leanModal" data-course-id="${course_overview.id}" data-course-number="${course_overview.number}" data-dashboard-index="${dashboard_index}" data-optout="${course_overview.id in course_optouts}">${_('Email Settings')}</a> - % else: - <a class="action action-email-settings is-disabled" data-course-id="${course_overview.id}" data-course-number="${course_overview.number}" data-dashboard-index="${dashboard_index}" data-optout="${course_overview.id in course_optouts}">${_('Email Settings')}</a> - % endif % endif </li> </ul> @@ -355,32 +336,6 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ <%include file="_dashboard_credit_info.html" args="credit_status=credit_status"/> % endif - % if is_course_blocked and entitlement: - <p id="block-course-msg" class="course-block"> - ${_("You can no longer access this course because payment has not yet been received. You can contact the account holder to request payment, or you can unenroll from this course")} - </p> - % elif is_course_blocked: - <p id="block-course-msg" class="course-block"> - ${Text(_("You can no longer access this course because payment has not yet been received. " - "You can {contact_link_start}contact the account holder{contact_link_end} " - "to request payment, or you can " - "{unenroll_link_start}unenroll{unenroll_link_end} " - "from this course")).format( - contact_link_start=HTML('<button type="button">'), - contact_link_end=HTML('</button>'), - unenroll_link_start=HTML( - '<a id="unregister_block_course" rel="leanModal" ' - 'data-course-id="{course_id}" data-course-number="{course_number}" data-course-name="{course_name}" ' - 'href="#unenroll-modal">' - ).format( - course_id=course_overview.id, - course_number=course_overview.number, - course_name=course_overview.display_name_with_default, - ), - unenroll_link_end=HTML('</a>'), - )} - </p> - % else: % if show_consent_link: <%include file="_dashboard_show_consent.html" args="course_overview=course_overview, course_target=course_target, enrollment=enrollment, enterprise_customer_name=enterprise_customer_name"/> %endif @@ -406,10 +361,10 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ </div> % elif verification_status['status'] == VERIFY_STATUS_SUBMITTED: <h4 class="message-title">${_('You have submitted your verification information.')}</h4> - <p class="message-copy">${_('You will see a message on your dashboard when the verification process is complete (usually within 1-2 days).')}</p> + <p class="message-copy">${_('You will see a message on your dashboard when the verification process is complete (usually within 5-7 days).')}</p> % elif verification_status['status'] == VERIFY_STATUS_RESUBMITTED: <h4 class="message-title">${_('Your current verification will expire soon!')}</h4> - <p class="message-copy">${_('You have submitted your reverification information. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days).')}</p> + <p class="message-copy">${_('You have submitted your reverification information. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days).')}</p> % elif verification_status['status'] == VERIFY_STATUS_APPROVED: <h4 class="message-title">${_('You have successfully verified your ID with edX')}</h4> % if verification_status.get('verification_good_until') is not None: @@ -464,7 +419,6 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ </div> </div> % endif - % endif % if course_requirements: ## Multiple pre-requisite courses are not supported on frontend that's why we are pulling first element @@ -484,16 +438,6 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_ </article> </div> </li> -<script> - $( document ).ready(function() { - - if("${is_course_blocked | n, dump_js_escaped_json}" == 'true'){ - $( "#unregister_block_course" ).click(function() { - $('.disable-look-unregister').click(); - }); - } - }); -</script> % if share_settings.get('DASHBOARD_FACEBOOK', False) and share_settings.get('DASHBOARD_TWITTER', False): <%static:require_module_async module_name="js/course_sharing/course_sharing_events" class_name="CourseSharingEvents"> diff --git a/lms/templates/dashboard/_dashboard_course_resume.html b/lms/templates/dashboard/_dashboard_course_resume.html index 4478376fa05f5a0ccaa3d60a27da80e9f18462cc..a4d3c03c2d2d29e75a2b4cd60bcb9e81436ffe03 100644 --- a/lms/templates/dashboard/_dashboard_course_resume.html +++ b/lms/templates/dashboard/_dashboard_course_resume.html @@ -1,4 +1,4 @@ -<%page args="resume_button_url, course_overview, enrollment, is_unfulfilled_entitlement, is_course_blocked, course_target, related_programs" expression_filter="h"/> +<%page args="resume_button_url, course_overview, enrollment, is_unfulfilled_entitlement, course_target, related_programs" expression_filter="h"/> <%! import six @@ -14,7 +14,7 @@ from django.utils.translation import ugettext as _ ${course_overview.display_name_with_default} </span> </a> -% elif not is_course_blocked: +% else: <a href="${course_target}" class="course-target-link enter-course ${'hidden' if is_unfulfilled_entitlement else ''}" data-course-key="${enrollment.course_id}"> @@ -23,12 +23,4 @@ from django.utils.translation import ugettext as _ ${course_overview.display_name_with_default} </span> </a> -% else: - <a class="enter-course-blocked" - data-course-key="${enrollment.course_id}"> - ${_('View Course')} - <span class="sr"> - ${course_overview.display_name_with_default} - </span> - </a> % endif diff --git a/lms/templates/dates_banner.html b/lms/templates/dates_banner.html new file mode 100644 index 0000000000000000000000000000000000000000..8b0505a8785f1dc6a233452ebdd4d9d25003f74d --- /dev/null +++ b/lms/templates/dates_banner.html @@ -0,0 +1,109 @@ +## mako + +<%page expression_filter="h"/> +<%! +from django.utils.translation import ugettext as _ + +from lms.djangoapps.courseware.date_summary import CourseAssignmentDate +from course_modes.models import CourseMode +%> + +<% +additional_styling_class = 'on-mobile' if is_mobile_app else 'has-button' +%> + +<%def name="reset_dates_banner()"> + <div class="dates-banner ${additional_styling_class}"> + <div class="dates-banner-text"> + % if is_mobile_app: + ${_('It looks like you missed some important deadlines based on our suggested schedule. ')} + ${_('To keep yourself on track, you can update this schedule and shift the past due assignments into the future by visiting ')} + <a class="mobile-dates-link" href="${web_app_course_url}">edx.org</a>. + ${_(" Don't worry—you won't lose any of the progress you've made when you shift your due dates.")} + % else: + <strong>${_('It looks like you missed some important deadlines based on our suggested schedule.')}</strong> + ${_("To keep yourself on track, you can update this schedule and shift the past due assignments into the future. Don't worry—you won't lose any of the progress you've made when you shift your due dates.")} + % endif + </div> + % if not is_mobile_app: + <div class="upgrade-button"> + <form method="post" action="${reset_deadlines_url}"> + <input type="hidden" id="csrf_token" name="csrfmiddlewaretoken" value="${csrf_token}"> + <input type="hidden" name="reset_deadlines_redirect_url_base" value="${reset_deadlines_redirect_url_base}"> + <input type="hidden" name="reset_deadlines_redirect_url_id_dict" value="${reset_deadlines_redirect_url_id_dict}"> + <button class="btn reset-deadlines-button">${_("Shift due dates")}</button> + </form> + </div> + % endif + </div> +</%def> +<%def name="upgrade_to_reset_banner()"> + <div class="dates-banner ${additional_styling_class}"> + <div class="dates-banner-text"> + % if is_mobile_app: + <strong>${_('You are auditing this course,')}</strong> + ${_(' which means that you are unable to participate in graded assignments.')} + ${_(' It looks like you missed some important deadlines based on our suggested schedule. Graded assignments and schedule adjustment are available to Verified Track learners.')} + % else: + <strong>${_('You are auditing this course,')}</strong> + ${_(' which means that you are unable to participate in graded assignments.')} + ${_(' It looks like you missed some important deadlines based on our suggested schedule. To complete graded assignments as part of this course and shift the past due assignments into the future, you can upgrade today.')} + % endif + </div> + % if not is_mobile_app: + <div class="upgrade-button"> + <a href="${verified_upgrade_link}"> + <button type="button"> + ${_('Upgrade to shift due dates')} + </button> + </a> + </div> + % endif + </div> +</%def> +<%def name="upgrade_to_complete_graded_banner()"> + <div class="dates-banner ${additional_styling_class}"> + <div class="dates-banner-text"> + % if is_mobile_app: + <strong>${_('You are auditing this course,')}</strong> + ${_(' which means that you are unable to participate in graded assignments.')} + ${_('Graded assignments are available to Verified Track learners.')} + % else: + <strong>${_('You are auditing this course,')}</strong> + ${_(' which means that you are unable to participate in graded assignments.')} + ${_(' To complete graded assignments as part of this course, you can upgrade today.')} + % endif + </div> + % if not is_mobile_app: + <div class="upgrade-button"> + <a href="${verified_upgrade_link}"> + <button type="button"> + ${_('Upgrade now')} + </button> + </a> + </div> + % endif + </div> +</%def> + +% if not has_ended: + % if on_dates_tab and not missed_deadlines: + %if getattr(course, 'self_paced', False): + <div class="dates-banner"> + <div class="dates-banner-text"> + <strong>${_("We've built a suggested schedule to help you stay on track.")}</strong> + ${_("But don't worry—it's flexible so you can learn at your own pace. If you happen to fall behind on our suggested dates, you'll be able to adjust them to keep yourself on track.")} + </div> + </div> + % endif + % if content_type_gating_enabled: + ${upgrade_to_complete_graded_banner()} + % endif + % elif missed_deadlines: + % if missed_gated_content: + ${upgrade_to_reset_banner()} + % else: + ${reset_dates_banner()} + % endif + % endif +% endif diff --git a/lms/templates/edit_unit_link.html b/lms/templates/edit_unit_link.html deleted file mode 100644 index 6b507c1945cf1eb6e7f3fa9b1c9c5b9e9cc6b21c..0000000000000000000000000000000000000000 --- a/lms/templates/edit_unit_link.html +++ /dev/null @@ -1,7 +0,0 @@ -<%page expression_filter="h"/> -<%! from django.utils.translation import ugettext as _ %> - -<div class="wrap-instructor-info studio-view"> - <a class="instructor-info-action" href="${edit_link}">${_("View Unit in Studio")}</a> -</div> -${frag_content | n, decode.utf8} diff --git a/lms/templates/emails/registration_codes_sale_email.txt b/lms/templates/emails/registration_codes_sale_email.txt deleted file mode 100644 index 876a88855f42a372a476c0c01c4e9789ba3cdbef..0000000000000000000000000000000000000000 --- a/lms/templates/emails/registration_codes_sale_email.txt +++ /dev/null @@ -1,31 +0,0 @@ -## mako -<%! from django.utils.translation import ugettext as _ %> - -${_("Thank you for purchasing enrollments in {course_name}.").format(course_name=course.display_name)} - -${_("An invoice for {currency_symbol}{total_price} is attached. Payment is due upon receipt. You can find information about payment methods on the invoice.").format(currency_symbol=currency_symbol, total_price=sale_price)} - -${_("A .csv file that lists your enrollment codes is attached. You can use the email template below to distribute enrollment codes to your students. Each student must use a separate enrollment code.")} - -## Translators: This is the signature of an email. "\n" is a newline character -## and should be placed between the closing word and the signature. -${_("Thanks,\nThe {platform_name} Team").format(platform_name=platform_name)} - - -——————————————————————————————————————————— - - -## Translators: please translate the text inside [[ ]]. This is meant as a template for course teams to use. -${_("Dear [[Name]]:")} - -## Translators: please translate the text inside [[ ]]. This is meant as a template for course teams to use. -${_("We have provided a course enrollment code for you in {course_name}. To enroll in the course, click the following link:").format(course_name=course.display_name)} - -[[${_("HTML link from the attached CSV file")}]] - -${_("After you enroll, you can see the course on your student dashboard. You can see course materials after the course start date.")} - -## Translators: please translate the text inside [[ ]]. This is meant as a template for course teams to use. -## This is the signature of an email. "\n" is a newline character -## and should be placed between the closing word and the signature. -${_("Sincerely,\n[[Your Signature]]")} diff --git a/lms/templates/emails/registration_codes_sale_invoice_attachment.txt b/lms/templates/emails/registration_codes_sale_invoice_attachment.txt deleted file mode 100644 index ef1eacb73f9604220de846edecff4eeed92bb129..0000000000000000000000000000000000000000 --- a/lms/templates/emails/registration_codes_sale_invoice_attachment.txt +++ /dev/null @@ -1,43 +0,0 @@ -## mako -<%! from django.utils.translation import ugettext as _ %> -${_("INVOICE")} - -——————————————————————————————————————————— - -${corp_address} - -${_("Date: {date}").format(date=date)} -${_("Invoice No: {invoice_number}").format(invoice_number=invoice.id)} -${_("Terms: Due Upon Receipt")} -${_("Due Date: {date}").format(date=date)} - -${_("Bill to:")} -${invoice.company_name} -${invoice.address_line_1} -% if invoice.address_line_2: -${invoice.address_line_2} -% endif -% if invoice.address_line_3: -${invoice.address_line_3} -% endif -${invoice.city}, ${invoice.state}, ${invoice.zip} -${invoice.country} -${_("Customer Reference Number: {reference_number}").format(reference_number=invoice.customer_reference_number if invoice.customer_reference_number else "")} - - ${_("Balance Due: {currency_symbol}{sale_price}").format(currency_symbol=currency_symbol, sale_price=sale_price)} - -——————————————————————————————————————————— - -${_("Course: {course_name}").format(course_name=course.display_name)} -
${_("Price: {currency_symbol}{course_price} Quantity: {quantity} Sub-Total: {currency_symbol}{sub_total} Discount: {currency_symbol}{discount}").format(course_price=course_price, quantity=quantity, sub_total=sub_total, discount=discount, currency_symbol=currency_symbol)} -${_("Total: {currency_symbol}{sale_price}").format(sale_price=sale_price, currency_symbol=currency_symbol)} - -——————————————————————————————————————————— - -${_("Payment Instructions")} - -${payment_instructions} - -${_("If we do not receive payment, the learner enrollments that use these codes will be canceled and learners will not be able to access course materials. All purchases are final. For more information, see the {site_name} cancellation policy.").format(site_name=site_name)} - -${_("For payment questions, contact {contact_email}").format(contact_email=contact_email)} diff --git a/lms/templates/financial-assistance/financial_assessment_form.underscore b/lms/templates/financial-assistance/financial_assessment_form.underscore index 859a2fc5863633c08782ba38f00e48ae41b52298..e6c76428fc0feaa30d922e79b9ba257c6b2754b3 100644 --- a/lms/templates/financial-assistance/financial_assessment_form.underscore +++ b/lms/templates/financial-assistance/financial_assessment_form.underscore @@ -13,8 +13,8 @@ <div class="user-info"> <h2><%- gettext('About You') %></h2> <p><%- interpolate_text( - gettext('The following information is already a part of your {platform} profile. We\'ve included it here for your application.'), - {platform: platform_name} + gettext("The following information is already a part of your {platform} profile. We've included it here for your application."), + {platform: platform_name} ) %></p> <div class="info-column"> <div class="title"><%- gettext('Username') %></div> @@ -34,7 +34,8 @@ </div> </div> - <%= fields %> + <% // xss-lint: disable=underscore-not-escaped %> + <%= fields %> <div class="cta-wrapper clearfix"> <a href="<%- student_faq_url %>" class="nav-link"><%- interpolate_text( diff --git a/lms/templates/header/navbar-authenticated.html b/lms/templates/header/navbar-authenticated.html index 82d4cda9eee021dcee02428a48a6544d05c52b09..24c7cfc219ada71750245504b283ed0329c62573 100644 --- a/lms/templates/header/navbar-authenticated.html +++ b/lms/templates/header/navbar-authenticated.html @@ -60,13 +60,6 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_ % endif </div> <div class="secondary"> - % if should_display_shopping_cart_func() and not (course and static.is_request_in_themed_site()): # see shoppingcart.context_processor.user_has_cart_context_processor - <div class="mobile-nav-item hidden-mobile nav-item"> - <a class="shopping-cart" href="${reverse('shoppingcart.views.show_cart')}"> - <span class="icon fa fa-shopping-cart" aria-hidden="true"></span> ${_("Shopping Cart")} - </a> - </div> - % endif <div class="mobile-nav-item hidden-mobile nav-item"> <a class="help-link" href="${help_link}" rel="noopener" target="_blank">${_("Help")}</a> </div> diff --git a/lms/templates/header/user_dropdown.html b/lms/templates/header/user_dropdown.html index 0f18b836bc1ed6d0853cc4a34b1157889d37efdc..29288047c87f73be7da98061eb7b5911ac0ed64c 100644 --- a/lms/templates/header/user_dropdown.html +++ b/lms/templates/header/user_dropdown.html @@ -1,6 +1,6 @@ ## mako <%page expression_filter="h"/> -<%namespace name='static' file='../static_content.html'/> +<%namespace name='static' file='static_content.html'/> <%! from django.conf import settings @@ -22,12 +22,6 @@ resume_block = retrieve_last_sitewide_block_completed(self.real_user) displayname = get_enterprise_learner_generic_name(request) or username %> -<%static:webpack entry="CustomUserMenuLinks"> - $(document).ready(function() { - CustomUserMenuLinks(); - }); -</%static:webpack> - <div class="nav-item hidden-mobile"> <a href="${reverse('dashboard')}" class="menu-title"> <img class="user-image-frame" src="${profile_image_url}" alt=""> @@ -43,7 +37,7 @@ displayname = get_enterprise_learner_generic_name(request) or username % if resume_block: <div class="mobile-nav-item dropdown-item dropdown-nav-item"><a href="${resume_block}" role="menuitem">${_("Resume your last course")}</a></div> % endif - <div class="mobile-nav-item dropdown-item dropdown-nav-item dashboard"><a href="${reverse('dashboard')}" role="menuitem">${_("Dashboard")}</a></div> + <div class="mobile-nav-item dropdown-item dropdown-nav-item"><a href="${reverse('dashboard')}" role="menuitem">${_("Dashboard")}</a></div> <div class="mobile-nav-item dropdown-item dropdown-nav-item"><a href="${reverse('learner_profile', kwargs={'username': username})}" role="menuitem">${_("Profile")}</a></div> <div class="mobile-nav-item dropdown-item dropdown-nav-item"><a href="${reverse('account_settings')}" role="menuitem">${_("Account")}</a></div> % if should_redirect_to_order_history_microfrontend(): diff --git a/lms/templates/instructor/edx_ace/enrollenrolled/email/body.html b/lms/templates/instructor/edx_ace/enrollenrolled/email/body.html index 7255ffc7c999102e485439f86d17bd038cabb84b..c8cfb00995d22017b5d7c73cbae44c8d2923a114 100644 --- a/lms/templates/instructor/edx_ace/enrollenrolled/email/body.html +++ b/lms/templates/instructor/edx_ace/enrollenrolled/email/body.html @@ -21,7 +21,9 @@ <br /> </p> - {% trans "Access the Course Materials Now" as course_cta_text %} + {% filter force_escape %} + {% blocktrans asvar course_cta_text %}Access the Course Materials Now{% endblocktrans %} + {% endfilter %} {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text course_cta_url=course_url %} <p style="color: rgba(0,0,0,.75);"> diff --git a/lms/templates/learner_dashboard/course_enroll.underscore b/lms/templates/learner_dashboard/course_enroll.underscore index 99d079ec97123882628cc7733ca1dea99bf2db12..4d61f6118e6669fb3e6539ec949755641dbf474c 100644 --- a/lms/templates/learner_dashboard/course_enroll.underscore +++ b/lms/templates/learner_dashboard/course_enroll.underscore @@ -1,61 +1,58 @@ -<% if (is_enrolled && collectionCourseStatus === 'completed') { %> - <div class="final-grade"> - <div class="grade-header"><%- gettext('Final Grade') %><span class="sr"><%- StringUtils.interpolate(gettext('for {courseName}'), {courseName: title}) %></span></div> - <div class="grade-display"><%- grade %>%</div> - </div> -<% } else if (is_enrolled && (typeof expired === 'undefined' || expired === false)) { %> - <a href="<%- course_url %>" class="view-course-button btn-brand btn cta-primary"> - <% if (is_course_ended) { %> - <%- gettext('View Archived Course') %> +<% if (!(is_enrolled && collectionCourseStatus === 'completed')) { %> + <% if (is_enrolled && (typeof expired === 'undefined' || expired === false)) { %> + <a href="<%- course_url %>" class="view-course-button btn-brand btn cta-primary"> + <% if (is_course_ended) { %> + <%- gettext('View Archived Course') %> + <% } else { %> + <%- gettext('View Course') %> + <% } %> + </a> + <% } else if (!user_entitlement) { %> + <% if (enrollable_course_runs.length > 0) { %> + <% if (enrollable_course_runs.length > 1) { %> + <div class="run-select-container"> + <label class="select-choice" for="select-<%- course_key %>-run"> + <%- gettext('Select a session:') %> + </label> + <select id="select-<%- course_key %>-run" class="run-select field-input input-select" autocomplete="off"> + <% _.each (enrollable_course_runs, function(courseRun) { %> + <option + value="<%- courseRun.key %>" + <% if (key === courseRun.key) { %> + selected="selected" + <% }%> + > + <%- courseRun.dateString %> + </option> + <% }); %> + </select> + </div> + <% } %> + <div class="enroll-button"> + <% if (typeof is_mobile_only != 'undefined' && is_mobile_only === true) { %> + <a href="edxapp://enroll?course_id=<%- course_run_key %>&email_opt_in=true" class="enroll-course-button btn-brand btn cta-primary"> + <%- gettext('Enroll Now') %> + </a> + <% } else { %> + <button type="button" class="btn-brand btn cta-primary"> + <%- gettext('Enroll Now') %> + </button> + <% } %> + </div> + <% } else if (upcoming_course_runs.length > 0) {%> + <div class="no-action-message"> + <%- gettext('Coming Soon') %> + </div> + <div class="enrollment-opens"> + <%- gettext('Enrollment Opens on') %> + <span class="enrollment-open-date"> + <%- upcoming_course_runs[0].enrollment_open_date %> + </span> + </div> <% } else { %> - <%- gettext('View Course') %> - <% } %> - </a> -<% } else if (!user_entitlement) { %> - <% if (enrollable_course_runs.length > 0) { %> - <% if (enrollable_course_runs.length > 1) { %> - <div class="run-select-container"> - <label class="select-choice" for="select-<%- course_key %>-run"> - <%- gettext('Select a session:') %> - </label> - <select id="select-<%- course_key %>-run" class="run-select field-input input-select" autocomplete="off"> - <% _.each (enrollable_course_runs, function(courseRun) { %> - <option - value="<%- courseRun.key %>" - <% if (key === courseRun.key) { %> - selected="selected" - <% }%> - > - <%- courseRun.dateString %> - </option> - <% }); %> - </select> + <div class="no-action-message"> + <%- gettext('Not Currently Available') %> </div> <% } %> - <div class="enroll-button"> - <% if (typeof is_mobile_only != 'undefined' && is_mobile_only === true) { %> - <a href="edxapp://enroll?course_id=<%- course_run_key %>&email_opt_in=true" class="enroll-course-button btn-brand btn cta-primary"> - <%- gettext('Enroll Now') %> - </a> - <% } else { %> - <button type="button" class="btn-brand btn cta-primary"> - <%- gettext('Enroll Now') %> - </button> - <% } %> - </div> - <% } else if (upcoming_course_runs.length > 0) {%> - <div class="no-action-message"> - <%- gettext('Coming Soon') %> - </div> - <div class="enrollment-opens"> - <%- gettext('Enrollment Opens on') %> - <span class="enrollment-open-date"> - <%- upcoming_course_runs[0].enrollment_open_date %> - </span> - </div> - <% } else { %> - <div class="no-action-message"> - <%- gettext('Not Currently Available') %> - </div> <% } %> <% } %> diff --git a/lms/templates/learner_dashboard/program_details.html b/lms/templates/learner_dashboard/program_details.html index 37b1151dd558b4feb410a8f28c26666d74b62293..b18c48d151fa22b0283eb2fca778fbf6e5f85c51 100644 --- a/lms/templates/learner_dashboard/program_details.html +++ b/lms/templates/learner_dashboard/program_details.html @@ -1,5 +1,5 @@ -## Override the default styles_version to the Pattern Library version (version 2) -<%! main_css = "style-learner-dashboard" %> + +<%! main_css = "css/bootstrap/lms-main.css" %> <%page expression_filter="h"/> <%inherit file="../main.html" /> diff --git a/lms/templates/learner_dashboard/programs.html b/lms/templates/learner_dashboard/programs.html index be4576252cc783ae57cb2054f1a698ec085c1a59..c37db0af4b2d3234f6fe9d28ee7ddb9b145cb7f3 100644 --- a/lms/templates/learner_dashboard/programs.html +++ b/lms/templates/learner_dashboard/programs.html @@ -1,5 +1,4 @@ -## Override the default styles_version to the Pattern Library version (version 2) -<%! main_css = "style-learner-dashboard" %> +<%! main_css = "css/bootstrap/lms-main.css" %> <%page expression_filter="h"/> <%inherit file="../main.html" /> diff --git a/lms/templates/main.html b/lms/templates/main.html index efeeca17182f571065e5ec9328a02c27387c4a31..48edc767a132895becd6eaeacf25ca5e9ec1108e 100644 --- a/lms/templates/main.html +++ b/lms/templates/main.html @@ -185,11 +185,6 @@ from pipeline_mako import render_require_js_path_overrides <%include file="/preview_menu.html" /> % endif - <% is_course_staff = bool(user and course and has_access(user, 'staff', course, course.id)) %> - % if course and course.self_paced and display_reset_dates_banner and not is_course_staff: - <%include file="/reset_deadlines_banner.html" /> - % endif - <%include file="/page_banner.html" /> <div class="marketing-hero"><%block name="marketing_hero"></%block></div> diff --git a/lms/templates/modal/_modal-settings-language.html b/lms/templates/modal/_modal-settings-language.html index 8c50d0e3ef6af8b63b39d9d08e31f6e1413846eb..797cdcbad3dd3be4e7d2d11eea85b336549cd80e 100644 --- a/lms/templates/modal/_modal-settings-language.html +++ b/lms/templates/modal/_modal-settings-language.html @@ -1,5 +1,7 @@ +<%page expression_filter="h"/> <%namespace name='static' file='../static_content.html'/> <%! +from openedx.core.djangolib.markup import HTML, Text from django.utils.translation import ugettext as _ from django.urls import reverse %> @@ -53,12 +55,12 @@ from django.urls import reverse <ul class="list list-actions actions-supplemental"> <li class="list-actions-item"> - ${_("Don't see your preferred language? {link_start}Volunteer to become a translator!{link_end}").format( - link_start='<a class=" action action-volunteer" rel="external" target="_blank" href={translators_guide}>'.format( - translators_guide=settings.TRANSLATORS_GUIDE - ), - link_end="</a>" - )} + ${Text(_("Don't see your preferred language? {link_start}Volunteer to become a translator!{link_end}")).format( + link_start=HTML('<a class=" action action-volunteer" rel="external" target="_blank"\ + href={translators_guide}>').format(translators_guide=settings.TRANSLATORS_GUIDE), + link_end=HTML("</a>") + ) + } </li> </ul> </div> diff --git a/lms/templates/module-error.html b/lms/templates/module-error.html index e8a251b6930c08a241ae86d5fe1f823805d762e3..d0225979652fe3b3fbaf5eb766692c2fadae940f 100644 --- a/lms/templates/module-error.html +++ b/lms/templates/module-error.html @@ -13,10 +13,7 @@ from openedx.core.djangolib.markup import HTML, Text </h1> <p> ${Text(_("We're sorry, this module is temporarily unavailable. Our staff is working " - "to fix it as soon as possible. Please email us at {tech_support_email} to " - "report any problems or downtime.")).format( - tech_support_email=HTML(u"<a href=\"mailto:{0}\">{0}</a>").format(static.get_tech_support_email_address()) - )} + "to fix it as soon as possible. " )) } </p> % if staff_access: diff --git a/lms/templates/navigation/bootstrap/navbar-authenticated.html b/lms/templates/navigation/bootstrap/navbar-authenticated.html index e3b709f33edc624ee71ea3b7d6de7f05a62f364e..529f7984e25a80731fac3498596c9104ac901b9f 100644 --- a/lms/templates/navigation/bootstrap/navbar-authenticated.html +++ b/lms/templates/navigation/bootstrap/navbar-authenticated.html @@ -57,12 +57,6 @@ from django.utils.translation import ugettext as _ </ul> <ul class="navbar-nav navbar-right"> - % if should_display_shopping_cart_func() and not (course and static.is_request_in_themed_site()): # see shoppingcart.context_processor.user_has_cart_context_processor - <a role="button" class="nav-item-open-collapsed btn-shopping-cart btn" href="${reverse('shoppingcart.views.show_cart')}"> - <span class="icon fa fa-shopping-cart" aria-hidden="true"></span> ${_("Shopping Cart")} - </a> - % endif - <li class="nav-item mt-2 nav-item-open-collapsed"> <a href="${get_online_help_info(online_help_token)['doc_url']}" rel="noopener" diff --git a/lms/templates/navigation/navbar-authenticated.html b/lms/templates/navigation/navbar-authenticated.html index ab01763666087ca9c5dcde82d837046526998066..b27f17bd4281fd7208876772d22b4370fb3b1052 100644 --- a/lms/templates/navigation/navbar-authenticated.html +++ b/lms/templates/navigation/navbar-authenticated.html @@ -45,13 +45,3 @@ from django.utils.translation import ugettext as _ rel="noopener" target="_blank" class="doc-link">${_("Help")}</a> - -% if should_display_shopping_cart_func() and not (course and static.is_request_in_themed_site()): # see shoppingcart.context_processor.user_has_cart_context_processor - <ol class="user"> - <li class="primary"> - <a class="shopping-cart" href="${reverse('shoppingcart.views.show_cart')}"> - <span class="icon fa fa-shopping-cart" aria-hidden="true"></span> ${_("Shopping Cart")} - </a> - </li> - </ol> -% endif diff --git a/lms/templates/preview_menu.html b/lms/templates/preview_menu.html index cd7da9f5031027ef3afd07cd4345cec33f988e5d..b9d5d223ddeb27fa70131c4aa7128d3fb48c0b3b 100644 --- a/lms/templates/preview_menu.html +++ b/lms/templates/preview_menu.html @@ -26,10 +26,34 @@ show_preview_menu = course and can_masquerade and supports_preview_menu staff_selected = selected(not masquerade or masquerade.role != "student") specific_student_selected = selected(not staff_selected and masquerade.user_name) student_selected = selected(not staff_selected and not specific_student_selected and not masquerade_group_id) + + if settings.HTTPS == 'on': + protocol = 'https' + else: + protocol = 'http' + insights_base_url = '' + if settings.ANALYTICS_DASHBOARD_URL: + insights_base_url = settings.ANALYTICS_DASHBOARD_URL + '/courses' + studio_base_url = '' + if settings.CMS_BASE: + studio_base_url = protocol + '://' + settings.CMS_BASE + insights_url = insights_base_url + studio_url = studio_base_url + if course and course.id: + if insights_base_url: + insights_url = "{base_url}/{course_id}".format( + base_url=insights_base_url, + course_id=course.id, + ) + if studio_base_url: + studio_url = "{base_url}/course/{course_id}".format( + base_url=studio_base_url, + course_id=course.id, + ) %> <nav class="wrapper-preview-menu" aria-label="${_('Course View')}"> <div class="preview-menu" style="display: flex; align-items: center;"> - <ol class="preview-actions"> + <ol class="preview-actions" style="flex-grow: 1;"> <li class="action-preview"> <form action="#" class="action-preview-form" method="post"> <label for="action-preview-select" class="action-preview-label">${_("View this course as:")}</label> @@ -66,13 +90,59 @@ show_preview_menu = course and can_masquerade and supports_preview_menu </p> </div> % endif + <div style="flex-shrink: 1; text-align: center;"> % if microfrontend_link: - <div style="flex-grow: 1; text-align: right;"> <a class="btn btn-primary" style="border: solid 1px white;" href="${microfrontend_link}"> - ${_("View this unit in the new experience")} + ${_("View in the new experience")} </a> - </div> % endif + % if studio_url: + <a + class="btn btn-primary view-in-studio" + style="border: solid 1px white;" + href="${studio_url}" + data-studio-base-url="${studio_base_url}" + > + ${_("View in Studio")} + </a> + <script type="text/javascript"> + $(function () { + $('.wrapper-preview-menu a.view-in-studio').click(function (event) { + /* + When we start rendering this template, we + don't yet have a vertical in the context + (that happens in a separate `render` call, + if this is even on a unit-level page), + so we dynamically lookup the vertical element in + the DOM and use its data-* attributes to + construct a Studio link directly to this unit. + If no vertical is present, the link behaves as + normal. + */ + var verticals = $('.xblock-student_view-vertical'); + if (verticals.length > 0) { + var blockId = verticals[0].dataset.usageId; + var url = [ + this.dataset.studioBaseUrl, + 'container', + blockId, + ].join('/'); + window.location.href = url; + return false; + } + // There's no vertical, so let the event + // bubble up, ie, work like a normal link. + return true; + }); + }); + </script> + % endif + % if insights_url: + <a class="btn btn-primary" style="border: solid 1px white;" href="${insights_url}"> + ${_("View in Insights")} + </a> + % endif + </div> </div> </nav> diff --git a/lms/templates/reset_deadlines_banner.html b/lms/templates/reset_deadlines_banner.html deleted file mode 100644 index a4de68053e0a1b9004b50ad5891538eaaf7ade76..0000000000000000000000000000000000000000 --- a/lms/templates/reset_deadlines_banner.html +++ /dev/null @@ -1,25 +0,0 @@ -## mako - -<%page expression_filter="h"/> -<%! -from django.utils.translation import ugettext as _ -%> -<div class="reset-deadlines-banner"> - <div class="reset-deadlines-text"> - % if web_app_course_url: - ${_("It looks like you've missed some important deadlines. Visit ")} - <a href="${web_app_course_url}">${_("edx.org")}</a> - ${_(" to reset your deadlines and get started today.")} - % else: - ${_("It looks like you've missed some important deadlines. Reset your deadlines and get started today.")} - % endif - </div> - % if not web_app_course_url: - <form method="post" action="${reset_deadlines_url}"> - <input type="hidden" id="csrf_token" name="csrfmiddlewaretoken" value="${csrf_token}"> - <input type="hidden" name="reset_deadlines_redirect_url_base" value="${reset_deadlines_redirect_url_base}"> - <input type="hidden" name="reset_deadlines_redirect_url_id_dict" value="${reset_deadlines_redirect_url_id_dict}"> - <button class="btn reset-deadlines-button">${_("Reset my deadlines")}</button> - </form> - % endif -</div> diff --git a/lms/templates/seq_module.html b/lms/templates/seq_module.html index 6a49a60b6e09be2d090dc8f1926f8fb51476e2b0..68b99334d54bedfe2e7d58c9a3e989f7e8c2cab4 100644 --- a/lms/templates/seq_module.html +++ b/lms/templates/seq_module.html @@ -21,6 +21,7 @@ </div> % endif % endif + % if not gated_sequence_fragment: <div class="sequence-nav"> <button class="sequence-nav-button button-previous"> <span class="icon fa fa-chevron-prev" aria-hidden="true"></span> @@ -98,9 +99,15 @@ </ol> </nav> </div> + % endif % if not exclude_units: % if gated_content['gated']: <%include file="_gated_content.html" args="prereq_url=gated_content['prereq_url'], prereq_section_name=gated_content['prereq_section_name'], gated_section_name=gated_content['gated_section_name']"/> + % elif gated_sequence_fragment: + <h2 class="hd hd-2 unit-title"> + ${sequence_name}<span class="sr">${_("Content Locked")}</span> + </h2> + ${gated_sequence_fragment | n, decode.utf8} % else: <div class="sr-is-focusable" tabindex="-1"></div> diff --git a/lms/templates/static_templates/embargo.html b/lms/templates/static_templates/embargo.html index bb2188e7ebbd1da7c5afb127458750a58483fbd1..4a22d27ed4e581263749615b1d62066d4905f343 100644 --- a/lms/templates/static_templates/embargo.html +++ b/lms/templates/static_templates/embargo.html @@ -15,13 +15,13 @@ from openedx.core.djangolib.markup import HTML, Text </h1> % endif <p> - <%block name="pagecontent">${page_content or Text(_("Our system indicates that you are trying to access this {platform_name} " - "course from a country or region currently subject to U.S. economic and trade sanctions." - "Unfortunately, because {platform_name} is required to comply with export controls," - "we cannot allow you to access this course at this time." - )).format( + <%block name="pagecontent">${page_content or Text(_("Our system indicates that you are trying to access this {platform_name} " + "course from a country or region currently subject to U.S. economic and trade sanctions. " + "Unfortunately, because {platform_name} is required to comply with export controls, " + "we cannot allow you to access this course at this time." + )).format( platform_name=Text(settings.PLATFORM_NAME), - )}} + )} </%block> </p> </section> diff --git a/lms/templates/student_account/access.underscore b/lms/templates/student_account/access.underscore index 2f765aef1bb1d3f495cb1dd5a447283ee4c0c078..d52784e9c1980db0e228ccbb3496d29e32489a10 100644 --- a/lms/templates/student_account/access.underscore +++ b/lms/templates/student_account/access.underscore @@ -7,7 +7,7 @@ </section> <section id="password-reset-anchor" class="form-type"> - <div id="password-reset-form" class="form-wrapper hidden"></div> + <div id="password-reset-form" class="form-wrapper <% if ( mode !== 'reset' ) { %>hidden<% } %>"></div> </section> <section id="institution_login-anchor" class="form-type"> diff --git a/lms/templates/student_account/account_settings.html b/lms/templates/student_account/account_settings.html index 184c58411fb48bd0943b715ccf2945859a446677..83bb822327b3a0de0ac6f74d6729929a5e0db705 100644 --- a/lms/templates/student_account/account_settings.html +++ b/lms/templates/student_account/account_settings.html @@ -10,7 +10,7 @@ from django.utils.translation import ugettext as _ from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_string from openedx.core.djangolib.markup import HTML from webpack_loader.templatetags.webpack_loader import render_bundle -from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled_for_user +from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled %> <%inherit file="/main.html" /> @@ -47,7 +47,7 @@ from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_f edxSupportUrl = '${ edx_support_url | n, js_escaped_string }', extendedProfileFields = ${ extended_profile_fields | n, dump_js_escaped_json }, displayAccountDeletion = ${ enable_account_deletion | n, dump_js_escaped_json}; - isSecondaryEmailFeatureEnabled = ${ bool(is_secondary_email_feature_enabled_for_user(user)) | n, dump_js_escaped_json }, + isSecondaryEmailFeatureEnabled = ${ bool(is_secondary_email_feature_enabled()) | n, dump_js_escaped_json }, AccountSettingsFactory( fieldsData, diff --git a/lms/templates/student_account/form_field.underscore b/lms/templates/student_account/form_field.underscore index 6350d77bdf04d5a0c0201745aa4288ab9f72e9f9..080e38b8ba5c7bb93749eccac32705344d41491e 100644 --- a/lms/templates/student_account/form_field.underscore +++ b/lms/templates/student_account/form_field.underscore @@ -127,12 +127,24 @@ <span id="<%- form %>-<%- name %>-validation-error" class="tip error" aria-live="assertive"> <span class="sr-only"></span> - <span id="<%- form %>-<%- name %>-validation-error-msg"></span> + <span id="<%- form %>-<%- name %>-validation-error-msg"><ul class="fa-ul"></ul></span> </span> <% if ( instructions ) { %> <span class="tip tip-input" id="<%- form %>-<%- name %>-desc"><%- instructions %></span><% } %> <% } %> <% if( form === 'login' && name === 'password' ) { %> - <button type="button" class="forgot-password field-link"><%- gettext("Need help logging in?") %></button> + <button type="button" class="login-help field-link"><i class="fa fa-caret-right" /><%- gettext("Need help signing in?") %></button> + <div id="login-help" style="display:none"> + <button type="button" class="field-link form-toggle" data-type="password-reset"><%- gettext("Forgot my password") %></button> + <span><a class="field-link" href="https://support.edx.org/hc/en-us/sections/115004153367-Solve-a-Sign-in-Problem"><%- gettext("Other sign-in issues") %></a></span> + </div> + <button type="button" class="enterprise-login field-link"><%- gettext("Sign in with your company or school") %></button> + <% } %> + <% if( form === 'password-reset' && name === 'email' ) { %> + <button type="button" class="reset-help field-link" ><i class="fa fa-caret-right" /><%- gettext("Need other help signing in?") %></button> + <div id="reset-help" style="display:none"> + <button type="button" class="field-link form-toggle" data-type="register"><%- gettext("Create an account") %></button> + <span><a class="field-link" href="https://support.edx.org/hc/en-us/sections/115004153367-Solve-a-Sign-in-Problem"><%- gettext("Other sign-in issues") %></a></span> + </div> <% } %> </div> diff --git a/lms/templates/support/refund.html b/lms/templates/support/refund.html deleted file mode 100644 index d45dd149f6fdc1b0035f5998f5b24c0744e83b44..0000000000000000000000000000000000000000 --- a/lms/templates/support/refund.html +++ /dev/null @@ -1,83 +0,0 @@ -## mako - -<%page expression_filter="h"/> - -<%! -from django.utils.translation import ugettext as _ -from django.utils.html import escape -%> - -<%inherit file="../main.html"/> - -<%block name="title"> -<title> -Manual Refund -</title> -</%block> -<%block name="headextra"> - -<style type="text/css"> -.errorlist,.messages { - color: red; -} -.success { - color: green; -} -strong { - padding-right: 10px; -} -</style> -</%block> - - -<%block name="body"> -<div class="content-wrapper" id="content"> - <div class="container about"> - <h1>${_("Manual Refund")}</h1> - % if messages: - <ul class="messages"> - % for message in messages: - <li class="${message.tags if message.tags else ''}">${message}</li> - % endfor - </ul> - % endif - - <form method="POST" id="refund_form"> - <input type="hidden" id="csrf_token" name="csrfmiddlewaretoken" value="${csrf_token}" /> - ${form.as_p()} - <p> - <input type="button" value="Cancel" onclick="javascript:location=location"/> <input type="submit" value="${'Refund' if cert else 'Confirm'}" /> - </p> - </form> - % if cert: - <section class="content-wrapper"> - <h2> - ${_("About to refund this order:")} - </h2> - <p> - <strong>${_("Order Id:")}</strong> ${cert.order.id} - </p> - <p> - <strong>${_("Enrollment:")}</strong> ${escape(enrollment.course_id)} ${enrollment.mode} - (${_("enrolled") if enrollment.is_active else _("unenrolled")}) - </p> - <p> - <strong>${_("Cost:")}</strong> ${cert.unit_cost} ${cert.currency} - </p> - <p> - <strong>${_("CertificateItem Status:")}</strong> ${cert.status} - </p> - <p> - <strong>${_("Order Status:")}</strong> ${cert.order.status} - </p> - <p> - <strong>${_("Fulfilled Time:")}</strong> ${cert.fulfilled_time} - </p> - <p> - <strong>${_("Refund Request Time:")}</strong> ${cert.refund_requested_time} - </p> - </section> - % endif - </div> -</div> -</%block> diff --git a/lms/templates/verify_student/reverify_not_allowed.html b/lms/templates/verify_student/reverify_not_allowed.html index 019ce41661907c31d2b14536d76c790e31c74576..8fc7d63f86a298b63fff790005b76536f3f07507 100644 --- a/lms/templates/verify_student/reverify_not_allowed.html +++ b/lms/templates/verify_student/reverify_not_allowed.html @@ -14,7 +14,7 @@ <div class="instructions"> <p> % if status in ["pending", "approved"]: - ${_("You have already submitted your verification information. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days).")} + ${_("You have already submitted your verification information. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days).")} % else: ${_("You cannot verify your identity at this time.")} % endif diff --git a/lms/templates/verify_student/reverify_success_step.underscore b/lms/templates/verify_student/reverify_success_step.underscore index 8c6e2e9fdb091a6b38c3f4b093cb06f386382fd2..ca0d0a2c8883b023b051c23adac7a0ceea3f1a0e 100644 --- a/lms/templates/verify_student/reverify_success_step.underscore +++ b/lms/templates/verify_student/reverify_success_step.underscore @@ -2,7 +2,7 @@ <h1 class="title"><%- gettext( "Identity Verification In Progress" ) %></h3> <div class="instruction"> - <p><%- gettext( "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 1-2 days). In the meantime, you can still access all available course content." ) %></p> + <p><%- gettext( "We have received your information and are verifying your identity. You will see a message on your dashboard when the verification process is complete (usually within 5-7 days). In the meantime, you can still access all available course content." ) %></p> </div> <div class="wrapper-actions"> diff --git a/lms/templates/vert_module.html b/lms/templates/vert_module.html index 69620585f7fe153947776fc20f58652896c2a051..bc0f54120739852b025872f7a1ae8f965e792cb1 100644 --- a/lms/templates/vert_module.html +++ b/lms/templates/vert_module.html @@ -1,10 +1,31 @@ <%page expression_filter="h"/> -<%! from openedx.core.djangolib.markup import HTML %> + +<%namespace name='static' file='/static_content.html'/> + +<%! +from django.utils.translation import gettext as _ + +from openedx.core.djangolib.markup import HTML +%> %if unit_title and show_title: <h2 class="hd hd-2 unit-title">${unit_title}</h2> % endif +% if due: + <% + data_string = _("{subsection_format} due {{date}}").format(subsection_format=subsection_format) + %> + <div class="vert-due-date"> + <div class="localized-datetime" data-datetime="${due}" data-string="${data_string}" data-timezone="${user_timezone}"></div> + % if completed: + <div class="pill completed">${_('Completed')}</div> + % elif past_due: + <div class="pill past-due">${_('Past Due')}</div> + %endif + </div> +% endif + % if show_bookmark_button: <%include file='bookmark_button.html' args="bookmark_id=bookmark_id, is_bookmarked=bookmarked"/> % endif @@ -18,3 +39,7 @@ %endif % endfor </div> + +<%static:require_module_async module_name="js/dateutil_factory" class_name="DateUtilFactory"> + DateUtilFactory.transform('.localized-datetime'); +</%static:require_module_async> diff --git a/lms/templates/wiki/plugins/attachments/index.html b/lms/templates/wiki/plugins/attachments/index.html index c8ebda39d41acc0af9af63e887948ba0b52fc694..7423356e598e6f5b0b4b27fe8399b6b9de74c5a8 100644 --- a/lms/templates/wiki/plugins/attachments/index.html +++ b/lms/templates/wiki/plugins/attachments/index.html @@ -61,6 +61,7 @@ <div class="attachment-list"> + # xss-lint: disable=django-trans-missing-escape <!--<p class="lead">{% trans "The following files are available for this article. Copy the markdown tag to directly refer to a file from the article text." %}</p>--> <ul> {% for attachment in attachments %} diff --git a/lms/urls.py b/lms/urls.py index 29e961942e60d37e8a28ffda24344174faebd9c2..33248fafb0de3e9af9058fb9e0926d77ab245cbd 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -15,7 +15,7 @@ from ratelimitbackend import admin from branding import views as branding_views from debug import views as debug_views from lms.djangoapps.certificates import views as certificates_views -from lms.djangoapps.courseware.masquerade import handle_ajax as courseware_masquerade_handle_ajax +from lms.djangoapps.courseware.masquerade import MasqueradeView from lms.djangoapps.courseware.module_render import ( handle_xblock_callback, handle_xblock_callback_noauth, @@ -27,9 +27,7 @@ from lms.djangoapps.courseware.views.index import CoursewareIndex from lms.djangoapps.courseware.views.views import CourseTabView, EnrollStaffView, StaticCourseTabView from lms.djangoapps.discussion import views as discussion_views from lms.djangoapps.discussion.notification_prefs import views as notification_prefs_views -from lms.djangoapps.instructor.views import coupons as instructor_coupons_views from lms.djangoapps.instructor.views import instructor_dashboard as instructor_dashboard_views -from lms.djangoapps.instructor.views import registration_codes as instructor_registration_codes_views from lms.djangoapps.instructor_task import views as instructor_task_views from openedx.core.apidocs import api_info from openedx.core.djangoapps.auth_exchange.views import LoginWithAccessTokenView @@ -57,6 +55,7 @@ from util import views as util_views RESET_COURSE_DEADLINES_NAME = 'reset_course_deadlines' RENDER_XBLOCK_NAME = 'render_xblock' +COURSE_DATES_NAME = 'dates' if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'): django_autodiscover() @@ -117,7 +116,7 @@ urlpatterns = [ url(r'^api/enrollment/v1/', include('openedx.core.djangoapps.enrollments.urls')), # Entitlement API RESTful endpoints - url(r'^api/entitlements/', include(('entitlements.api.urls', 'common.djangoapps.entitlements'), + url(r'^api/entitlements/', include(('entitlements.rest_api.urls', 'common.djangoapps.entitlements'), namespace='entitlements_api')), # Courseware search endpoints @@ -228,19 +227,6 @@ if settings.WIKI_ENABLED: include((wiki_url_patterns, 'course_wiki_do_not_reverse'), namespace='course_wiki_do_not_reverse')), ] -COURSE_URLS = [ - url( - r'^look_up_registration_code$', - instructor_registration_codes_views.look_up_registration_code, - name='look_up_registration_code', - ), - url( - r'^registration_code_details$', - instructor_registration_codes_views.registration_code_details, - name='registration_code_details', - ), -] - urlpatterns += [ # jump_to URLs for direct access to a location in the course url( @@ -486,7 +472,7 @@ urlpatterns += [ settings.COURSE_ID_PATTERN, ), courseware_views.dates, - name='dates', + name=COURSE_DATES_NAME, ), # Takes optional student_id for instructor use--shows profile as that student sees it. @@ -522,41 +508,6 @@ urlpatterns += [ instructor_dashboard_views.set_course_mode_price, name='set_course_mode_price', ), - url( - r'^courses/{}/remove_coupon$'.format( - settings.COURSE_ID_PATTERN, - ), - instructor_coupons_views.remove_coupon, - name='remove_coupon', - ), - url( - r'^courses/{}/add_coupon$'.format( - settings.COURSE_ID_PATTERN, - ), - instructor_coupons_views.add_coupon, - name='add_coupon', - ), - url( - r'^courses/{}/update_coupon$'.format( - settings.COURSE_ID_PATTERN, - ), - instructor_coupons_views.update_coupon, - name='update_coupon', - ), - url( - r'^courses/{}/get_coupon_info$'.format( - settings.COURSE_ID_PATTERN, - ), - instructor_coupons_views.get_coupon_info, - name='get_coupon_info', - ), - - url( - r'^courses/{}/'.format( - settings.COURSE_ID_PATTERN, - ), - include(COURSE_URLS) - ), # Discussions Management url( @@ -720,7 +671,7 @@ if settings.FEATURES.get('ENABLE_MASQUERADE'): r'^courses/{}/masquerade$'.format( settings.COURSE_KEY_PATTERN, ), - courseware_masquerade_handle_ajax, + MasqueradeView.as_view(), name='masquerade_update', ), ] @@ -816,7 +767,6 @@ if configuration_helpers.get_value('ENABLE_BULK_ENROLLMENT_VIEW', settings.FEATU # Shopping cart urlpatterns += [ url(r'^shoppingcart/', include('shoppingcart.urls')), - url(r'^commerce/', include(('lms.djangoapps.commerce.urls', 'lms.djangoapps.commerce'), namespace='commerce')), ] # Course goals @@ -997,4 +947,24 @@ if 'openedx.testing.coverage_context_listener' in settings.INSTALLED_APPS: url(r'coverage_context', include('openedx.testing.coverage_context_listener.urls')) ] +urlpatterns.append( + url( + r'^api/learning_sequences/', + include( + ('openedx.core.djangoapps.content.learning_sequences.urls', 'learning_sequences'), + namespace='learning_sequences' + ), + ), +) + urlpatterns.extend(plugin_urls.get_patterns(plugin_constants.ProjectType.LMS)) + +# Course Home API urls +urlpatterns += [ + url(r'^api/course_home/', include('lms.djangoapps.course_home_api.urls')), +] + +# Course Experience API urls +urlpatterns += [ + url(r'^api/course_experience/', include('openedx.features.course_experience.api.v1.urls')), +] diff --git a/lms/wsgi.py b/lms/wsgi.py index d71a2c26ebcddb73d126376cfe4fa6ef3f9df473..2893066edd312f7a4091cfc63692d41bcb4993c9 100644 --- a/lms/wsgi.py +++ b/lms/wsgi.py @@ -32,4 +32,4 @@ modulestore() # This application object is used by the development server # as well as any WSGI server configured to use this file. from django.core.wsgi import get_wsgi_application -application = get_wsgi_application() # pylint: disable=invalid-name +application = get_wsgi_application() diff --git a/openedx/core/apidocs.py b/openedx/core/apidocs.py index 9f81cfa59110da9c2b4d0e066967dd79164d8bfa..3651a2162c4db00ebe94a6864660e4b495b14dda 100644 --- a/openedx/core/apidocs.py +++ b/openedx/core/apidocs.py @@ -3,6 +3,7 @@ Open API support. """ from edx_api_doc_tools import make_api_info +from rest_framework import serializers api_info = make_api_info( title="Open edX API", @@ -12,3 +13,42 @@ api_info = make_api_info( email="oscm@edx.org", #license=openapi.License(name="BSD License"), # TODO: What does this mean? ) + + +def cursor_paginate_serializer(inner_serializer_class): + """ + Create a cursor-paginated version of a serializer. + + This is hacky workaround for an edx-api-doc-tools issue described here: + https://github.com/edx/api-doc-tools/issues/32 + + It assumes we are using cursor-style pagination and assumes a specific + schema for the pages. It should be removed once we address the underlying issue. + + Arguments: + inner_serializer_class (type): A subclass of ``Serializer``. + + Returns: type + A subclass of ``Serializer`` to model the schema of a page of a cursor-paginated + endpoint. + """ + class PageOfInnerSerializer(serializers.Serializer): + """ + A serializer for a page of a cursor-paginated list of ``inner_serializer_class``. + """ + # pylint: disable=abstract-method + previous = serializers.URLField( + required=False, + help_text="Link to the previous page or results, or null if this is the first.", + ) + next = serializers.URLField( + required=False, + help_text="Link to the next page of results, or null if this is the last.", + ) + results = serializers.ListField( + child=inner_serializer_class(), + help_text="The list of result objects on this page.", + ) + + PageOfInnerSerializer.__name__ = 'PageOf{}'.format(inner_serializer_class.__name__) + return PageOfInnerSerializer diff --git a/openedx/core/djangoapps/auth_exchange/tests/test_forms.py b/openedx/core/djangoapps/auth_exchange/tests/test_forms.py index a326ca6f06b74bd6d859675f01508bed7cc8f7f5..db135b68bb263a0d194441c2ac26a1be325a157e 100644 --- a/openedx/core/djangoapps/auth_exchange/tests/test_forms.py +++ b/openedx/core/djangoapps/auth_exchange/tests/test_forms.py @@ -67,6 +67,7 @@ class DOTAccessTokenExchangeFormTestFacebook( """ pass + # This is necessary because cms does not implement third party auth @unittest.skipUnless(TPA_FEATURE_ENABLED, TPA_FEATURES_KEY + " not enabled") @httpretty.activate diff --git a/openedx/core/djangoapps/bookmarks/views.py b/openedx/core/djangoapps/bookmarks/views.py index a2c897e0721c9fa06c9a03ca0a1124c830175a07..03720e944d3575f4c53de4586a8eb48d4c5c5a3b 100644 --- a/openedx/core/djangoapps/bookmarks/views.py +++ b/openedx/core/djangoapps/bookmarks/views.py @@ -137,7 +137,7 @@ class BookmarksListView(ListCreateAPIView, BookmarksViewMixin): * "display_name" * "path" - # Example Requests + **Example Requests** GET /api/bookmarks/v1/bookmarks/?course_id={course_id1}&fields=display_name,path """ @@ -211,7 +211,7 @@ class BookmarksListView(ListCreateAPIView, BookmarksViewMixin): the usage_id is invalid or a block corresponding to the usage_id could not be found. - # Example Requests + **Example Requests** POST /api/bookmarks/v1/bookmarks/ Request data: {"usage_id": <usage-id>} @@ -316,7 +316,7 @@ class BookmarksDetailView(APIView, BookmarksViewMixin): """ Get a specific bookmark for a user. - # Example Requests + **Example Requests** GET /api/bookmarks/v1/bookmarks/{username},{usage_id}?fields=display_name,path """ diff --git a/openedx/core/djangoapps/catalog/docs/decisions/001-programs-cache.rst b/openedx/core/djangoapps/catalog/docs/decisions/001-programs-cache.rst new file mode 100644 index 0000000000000000000000000000000000000000..bf8540632359137a141f043583ecc4c63dde687a --- /dev/null +++ b/openedx/core/djangoapps/catalog/docs/decisions/001-programs-cache.rst @@ -0,0 +1,83 @@ +Programs Cache in LMS +_____________________ + +Status +====== +Accepted + +Decision +========= +1. Developers working on code involving programs (which is not limited Programs theme developers) should be directed to this ADR for context on the usage and limitations of the programs cache. + +2. Consumers of the programs cache should expect cache misses and either handle them gracefully when possible or explicitly fail (with logging). + + a. Depending on the cache access pattern, it may be impossible to distinguish between a non-existent program and an existent program that is missing from the cache. +3. Introduce logging to the programs cache, especially in the case of cache misses or an empty cache. This will make debugging easier and make it more apparent when intervention (such as manually running cache_programs) is necessary. + +4. All edX.org developers should be given access to the Jenkins job that runs cache_programs. + +Context +======= +The LMS in edx-platform has a limited understanding of the structure and content of programs, as they are stored authoritatively in the Discovery service's SQL database. However, certain features of the LMS, such as displaying a learner’s programs on their dashboard, require access to the programs’ data. To fulfill this need, the LMS has the JSON responses from Discovery’s /api/v1/programs endpoint stored in memcached. The LMS uses the cache to understand what program or programs a course (run) is in. The contents of the cache are exposed through the ``openedx.core.djangoapps.catalog`` app. This system is what we are referring to when we say "the programs cache†or simply “the cacheâ€. + +This cache is populated by calling LMS’s cache_programs management command. +The cache is regularly refreshed via an external process. +By design, the cache does not populate itself by calling out to the Discovery API upon a cache miss. + +Below is a (not-necessarily-exhaustive) list of features that depend on the programs cache: + +* The learner dashboard shows “Related Programs†under the cards of courses that are in programs. +* The programs progress page. +* The creation of external IDs for users enrolled in courses within MicroBachelors programs requires knowledge of programs. +* The program_enrollments system, which Masters uses for institution-managed enrollments in degree programs, uses the programs cache for validation of when creating associations between program enrollments and course enrollments. +* The LMS management commands that populate program credentials need knowledge of programs. +* Temporary Experiments often utilize the programs cache. +* Courseware will reference programs information in order to show in-course recommendations. + +Issues +====== +Correctness & Resiliency +------------------------ + +Because the cache is held in volatile memory, any crash or restart of the memcache server holding the programs cache can surface these issues. While the cache_programs command can be run immediately afterwards, this is not a foolproof solution: + +* For a large course catalog, this command takes time to run, so there will be at least some time where LMS programs features are broken due to missing data. +* Site operators may not know that this has to be done. Even if they do, it adds operational complexity. +* The command may fail. + +Recently, the edX.org memcached cluster was restarted due to an increased LMS load. Following the restart, the cache_programs was not run immediately. As a result, there may have been an impact on LMS functionality due to the empty cache. + +Developer & operator experience +------------------------------- + +Requiring the regularly-scheduled execution of a management command to make the LMS fully functional adds operational complexity to courses.edx.org, Open edX instances, Devstack, and Sandboxes. + +Knowledge & access +------------------ +The requirements to populate the cache via the edx.org Jenkins job, the privileges required or the fact that the cache is not auto refreshed are not well known. + +Future Recommendations and Alternatives +========================================= +* Call into Discovery service if cache miss happens. + * Pros: + * Removes the issues that arise when a program is not present in the cache. + * Handles the case of a completely empty cache. + * Cons: + * Increases the dependence of LMS on Discovery. + * Increases the potential load on the Discovery API. + * Involves some engineering effort. +* Persist Discovery data in LMS MySQL database. + * Pros: + * Moving to persistent storage would mitigate the “cache accidentally emptied†issue that is inherent to volatile storage. + + * Cons: + * Data duplication. + * Ensuring that data is synchronized between the two caches. + * Managing an additional SQL schema. + * Involves significant engineering effort. +* Remove logic from LMS that relies on programs. + * Pros: + * Potentially best long-term solution as it reduces the amount of data/complexity. + * All programs cache issues are de facto resolved. + * Cons: + * Involves potentially huge engineering and product effort to accomplish, as many features would have to be replicated elsewhere or removed. diff --git a/openedx/core/djangoapps/catalog/tests/factories.py b/openedx/core/djangoapps/catalog/tests/factories.py index 0fe37b1985efd8d1bd315c93ab77a20e9ae5308f..83dd08d25ff5225ff3a92b5501c76c52a3b6ced3 100644 --- a/openedx/core/djangoapps/catalog/tests/factories.py +++ b/openedx/core/djangoapps/catalog/tests/factories.py @@ -1,5 +1,5 @@ """Factories for generating fake catalog data.""" -# pylint: disable=missing-docstring, invalid-name +# pylint: disable=missing-class-docstring, invalid-name import uuid @@ -61,6 +61,37 @@ class DictFactoryBase(factory.Factory): class Meta(object): model = dict + def __getitem__(self, item): + """ + Pass-through to superclass's __getitem__. + + This is a no-op hack to convince pylint that instances of this class + are subscriptable. + + As a specific example, it stops pylint from complaining about: + program = ProgramFactory() + courses = program['courses'] + with `Value 'program' is unsubscriptable`. + """ + # pylint: disable=useless-super-delegation + return super().__getitem__(item) # pylint: disable=no-member + + def __setitem__(self, item, value): + """ + Pass-through to superclass's __setitem__. + + This is no-op hack to convince pylint that instances of this class + support item assignment. + + As a specific example, it stops pylint from complaining about: + program = ProgramFactory() + new_course = ... + program['courses'] += [new_course] + with `Value 'program' does not support item assignment`. + """ + # pylint: disable=no-member,useless-super-delegation + return super().__setitem__(item, value) + class ImageFactoryBase(DictFactoryBase): height = factory.Faker('random_int') diff --git a/openedx/core/djangoapps/content/block_structure/block_structure.py b/openedx/core/djangoapps/content/block_structure/block_structure.py index 612c9dd584d8393e3a243e0081cd30fdf8db6521..c3568d35638ecd9d98d5486dd63841773ced367f 100644 --- a/openedx/core/djangoapps/content/block_structure/block_structure.py +++ b/openedx/core/djangoapps/content/block_structure/block_structure.py @@ -482,7 +482,7 @@ class BlockStructureBlockData(BlockStructure): override_data (object) - The data you want to set """ - block_data = self._block_data_map.get(usage_key) + block_data = self._get_or_create_block(usage_key) setattr(block_data, field_name, override_data) def get_transformer_data(self, transformer, key, default=None): diff --git a/openedx/core/djangoapps/content/block_structure/tests/test_signals.py b/openedx/core/djangoapps/content/block_structure/tests/test_signals.py index 52360b6fa3a90bd2f575cbbac277772ec826a776..d1679edb39af382bbb395123b9f3e9e272cea935 100644 --- a/openedx/core/djangoapps/content/block_structure/tests/test_signals.py +++ b/openedx/core/djangoapps/content/block_structure/tests/test_signals.py @@ -75,7 +75,7 @@ class CourseBlocksSignalTest(ModuleStoreTestCase): @ddt.data( (CourseLocator(org='org', course='course', run='run'), True), - (LibraryLocator(org='org', course='course'), False), + (LibraryLocator(org='org', library='course'), False), ) @ddt.unpack @patch('openedx.core.djangoapps.content.block_structure.tasks.update_course_in_cache_v2.apply_async') diff --git a/openedx/core/djangoapps/content/block_structure/transformer.py b/openedx/core/djangoapps/content/block_structure/transformer.py index 5f1ad27530b65a4f389a6500f6647db5e7bfb9cb..31099a4a41e8576be40f3635537bb026c01e7b43 100644 --- a/openedx/core/djangoapps/content/block_structure/transformer.py +++ b/openedx/core/djangoapps/content/block_structure/transformer.py @@ -5,6 +5,7 @@ Transformers. from abc import abstractmethod +import functools class BlockStructureTransformer(object): @@ -177,7 +178,8 @@ class FilteringTransformerMixin(BlockStructureTransformer): transform_block_filters calls will be combined and used in a single tree traversal. """ - block_structure.filter_topological_traversal(self.transform_block_filters(usage_info, block_structure)) + filters = self.transform_block_filters(usage_info, block_structure) + block_structure.filter_topological_traversal(combine_filters(block_structure, filters)) @abstractmethod def transform_block_filters(self, usage_info, block_structure): @@ -209,3 +211,19 @@ class FilteringTransformerMixin(BlockStructureTransformer): transformer, that is to be transformed in place. """ raise NotImplementedError + + +def combine_filters(block_structure, filters): + return functools.reduce( + _filter_chain, + filters, + block_structure.create_universal_filter() + ) + + +def _filter_chain(accumulated, additional): + """ + Given two functions that take a block_key and return a boolean, yield + a function that takes a block key, and 'ands' the functions together + """ + return lambda block_key: accumulated(block_key) and additional(block_key) diff --git a/openedx/core/djangoapps/content/block_structure/transformers.py b/openedx/core/djangoapps/content/block_structure/transformers.py index ae7a0028138a187edaa8e3d5e5e7e8ed4f6b2722..4c535e8e5e3c8cd29a7c470eed248261d69d24ac 100644 --- a/openedx/core/djangoapps/content/block_structure/transformers.py +++ b/openedx/core/djangoapps/content/block_structure/transformers.py @@ -7,7 +7,7 @@ import functools from logging import getLogger from .exceptions import TransformerDataIncompatible, TransformerException -from .transformer import FilteringTransformerMixin +from .transformer import FilteringTransformerMixin, combine_filters from .transformer_registry import TransformerRegistry logger = getLogger(__name__) # pylint: disable=C0103 @@ -131,20 +131,9 @@ class BlockStructureTransformers(object): for transformer in self._transformers['supports_filter']: filters.extend(transformer.transform_block_filters(self.usage_info, block_structure)) - combined_filters = functools.reduce( - self._filter_chain, - filters, - block_structure.create_universal_filter() - ) + combined_filters = combine_filters(block_structure, filters) block_structure.filter_topological_traversal(combined_filters) - def _filter_chain(self, accumulated, additional): - """ - Given two functions that take a block_key and return a boolean, yield - a function that takes a block key, and 'ands' the functions together - """ - return lambda block_key: accumulated(block_key) and additional(block_key) - def _transform_without_filters(self, block_structure): """ Transforms the given block_structure using the transform diff --git a/openedx/core/djangoapps/content/course_overviews/migrations/0021_courseoverviewtab_link.py b/openedx/core/djangoapps/content/course_overviews/migrations/0021_courseoverviewtab_link.py new file mode 100644 index 0000000000000000000000000000000000000000..bc0bc6a9337f944cee643b9cba2aa930659352ce --- /dev/null +++ b/openedx/core/djangoapps/content/course_overviews/migrations/0021_courseoverviewtab_link.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-04-21 15:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('course_overviews', '0020_courseoverviewtab_url_slug'), + ] + + operations = [ + migrations.AddField( + model_name='courseoverviewtab', + name='link', + field=models.TextField(null=True), + ), + ] diff --git a/openedx/core/djangoapps/content/course_overviews/migrations/0022_courseoverviewtab_is_hidden.py b/openedx/core/djangoapps/content/course_overviews/migrations/0022_courseoverviewtab_is_hidden.py new file mode 100644 index 0000000000000000000000000000000000000000..a6ee3d56930647486040c71b27b0479132531fb5 --- /dev/null +++ b/openedx/core/djangoapps/content/course_overviews/migrations/0022_courseoverviewtab_is_hidden.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-04-30 15:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('course_overviews', '0021_courseoverviewtab_link'), + ] + + operations = [ + migrations.AddField( + model_name='courseoverviewtab', + name='is_hidden', + field=models.BooleanField(default=False), + ), + ] diff --git a/openedx/core/djangoapps/content/course_overviews/models.py b/openedx/core/djangoapps/content/course_overviews/models.py index cb28d09ca1ed1f27bcab74e17638fc167c632c55..27198452d06af47db1feaeff609c277c35de28a8 100644 --- a/openedx/core/djangoapps/content/course_overviews/models.py +++ b/openedx/core/djangoapps/content/course_overviews/models.py @@ -40,6 +40,10 @@ from xmodule.tabs import CourseTab log = logging.getLogger(__name__) +class CourseOverviewCaseMismatchException(Exception): + pass + + @python_2_unicode_compatible class CourseOverview(TimeStampedModel): """ @@ -59,7 +63,7 @@ class CourseOverview(TimeStampedModel): app_label = 'course_overviews' # IMPORTANT: Bump this whenever you modify this model and/or add a migration. - VERSION = 9 + VERSION = 11 # this one goes to eleven # Cache entry versioning. version = IntegerField() @@ -167,6 +171,11 @@ class CourseOverview(TimeStampedModel): if course_overview.exists(): log.info(u'Updating course overview for %s.', six.text_type(course.id)) course_overview = course_overview.first() + # MySQL ignores casing, but CourseKey doesn't. To prevent multiple + # courses with different cased keys from overriding each other, we'll + # check for equality here in python. + if course_overview.id != course.id: + raise CourseOverviewCaseMismatchException(course_overview.id, course.id) else: log.info(u'Creating course overview for %s.', six.text_type(course.id)) course_overview = cls() @@ -248,8 +257,8 @@ class CourseOverview(TimeStampedModel): with store.bulk_operations(course_id): course = store.get_course(course_id) if isinstance(course, CourseDescriptor): - course_overview = cls._create_or_update(course) try: + course_overview = cls._create_or_update(course) with transaction.atomic(): course_overview.save() # Remove and recreate all the course tabs @@ -261,6 +270,8 @@ class CourseOverview(TimeStampedModel): name=tab.name, course_staff_only=tab.course_staff_only, url_slug=tab.get('url_slug'), + link=tab.get('link'), + is_hidden=tab.get('is_hidden', False), course_overview=course_overview) for tab in course.tabs ]) @@ -862,6 +873,8 @@ class CourseOverviewTab(models.Model): name = models.TextField(null=True) course_staff_only = models.BooleanField(default=False) url_slug = models.TextField(null=True) + link = models.TextField(null=True) + is_hidden = models.BooleanField(default=False) def __str__(self): return self.tab_id diff --git a/openedx/core/djangoapps/content/course_overviews/tests/test_course_overviews.py b/openedx/core/djangoapps/content/course_overviews/tests/test_course_overviews.py index f5f8b95a0eff1999318cb36682d04a499791cfe1..05bb64cb2243ab876af15f0fb6e46061c2f3f27e 100644 --- a/openedx/core/djangoapps/content/course_overviews/tests/test_course_overviews.py +++ b/openedx/core/djangoapps/content/course_overviews/tests/test_course_overviews.py @@ -65,7 +65,7 @@ class CourseOverviewTestCase(CatalogIntegrationMixin, ModuleStoreTestCase, Cache None: None, } - COURSE_OVERVIEW_TABS = {'courseware', 'info', 'textbooks', 'discussion', 'wiki', 'progress', 'dates'} + COURSE_OVERVIEW_TABS = {'courseware', 'info', 'textbooks', 'discussion', 'wiki', 'progress'} ENABLED_SIGNALS = ['course_deleted', 'course_published'] diff --git a/openedx/core/djangoapps/content/learning_sequences/README.rst b/openedx/core/djangoapps/content/learning_sequences/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..e11670c1d2fcfa6237b860d1458ee2886cb9e254 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/README.rst @@ -0,0 +1,89 @@ +================== +Learning Sequences +================== + +This package creates a ModuleStore-independent representation of learning +sequences (a.k.a. "subsections" in Studio), as well as how they are put together +into courses. It is intended to serve metadata about Learning Sequences to end +users through the LMS, though it is also available to Studio for pushing data +into the system. The first API this app implements is computing the Course +Outline. + +--------------- +Direction: Keep +--------------- + +This package is being actively developed, but in a very early state. We're not +going to start feeding data into it (by triggering off of publish) until it's a +little more complete, so that it's easier to make drastic changes to the data +model if necessary. During development, you can seed data into it by using the +``update_course_outline`` management command. + +----- +Usage +----- + +* You may make foreign keys to learning_sequence models from your own app. +* You may refer to data structures defined in + ``openedx.djangoapps.content.learning_sequences.api.data``. +* Otherwise, you should only ever import and use functions from the top level + ``openedx.djangoapps.content.learning_sequences.api`` package. Do not import + from anywhere else in the package, including sub-modules of ``api``. + +---------- +Motivation +---------- + +We already have ModuleStore and Block Tranformers, so why create yet another way +to access course structure data? Isn't that going to cause bugs because access +rules will have to be reimplmented–as we've already seen with mobile APIs? + +1. To enable more dynamic courseware, we're shifting responsibility for + course structure and navigation out of ModuleStore/XBlock. We are keeping OLX + compatibility, but eventually the LMS XBlock runtime would only be invoked at + the Unit level and below. +2. Block Transformers operate on the entire course at one time, and lack the + kind of granular database models we'd want for quick lookups of metadata for + a single sequence. +3. Block Transformers are extremely powerful, but also complex and slow. + Optimizing them to suit our use case would be a lot of work and result in + even more complexity. Sequence and outline related metadata is much smaller, + and we can make simplifying assumptions like treating the outline as a tree + and not a DAG (i.e. each Sequence being in only one Section). + +-------------- +How to Extend? +-------------- + +This app is experimenting with some new conventions, so please read the decision +docs (``docs/decisions``). Many of the modules also have a long top-level +docstring explaining what they should be used for–please read these. Many of the +conventions are there to promote predictable behavior and are dramatically less +effective if broken even in little ways. + +I want to add more data to the public API. +========================================== + +The public data types are in ``api/data.py``. Database persistence is in +``models.py`` like all Django apps, but our Django models are extremely thin and +dumb. All real business logic should happen in a module within the ``api`` +package. Currently, all the existing API logic is handled in ``api/outlines.py`` +and re-exported at the top level in ``api/__init__.py``. If your new +functionality is outlines related, please follow this convention. Otherwise, you +can create a new module in ``api/`` (e.g. ``api/sequences.py``) to hold your +logic, and re-export that via the top level ``api/__init__.py``. + +I want to add a new rule affecting how sequences show up in the outline. +======================================================================== + +You probably want to create or modify an OutlineProcessor (``api/processors``). +This is not yet a pluggable interface, though it was designed to make it easy to +turn into one. Please see the docstrings in ``api/processors/base.py`` for +details on how to write one. + +I want to pull data from ModuleStore or Block Structures. +========================================================= + +Making any synchronous calls to these systems will break the performance goals +of this app. If you need data from these systems, please find a way to push that +data into smaller mdoels at course publish time. diff --git a/openedx/core/djangoapps/content/learning_sequences/__init__.py b/openedx/core/djangoapps/content/learning_sequences/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/core/djangoapps/content/learning_sequences/api/__init__.py b/openedx/core/djangoapps/content/learning_sequences/api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..9436136139511cd751184b502be54fbddf66718b --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/api/__init__.py @@ -0,0 +1,6 @@ +from .outlines import ( + get_course_outline, + get_user_course_outline, + get_user_course_outline_details, + replace_course_outline, +) diff --git a/openedx/core/djangoapps/content/learning_sequences/api/data.py b/openedx/core/djangoapps/content/learning_sequences/api/data.py new file mode 100644 index 0000000000000000000000000000000000000000..0812c45e28f5a8ae22374bcda282fdc439f772b0 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/api/data.py @@ -0,0 +1,262 @@ +""" +Public data structures for this app. + +Guidelines: + +1. Make these data structures immutable (frozen=True) wherever possible, as it + simplifies debugging. +2. This module should not import any other part of the app. This is the module + that everything else imports, not the other way around. Dependencies should + be kept to an absolute minimum–the Python stdlib, attr, opaque keys, and some + Django primitives. +3. Keep the data classes dumb. Business logic should go into the api package + modules that operate on this data. Do not attach complex objects with methods + as attributes to data classes, as this makes them more difficult to mock out + and make guarantees about behavior. +4. These data classes can perform validation, but only if that validation is + entirely self-contained. They MUST NOT make database calls, network requests, + or use API functions from other apps. They should not trigger expensive + computation. + +Note: we're using old-style syntax for attrs because we need to support Python +3.5, but we can move to the PEP-526 style once we move to Python 3.6+. + +TODO: Validate all datetimes to be UTC. +""" +import logging +from datetime import datetime, timezone +from typing import Dict, List, Optional, Set + +import attr +from django.contrib.auth import get_user_model +from opaque_keys.edx.keys import CourseKey, UsageKey + + +User = get_user_model() +log = logging.getLogger(__name__) + + +class ObjectDoesNotExist(Exception): + """ + Imitating Django model conventions, we put a subclass of this in some of our + data classes to indicate when something is not found. + """ + pass + + +@attr.s(frozen=True) +class VisibilityData: + """ + XBlock attributes that help determine item visibility. + """ + # This is an obscure, OLX-only flag (there is no UI for it in Studio) that + # lets you define a Sequence that is reachable by direct URL but not shown + # in Course navigation. It was used for things like supplementary tutorials + # that were not considered a part of the normal course path. + hide_from_toc = attr.ib(type=bool) + + # Restrict visibility to course staff, regardless of start date. This is + # often used to hide content that either still being built out, or is a + # scratch space of content that will eventually be copied over to other + # sequences. + visible_to_staff_only = attr.ib(type=bool) + + +@attr.s(frozen=True) +class CourseLearningSequenceData: + """ + A Learning Sequence (a.k.a. subsection) from a Course. + + It's possible that at some point we'll want a LearningSequenceData + superclass to encapsulate the minimum set of data that is shared between + learning sequences in Courses vs. Pathways vs. Libraries. Such an object + would likely not have `visibility` as that holds course-specific concepts. + """ + usage_key = attr.ib(type=UsageKey) + title = attr.ib(type=str) + visibility = attr.ib(type=VisibilityData) + + +@attr.s(frozen=True) +class CourseSectionData: + """ + A Section in a Course (sometimes called a Chapter). + """ + usage_key = attr.ib(type=UsageKey) + title = attr.ib(type=str) + visibility = attr.ib(type=VisibilityData) + sequences = attr.ib(type=List[CourseLearningSequenceData]) + + +@attr.s(frozen=True) +class CourseOutlineData: + """ + Course Outline information without any user-specific data. + """ + MAX_SEQUENCE_COUNT = 1000 + + class DoesNotExist(ObjectDoesNotExist): + pass + + course_key = attr.ib(type=CourseKey) + + @course_key.validator + def not_deprecated(self, _attribute, value): + """ + Only non-deprecated course keys (e.g. course-v1:) are supported. + The older style of "Org/Course/Run" slash-separated keys will not work. + """ + if value.deprecated: + raise ValueError("course_key cannot be a slash-separated course key (.deprecated=True)") + + title = attr.ib(type=str) + + # The time the course was last published. This may be different from the + # time that the course outline data was generated, since course outline + # generation happens asynchronously and could be severely delayed by + # operational issues or bugs that prevent the processing of certain courses. + published_at = attr.ib(type=datetime) + + # String representation of the version information for a course. There is no + # guarantee as to what this value is (e.g. a serialization of a BSON + # ObjectID, a base64 encoding of a BLAKE2 hash, etc.). The only guarantee is + # that it will change to something different every time the underlying + # course is modified. + published_version = attr.ib(type=str) + + sections = attr.ib(type=List[CourseSectionData]) + + # To make sure that our data structure is consistent, this field is + # derived from what you pass into `sections`. Do not set this directly. + sequences = attr.ib(type=Dict[UsageKey, CourseLearningSequenceData], init=False) + + def __attrs_post_init__(self): + """Post-init hook that validates and inits the `sequences` field.""" + sequences = {} + for section in self.sections: + for seq in section.sequences: + if seq.usage_key in sequences: + raise ValueError( + "Sequence {} appears in more than one Section." + .format(seq.usage_key) + ) + else: + sequences[seq.usage_key] = seq + + # Have to use this to get around the fact that the class is frozen + # (which we almost always want, but not while we're initializing it). + object.__setattr__(self, "sequences", sequences) + + # Because this is in the post-init hook, we have to do validation of + # sequences manually here, instead of in a @sequences.validator + if len(sequences) > self.MAX_SEQUENCE_COUNT: + raise ValueError( + "sequences cannot have more than {} entries ({} attempted)" + .format(self.MAX_SEQUENCE_COUNT, len(sequences)) + ) + + def remove(self, usage_keys): + """ + Create a new CourseOutlineData by removing a set of UsageKeys. + + The UsageKeys can be for Sequences or Sections/Chapters. Removing a + Section will remove all Sequences in that Section. It is not an error to + pass in UsageKeys that do not exist in the outline. + """ + keys_to_remove = set(usage_keys) + + # If we remove a Section, we also remove all Sequences in that Section. + for section in self.sections: + if section.usage_key in keys_to_remove: + keys_to_remove |= {seq.usage_key for seq in section.sequences} + + return attr.evolve( + self, + sections=[ + attr.evolve( + section, + sequences=[ + seq + for seq in section.sequences + if seq.usage_key not in keys_to_remove + ] + ) + for section in self.sections + if section.usage_key not in keys_to_remove + ] + ) + + +@attr.s(frozen=True) +class ScheduleItemData: + """ + Scheduling specific data (start/end/due dates) for a single item. + """ + usage_key = attr.ib(type=UsageKey) + + # Start date that is specified for this item + start = attr.ib(type=Optional[datetime]) + + # Effective release date that it's available (may be affected by parents) + effective_start = attr.ib(type=Optional[datetime]) + due = attr.ib(type=Optional[datetime]) + + +@attr.s(frozen=True) +class ScheduleData: + """ + Overall course schedule data. + """ + course_start = attr.ib(type=Optional[datetime]) + course_end = attr.ib(type=Optional[datetime]) + sections = attr.ib(type=Dict[UsageKey, ScheduleItemData]) + sequences = attr.ib(type=Dict[UsageKey, ScheduleItemData]) + + +@attr.s(frozen=True) +class UserCourseOutlineData(CourseOutlineData): + """ + A course outline that has been customized for a specific user and time. + + This is a subclass of CourseOutlineData that has been trimmed to only show + those things that a user is allowed to know exists. That being said, this + class is a pretty dumb container that doesn't understand anything about how + to derive that trimmed-down state. It's the responsibility of functions in + the learning_sequences.api package to figure out how to derive the correct + values to instantiate this class. + """ + # The CourseOutlineData that this UserCourseOutlineData is ultimately + # derived from. If we have an instance of a UserCourseOutlineData and need + # to reach up into parts of a Course that the user is not normally allowed + # to know the existence of (e.g. Sequences marked `visible_to_staff_only`), + # we can use this attribute. + base_outline = attr.ib(type=CourseOutlineData) + + # Django User representing who we've customized this outline for. This may + # be the AnonymousUser. + user = attr.ib(type=User) + + # UTC TZ time representing the time for which this user course outline was + # created. It is possible to create UserCourseOutlineData for a time in the + # future (i.e. "What will this user be able to see next week?") + at_time = attr.ib(type=datetime) + + # What Sequences is this `user` allowed to access? Anything in the `outline` + # is something that the `user` is allowed to know exists, but they might not + # be able to actually interact with it. For example: + # * A user might see an exam that has closed, but not be able to access it + # any longer. + # * If anonymous course access is enabled in "public_outline" mode, + # unauthenticated users (AnonymousUser) will see the course outline but + # not be able to access anything inside. + accessible_sequences = attr.ib(type=Set[UsageKey]) + + +@attr.s(frozen=True) +class UserCourseOutlineDetailsData: + """ + Class that has a user's course outline plus useful details (like schedules). + Will eventually expand to include other systems like Completion. + """ + outline = attr.ib(type=UserCourseOutlineData) + schedule = attr.ib(type=ScheduleData) diff --git a/openedx/core/djangoapps/content/learning_sequences/api/outlines.py b/openedx/core/djangoapps/content/learning_sequences/api/outlines.py new file mode 100644 index 0000000000000000000000000000000000000000..ed64cec0948fa89494af365854ba88bfaec37bb5 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/api/outlines.py @@ -0,0 +1,322 @@ +""" +All Course Outline related business logic. Do not import from this module +directly. Use openedx.core.djangoapps.content.learning_sequences.api -- that +__init__.py imports from here, and is a more stable place to import from. +""" +import logging +from collections import defaultdict +from datetime import datetime +from typing import Optional + +import attr +from django.contrib.auth import get_user_model +from django.db import transaction +from edx_django_utils.cache import TieredCache, get_cache_key +from edx_django_utils.monitoring import function_trace +from opaque_keys.edx.keys import CourseKey, UsageKey + +from .data import ( + CourseOutlineData, CourseSectionData, CourseLearningSequenceData, + UserCourseOutlineData, UserCourseOutlineDetailsData, VisibilityData, +) +from ..models import ( + CourseSection, CourseSectionSequence, LearningContext, LearningSequence +) +from .permissions import can_see_all_content +from .processors.schedule import ScheduleOutlineProcessor +from .processors.visibility import VisibilityOutlineProcessor + +User = get_user_model() +log = logging.getLogger(__name__) + +# Public API... +__all__ = [ + 'get_course_outline', + 'get_user_course_outline', + 'get_user_course_outline_details', + 'replace_course_outline', +] + + +def get_course_outline(course_key: CourseKey) -> CourseOutlineData: + """ + Get the outline of a course run. + + There is no user-specific data or permissions applied in this function. + + See the definition of CourseOutlineData for details about the data returned. + """ + learning_context = _get_learning_context_for_outline(course_key) + + # Check to see if it's in the cache. + cache_key = "learning_sequences.api.get_course_outline.v1.{}.{}".format( + learning_context.context_key, learning_context.published_version + ) + outline_cache_result = TieredCache.get_cached_response(cache_key) + if outline_cache_result.is_found: + return outline_cache_result.value + + # Fetch model data, and remember that empty Sections should still be + # represented (so query CourseSection explicitly instead of relying only on + # select_related from CourseSectionSequence). + section_models = CourseSection.objects \ + .filter(learning_context=learning_context) \ + .order_by('ordering') + section_sequence_models = CourseSectionSequence.objects \ + .filter(learning_context=learning_context) \ + .order_by('ordering') \ + .select_related('sequence') + + # Build mapping of section.id keys to sequence lists. + sec_ids_to_sequence_list = defaultdict(list) + + for sec_seq_model in section_sequence_models: + sequence_model = sec_seq_model.sequence + sequence_data = CourseLearningSequenceData( + usage_key=sequence_model.usage_key, + title=sequence_model.title, + visibility=VisibilityData( + hide_from_toc=sec_seq_model.hide_from_toc, + visible_to_staff_only=sec_seq_model.visible_to_staff_only, + ) + ) + sec_ids_to_sequence_list[sec_seq_model.section_id].append(sequence_data) + + sections_data = [ + CourseSectionData( + usage_key=section_model.usage_key, + title=section_model.title, + sequences=sec_ids_to_sequence_list[section_model.id], + visibility=VisibilityData( + hide_from_toc=section_model.hide_from_toc, + visible_to_staff_only=section_model.visible_to_staff_only, + ) + ) + for section_model in section_models + ] + + outline_data = CourseOutlineData( + course_key=learning_context.context_key, + title=learning_context.title, + published_at=learning_context.published_at, + published_version=learning_context.published_version, + sections=sections_data, + ) + TieredCache.set_all_tiers(cache_key, outline_data, 300) + + return outline_data + + +def _get_learning_context_for_outline(course_key: CourseKey) -> LearningContext: + if course_key.deprecated: + raise ValueError( + "Learning Sequence API does not support Old Mongo courses: {}" + .format(course_key), + ) + try: + learning_context = LearningContext.objects.get(context_key=course_key) + except LearningContext.DoesNotExist: + # Could happen if it hasn't been published. + raise CourseOutlineData.DoesNotExist( + "No CourseOutlineData for {}".format(course_key) + ) + return learning_context + + +def get_user_course_outline(course_key: CourseKey, + user: User, + at_time: datetime) -> UserCourseOutlineData: + """ + Get an outline customized for a particular user at a particular time. + + `user` is a Django User object (including the AnonymousUser) + `at_time` should be a UTC datetime.datetime object. + + See the definition of UserCourseOutlineData for details about the data + returned. + """ + user_course_outline, _ = _get_user_course_outline_and_processors(course_key, user, at_time) + return user_course_outline + + +def get_user_course_outline_details(course_key: CourseKey, + user: User, + at_time: datetime) -> UserCourseOutlineDetailsData: + """ + Get an outline with supplementary data like scheduling information. + + See the definition of UserCourseOutlineDetailsData for details about the + data returned. + """ + user_course_outline, processors = _get_user_course_outline_and_processors( + course_key, user, at_time + ) + schedule_processor = processors['schedule'] + + return UserCourseOutlineDetailsData( + outline=user_course_outline, + schedule=schedule_processor.schedule_data(user_course_outline) + ) + + +def _get_user_course_outline_and_processors(course_key: CourseKey, + user: User, + at_time: datetime): + full_course_outline = get_course_outline(course_key) + user_can_see_all_content = can_see_all_content(user, course_key) + + # These are processors that alter which sequences are visible to students. + # For instance, certain sequences that are intentionally hidden or not yet + # released. These do not need to be run for staff users. This is where we + # would add in pluggability for OutlineProcessors down the road. + processor_classes = [ + ('schedule', ScheduleOutlineProcessor), + ('visibility', VisibilityOutlineProcessor), + # Future: + # ('content_gating', ContentGatingOutlineProcessor), + # ('milestones', MilestonesOutlineProcessor), + # ('user_partitions', UserPartitionsOutlineProcessor), + ] + + # Run each OutlineProcessor in order to figure out what items we have to + # remove from the CourseOutline. + processors = dict() + usage_keys_to_remove = set() + inaccessible_sequences = set() + for name, processor_cls in processor_classes: + # Future optimization: This should be parallelizable (don't rely on a + # particular ordering). + processor = processor_cls(course_key, user, at_time) + processors[name] = processor + processor.load_data() + if not user_can_see_all_content: + # function_trace lets us see how expensive each processor is being. + with function_trace('processor:{}'.format(name)): + processor_usage_keys_removed = processor.usage_keys_to_remove(full_course_outline) + processor_inaccessible_sequences = processor.inaccessible_sequences(full_course_outline) + usage_keys_to_remove |= processor_usage_keys_removed + inaccessible_sequences |= processor_inaccessible_sequences + + # Open question: Does it make sense to remove a Section if it has no Sequences in it? + trimmed_course_outline = full_course_outline.remove(usage_keys_to_remove) + accessible_sequences = set(trimmed_course_outline.sequences) - inaccessible_sequences + + user_course_outline = UserCourseOutlineData( + base_outline=full_course_outline, + user=user, + at_time=at_time, + accessible_sequences=accessible_sequences, + **{ + name: getattr(trimmed_course_outline, name) + for name in ['course_key', 'title', 'published_at', 'published_version', 'sections'] + } + ) + + return user_course_outline, processors + + +def replace_course_outline(course_outline: CourseOutlineData): + """ + Replace the model data stored for the Course Outline with the contents of + course_outline (a CourseOutlineData). + + This isn't particularly optimized at the moment. + """ + log.info( + "Replacing CourseOutline for %s (version %s, %d sequences)", + course_outline.course_key, course_outline.published_version, len(course_outline.sequences) + ) + + with transaction.atomic(): + # Update or create the basic LearningContext... + learning_context = _update_learning_context(course_outline) + + # Wipe out the CourseSectionSequences join+ordering table so we can + # delete CourseSection and LearningSequence objects more easily. + learning_context.section_sequences.all().delete() + + _update_sections(course_outline, learning_context) + _update_sequences(course_outline, learning_context) + _update_course_section_sequences(course_outline, learning_context) + + +def _update_learning_context(course_outline: CourseOutlineData): + learning_context, created = LearningContext.objects.update_or_create( + context_key=course_outline.course_key, + defaults={ + 'title': course_outline.title, + 'published_at': course_outline.published_at, + 'published_version': course_outline.published_version + } + ) + if created: + log.info("Created new LearningContext for %s", course_outline.course_key) + else: + log.info("Found LearningContext for %s, updating...", course_outline.course_key) + + return learning_context + + +def _update_sections(course_outline: CourseOutlineData, learning_context: LearningContext): + # Add/update relevant sections... + for ordering, section_data in enumerate(course_outline.sections): + CourseSection.objects.update_or_create( + learning_context=learning_context, + usage_key=section_data.usage_key, + defaults={ + 'title': section_data.title, + 'ordering': ordering, + 'hide_from_toc': section_data.visibility.hide_from_toc, + 'visible_to_staff_only': section_data.visibility.visible_to_staff_only, + } + ) + # Delete sections that we don't want any more + section_usage_keys_to_keep = [ + section_data.usage_key for section_data in course_outline.sections + ] + CourseSection.objects \ + .filter(learning_context=learning_context) \ + .exclude(usage_key__in=section_usage_keys_to_keep) \ + .delete() + + +def _update_sequences(course_outline: CourseOutlineData, learning_context: LearningContext): + for section_data in course_outline.sections: + for sequence_data in section_data.sequences: + LearningSequence.objects.update_or_create( + learning_context=learning_context, + usage_key=sequence_data.usage_key, + defaults={'title': sequence_data.title} + ) + LearningSequence.objects \ + .filter(learning_context=learning_context) \ + .exclude(usage_key__in=course_outline.sequences) \ + .delete() + + +def _update_course_section_sequences(course_outline: CourseOutlineData, learning_context: LearningContext): + section_models = { + section_model.usage_key: section_model + for section_model + in CourseSection.objects.filter(learning_context=learning_context).all() + } + sequence_models = { + sequence_model.usage_key: sequence_model + for sequence_model + in LearningSequence.objects.filter(learning_context=learning_context).all() + } + + ordering = 0 + for section_data in course_outline.sections: + for sequence_data in section_data.sequences: + CourseSectionSequence.objects.update_or_create( + learning_context=learning_context, + section=section_models[section_data.usage_key], + sequence=sequence_models[sequence_data.usage_key], + defaults={ + 'ordering': ordering, + 'hide_from_toc': sequence_data.visibility.hide_from_toc, + 'visible_to_staff_only': sequence_data.visibility.visible_to_staff_only, + }, + ) + ordering += 1 diff --git a/openedx/core/djangoapps/content/learning_sequences/api/permissions.py b/openedx/core/djangoapps/content/learning_sequences/api/permissions.py new file mode 100644 index 0000000000000000000000000000000000000000..a6874903a09335e7cb94b03c1797aa59adb1be25 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/api/permissions.py @@ -0,0 +1,8 @@ +""" +This is a dummy placeholder for now, as access to this endpoint is currently +limited to global staff. +""" + + +def can_see_all_content(requesting_user, _course_key): + return requesting_user.is_staff diff --git a/openedx/core/djangoapps/content/learning_sequences/api/processors/__init__.py b/openedx/core/djangoapps/content/learning_sequences/api/processors/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/core/djangoapps/content/learning_sequences/api/processors/base.py b/openedx/core/djangoapps/content/learning_sequences/api/processors/base.py new file mode 100644 index 0000000000000000000000000000000000000000..f19d188b7c7cd55d68742c651334ca7c4358c6c1 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/api/processors/base.py @@ -0,0 +1,80 @@ +""" +This module defines the base OutlineProcessor class that is the primary method +of adding new logic that manipulates the Course Outline for a given student. +""" +import logging +from datetime import datetime + +from django.contrib.auth import get_user_model +from opaque_keys.edx.keys import CourseKey, UsageKey + +from ..data import ScheduleData, ScheduleItemData + +User = get_user_model() +log = logging.getLogger(__name__) + + +class OutlineProcessor: + """ + Base class for manipulating the Course Outline. + + You can inherit from this class and extend any of its four main methods: + __init__, load_data, inaccessible_sequences, usage_keys_to_remove. + + An OutlineProcessor is invoked synchronously during a request for the + CourseOutline. The steps are: + * __init__ + * load_data + * inaccessible_sequences, usage_keys_to_remove (no ordering guarantee) + + Also note that you should not assume any ordering relative to any other + OutlineProcessor. Once async support works its way fully into Django, we'll + likely even want to run these in parallel. + + Some outline processors (like ScheduleOutlineProcessor) may choose to have + additional methods to return specific metadata to feed into + UserCourseOutlineDetailsData. + """ + def __init__(self, course_key: CourseKey, user: User, at_time: datetime): + """ + Basic initialization. + + Extend to set your own data attributes, but don't do any real work (e.g. + database access, expensive computation) here. + """ + self.course_key = course_key + self.user = user + self.at_time = at_time + + def load_data(self): + """ + Fetch whatever data you need about the course and user here. + + If everything you need is already in the CourseOutlineData, there is no + need to override this method. + + DO NOT USE MODULESTORE OR BLOCKSTRUCTURES HERE, as the up-front + performance penalties of those modules are the entire reason this app + exists. Running this method in your subclass should take no more than + tens of milliseconds, even on courses with hundreds of learning + sequences. + """ + pass + + def inaccessible_sequences(self, full_course_outline): + """ + Return a set/frozenset of Sequence UsageKeys that are not accessible. + + This will not be run for staff users (who can access everything), so + there is no need to check for staff access here. + """ + return frozenset() + + def usage_keys_to_remove(self, full_course_outline): + """ + Return a set/frozenset of UsageKeys to remove altogether. + + This will not be run for staff users (who can see everything), so + there is no need to check for staff access here. + """ + return frozenset() diff --git a/openedx/core/djangoapps/content/learning_sequences/api/processors/schedule.py b/openedx/core/djangoapps/content/learning_sequences/api/processors/schedule.py new file mode 100644 index 0000000000000000000000000000000000000000..6d86bc1f37cc189753405034336a1c9b496d19fc --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/api/processors/schedule.py @@ -0,0 +1,131 @@ +import logging +from collections import defaultdict, OrderedDict +from datetime import datetime + +from django.contrib.auth import get_user_model +from edx_when.api import get_dates_for_course +from opaque_keys.edx.keys import CourseKey, UsageKey + +from ..data import ScheduleData, ScheduleItemData, UserCourseOutlineData +from .base import OutlineProcessor + +User = get_user_model() +log = logging.getLogger(__name__) + + +class ScheduleOutlineProcessor(OutlineProcessor): + """ + Responsible for applying all start/due/end date outline processing. + + We never hide the existence of a piece of content because of start or due + dates. Content may be inaccessible because it has yet to be released or the + exam has closed, but students are never prevented from knowing the content + exists based on the start and due date information. + + This processor depends on edx-when to get customized due date information + for users and content. + + Things we don't handle yet: + * Beta test users + * Self-paced courses + * Things that are made inaccessible after they're due. + """ + + def __init__(self, course_key: CourseKey, user: User, at_time: datetime): + super().__init__(course_key, user, at_time) + self.dates = None + self.keys_to_schedule_fields = defaultdict(dict) + self._course_start = None + self._course_end = None + + def load_data(self): + """Pull dates information from edx-when.""" + # (usage_key, 'due'): datetime.datetime(2019, 12, 11, 15, 0, tzinfo=<UTC>) + # TODO: Merge https://github.com/edx/edx-when/pull/48 and add `outline_only=True` + self.dates = get_dates_for_course(self.course_key, self.user) + + for (usage_key, field_name), date in self.dates.items(): + self.keys_to_schedule_fields[usage_key][field_name] = date + + course_usage_key = self.course_key.make_usage_key('course', 'course') + self._course_start = self.keys_to_schedule_fields[course_usage_key].get('start') + self._course_end = self.keys_to_schedule_fields[course_usage_key].get('end') + + def inaccessible_sequences(self, full_course_outline): + """ + This might include Sequences that have not yet started, or Sequences + for exams that have closed. If a Section has not started, all of its + Sequences are inaccessible, regardless of the individual Sequence start + dates. + """ + # If the course hasn't started at all, then everything is inaccessible. + if self._course_start is None or self.at_time < self._course_start: + return set(full_course_outline.sequences) + + inaccessible = set() + for section in full_course_outline.sections: + section_start = self.keys_to_schedule_fields[section.usage_key].get('start') + if section_start and self.at_time < section_start: + # If the section hasn't started yet, all the sequences it + # contains are inaccessible, regardless of the start value for + # those sequences. + inaccessible |= {seq.usage_key for seq in section.sequences} + else: + for seq in section.sequences: + seq_start = self.keys_to_schedule_fields[seq.usage_key].get('start') + if seq_start and self.at_time < seq_start: + inaccessible.add(seq.usage_key) + + return inaccessible + + def schedule_data(self, pruned_course_outline: UserCourseOutlineData) -> ScheduleData: + """ + Return supplementary scheduling information for this outline. + + Be careful to pass in a UserCourseOutlineData–i.e. an outline that has + already been pruned to what a user is allowed to see. That way, we can + use this to make sure that we're not returning data about + LearningSequences that the user can't see because it was hidden by a + different OutlineProcessor. + """ + def _effective_start(*dates): + specified_dates = [date for date in dates if date is not None] + return max(specified_dates) if specified_dates else None + + pruned_section_keys = {section.usage_key for section in pruned_course_outline.sections} + course_usage_key = self.course_key.make_usage_key('course', 'course') + course_start = self.keys_to_schedule_fields[course_usage_key].get('start') + course_end = self.keys_to_schedule_fields[course_usage_key].get('end') + + sequences = {} + sections = {} + for section in pruned_course_outline.sections: + section_dict = self.keys_to_schedule_fields[section.usage_key] + section_start = section_dict.get('start') + section_effective_start = _effective_start(course_start, section_start) + section_due = section_dict.get('due') + + sections[section.usage_key] = ScheduleItemData( + usage_key=section.usage_key, + start=section_start, + effective_start=section_effective_start, + due=section_due, + ) + + for seq in section.sequences: + seq_dict = self.keys_to_schedule_fields[seq.usage_key] + seq_start = seq_dict.get('start') + seq_due = seq_dict.get('due') + sequences[seq.usage_key] = ScheduleItemData( + usage_key=seq.usage_key, + start=seq_start, + effective_start=_effective_start(section_effective_start, seq_start), + due=seq_due, + ) + + return ScheduleData( + course_start=course_start, + course_end=course_end, + sections=sections, + sequences=sequences, + ) diff --git a/openedx/core/djangoapps/content/learning_sequences/api/processors/visibility.py b/openedx/core/djangoapps/content/learning_sequences/api/processors/visibility.py new file mode 100644 index 0000000000000000000000000000000000000000..605e4c6ee301c4baca21fecaffb1d71d811e676a --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/api/processors/visibility.py @@ -0,0 +1,38 @@ +from .base import OutlineProcessor + + +class VisibilityOutlineProcessor(OutlineProcessor): + """ + Simple OutlineProcessor that removes items based on VisibilityData. + + We only remove items with this Processor, we never make them visible-but- + inaccessible. There is no need to implement `load_data` because everything + we need comes from the CourseOutlineData itself. + """ + def usage_keys_to_remove(self, full_course_outline): + """ + Remove anything flagged with `hide_from_toc` or `visible_to_staff_only`. + + It's possible to argue that we should include `hide_from_toc` items in + the outline, but flag them in a special way. Students aren't precisely + forbidden from knowing that these items exist, they just aren't supposed + to see them in the course navigation. That being said, a) this is an + obscure and long-deprecated feature; b) this implementation will + preserve the behavior that students won't see it (though staff will); + and c) it simplifies REST API clients to never have to deal with the + concept at all. + """ + def should_remove(visibility): + return visibility.hide_from_toc or visibility.visible_to_staff_only + + sections_to_remove = { + sec.usage_key + for sec in full_course_outline.sections + if should_remove(sec.visibility) + } + seqs_to_remove = { + seq.usage_key + for seq in full_course_outline.sequences.values() + if should_remove(seq.visibility) + } + return frozenset(sections_to_remove | seqs_to_remove) diff --git a/openedx/core/djangoapps/content/learning_sequences/api/tests/__init__.py b/openedx/core/djangoapps/content/learning_sequences/api/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/core/djangoapps/content/learning_sequences/api/tests/test_data.py b/openedx/core/djangoapps/content/learning_sequences/api/tests/test_data.py new file mode 100644 index 0000000000000000000000000000000000000000..c1b86ad2c432c045ae851943e1859e164db7fe77 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/api/tests/test_data.py @@ -0,0 +1,133 @@ +from datetime import datetime, timezone +from unittest import TestCase + +from opaque_keys.edx.keys import CourseKey +import attr + +from ..data import ( + CourseOutlineData, CourseSectionData, CourseLearningSequenceData, VisibilityData +) + + +class TestCourseOutlineData(TestCase): + """ + Simple set of tests for data class validations. + """ + @classmethod + def setUpClass(cls): + """ + All our data classes are immutable, so we can set up a baseline course + outline and then make slightly modified versions for each particular + test as needed. + """ + super().setUpClass() + normal_visibility = VisibilityData(hide_from_toc=False, visible_to_staff_only=False) + cls.course_key = CourseKey.from_string("course-v1:OpenEdX+Learning+TestRun") + cls.course_outline = CourseOutlineData( + course_key=cls.course_key, + title="Exciting Test Course!", + published_at=datetime(2020, 5, 19, tzinfo=timezone.utc), + published_version="5ebece4b69dd593d82fe2014", + sections=generate_sections(cls.course_key, [3, 2]) + ) + + def test_deprecated_course_key(self): + """Old-Mongo style, "Org/Course/Run" keys are not supported.""" + old_course_key = CourseKey.from_string("OpenEdX/TestCourse/TestRun") + with self.assertRaises(ValueError): + attr.evolve(self.course_outline, course_key=old_course_key) + + def test_sequence_building(self): + """Make sure sequences were set correctly from sections data.""" + for section in self.course_outline.sections: + for seq in section.sequences: + self.assertEqual(seq, self.course_outline.sequences[seq.usage_key]) + self.assertEqual( + sum(len(section.sequences) for section in self.course_outline.sections), + len(self.course_outline.sequences), + ) + + def test_duplicate_sequence(self): + """We don't support DAGs. Sequences can only be in one Section.""" + # This section has Chapter 2's sequences in it + section_with_dupe_seq = attr.evolve( + self.course_outline.sections[1], title="Chapter 2 dupe", + ) + with self.assertRaises(ValueError): + attr.evolve( + self.course_outline, + sections=self.course_outline.sections + [section_with_dupe_seq] + ) + + def test_size(self): + """Limit how large a CourseOutline is allowed to be.""" + with self.assertRaises(ValueError): + attr.evolve( + self.course_outline, + sections=generate_sections(self.course_key, [1001]) + ) + + def test_remove_sequence(self): + """Remove a single sequence from the CourseOutlineData (creates a copy).""" + seq_to_remove = self.course_outline.sections[0].sequences[0] + new_outline = self.course_outline.remove({seq_to_remove.usage_key}) + assert self.course_outline != new_outline + assert seq_to_remove.usage_key in self.course_outline.sequences + assert seq_to_remove.usage_key not in new_outline.sequences + assert len(new_outline.sections[0].sequences) == len(self.course_outline.sections[0].sequences) - 1 + for seq in new_outline.sections[0].sequences: + assert seq != seq_to_remove + + def test_remove_section(self): + """ + Remove a whole Section from the CourseOutlineData (creates a copy). + + Removing a Section also removes all Sequences in that Section. + """ + section_to_remove = self.course_outline.sections[0] + new_outline = self.course_outline.remove({section_to_remove.usage_key}) + assert self.course_outline != new_outline + assert len(new_outline.sections) == len(self.course_outline.sections) - 1 + assert section_to_remove != new_outline.sections[0] + for seq in section_to_remove.sequences: + assert seq.usage_key not in new_outline.sequences + + def test_remove_nonexistant(self): + """Removing something that's not already there is a no-op.""" + seq_key_to_remove = self.course_key.make_usage_key('sequential', 'not_here') + new_outline = self.course_outline.remove({seq_key_to_remove}) + assert new_outline == self.course_outline + + +def generate_sections(course_key, num_sequences): + """ + Generate a list of CourseSectionData. + + `num_sequences` is a list that contains the length of each CourseSectionData + in order. So if you pass in [1, 3, 5], we would pass back a list of three + CourseSectionData, where the first one has 1 CourseLearningSequenceData as + it sequences, the second had 3 sequences, and the third had 5 sequences. + + All sections and sequences have normal visibility. + """ + normal_visibility = VisibilityData(hide_from_toc=False, visible_to_staff_only=False) + sections = [] + for sec_num, seq_count in enumerate(num_sequences, 1): + sections.append( + CourseSectionData( + usage_key=course_key.make_usage_key('chapter', 'ch_{}'.format(sec_num)), + title="Chapter {}: 🔥".format(sec_num), + visibility=normal_visibility, + sequences=[ + CourseLearningSequenceData( + usage_key=course_key.make_usage_key( + 'sequential', 'seq_{}_{}'.format(sec_num, seq_num) + ), + title="Seq {}.{}: 🔥".format(sec_num, seq_num), + visibility=normal_visibility, + ) + for seq_num in range(seq_count) + ] + ) + ) + return sections diff --git a/openedx/core/djangoapps/content/learning_sequences/api/tests/test_outlines.py b/openedx/core/djangoapps/content/learning_sequences/api/tests/test_outlines.py new file mode 100644 index 0000000000000000000000000000000000000000..3270f4edfb591ab326a782226f45a96a412026d5 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/api/tests/test_outlines.py @@ -0,0 +1,381 @@ +""" +Top level API tests. Tests API public contracts only. Do not import/create/mock +models for this app. +""" +from datetime import datetime, timezone + +from django.contrib.auth.models import User, AnonymousUser +from edx_when.api import set_dates_for_course +from opaque_keys.edx.keys import CourseKey, UsageKey +from opaque_keys.edx.locator import BlockUsageLocator +import attr + +from openedx.core.djangolib.testing.utils import CacheIsolationTestCase +from ..data import ( + CourseOutlineData, CourseSectionData, CourseLearningSequenceData, + VisibilityData +) +from ..outlines import ( + get_course_outline, get_user_course_outline, + get_user_course_outline_details, replace_course_outline +) +from .test_data import generate_sections + + +class CourseOutlineTestCase(CacheIsolationTestCase): + """ + Simple tests around reading and writing CourseOutlineData. No user info. + """ + @classmethod + def setUpTestData(cls): + cls.course_key = CourseKey.from_string("course-v1:OpenEdX+Learn+Roundtrip") + normal_visibility = VisibilityData( + hide_from_toc=False, visible_to_staff_only=False + ) + cls.course_outline = CourseOutlineData( + course_key=cls.course_key, + title="Roundtrip Test Course!", + published_at=datetime(2020, 5, 20, tzinfo=timezone.utc), + published_version="5ebece4b69dd593d82fe2015", + sections=generate_sections(cls.course_key, [2, 2]), + ) + + def test_deprecated_course_key(self): + """Don't allow Old Mongo Courses at all.""" + old_course_key = CourseKey.from_string("Org/Course/Run") + with self.assertRaises(ValueError): + outline = get_course_outline(old_course_key) + + def test_simple_roundtrip(self): + """Happy path for writing/reading-back a course outline.""" + with self.assertRaises(CourseOutlineData.DoesNotExist): + course_outline = get_course_outline(self.course_key) + + replace_course_outline(self.course_outline) + outline = get_course_outline(self.course_key) + assert outline == self.course_outline + + def test_empty_course(self): + """Empty Courses are a common case (when authoring just starts).""" + empty_outline = attr.evolve(self.course_outline, sections=[]) + self.assertFalse(empty_outline.sections) + self.assertFalse(empty_outline.sequences) + replace_course_outline(empty_outline) + assert empty_outline == get_course_outline(self.course_key) + + def test_empty_sections(self): + """Empty Sections aren't very useful, but they shouldn't break.""" + empty_section_outline = attr.evolve( + self.course_outline, sections=generate_sections(self.course_key, [0]) + ) + replace_course_outline(empty_section_outline) + assert empty_section_outline == get_course_outline(self.course_key) + + def test_cached_response(self): + # First lets seed the data... + replace_course_outline(self.course_outline) + + # Uncached access always makes three database checks: LearningContext, + # CourseSection, and CourseSectionSequence. + with self.assertNumQueries(3): + uncached_outline = get_course_outline(self.course_key) + assert uncached_outline == self.course_outline + + # Successful cache access only makes a query to LearningContext to check + # the current published version. That way we know that values are never + # stale. + with self.assertNumQueries(1): + cached_outline = get_course_outline(self.course_key) + + # Cache hits in the same process are literally the same object. + assert cached_outline is uncached_outline + + # Now we put a new version into the cache... + new_version_outline = attr.evolve( + self.course_outline, published_version="2222222222222222" + ) + replace_course_outline(new_version_outline) + + # Make sure this new outline is returned instead of the previously + # cached one. + with self.assertNumQueries(3): + uncached_new_version_outline = get_course_outline(self.course_key) + assert new_version_outline == new_version_outline + + +class UserCourseOutlineTestCase(CacheIsolationTestCase): + """ + Tests for basic UserCourseOutline functionality. + """ + + @classmethod + def setUpTestData(cls): + # Users... + cls.global_staff = User.objects.create_user( + 'global_staff', email='gstaff@example.com', is_staff=True + ) + cls.student = User.objects.create_user( + 'student', email='student@example.com', is_staff=False + ) + # TODO: Add AnonymousUser here. + + # Seed with data + cls.course_key = CourseKey.from_string("course-v1:OpenEdX+Outline+T1") + normal_visibility = VisibilityData( + hide_from_toc=False, visible_to_staff_only=False + ) + cls.simple_outline = CourseOutlineData( + course_key=cls.course_key, + title="User Outline Test Course!", + published_at=datetime(2020, 5, 20, tzinfo=timezone.utc), + published_version="5ebece4b69dd593d82fe2020", + sections=generate_sections(cls.course_key, [2, 1, 3]) + ) + replace_course_outline(cls.simple_outline) + + def test_simple_outline(self): + """This outline is the same for everyone.""" + at_time = datetime(2020, 5, 21, tzinfo=timezone.utc) + student_outline = get_user_course_outline( + self.course_key, self.student, at_time + ) + global_staff_outline = get_user_course_outline( + self.course_key, self.global_staff, at_time + ) + assert student_outline.sections == global_staff_outline.sections + assert student_outline.at_time == at_time + + student_outline_details = get_user_course_outline_details( + self.course_key, self.student, at_time + ) + assert student_outline_details.outline == student_outline + + global_staff_outline_details = get_user_course_outline_details( + self.course_key, self.global_staff, at_time + ) + assert global_staff_outline_details.outline == global_staff_outline + + +class ScheduleTestCase(CacheIsolationTestCase): + """ + Schedule-specific Outline tests. + + These aren't super-comprehensive with edge cases yet, partly because it's + still lacking a few important features (e.g. early beta releases, close- + after-due policy, etc.), and I'm not sure how we want to structure the + testing after all that's rolled up. + """ + + @classmethod + def setUpTestData(cls): + # Users... + cls.global_staff = User.objects.create_user( + 'global_staff', email='gstaff@example.com', is_staff=True + ) + cls.student = User.objects.create_user( + 'student', email='student@example.com', is_staff=False + ) + # TODO: Add AnonymousUser here. + + cls.course_key = CourseKey.from_string("course-v1:OpenEdX+Outline+T1") + + # The UsageKeys we're going to set up for date tests. + cls.section_key = cls.course_key.make_usage_key('chapter', 'ch1') + cls.seq_before_key = cls.course_key.make_usage_key('sequential', 'seq_before') + cls.seq_same_key = cls.course_key.make_usage_key('sequential', 'seq_same') + cls.seq_after_key = cls.course_key.make_usage_key('sequential', 'seq_after') + cls.seq_inherit_key = cls.course_key.make_usage_key('sequential', 'seq_inherit') + + # Set scheduling information into edx-when for a single Section with + # sequences starting at various times. + set_dates_for_course( + cls.course_key, + [ + ( + cls.course_key.make_usage_key('course', 'course'), + {'start': datetime(2020, 5, 10, tzinfo=timezone.utc)} + ), + ( + cls.section_key, + {'start': datetime(2020, 5, 15, tzinfo=timezone.utc)} + ), + # Sequence that starts before containing Section. + ( + cls.seq_before_key, + {'start': datetime(2020, 5, 14, tzinfo=timezone.utc)} + ), + # Sequence starts at same time as containing Section. + ( + cls.seq_same_key, + {'start': datetime(2020, 5, 15, tzinfo=timezone.utc)} + ), + # Sequence starts after containing Section. + ( + cls.seq_after_key, + {'start': datetime(2020, 5, 16, tzinfo=timezone.utc)} + ), + # Sequence should inherit start information from Section. + ( + cls.seq_inherit_key, + {'start': None} + ), + ] + ) + visibility = VisibilityData(hide_from_toc=False, visible_to_staff_only=False) + cls.outline = CourseOutlineData( + course_key=cls.course_key, + title="User Outline Test Course!", + published_at=datetime(2020, 5, 20, tzinfo=timezone.utc), + published_version="5ebece4b69dd593d82fe2020", + sections=[ + CourseSectionData( + usage_key=cls.section_key, + title="Section", + visibility=visibility, + sequences=[ + CourseLearningSequenceData( + usage_key=cls.seq_before_key, title='Before', visibility=visibility + ), + CourseLearningSequenceData( + usage_key=cls.seq_same_key, title='Same', visibility=visibility + ), + CourseLearningSequenceData( + usage_key=cls.seq_after_key, title='After', visibility=visibility + ), + CourseLearningSequenceData( + usage_key=cls.seq_inherit_key, title='Inherit', visibility=visibility + ), + ] + ) + ] + ) + replace_course_outline(cls.outline) + + def get_details(self, at_time): + staff_details = get_user_course_outline_details(self.course_key, self.global_staff, at_time) + student_details = get_user_course_outline_details(self.course_key, self.student, at_time) + return staff_details, student_details + + def test_before_course_starts(self): + staff_details, student_details = self.get_details( + datetime(2020, 5, 9, tzinfo=timezone.utc) + ) + # Staff can always access all sequences + assert len(staff_details.outline.accessible_sequences) == 4 + # Student can access nothing + assert len(student_details.outline.accessible_sequences) == 0 + + # Everyone can see everything + assert len(staff_details.outline.sequences) == 4 + assert len(student_details.outline.sequences) == 4 + + def test_before_section_starts(self): + staff_details, student_details = self.get_details( + datetime(2020, 5, 14, tzinfo=timezone.utc) + ) + # Staff can always access all sequences + assert len(staff_details.outline.accessible_sequences) == 4 + + # Student can access nothing -- even though one of the sequences is set + # to start on 2020-05-14, it's not available because the section hasn't + # started yet. + assert len(student_details.outline.accessible_sequences) == 0 + before_seq_sched_item_data = student_details.schedule.sequences[self.seq_before_key] + assert before_seq_sched_item_data.start == datetime(2020, 5, 14, tzinfo=timezone.utc) + assert before_seq_sched_item_data.effective_start == datetime(2020, 5, 15, tzinfo=timezone.utc) + + def test_at_section_start(self): + staff_details, student_details = self.get_details( + datetime(2020, 5, 15, tzinfo=timezone.utc) + ) + # Staff can always access all sequences + assert len(staff_details.outline.accessible_sequences) == 4 + + # Student can access all sequences except the one that starts after this + # datetime (self.seq_after_key) + assert len(student_details.outline.accessible_sequences) == 3 + assert self.seq_before_key in student_details.outline.accessible_sequences + assert self.seq_same_key in student_details.outline.accessible_sequences + assert self.seq_inherit_key in student_details.outline.accessible_sequences + + +class VisbilityTestCase(CacheIsolationTestCase): + """ + Visibility-related tests. + """ + + @classmethod + def setUpTestData(cls): + # Users... + cls.global_staff = User.objects.create_user( + 'global_staff', email='gstaff@example.com', is_staff=True + ) + cls.student = User.objects.create_user( + 'student', email='student@example.com', is_staff=False + ) + # TODO: Add AnonymousUser here. + cls.course_key = CourseKey.from_string("course-v1:OpenEdX+Outline+T1") + + # The UsageKeys we're going to set up for date tests. + cls.normal_section_key = cls.course_key.make_usage_key('chapter', 'normal_section') + cls.staff_section_key = cls.course_key.make_usage_key('chapter', 'staff_only_section') + + cls.staff_in_normal_key = cls.course_key.make_usage_key('sequential', 'staff_in_normal') + cls.hide_in_normal_key = cls.course_key.make_usage_key('sequential', 'hide_in_normal') + cls.normal_in_normal_key = cls.course_key.make_usage_key('sequential', 'normal_in_normal') + cls.normal_in_staff_key = cls.course_key.make_usage_key('sequential', 'normal_in_staff') + + v_normal = VisibilityData(hide_from_toc=False, visible_to_staff_only=False) + v_hide_from_toc = VisibilityData(hide_from_toc=True, visible_to_staff_only=False) + v_staff_only = VisibilityData(hide_from_toc=False, visible_to_staff_only=True) + + cls.outline = CourseOutlineData( + course_key=cls.course_key, + title="User Outline Test Course!", + published_at=datetime(2020, 5, 20, tzinfo=timezone.utc), + published_version="5ebece4b69dd593d82fe2020", + sections=[ + CourseSectionData( + usage_key=cls.normal_section_key, + title="Normal Section", + visibility=v_normal, + sequences=[ + CourseLearningSequenceData( + usage_key=cls.staff_in_normal_key, title='Before', visibility=v_staff_only + ), + CourseLearningSequenceData( + usage_key=cls.hide_in_normal_key, title='Same', visibility=v_hide_from_toc + ), + CourseLearningSequenceData( + usage_key=cls.normal_in_normal_key, title='After', visibility=v_normal + ), + ] + ), + CourseSectionData( + usage_key=cls.staff_section_key, + title="Staff Only Section", + visibility=v_staff_only, + sequences=[ + CourseLearningSequenceData( + usage_key=cls.normal_in_staff_key, title='Before', visibility=v_normal + ), + ] + ) + + ] + ) + replace_course_outline(cls.outline) + + def test_visibility(self): + at_time = datetime(2020, 5, 21, tzinfo=timezone.utc) # Exact value doesn't matter + staff_details = get_user_course_outline_details(self.course_key, self.global_staff, at_time) + student_details = get_user_course_outline_details(self.course_key, self.student, at_time) + + # Sections visible + assert len(staff_details.outline.sections) == 2 + assert len(student_details.outline.sections) == 1 + + # Sequences visible + assert len(staff_details.outline.sequences) == 4 + assert len(student_details.outline.sequences) == 1 + assert self.normal_in_normal_key in student_details.outline.sequences diff --git a/openedx/core/djangoapps/content/learning_sequences/apps.py b/openedx/core/djangoapps/content/learning_sequences/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..0cddb3094943161a4b37a4c12434217a09f9ee40 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/apps.py @@ -0,0 +1,12 @@ +from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ + + +class LearningSequencesConfig(AppConfig): + name = 'openedx.core.djangoapps.content.learning_sequences' + verbose_name = _('Learning Sequences') + + def ready(self): + # Register celery workers + # from .tasks import ls_listen_for_course_publish # pylint: disable=unused-variable + pass diff --git a/openedx/core/djangoapps/content/learning_sequences/docs/decisions/0001-extensions-to-inter-app-apis.rst b/openedx/core/djangoapps/content/learning_sequences/docs/decisions/0001-extensions-to-inter-app-apis.rst new file mode 100644 index 0000000000000000000000000000000000000000..71ac16e32e813c4cf7b43bebd291fc55ea851dc4 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/docs/decisions/0001-extensions-to-inter-app-apis.rst @@ -0,0 +1,80 @@ +Extensions to Inter-app API Conventions +======================================= + +Status +------ + +Draft + + +Context +------- + +In order to improve the maintainability and stability of our applications, we +introduced ``edx-platform/docs/decisions/0002-inter-app-apis.rst``, which +outlines the use of package level ``api.py`` files to provide single-points of +entry to the app's functionality. + +This ADR seeks to add further conventions to help address issues that have come +up in our usage over the years. Namely: + +* It is difficult to determine exactly what is being returned by inter-app APIs. +* It is difficult to know exactly what valid inputs to inter-app APIs are. +* It is difficult to tell when we break compatibility in an inter-app API. +* Critical functionality (exercised via views) is sometimes missing from the + inter-app API, or behaves differently from its REST counterpart. + +If we find that this ADR's additional conventions are helpful, we can add them +to the existing set of Inter-app APIs defined at the top level of edx-platform. + + +Decision +-------- + +#. All API data structures will be declared as immutable attrs classes in a +separate ``data.py`` file. All data class attributes will have type annotations. + +#. Data structures in ``data.py`` will include basic validation of their inputs, +though this will *not* include validation that requires database access. + +#. All public inter-app API functions will use type annotations for arguments +and return values. + +#. All public inter-app API functions will be exported in the top level ``api`` +package. Other applications will only ever import from this top level package. + +#. Views, tasks, and any other parts of the learning_sequences app that are not +in the api package will obey the same rules that external apps would follow. +This means that views for learning_sequences will only import from api and will +not directly import from models. + +#. Serializers for REST APIs will be defined as inner classes on the views. +Serializer re-use across use cases will be explicitly discouraged to prevent +modifications from rippling across and breaking compatibility elsewhere. + +#. Wherever possible, API-level tests will be written without mocking internals, +or prepping the database with model manipulations. The goal of this is to make +it so that that API-level tests *only* break when there are in fact API changes. +We can mock calls to other services, like grades. + + +Consequences +------------ + +#. It will be easier for other applications to access learning_sequence +functionality in a more easily understood and maintainable way. + +#. It will be easier to build and maintain plugin code that depends on this +application. + +#. Changes that break backwards compatibility will be more obvious. + + +References +---------- + +A lot of these extensions were either copied from or inspired by +`Django structure for scale and longevity <https://www.youtube.com/watch?v=yG3ZdxBb1oo>`_ +presented by Radoslav Georgiev at EuroPython 2018, though there are a number of +differences like our use of ``attrs``, and trying to keep better backwards +compatibility with our existing ``api.py`` conventions. diff --git a/openedx/core/djangoapps/content/learning_sequences/management/__init__.py b/openedx/core/djangoapps/content/learning_sequences/management/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/core/djangoapps/content/learning_sequences/management/commands/__init__.py b/openedx/core/djangoapps/content/learning_sequences/management/commands/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/core/djangoapps/content/learning_sequences/management/commands/update_course_outline.py b/openedx/core/djangoapps/content/learning_sequences/management/commands/update_course_outline.py new file mode 100644 index 0000000000000000000000000000000000000000..996d31fba248754c4bb2ebf8dba7c5e4648d4b3f --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/management/commands/update_course_outline.py @@ -0,0 +1,16 @@ +from django.core.management.base import BaseCommand, CommandError + +from opaque_keys.edx.keys import CourseKey + +from ...tasks import update_from_modulestore + + +class Command(BaseCommand): + help = "Updates a single course outline based on modulestore content." + + def add_arguments(self, parser): + parser.add_argument('course_key') + + def handle(self, *args, **options): + course_key = CourseKey.from_string(options['course_key']) + update_from_modulestore(course_key) diff --git a/openedx/core/djangoapps/content/learning_sequences/migrations/0001_initial.py b/openedx/core/djangoapps/content/learning_sequences/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..22aad21ffb27be5b9c3c37c346c29259e0236f6c --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/migrations/0001_initial.py @@ -0,0 +1,124 @@ +# Generated by Django 2.2.12 on 2020-05-21 00:22 +# +# Manually modified to collate some fields as utf8_bin for case sensitive +# matching. + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import model_utils.fields +import opaque_keys.edx.django.models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='CourseSection', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('ordering', models.PositiveIntegerField()), + ('usage_key', opaque_keys.edx.django.models.UsageKeyField(max_length=255)), + ('title', models.CharField(max_length=1000)), + ('hide_from_toc', models.BooleanField(default=False)), + ('visible_to_staff_only', models.BooleanField(default=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ], + ), + migrations.CreateModel( + name='CourseSectionSequence', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('ordering', models.PositiveIntegerField()), + ('hide_from_toc', models.BooleanField(default=False)), + ('visible_to_staff_only', models.BooleanField(default=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ], + ), + migrations.CreateModel( + name='LearningContext', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('context_key', opaque_keys.edx.django.models.LearningContextKeyField(db_index=True, max_length=255, unique=True)), + ('title', models.CharField(max_length=255)), + ('published_at', models.DateTimeField()), + ('published_version', models.CharField(max_length=255)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ], + ), + migrations.CreateModel( + name='LearningSequence', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('learning_context', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sequences', to='learning_sequences.LearningContext')), + ('usage_key', opaque_keys.edx.django.models.UsageKeyField(max_length=255)), + ('title', models.CharField(max_length=1000)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), + ], + ), + migrations.AddIndex( + model_name='learningcontext', + index=models.Index(fields=['-published_at'], name='learning_se_publish_62319b_idx'), + ), + migrations.AddField( + model_name='coursesectionsequence', + name='learning_context', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='section_sequences', to='learning_sequences.LearningContext'), + ), + migrations.AddField( + model_name='coursesectionsequence', + name='section', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='learning_sequences.CourseSection'), + ), + migrations.AddField( + model_name='coursesectionsequence', + name='sequence', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='learning_sequences.LearningSequence'), + ), + migrations.AddField( + model_name='coursesection', + name='learning_context', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sections', to='learning_sequences.LearningContext'), + ), + migrations.AlterUniqueTogether( + name='learningsequence', + unique_together={('learning_context', 'usage_key')}, + ), + migrations.AlterUniqueTogether( + name='coursesectionsequence', + unique_together={('learning_context', 'ordering')}, + ), + migrations.AlterUniqueTogether( + name='coursesection', + unique_together={('learning_context', 'usage_key')}, + ), + migrations.AlterIndexTogether( + name='coursesection', + index_together={('learning_context', 'ordering')}, + ), + + # Custom code: Convert columns to utf8_bin because we want to allow + # case-sensitive comparisons for things like UsageKeys, CourseKeys, and + # slugs. + migrations.RunSQL( + 'ALTER TABLE learning_sequences_learningcontext MODIFY context_key VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin;', + reverse_sql=migrations.RunSQL.noop, + ), + migrations.RunSQL( + 'ALTER TABLE learning_sequences_coursesection MODIFY usage_key VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin;', + reverse_sql=migrations.RunSQL.noop, + ), + migrations.RunSQL( + 'ALTER TABLE learning_sequences_learningsequence MODIFY usage_key VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin;', + reverse_sql=migrations.RunSQL.noop, + ), + ] diff --git a/openedx/core/djangoapps/content/learning_sequences/migrations/__init__.py b/openedx/core/djangoapps/content/learning_sequences/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/core/djangoapps/content/learning_sequences/models.py b/openedx/core/djangoapps/content/learning_sequences/models.py new file mode 100644 index 0000000000000000000000000000000000000000..5d2568f30715438b16b34e352407d1203265170c --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/models.py @@ -0,0 +1,178 @@ +""" +Models for Learning Sequences and Course Outline generation. + +Conventions: + +1. Only things in the `api` package should ever import this file. Do NOT import +from views.py or anywhere else. Even if that means we have to give up some DRF +niceties. + +2. The vast majority of what our public API promises should be efficiently +queryable with these models. We might occasionally reach into other systems +built for fast course-level queries (e.g. grading, scheduling), but we should +never touch ModuleStore or Block Transformers. + +3. It's okay for some basic validation to happen at the model layer. Constraints +like uniqueness should absolutely be enforced at this layer. But business logic +should happen in the `api` package. + +4. Try to avoid blob-like entites (e.g. JSON fields) as much as possible and +push things into normalized tables. + +5. In general, keep models as a thin, dumb persistence layer. Let the `api` +package decide when and where it's safe to cache things. + +6. Models and data.py datastructures don't have to map 1:1, but the convention +is that the data struct has a "...Data" appended to it. For instance, +LearningContext -> LearningContextData. This is because the Python name for +dataclasses (what attrs is close to), and for better backwards compatibility if +we want to adopt this convention elsewhere. + +7. Strongly separate things that are intrinsic to Learning Sequences as a whole +vs. things that only apply to Sequences in the context of a Course. We have +other uses for sequences (e.g. Content Libraries, Pathways) and we want to keep +that separated. + +8. Your app _may_ make foreign keys to models in this app, but you should limit +yourself to the LearningContext and LearningSequence models. Other tables are +not guaranteed to stick around, and values may be deleted unexpectedly. +""" +from django.db import models +from model_utils.models import TimeStampedModel + +from opaque_keys.edx.django.models import ( + CourseKeyField, LearningContextKeyField, UsageKeyField +) + + +class LearningContext(TimeStampedModel): + """ + These are used to group Learning Sequences so that many of them can be + pulled at once. We use this instead of a foreign key to CourseOverview + because this table can contain things that are not courses. + + It is okay to make a foreign key against this table. + """ + id = models.BigAutoField(primary_key=True) + context_key = LearningContextKeyField( + max_length=255, db_index=True, unique=True, null=False + ) + title = models.CharField(max_length=255) + published_at = models.DateTimeField(null=False) + published_version = models.CharField(max_length=255) + + class Meta: + indexes = [ + models.Index(fields=['-published_at']) + ] + + +class LearningSequence(TimeStampedModel): + """ + The reason why this model doesn't have a direct foreign key to CourseSection + is because we eventually want to have LearningSequences that exist outside + of courses. Attributes that apply directly to all LearningSequences + (usage_key, title, learning_context, etc.) will apply here, but anything + that is specific to how a LearningContext is rendered for a course (e.g. + permissions, staff visibility, is_entrance_exam) wil live in + CourseSectionSequence. + + It is okay to make a foreign key against this table. + """ + id = models.BigAutoField(primary_key=True) + learning_context = models.ForeignKey( + LearningContext, on_delete=models.CASCADE, related_name='sequences' + ) + usage_key = UsageKeyField(max_length=255) + + # Yes, it's crazy to have a title 1K chars long. But we have ones at least + # 270 long, meaning we wouldn't be able to make it indexed anyway in InnoDB. + title = models.CharField(max_length=1000) + + # Separate field for when this Sequence's content was last changed? + class Meta: + unique_together = [ + ['learning_context', 'usage_key'], + ] + + +class CourseContentVisibilityMixin(models.Model): + """ + This mixin stores XBlock information that affects outline level visibility + for a single LearningSequence or Section in a course. + + We keep the XBlock field names here, even if they're somewhat misleading. + Please read the comments carefully for each field. + """ + # This is an obscure, OLX-only flag (there is no UI for it in Studio) that + # lets you define a Sequence that is reachable by direct URL but not shown + # in Course navigation. It was used for things like supplementary tutorials + # that were not considered a part of the normal course path. + hide_from_toc = models.BooleanField(null=False, default=False) + + # Restrict visibility to course staff, regardless of start date. This is + # often used to hide content that either still being built out, or is a + # scratch space of content that will eventually be copied over to other + # sequences. + visible_to_staff_only = models.BooleanField(null=False, default=False) + + class Meta: + abstract = True + + +class CourseSection(CourseContentVisibilityMixin, TimeStampedModel): + """ + Course Section data, mapping to the 'chapter' block type. + + Do NOT make a foreign key against this table, as the values are deleted and + re-created on course publish. + """ + id = models.BigAutoField(primary_key=True) + learning_context = models.ForeignKey( + LearningContext, on_delete=models.CASCADE, related_name='sections' + ) + usage_key = UsageKeyField(max_length=255) + title = models.CharField(max_length=1000) + + # What is our position within the Course? (starts with 0) + ordering = models.PositiveIntegerField(null=False) + + class Meta: + unique_together = [ + ['learning_context', 'usage_key'], + ] + index_together = [ + ['learning_context', 'ordering'], + ] + + +class CourseSectionSequence(CourseContentVisibilityMixin, TimeStampedModel): + """ + This is a join+ordering table, with entries that could get wiped out and + recreated with every course publish. Do NOT make a ForeignKey against this + table before implementing smarter replacement logic when publishing happens, + or you'll see deletes all the time. + + CourseContentVisibilityMixin is applied here (and not in LearningSequence) + because CourseContentVisibilityMixin describes attributes that are part of + how a LearningSequence is used within a course, and may not apply to other + kinds of LearningSequences. + + Do NOT make a foreign key against this table, as the values are deleted and + re-created on course publish. + """ + id = models.BigAutoField(primary_key=True) + learning_context = models.ForeignKey( + LearningContext, on_delete=models.CASCADE, related_name='section_sequences' + ) + section = models.ForeignKey(CourseSection, on_delete=models.CASCADE) + sequence = models.ForeignKey(LearningSequence, on_delete=models.CASCADE) + + # Ordering, starts with 0, but global for the course. So if you had 200 + # sequences across 20 sections, the numbering here would be 0-199. + ordering = models.PositiveIntegerField(null=False) + + class Meta: + unique_together = [ + ['learning_context', 'ordering'], + ] diff --git a/openedx/core/djangoapps/content/learning_sequences/tasks.py b/openedx/core/djangoapps/content/learning_sequences/tasks.py new file mode 100644 index 0000000000000000000000000000000000000000..d9e0f00a9e122ba97f7a2bcbd1415185be93a853 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/tasks.py @@ -0,0 +1,67 @@ +""" +This module is here as a placeholder, but knowledge of the modulestore should +eventually be moved out of the learning_sequence app entirely. + +Also note that right now we're not hooked into the publish flow. This task code +is only invoked by the "update_course_outline" management command. +""" +from xmodule.modulestore import ModuleStoreEnum +from xmodule.modulestore.django import modulestore + +from .api import replace_course_outline +from .api.data import ( + CourseOutlineData, CourseSectionData, CourseLearningSequenceData, VisibilityData +) + + +def update_from_modulestore(course_key): + """ + Update the CourseOutlineData for course_key with ModuleStore data (i.e. what + was most recently published in Studio). + + We should move this out so that learning_sequences does not depend on + ModuleStore. + """ + def _make_section_data(section): + sequences_data = [] + for sequence in section.get_children(): + sequences_data.append( + CourseLearningSequenceData( + usage_key=sequence.location, + title=sequence.display_name, + visibility=VisibilityData( + hide_from_toc=sequence.hide_from_toc, + visible_to_staff_only=sequence.visible_to_staff_only + ), + ) + ) + + section_data = CourseSectionData( + usage_key=section.location, + title=section.display_name, + sequences=sequences_data, + visibility=VisibilityData( + hide_from_toc=section.hide_from_toc, + visible_to_staff_only=section.visible_to_staff_only + ), + ) + return section_data + + store = modulestore() + sections = [] + with store.branch_setting(ModuleStoreEnum.Branch.published_only, course_key): + course = store.get_course(course_key, depth=2) + sections_data = [] + for section in course.get_children(): + section_data = _make_section_data(section) + sections_data.append(section_data) + + course_outline_data = CourseOutlineData( + course_key=course_key, + title=course.display_name, + published_at=course.subtree_edited_on, + published_version=str(course.course_version), # .course_version is a BSON obj + sections=sections_data, + ) + + replace_course_outline(course_outline_data) diff --git a/openedx/core/djangoapps/content/learning_sequences/tests/__init__.py b/openedx/core/djangoapps/content/learning_sequences/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/core/djangoapps/content/learning_sequences/tests/test_views.py b/openedx/core/djangoapps/content/learning_sequences/tests/test_views.py new file mode 100644 index 0000000000000000000000000000000000000000..efb0e0b879f3acdcf7d6163a0d8ca89a27e7a011 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/tests/test_views.py @@ -0,0 +1,112 @@ +""" +Tests for the learning_sequences REST API. + +The goals of this module are to: +* Test the serialization of the REST API. +* Make sure that arguments to the REST API (like masquerading) work properly. +* Prevent accidental breaking of backwards compatibility as we add to the API. + +Testing the fine grained logic of, "What should be visible/accessible when you +have a Course + User with these properties?" is the responsibility of the +.api.tests package of this app. + +Where possible, seed data using public API methods (e.g. replace_course_outline +from this app, edx-when's set_dates_for_course). +""" +from datetime import datetime, timezone + +from django.contrib.auth.models import User +from opaque_keys.edx.keys import CourseKey, UsageKey +from rest_framework.test import APITestCase, APIClient + +from openedx.core.djangolib.testing.utils import CacheIsolationTestCase +from student.tests.factories import UserFactory + +from ..api import replace_course_outline +from ..api.data import CourseOutlineData +from ..api.tests.test_data import generate_sections + + +class CourseOutlineViewTest(CacheIsolationTestCase, APITestCase): + + @classmethod + def setUpTestData(cls): + cls.staff = UserFactory.create( + username='staff', email='staff@example.com', is_staff=True, password='staff_pass' + ) + cls.student = UserFactory.create( + username='student', email='student@example.com', is_staff=False, password='student_pass' + ) + cls.course_key = CourseKey.from_string("course-v1:OpenEdX+Seq+View") + cls.course_url = cls.url_for(cls.course_key) + cls.outline = CourseOutlineData( + course_key=cls.course_key, + title="Views Test Course!", + published_at=datetime(2020, 5, 20, tzinfo=timezone.utc), + published_version="5ebece4b69dd593d82fe2020", + sections=generate_sections(cls.course_key, [2, 2]) + ) + replace_course_outline(cls.outline) + + def setUp(self): + super().setUp() + self.client = APIClient() + + @classmethod + def url_for(cls, course_key): + return '/api/learning_sequences/v1/course_outline/{}'.format(course_key) + + def test_student_access_denied(self): + """ + For now, make sure you need staff access bits to use the API. + + This is a temporary safeguard until the API is more complete. + """ + self.client.login(username='student', password='student_pass') + result = self.client.get(self.course_url) + assert result.status_code == 403 + + def test_deprecated_course_key(self): + """ + For now, make sure you need staff access bits to use the API. + + This is a temporary safeguard until the API is more complete. + """ + self.client.login(username='staff', password='staff_pass') + old_course_key = CourseKey.from_string("OldOrg/OldCourse/OldRun") + result = self.client.get(self.url_for(old_course_key)) + assert result.status_code == 400 + + def test_outline_as_staff(self): + """ + This is a pretty rudimentary test of a course that's returned. + + We'll want to flesh this out in a lot more detail once the API is more + complete and the format more stable. + """ + self.client.login(username='staff', password='staff_pass') + result = self.client.get(self.course_url) + data = result.data + assert data['course_key'] == str(self.course_key) + assert data['user_id'] == self.staff.id + assert data['username'] == 'staff' + + # API test client automatically parses these into dates. Should we do + # the raw form for max compatibility (i.e. guard against serialization + # of dates changing), or do the parsing for conveninece? Convenience for + # now. + assert data['published_at'] == datetime(2020, 5, 20, tzinfo=timezone.utc) + assert data['published_version'] == "5ebece4b69dd593d82fe2020" + + # Basic outline structure checks + assert len(data['outline']['sections']) == 2 + assert len(data['outline']['sections'][0]['sequence_ids']) == 2 + assert len(data['outline']['sections'][1]['sequence_ids']) == 2 + assert len(data['outline']['sequences']) == 4 + + def test_query_for_other_user(self): + self.client.login(username='staff', password='staff_pass') + result = self.client.get(self.course_url + "?user=student") + data = result.data + assert data['username'] == 'student' + assert data['user_id'] == self.student.id diff --git a/openedx/core/djangoapps/content/learning_sequences/urls.py b/openedx/core/djangoapps/content/learning_sequences/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..7681ecbbbbbf96d4b9ec2c933ebc47df8b803569 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/urls.py @@ -0,0 +1,12 @@ +from django.conf.urls import url + +from .views import CourseOutlineView + + +urlpatterns = [ + url( + r'^v1/course_outline/(?P<course_key_str>.+)$', + CourseOutlineView.as_view(), + name='course_outline', + ) +] diff --git a/openedx/core/djangoapps/content/learning_sequences/views.py b/openedx/core/djangoapps/content/learning_sequences/views.py new file mode 100644 index 0000000000000000000000000000000000000000..41d87fab234108235b5dba0b6ba5ead4c9890340 --- /dev/null +++ b/openedx/core/djangoapps/content/learning_sequences/views.py @@ -0,0 +1,184 @@ +""" +The views.py for this app is intentionally thin, and only exists to translate +user input/output to and from the business logic in the `api` package. +""" +from datetime import datetime, timezone +import json +import logging + +from django.contrib.auth import get_user_model +from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication +from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser +from opaque_keys import InvalidKeyError +from opaque_keys.edx.keys import CourseKey +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import serializers +import attr + +from openedx.core.lib.api.permissions import IsStaff +from .api import get_user_course_outline_details +from .api.data import ScheduleData, UserCourseOutlineData + + +User = get_user_model() +log = logging.getLogger(__name__) + + +class CourseOutlineView(APIView): + """ + Display all CourseOutline information for a given user. + """ + # We want to eventually allow unauthenticated users to use this as well... + authentication_classes = (JwtAuthentication, SessionAuthenticationAllowInactiveUser) + + # For early testing, restrict this to only global staff... + permission_classes = (IsStaff,) + + class UserCourseOutlineDataSerializer(serializers.BaseSerializer): + """ + Read-only serializer for CourseOutlineData for this endpoint. + + This serializer was purposefully declared inline with the + CourseOutlineView to discourage reuse/magic. Our goal is to make it + extremely obvious how things are being serialized, and not have suprise + regressions because a shared serializer in another module was modified + to fix an issue in one of its three use cases. + + The data structures in api/data.py send back try to separate the data by + lifecycle (e.g. CourseOutlineData vs UserCourseOutlineData) and by + logical system (e.g. ScheduleData) to promote performance and + pluggability. But for the REST API, we're just trying to collapse those + into the simplest, most convenient output possible. + + We also remove any references to "usage_keys" at this layer. UsageKeys + are a critical part of the internals of edx-platform, so the in-process + API uses them, but we translate them to "ids" for REST API clients. + """ + def to_representation(self, user_course_outline_details): + """ + Convert to something DRF knows how to serialize (so no custom types) + + This is intentionally dumb and lists out every field to make API + additions/changes more obvious. + """ + user_course_outline = user_course_outline_details.outline + schedule = user_course_outline_details.schedule + return { + # Top level course information + "course_key": str(user_course_outline.course_key), + "course_start": schedule.course_start, + "course_end": schedule.course_end, + "title": user_course_outline.title, + "published_at": user_course_outline.published_at, + "published_version": user_course_outline.published_version, + + # Who and when this request was generated for (we can eventually + # support arbitrary times). + "username": user_course_outline.user.username, # "" if anonymous + "user_id": user_course_outline.user.id, # null if anonymous + "at_time": user_course_outline.at_time, + + # The actual course structure information... + "outline": { + "sections": [ + self._section_repr(section, schedule.sections.get(section.usage_key)) + for section in user_course_outline.sections + ], + "sequences": { + str(seq_usage_key): self._sequence_repr( + sequence, + schedule.sequences.get(seq_usage_key), + user_course_outline.accessible_sequences, + ) + for seq_usage_key, sequence in user_course_outline.sequences.items() + }, + }, + } + + def _sequence_repr(self, sequence, sequence_schedule, accessible_sequences): + """Representation of a Sequence.""" + if sequence_schedule is None: + schedule_item_dict = {'start': None, 'effective_start': None, 'due': None} + else: + schedule_item_dict = { + # Any of these values could be `None` + 'start': sequence_schedule.start, + 'effective_start': sequence_schedule.effective_start, + 'due': sequence_schedule.due, + } + + return { + "id": str(sequence.usage_key), + "title": sequence.title, + "accessible": sequence.usage_key in accessible_sequences, + **schedule_item_dict, + } + + def _section_repr(self, section, section_schedule): + """Representation of a Section.""" + if section_schedule is None: + schedule_item_dict = {'start': None, 'effective_start': None} + else: + # Scheduling data is very similiar to Sequences, but there are + # no due dates for Sections. It's in the data model because OLX + # lets you put it there, but that's a quirk that API clients + # shouldn't have to care about. + schedule_item_dict = { + # Any of these values could be `None` + 'start': section_schedule.start, + 'effective_start': section_schedule.effective_start, + } + + return { + "id": str(section.usage_key), + "title": section.title, + "sequence_ids": [ + str(seq.usage_key) for seq in section.sequences + ], + **schedule_item_dict, + } + + def get(self, request, course_key_str, format=None): + """ + The CourseOutline, customized for a given user. + + Currently restricted to global staff. + + TODO: Swagger docs of API. For an exemplar to imitate, see: + https://github.com/edx/edx-platform/blob/master/lms/djangoapps/program_enrollments/rest_api/v1/views.py#L792-L820 + """ + # Translate input params and do any substitutions... + course_key = self._validate_course_key(course_key_str) + at_time = datetime.now(timezone.utc) + user = self._determine_user(request) + + # Grab the user's outline and send our response... + user_course_outline_details = get_user_course_outline_details(course_key, user, at_time) + serializer = self.UserCourseOutlineDataSerializer(user_course_outline_details) + return Response(serializer.data) + + def _validate_course_key(self, course_key_str): + try: + course_key = CourseKey.from_string(course_key_str) + except InvalidKeyError: + raise serializers.ValidationError( + "{} is not a valid CourseKey".format(course_key_str) + ) + if course_key.deprecated: + raise serializers.ValidationError( + "Deprecated CourseKeys (Org/Course/Run) are not supported." + ) + return course_key + + def _determine_user(self, request): + """ + Requesting for a different user (easiest way to test for students) + while restricting access to only global staff. This is a placeholder + until we have more full fledged permissions/masquerading. + """ + requested_username = request.GET.get("user") + if request.user.is_staff and requested_username: + return User.objects.get(username=requested_username) + + return request.user diff --git a/openedx/core/djangoapps/content_libraries/api.py b/openedx/core/djangoapps/content_libraries/api.py index 9dc65708946af3166f18a3238c6a42195d3a508c..0366a87d46886d12c26c2d33c232e8f09d1a3662 100644 --- a/openedx/core/djangoapps/content_libraries/api.py +++ b/openedx/core/djangoapps/content_libraries/api.py @@ -1,8 +1,39 @@ """ Python API for content libraries. -Unless otherwise specified, all APIs in this file deal with the DRAFT version -of the content library. +Via 'views.py', most of these API methods are also exposed as a REST API. + +The API methods in this file are focused on authoring and specific to content +libraries; they wouldn't necessarily apply or work in other learning contexts +such as courses, blogs, "pathways," etc. + +** As this is an authoring-focused API, all API methods in this file deal with +the DRAFT version of the content library. ** + +Some of these methods will work and may be used from the LMS if needed (mostly +for test setup; other use is discouraged), but some of the implementation +details rely on Studio so other methods will raise errors if called from the +LMS. (The REST API is not available at all from the LMS.) + +Any APIs that use/affect content libraries but are generic enough to work in +other learning contexts too are in the core XBlock python/REST API at + openedx.core.djangoapps.xblock.api/rest_api + +For example, to render a content library XBlock as HTML, one can use the generic + render_block_view(block, view_name, user) +API in openedx.core.djangoapps.xblock.api (use it from Studio for the draft +version, from the LMS for published version). + +There are one or two methods in this file that have some overlap with the core +XBlock API; for example, this content library API provides a get_library_block() +which returns metadata about an XBlock; it's in this API because it also returns +data about whether or not the XBlock has unpublished edits, which is an +authoring-only concern. Likewise, APIs for getting/setting an individual +XBlock's OLX directly seem more appropriate for small, reusable components in +content libraries and may not be appropriate for other learning contexts so they +are implemented here in the library API only. In the future, if we find a need +for these in most other learning contexts then those methods could be promoted +to the core XBlock API and made generic. """ from uuid import UUID import logging @@ -13,6 +44,7 @@ from django.core.exceptions import PermissionDenied from django.core.validators import validate_unicode_slug from django.db import IntegrityError from lxml import etree +from opaque_keys.edx.keys import LearningContextKey from opaque_keys.edx.locator import BundleDefinitionLocator, LibraryLocatorV2, LibraryUsageLocatorV2 from organizations.models import Organization import six @@ -34,6 +66,7 @@ from openedx.core.lib.blockstore_api import ( update_bundle, delete_bundle, write_draft_file, + set_draft_link, commit_draft, delete_draft, ) @@ -69,7 +102,7 @@ class InvalidNameError(ValueError): # Models: @attr.s -class ContentLibraryMetadata(object): +class ContentLibraryMetadata: """ Class that represents the metadata about a content library. """ @@ -90,7 +123,7 @@ class ContentLibraryMetadata(object): allow_public_read = attr.ib(False) -class AccessLevel(object): +class AccessLevel: """ Enum defining library access levels/permissions """ ADMIN_LEVEL = ContentLibraryPermission.ADMIN_LEVEL AUTHOR_LEVEL = ContentLibraryPermission.AUTHOR_LEVEL @@ -99,7 +132,7 @@ class AccessLevel(object): @attr.s -class ContentLibraryPermissionEntry(object): +class ContentLibraryPermissionEntry: """ A user or group granted permission to use a content library. """ @@ -109,7 +142,7 @@ class ContentLibraryPermissionEntry(object): @attr.s -class LibraryXBlockMetadata(object): +class LibraryXBlockMetadata: """ Class that represents the metadata about an XBlock in a content library. """ @@ -120,7 +153,7 @@ class LibraryXBlockMetadata(object): @attr.s -class LibraryXBlockStaticFile(object): +class LibraryXBlockStaticFile: """ Class that represents a static file in a content library, associated with a particular XBlock. @@ -135,7 +168,7 @@ class LibraryXBlockStaticFile(object): @attr.s -class LibraryXBlockType(object): +class LibraryXBlockType: """ An XBlock type that can be added to a content library """ @@ -143,6 +176,33 @@ class LibraryXBlockType(object): display_name = attr.ib("") +@attr.s +class LibraryBundleLink: + """ + A link from a content library blockstore bundle to another blockstore bundle + """ + # Bundle that is linked to + bundle_uuid = attr.ib(type=UUID) + # Link name (slug) + id = attr.ib("") + # What version of this bundle we are currently linking to. + version = attr.ib(0) + # What the latest version of the linked bundle is: + # (if latest_version > version), the link can be "updated" to the latest version. + latest_version = attr.ib(0) + # Opaque key: If the linked bundle is a library or other learning context whose opaque key we can deduce, then this + # is the key. If we don't know what type of blockstore bundle this link is pointing to, then this is blank. + opaque_key = attr.ib(type=LearningContextKey, default=None) + + +class AccessLevel: + """ Enum defining library access levels/permissions """ + ADMIN_LEVEL = ContentLibraryPermission.ADMIN_LEVEL + AUTHOR_LEVEL = ContentLibraryPermission.AUTHOR_LEVEL + READ_LEVEL = ContentLibraryPermission.READ_LEVEL + NO_ACCESS = None + + def list_libraries_for_user(user): """ Lists up to 50 content libraries that the user has permission to view. @@ -643,6 +703,93 @@ def get_allowed_block_types(library_key): # pylint: disable=unused-argument return info +def get_bundle_links(library_key): + """ + Get the list of bundles/libraries linked to this content library. + + Returns LibraryBundleLink objects (defined above). + + Because every content library is a blockstore bundle, it can have "links" to + other bundles, which may or may not be content libraries. This allows using + XBlocks (or perhaps even static assets etc.) from another bundle without + needing to duplicate/copy the data. + + Links always point to a specific published version of the target bundle. + Links are identified by a slug-like ID, e.g. "link1" + """ + ref = ContentLibrary.objects.get_by_key(library_key) + links = blockstore_cache.get_bundle_draft_direct_links_cached(ref.bundle_uuid, DRAFT_NAME) + results = [] + # To be able to quickly get the library ID from the bundle ID for links which point to other libraries, build a map: + bundle_uuids = set(link_data.bundle_uuid for link_data in links.values()) + libraries_linked = { + lib.bundle_uuid: lib + for lib in ContentLibrary.objects.select_related('org').filter(bundle_uuid__in=bundle_uuids) + } + for link_name, link_data in links.items(): + # Is this linked bundle a content library? + try: + opaque_key = libraries_linked[link_data.bundle_uuid].library_key + except KeyError: + opaque_key = None + # Append the link information: + results.append(LibraryBundleLink( + id=link_name, + bundle_uuid=link_data.bundle_uuid, + version=link_data.version, + latest_version=blockstore_cache.get_bundle_version_number(link_data.bundle_uuid), + opaque_key=opaque_key, + )) + return results + + +def create_bundle_link(library_key, link_id, target_opaque_key, version=None): + """ + Create a new link to the resource with the specified opaque key. + + For now, only LibraryLocatorV2 opaque keys are supported. + """ + ref = ContentLibrary.objects.get_by_key(library_key) + # Make sure this link ID/name is not already in use: + links = blockstore_cache.get_bundle_draft_direct_links_cached(ref.bundle_uuid, DRAFT_NAME) + if link_id in links: + raise InvalidNameError("That link ID is already in use.") + # Determine the target: + if not isinstance(target_opaque_key, LibraryLocatorV2): + raise TypeError("For now, only LibraryLocatorV2 opaque keys are supported by create_bundle_link") + target_bundle_uuid = ContentLibrary.objects.get_by_key(target_opaque_key).bundle_uuid + if version is None: + version = get_bundle(target_bundle_uuid).latest_version + # Create the new link: + draft = get_or_create_bundle_draft(ref.bundle_uuid, DRAFT_NAME) + set_draft_link(draft.uuid, link_id, target_bundle_uuid, version) + # Clear the cache: + LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear() + + +def update_bundle_link(library_key, link_id, version=None, delete=False): + """ + Update a bundle's link to point to the specified version of its target + bundle. Use version=None to automatically point to the latest version. + Use delete=True to delete the link. + """ + ref = ContentLibrary.objects.get_by_key(library_key) + draft = get_or_create_bundle_draft(ref.bundle_uuid, DRAFT_NAME) + if delete: + set_draft_link(draft.uuid, link_id, None, None) + else: + links = blockstore_cache.get_bundle_draft_direct_links_cached(ref.bundle_uuid, DRAFT_NAME) + try: + link = links[link_id] + except KeyError: + raise InvalidNameError("That link does not exist.") + if version is None: + version = get_bundle(link.bundle_uuid).latest_version + set_draft_link(draft.uuid, link_id, link.bundle_uuid, version) + # Clear the cache: + LibraryBundle(library_key, ref.bundle_uuid, draft_name=DRAFT_NAME).cache.clear() + + def publish_changes(library_key): """ Publish all pending changes to the specified library. diff --git a/openedx/core/djangoapps/content_libraries/library_bundle.py b/openedx/core/djangoapps/content_libraries/library_bundle.py index 954113a08c47b22181fa570adf1fbede89e9bf6f..27570a2ff83fe897232f0e74e11e3bfc5f4ae028 100644 --- a/openedx/core/djangoapps/content_libraries/library_bundle.py +++ b/openedx/core/djangoapps/content_libraries/library_bundle.py @@ -18,6 +18,7 @@ from openedx.core.djangoapps.xblock.runtime.olx_parsing import ( ) from openedx.core.djangolib.blockstore_cache import ( BundleCache, + get_bundle_direct_links_with_cache, get_bundle_files_cached, get_bundle_file_metadata_with_cache, get_bundle_version_number, @@ -299,6 +300,12 @@ class LibraryBundle(object): has_unpublished_changes = True break + if not has_unpublished_changes: + # Check if any links have changed: + old_links = set(get_bundle_direct_links_with_cache(self.bundle_uuid).items()) + new_links = set(get_bundle_direct_links_with_cache(self.bundle_uuid, draft_name=self.draft_name).items()) + has_unpublished_changes = new_links != old_links + published_file_paths = set(f.path for f in get_bundle_files_cached(self.bundle_uuid)) draft_file_paths = set(f.path for f in draft_files) for file_path in published_file_paths: diff --git a/openedx/core/djangoapps/content_libraries/permissions.py b/openedx/core/djangoapps/content_libraries/permissions.py index c2acfcf47fd25d2522656fdf618e356f290c8326..02f8e2a561e3c6cdd7ee3aded6daea9fbb8551b6 100644 --- a/openedx/core/djangoapps/content_libraries/permissions.py +++ b/openedx/core/djangoapps/content_libraries/permissions.py @@ -17,17 +17,16 @@ is_global_staff = is_user_active & rules.is_staff # Does the user have at least read permission for the specified library? has_explicit_read_permission_for_library = ( ManyRelation( - # In newer versions of bridgekeeper, the 1st and 3rd arguments below aren't needed. - 'permission_grants', 'contentlibrarypermission', ContentLibraryPermission, - Attribute('user', lambda user: user) | Relation('group', Group, in_current_groups) + 'contentlibrarypermission', + (Attribute('user', lambda user: user) | Relation('group', in_current_groups)) ) # We don't check 'access_level' here because all access levels grant read permission ) # Does the user have at least author permission for the specified library? has_explicit_author_permission_for_library = ( ManyRelation( - 'permission_grants', 'contentlibrarypermission', ContentLibraryPermission, - (Attribute('user', lambda user: user) | Relation('group', Group, in_current_groups)) & ( + 'contentlibrarypermission', + (Attribute('user', lambda user: user) | Relation('group', in_current_groups)) & ( Attribute('access_level', ContentLibraryPermission.AUTHOR_LEVEL) | Attribute('access_level', ContentLibraryPermission.ADMIN_LEVEL) ) @@ -36,8 +35,8 @@ has_explicit_author_permission_for_library = ( # Does the user have admin permission for the specified library? has_explicit_admin_permission_for_library = ( ManyRelation( - 'permission_grants', 'contentlibrarypermission', ContentLibraryPermission, - (Attribute('user', lambda user: user) | Relation('group', Group, in_current_groups)) & + 'contentlibrarypermission', + (Attribute('user', lambda user: user) | Relation('group', in_current_groups)) & Attribute('access_level', ContentLibraryPermission.ADMIN_LEVEL) ) ) @@ -56,7 +55,7 @@ perms[CAN_LEARN_FROM_THIS_CONTENT_LIBRARY] = ( # Regular users can learn if the library allows public learning: Attribute('allow_public_learning', True) | # Users/groups who are explicitly granted permission can learn from the library: - has_explicit_read_permission_for_library + (is_user_active & has_explicit_read_permission_for_library) ) # Is the user allowed to create content libraries? diff --git a/openedx/core/djangoapps/content_libraries/serializers.py b/openedx/core/djangoapps/content_libraries/serializers.py index 998df008811194e0d17c9657ffe248198fdb0392..e13f57c08369fb259936db0b490564cc252a4316 100644 --- a/openedx/core/djangoapps/content_libraries/serializers.py +++ b/openedx/core/djangoapps/content_libraries/serializers.py @@ -84,6 +84,32 @@ class LibraryXBlockTypeSerializer(serializers.Serializer): display_name = serializers.CharField() +class LibraryBundleLinkSerializer(serializers.Serializer): + """ + Serializer for a link from a content library blockstore bundle to another + blockstore bundle. + """ + id = serializers.SlugField() # Link name + bundle_uuid = serializers.UUIDField(format='hex_verbose', read_only=True) + # What version of this bundle we are currently linking to. + # This is never NULL but can optionally be set to null when creating a new link, which means "use latest version." + version = serializers.IntegerField(allow_null=True) + # What the latest version of the linked bundle is: + # (if latest_version > version), the link can be "updated" to the latest version. + latest_version = serializers.IntegerField(read_only=True) + # Opaque key: If the linked bundle is a library or other learning context whose opaque key we can deduce, then this + # is the key. If we don't know what type of blockstore bundle this link is pointing to, then this is blank. + opaque_key = serializers.CharField() + + +class LibraryBundleLinkUpdateSerializer(serializers.Serializer): + """ + Serializer for updating an existing link in a content library blockstore + bundle. + """ + version = serializers.IntegerField(allow_null=True) + + class LibraryXBlockCreationSerializer(serializers.Serializer): """ Serializer for adding a new XBlock to a content library diff --git a/openedx/core/djangoapps/content_libraries/tests/base.py b/openedx/core/djangoapps/content_libraries/tests/base.py index 63d8a7fa8ec5898c4431f50bb7458109f3c2f338..490ff4052b1c6281e5de13d41434f6b3e5fd8f53 100644 --- a/openedx/core/djangoapps/content_libraries/tests/base.py +++ b/openedx/core/djangoapps/content_libraries/tests/base.py @@ -3,12 +3,12 @@ Tests for Blockstore-based Content Libraries """ from contextlib import contextmanager +from io import BytesIO import unittest from django.conf import settings from organizations.models import Organization from rest_framework.test import APITestCase, APIClient -import six from student.tests.factories import UserFactory from openedx.core.djangolib.testing.utils import skip_unless_cms @@ -20,6 +20,7 @@ URL_PREFIX = '/api/libraries/v2/' URL_LIB_CREATE = URL_PREFIX URL_LIB_DETAIL = URL_PREFIX + '{lib_key}/' # Get data about a library, update or delete library URL_LIB_BLOCK_TYPES = URL_LIB_DETAIL + 'block_types/' # Get the list of XBlock types that can be added to this library +URL_LIB_LINKS = URL_LIB_DETAIL + 'links/' # Get the list of links in this library, or add a new one URL_LIB_COMMIT = URL_LIB_DETAIL + 'commit/' # Commit (POST) or revert (DELETE) all pending changes to this library URL_LIB_BLOCKS = URL_LIB_DETAIL + 'blocks/' # Get the list of XBlocks in this library, or add a new one URL_LIB_TEAM = URL_LIB_DETAIL + 'team/' # Get the list of users/groups authorized to use this library @@ -32,6 +33,7 @@ URL_LIB_BLOCK_ASSET_FILE = URL_LIB_BLOCK + 'assets/{file_name}' # Get, delete, URL_BLOCK_RENDER_VIEW = '/api/xblock/v2/xblocks/{block_key}/view/{view_name}/' URL_BLOCK_GET_HANDLER_URL = '/api/xblock/v2/xblocks/{block_key}/handler_url/{handler_name}/' +URL_BLOCK_METADATA_URL = '/api/xblock/v2/xblocks/{block_key}/' # Decorator for tests that require blockstore @@ -66,19 +68,19 @@ class ContentLibrariesRestApiTest(APITestCase): @classmethod def setUpClass(cls): - super(ContentLibrariesRestApiTest, cls).setUpClass() + super().setUpClass() cls.user = UserFactory.create(username="Bob", email="bob@example.com", password="edx") # Create a collection using Blockstore API directly only because there # is not yet any Studio REST API for doing so: cls.collection = blockstore_api.create_collection("Content Library Test Collection") # Create an organization - cls.organization = Organization.objects.create( - name="Content Libraries Tachyon Exploration & Survey Team", + cls.organization, _ = Organization.objects.get_or_create( short_name="CL-TEST", + defaults={"name": "Content Libraries Tachyon Exploration & Survey Team"}, ) def setUp(self): - super(ContentLibrariesRestApiTest, self).setUp() + super().setUp() self.clients_by_user = {} self.client.login(username=self.user.username, password="edx") @@ -142,6 +144,23 @@ class ContentLibrariesRestApiTest(APITestCase): """ Delete an existing library """ return self._api('delete', URL_LIB_DETAIL.format(lib_key=lib_key), None, expect_response) + def _get_library_links(self, lib_key): + """ Get the links of the specified content library """ + return self._api('get', URL_LIB_LINKS.format(lib_key=lib_key), None, expect_response=200) + + def _link_to_library(self, lib_key, link_id, other_library_key, version=None): + """ + Modify the library identified by lib_key to create a named link to + other_library_key. This allows you to use XBlocks from other_library in + lib. Optionally specify a version to link to. + """ + data = { + "id": link_id, + "opaque_key": other_library_key, + "version": version, + } + return self._api('post', URL_LIB_LINKS.format(lib_key=lib_key), data, expect_response=200) + def _commit_library_changes(self, lib_key, expect_response=200): """ Commit changes to an existing library """ return self._api('post', URL_LIB_COMMIT.format(lib_key=lib_key), None, expect_response) @@ -220,8 +239,8 @@ class ContentLibrariesRestApiTest(APITestCase): content should be a binary string. """ - assert isinstance(content, six.binary_type) - file_handle = six.BytesIO(content) + assert isinstance(content, bytes) + file_handle = BytesIO(content) url = URL_LIB_BLOCK_ASSET_FILE.format(block_key=block_key, file_name=file_name) response = self.client.put(url, data={"content": file_handle}) self.assertEqual( diff --git a/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py b/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py index 59ad24819c4b630bf608d17e123df63650acea92..afa54fd12910e8573a4ede63287f8b1d0ed46942 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py @@ -355,3 +355,91 @@ class ContentLibrariesTest(ContentLibrariesRestApiTest): self._delete_library_block(block3_key) self._commit_library_changes(lib_id) self._revert_library_changes(lib_id) # This is a no-op after the commit, but should still have 200 response + + def test_library_blocks_with_links(self): + """ + Test that libraries can link to XBlocks in other content libraries + """ + # Create a problem bank: + bank_lib = self._create_library(slug="problem_bank", title="Problem Bank") + bank_lib_id = bank_lib["id"] + # Add problem1 to the problem bank: + p1 = self._add_block_to_library(bank_lib_id, "problem", "problem1") + self._set_library_block_olx(p1["id"], """ + <problem><multiplechoiceresponse> + <p>What is an even number?</p> + <choicegroup type="MultipleChoice"> + <choice correct="false">3</choice> + <choice correct="true">2</choice> + </choicegroup> + </multiplechoiceresponse></problem> + """) + # Commit the changes, creating version 1: + self._commit_library_changes(bank_lib_id) + # Now update problem 1 and create a new problem 2: + self._set_library_block_olx(p1["id"], """ + <problem><multiplechoiceresponse> + <p>What is an odd number?</p> + <choicegroup type="MultipleChoice"> + <choice correct="true">3</choice> + <choice correct="false">2</choice> + </choicegroup> + </multiplechoiceresponse></problem> + """) + p2 = self._add_block_to_library(bank_lib_id, "problem", "problem2") + self._set_library_block_olx(p2["id"], """ + <problem><multiplechoiceresponse> + <p>What holds this XBlock?</p> + <choicegroup type="MultipleChoice"> + <choice correct="false">A course</choice> + <choice correct="true">A problem bank</choice> + </choicegroup> + </multiplechoiceresponse></problem> + """) + # Commit the changes, creating version 2: + self._commit_library_changes(bank_lib_id) + # At this point, bank_lib contains two problems and has two versions. + # In version 1, problem1 is "What is an event number", and in version 2 it's "What is an odd number". + # Problem2 exists only in version 2 and asks "What holds this XBlock?" + + lib = self._create_library(slug="links_test_lib", title="Link Test Library") + lib_id = lib["id"] + # Link to the problem bank: + self._link_to_library(lib_id, "problem_bank", bank_lib_id) + self._link_to_library(lib_id, "problem_bank_v1", bank_lib_id, version=1) + + # Add a 'unit' XBlock to the library: + unit_block = self._add_block_to_library(lib_id, "unit", "unit1") + self._set_library_block_olx(unit_block["id"], """ + <unit> + <!-- version 2 link to "What is an odd number?" --> + <xblock-include source="problem_bank" definition="problem/problem1"/> + <!-- version 1 link to "What is an even number?" --> + <xblock-include source="problem_bank_v1" definition="problem/problem1" usage="p1v1" /> + <!-- link to "What holds this XBlock?" --> + <xblock-include source="problem_bank" definition="problem/problem2"/> + </unit> + """) + + # The unit can see and render its children: + fragment = self._render_block_view(unit_block["id"], "student_view") + self.assertIn("What is an odd number?", fragment["content"]) + self.assertIn("What is an even number?", fragment["content"]) + self.assertIn("What holds this XBlock?", fragment["content"]) + + # Also check the API for retrieving links: + links_created = self._get_library_links(lib_id) + links_created.sort(key=lambda link: link["id"]) + self.assertEqual(len(links_created), 2) + + self.assertEqual(links_created[0]["id"], "problem_bank") + self.assertEqual(links_created[0]["bundle_uuid"], bank_lib["bundle_uuid"]) + self.assertEqual(links_created[0]["version"], 2) + self.assertEqual(links_created[0]["latest_version"], 2) + self.assertEqual(links_created[0]["opaque_key"], bank_lib_id) + + self.assertEqual(links_created[1]["id"], "problem_bank_v1") + self.assertEqual(links_created[1]["bundle_uuid"], bank_lib["bundle_uuid"]) + self.assertEqual(links_created[1]["version"], 1) + self.assertEqual(links_created[1]["latest_version"], 2) + self.assertEqual(links_created[1]["opaque_key"], bank_lib_id) diff --git a/openedx/core/djangoapps/content_libraries/tests/test_runtime.py b/openedx/core/djangoapps/content_libraries/tests/test_runtime.py index 2dd2c3284d202a2307d7528013dbed7ed3773c6f..4f16dfb217d2e84dde73800d440fe920325ac47f 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_runtime.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_runtime.py @@ -16,6 +16,7 @@ from openedx.core.djangoapps.content_libraries.tests.base import ( requires_blockstore, URL_BLOCK_RENDER_VIEW, URL_BLOCK_GET_HANDLER_URL, + URL_BLOCK_METADATA_URL, ) from openedx.core.djangoapps.content_libraries.tests.user_state_block import UserStateTestBlock from openedx.core.djangoapps.xblock import api as xblock_api @@ -113,6 +114,57 @@ class ContentLibraryRuntimeTest(ContentLibraryContentTestMixin, TestCase): # And problems do have has_score True: self.assertEqual(problem_block.has_score, True) + @skip_unless_cms # creating child blocks only works properly in Studio + def test_xblock_metadata(self): + """ + Test the XBlock metadata API + """ + unit_block_key = library_api.create_library_block(self.library.key, "unit", "metadata-u1").usage_key + problem_key = library_api.create_library_block_child(unit_block_key, "problem", "metadata-p1").usage_key + new_olx = """ + <problem display_name="New Multi Choice Question" max_attempts="5"> + <multiplechoiceresponse> + <p>This is a normal capa problem. It has "maximum attempts" set to **5**.</p> + <label>Blockstore is designed to store.</label> + <choicegroup type="MultipleChoice"> + <choice correct="false">XBlock metadata only</choice> + <choice correct="true">XBlock data/metadata and associated static asset files</choice> + <choice correct="false">Static asset files for XBlocks and courseware</choice> + <choice correct="false">XModule metadata only</choice> + </choicegroup> + </multiplechoiceresponse> + </problem> + """.strip() + library_api.set_library_block_olx(problem_key, new_olx) + library_api.publish_changes(self.library.key) + + # Now view the problem as Alice: + client = APIClient() + client.login(username=self.student_a.username, password='edx') + + # Check the metadata API for the unit: + metadata_view_result = client.get( + URL_BLOCK_METADATA_URL.format(block_key=unit_block_key), + {"include": "children,editable_children"}, + ) + self.assertEqual(metadata_view_result.data["children"], [str(problem_key)]) + self.assertEqual(metadata_view_result.data["editable_children"], [str(problem_key)]) + + # Check the metadata API for the problem: + metadata_view_result = client.get( + URL_BLOCK_METADATA_URL.format(block_key=problem_key), + {"include": "student_view_data,index_dictionary"}, + ) + self.assertEqual(metadata_view_result.data["block_id"], str(problem_key)) + self.assertEqual(metadata_view_result.data["display_name"], "New Multi Choice Question") + self.assertNotIn("children", metadata_view_result.data) + self.assertNotIn("editable_children", metadata_view_result.data) + self.assertDictContainsSubset({ + "content_type": "CAPA", + "problem_types": ["multiplechoiceresponse"], + }, metadata_view_result.data["index_dictionary"]) + self.assertEqual(metadata_view_result.data["student_view_data"], None) # Capa doesn't provide student_view_data + @requires_blockstore # We can remove the line below to enable this in Studio once we implement a session-backed @@ -339,6 +391,7 @@ class ContentLibraryXBlockUserStateTest(ContentLibraryContentTestMixin, TestCase student_view_result = client.get(URL_BLOCK_RENDER_VIEW.format(block_key=block_id, view_name='student_view')) problem_key = "input_{}_2_1".format(block_id) self.assertIn(problem_key, student_view_result.data["content"]) + # And submit a wrong answer: result = client.get(URL_BLOCK_GET_HANDLER_URL.format(block_key=block_id, handler_name='xmodule_handler')) problem_check_url = result.data["handler_url"] + 'problem_check' diff --git a/openedx/core/djangoapps/content_libraries/urls.py b/openedx/core/djangoapps/content_libraries/urls.py index 2c08f870867f8c5bf5578c362bb52d56d51f29d5..74019affb1774dc87b9c1288ea96571f11dc28ff 100644 --- a/openedx/core/djangoapps/content_libraries/urls.py +++ b/openedx/core/djangoapps/content_libraries/urls.py @@ -20,6 +20,10 @@ urlpatterns = [ url(r'^$', views.LibraryDetailsView.as_view()), # Get the list of XBlock types that can be added to this library url(r'^block_types/$', views.LibraryBlockTypesView.as_view()), + # Get the list of Blockstore Bundle Links for this library, or add a new one: + url(r'^links/$', views.LibraryLinksView.as_view()), + # Update or delete a link: + url(r'^links/(?P<link_id>[^/]+)/$', views.LibraryLinkDetailView.as_view()), # Get the list of XBlocks in this library, or add a new one: url(r'^blocks/$', views.LibraryBlocksView.as_view()), # Commit (POST) or revert (DELETE) all pending changes to this library: diff --git a/openedx/core/djangoapps/content_libraries/views.py b/openedx/core/djangoapps/content_libraries/views.py index 6decb858033c041cd2892dad731cfcbb1664c5b9..7a1a41e5655fbee7e519590a9f53b52becf98660 100644 --- a/openedx/core/djangoapps/content_libraries/views.py +++ b/openedx/core/djangoapps/content_libraries/views.py @@ -24,6 +24,8 @@ from openedx.core.djangoapps.content_libraries.serializers import ( LibraryXBlockCreationSerializer, LibraryXBlockMetadataSerializer, LibraryXBlockTypeSerializer, + LibraryBundleLinkSerializer, + LibraryBundleLinkUpdateSerializer, LibraryXBlockOlxSerializer, LibraryXBlockStaticFileSerializer, LibraryXBlockStaticFilesSerializer, @@ -241,6 +243,80 @@ class LibraryBlockTypesView(APIView): return Response(LibraryXBlockTypeSerializer(result, many=True).data) +@view_auth_classes() +class LibraryLinksView(APIView): + """ + View to get the list of bundles/libraries linked to this content library. + + Because every content library is a blockstore bundle, it can have "links" to + other bundles, which may or may not be content libraries. This allows using + XBlocks (or perhaps even static assets etc.) from another bundle without + needing to duplicate/copy the data. + + Links always point to a specific published version of the target bundle. + Links are identified by a slug-like ID, e.g. "link1" + """ + @convert_exceptions + def get(self, request, lib_key_str): + """ + Get the list of bundles that this library links to, if any + """ + key = LibraryLocatorV2.from_string(lib_key_str) + api.require_permission_for_library_key(key, request.user, permissions.CAN_VIEW_THIS_CONTENT_LIBRARY) + result = api.get_bundle_links(key) + return Response(LibraryBundleLinkSerializer(result, many=True).data) + + @convert_exceptions + def post(self, request, lib_key_str): + """ + Create a new link in this library. + """ + key = LibraryLocatorV2.from_string(lib_key_str) + api.require_permission_for_library_key(key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY) + serializer = LibraryBundleLinkSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + target_key = LibraryLocatorV2.from_string(serializer.validated_data['opaque_key']) + api.create_bundle_link( + library_key=key, + link_id=serializer.validated_data['id'], + target_opaque_key=target_key, + version=serializer.validated_data['version'], # a number, or None for "use latest version" + ) + return Response({}) + + +@view_auth_classes() +class LibraryLinkDetailView(APIView): + """ + View to update/delete an existing library link + """ + @convert_exceptions + def patch(self, request, lib_key_str, link_id): + """ + Update the specified link to point to a different version of its + target bundle. + + Pass e.g. {"version": 40} or pass {"version": None} to update to the + latest published version. + """ + key = LibraryLocatorV2.from_string(lib_key_str) + api.require_permission_for_library_key(key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY) + serializer = LibraryBundleLinkUpdateSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + api.update_bundle_link(key, link_id, version=serializer.validated_data['version']) + return Response({}) + + @convert_exceptions + def delete(self, request, lib_key_str, link_id): # pylint: disable=unused-argument + """ + Delete a link from this library. + """ + key = LibraryLocatorV2.from_string(lib_key_str) + api.require_permission_for_library_key(key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY) + api.update_bundle_link(key, link_id, delete=True) + return Response({}) + + @view_auth_classes() class LibraryCommitView(APIView): """ diff --git a/openedx/core/djangoapps/cors_csrf/templates/cors_csrf/xdomain_proxy.html b/openedx/core/djangoapps/cors_csrf/templates/cors_csrf/xdomain_proxy.html index 66d1a4a31adb117eba111be102df1375be164b9c..7c74321daad8fed1a71b025067725afe75c16450 100644 --- a/openedx/core/djangoapps/cors_csrf/templates/cors_csrf/xdomain_proxy.html +++ b/openedx/core/djangoapps/cors_csrf/templates/cors_csrf/xdomain_proxy.html @@ -1,5 +1,12 @@ -<%namespace name='static' file='../static_content.html'/> +<%page expression_filter="h"/> +<%namespace name='static' file='../static_content.html'/> +<%! +from openedx.core.djangolib.js_utils import ( + dump_js_escaped_json +) +%> +<%! import json %> <!DOCTYPE HTML> <script src="${static.url('js/vendor/xdomain.min.js')}"></script> -<script>xdomain.masters(${xdomain_masters});</script> +<script>xdomain.masters(${json.loads(xdomain_masters) | n, dump_js_escaped_json});</script> diff --git a/openedx/core/djangoapps/course_date_signals/handlers.py b/openedx/core/djangoapps/course_date_signals/handlers.py index 2639f097aa5721b8cd7629da4e5ceed92f4022a7..69c6951121e19496e82211f21d44df33d6927d8c 100644 --- a/openedx/core/djangoapps/course_date_signals/handlers.py +++ b/openedx/core/djangoapps/course_date_signals/handlers.py @@ -9,7 +9,7 @@ from xblock.fields import Scope from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import SignalHandler, modulestore from .models import SelfPacedRelativeDatesConfig -from .utils import get_expected_duration +from .utils import spaced_out_sections from edx_when.api import FIELDS_TO_EXTRACT, set_dates_for_course log = logging.getLogger(__name__) @@ -49,19 +49,29 @@ def extract_dates_from_course(course): date_items = [(course.location, metadata)] if SelfPacedRelativeDatesConfig.current(course_key=course.id).enabled: - duration = get_expected_duration(course) - sections = course.get_children() - time_per_week = duration / len(sections) # Apply the same relative due date to all content inside a section, # unless that item already has a relative date set - for idx, section in enumerate(sections): + for _, section, weeks_to_complete in spaced_out_sections(course): items = [section] + has_non_ora_scored_content = False + section_date_items = [] while items: next_item = items.pop() - # TODO: Once studio can manually set relative dates, - # we would need to manually check for them here - date_items.append((next_item.location, {'due': time_per_week * (idx + 1)})) + # TODO: This is pretty gross, and should maybe be configurable in the future, + # especially if we find ourselves needing more exceptions. + if next_item.graded: + # TODO: Once studio can manually set relative dates, + # we would need to manually check for them here + section_date_items.append((next_item.location, {'due': weeks_to_complete})) + has_non_ora_scored_content = ( + has_non_ora_scored_content or + (next_item.has_score and next_item.category != 'openassessment') + ) + items.extend(next_item.get_children()) + + if has_non_ora_scored_content: + date_items.extend(section_date_items) else: date_items = [] store = modulestore() diff --git a/openedx/core/djangoapps/course_date_signals/tests.py b/openedx/core/djangoapps/course_date_signals/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..5001d11bd24c693acd4b608c7dcdfa1ffa3f1d57 --- /dev/null +++ b/openedx/core/djangoapps/course_date_signals/tests.py @@ -0,0 +1,42 @@ +from datetime import timedelta +import ddt +from unittest.mock import patch + +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from . import utils + + +@ddt.ddt +class SelfPacedDueDatesTests(ModuleStoreTestCase): + def setUp(self): + super().setUp() + self.course = CourseFactory.create() + for i in range(4): + ItemFactory(parent=self.course, category="sequential", display_name="Section {}".format(i)) + + def test_basic_spacing(self): + expected_sections = [ + (0, 'Section 0', timedelta(days=7)), + (1, 'Section 1', timedelta(days=14)), + (2, 'Section 2', timedelta(days=21)), + (3, 'Section 3', timedelta(days=28)), + ] + with patch.object(utils, 'get_expected_duration', return_value=timedelta(weeks=4)): + actual = [(idx, section.display_name, offset) for (idx, section, offset) in utils.spaced_out_sections(self.course)] + + self.assertEqual(actual, expected_sections) + + def test_hidden_sections(self): + for _ in range(2): + ItemFactory(parent=self.course, category="sequential", visible_to_staff_only=True) + expected_sections = [ + (0, 'Section 0', timedelta(days=7)), + (1, 'Section 1', timedelta(days=14)), + (2, 'Section 2', timedelta(days=21)), + (3, 'Section 3', timedelta(days=28)), + ] + with patch.object(utils, 'get_expected_duration', return_value=timedelta(weeks=4)): + actual = [(idx, section.display_name, offset) for (idx, section, offset) in utils.spaced_out_sections(self.course)] + + self.assertEqual(actual, expected_sections) diff --git a/openedx/core/djangoapps/course_date_signals/utils.py b/openedx/core/djangoapps/course_date_signals/utils.py index a006268c9e6ada2f7cac10afb1516f608980c84f..823e590f927b9d0d0b7bee3c58015ab48b2cc504 100644 --- a/openedx/core/djangoapps/course_date_signals/utils.py +++ b/openedx/core/djangoapps/course_date_signals/utils.py @@ -6,7 +6,6 @@ get_expected_duration: return the expected duration of a course (absent any user from datetime import timedelta -from course_modes.models import CourseMode from openedx.core.djangoapps.catalog.utils import get_course_run_details @@ -21,11 +20,6 @@ def get_expected_duration(course): access_duration = MIN_DURATION - verified_mode = CourseMode.verified_mode_for_course(course=course, include_expired=True) - - if not verified_mode: - return None - # The user course expiration date is the content availability date # plus the weeks_to_complete field from course-discovery. discovery_course_details = get_course_run_details(course.id, ['weeks_to_complete']) @@ -37,3 +31,24 @@ def get_expected_duration(course): access_duration = max(MIN_DURATION, min(MAX_DURATION, access_duration)) return access_duration + + +def spaced_out_sections(course): + """ + Generator that returns sections of the course module with a suggested time to complete for each + + Returns: + index (int): index of section + section (block): a section block of the course + relative time (timedelta): the amount of weeks to complete the section, since start of course + """ + duration = get_expected_duration(course) + sections = [ + section + for section + in course.get_children() + if not section.visible_to_staff_only + ] + weeks_per_section = duration / len(sections) + for idx, section in enumerate(sections): + yield idx, section, weeks_per_section * (idx + 1) diff --git a/openedx/core/djangoapps/course_groups/partition_scheme.py b/openedx/core/djangoapps/course_groups/partition_scheme.py index 53d437c15b9400d99b7e74afeab480ed405088de..d629d495c3826e7d58dead4d365f6a5883c35d59 100644 --- a/openedx/core/djangoapps/course_groups/partition_scheme.py +++ b/openedx/core/djangoapps/course_groups/partition_scheme.py @@ -61,7 +61,7 @@ class CohortPartitionScheme(object): # if we have a match but the partition doesn't match the requested # one it means the mapping is invalid. the previous state of the # partition configuration may have been modified. - log.warn( + log.warning( u"partition mismatch in CohortPartitionScheme: %r", { "requested_partition_id": user_partition.id, @@ -79,7 +79,7 @@ class CohortPartitionScheme(object): # if we have a match but the group doesn't exist in the partition, # it means the mapping is invalid. the previous state of the # partition configuration may have been modified. - log.warn( + log.warning( u"group not found in CohortPartitionScheme: %r", { "requested_partition_id": user_partition.id, 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 751c29673f80c478d8942e0a20b1c15c7e180c30..39c616a96481a7a93e87c7d50b17d6dcccf38b0b 100644 --- a/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py +++ b/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py @@ -228,8 +228,8 @@ class TestCohortPartitionScheme(ModuleStoreTestCase): # warning) with patch('openedx.core.djangoapps.course_groups.partition_scheme.log') as mock_log: self.assert_student_in_group(None, new_user_partition) - self.assertTrue(mock_log.warn.called) - self.assertRegex(mock_log.warn.call_args[0][0], 'group not found') + self.assertTrue(mock_log.warning.called) + self.assertRegex(mock_log.warning.call_args[0][0], 'group not found') def test_missing_partition(self): """ @@ -253,8 +253,8 @@ class TestCohortPartitionScheme(ModuleStoreTestCase): # scheme returns None (and logs a warning). with patch('openedx.core.djangoapps.course_groups.partition_scheme.log') as mock_log: self.assert_student_in_group(None, new_user_partition) - self.assertTrue(mock_log.warn.called) - self.assertRegex(mock_log.warn.call_args[0][0], 'partition mismatch') + self.assertTrue(mock_log.warning.called) + self.assertRegex(mock_log.warning.call_args[0][0], 'partition mismatch') class TestExtension(django.test.TestCase): diff --git a/openedx/core/djangoapps/courseware_api/serializers.py b/openedx/core/djangoapps/courseware_api/serializers.py index f9a70c9f619290ee672031aefcc1ec770e7ddf0c..6d8209f5f93177070352ff65b02f69f8b517844a 100644 --- a/openedx/core/djangoapps/courseware_api/serializers.py +++ b/openedx/core/djangoapps/courseware_api/serializers.py @@ -2,16 +2,8 @@ Course API Serializers. Representing course catalog data """ -from babel.numbers import get_currency_symbol - -from django.urls import reverse from rest_framework import serializers -from course_modes.models import CourseMode -from edxnotes.helpers import is_feature_enabled -from lms.djangoapps.courseware.tabs import get_course_tab_list -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link - from openedx.core.lib.api.fields import AbsoluteURLField @@ -69,6 +61,7 @@ class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract- Compare this with CourseDetailSerializer. """ + can_show_upgrade_sock = serializers.BooleanField() content_type_gating_enabled = serializers.BooleanField() course_expired_message = serializers.CharField() effort = serializers.CharField() @@ -79,6 +72,7 @@ class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract- media = _CourseApiMediaCollectionSerializer(source='*') name = serializers.CharField(source='display_name_with_default_escaped') number = serializers.CharField(source='display_number_with_default') + offer_html = serializers.CharField() org = serializers.CharField(source='display_org_with_default') short_description = serializers.CharField() start = serializers.DateTimeField() @@ -86,12 +80,14 @@ class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract- start_type = serializers.CharField() pacing = serializers.CharField() enrollment = serializers.DictField() - tabs = serializers.SerializerMethodField() - verified_mode = serializers.SerializerMethodField() + tabs = serializers.ListField() + verified_mode = serializers.DictField() show_calculator = serializers.BooleanField() is_staff = serializers.BooleanField() can_load_courseware = serializers.DictField() - notes = serializers.SerializerMethodField() + notes = serializers.DictField() + marketing_url = serializers.CharField() + celebrations = serializers.DictField() def __init__(self, *args, **kwargs): """ @@ -105,41 +101,3 @@ class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract- existing = set(self.fields) for field_name in existing - allowed: self.fields.pop(field_name) - - def get_tabs(self, course_overview): - """ - Return course tab metadata. - """ - tabs = [] - for priority, tab in enumerate(get_course_tab_list(course_overview.effective_user, course_overview)): - tabs.append({ - 'title': tab.title or tab.get('name', ''), - 'slug': tab.tab_id, - 'priority': priority, - 'type': tab.type, - 'url': tab.link_func(course_overview, reverse), - }) - return tabs - - def get_verified_mode(self, course_overview): - """ - Return verified mode information, or None. - """ - mode = CourseMode.verified_mode_for_course(course_overview.id) - if mode: - return { - 'price': mode.min_price, - 'currency': mode.currency.upper(), - 'currency_symbol': get_currency_symbol(mode.currency.upper()), - 'sku': mode.sku, - 'upgrade_url': verified_upgrade_deadline_link(course_overview.effective_user, course_overview), - } - - def get_notes(self, course_overview): - """ - Return whether edxnotes is enabled and visible. - """ - return { - 'enabled': is_feature_enabled(course_overview, course_overview.effective_user), - 'visible': course_overview.edxnotes_visibility, - } diff --git a/openedx/core/djangoapps/courseware_api/tests/test_views.py b/openedx/core/djangoapps/courseware_api/tests/test_views.py index 45d7afac9ffbd479209807fec7f8cd9d60859fe9..5c8df000f21e9e19c6114447e57d4451c701e000 100644 --- a/openedx/core/djangoapps/courseware_api/tests/test_views.py +++ b/openedx/core/djangoapps/courseware_api/tests/test_views.py @@ -1,26 +1,21 @@ """ Tests for courseware API """ -from datetime import datetime import unittest +from datetime import datetime + import ddt import mock - +from completion.test_utils import CompletionWaffleTestMixin, submit_completions_for_testing from django.conf import settings -from lms.djangoapps.courseware.access_utils import ( - ACCESS_DENIED, - ACCESS_GRANTED -) +from lms.djangoapps.courseware.access_utils import ACCESS_DENIED, ACCESS_GRANTED +from lms.djangoapps.courseware.tabs import ExternalLinkCourseTab +from student.models import CourseEnrollment, CourseEnrollmentCelebration +from student.tests.factories import CourseEnrollmentCelebrationFactory, UserFactory from xmodule.modulestore.django import modulestore - -from xmodule.modulestore.tests.django_utils import ( - TEST_DATA_SPLIT_MODULESTORE, - SharedModuleStoreTestCase -) +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import ItemFactory, ToyCourseFactory -from student.tests.factories import UserFactory -from student.models import CourseEnrollment @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @@ -29,6 +24,7 @@ class BaseCoursewareTests(SharedModuleStoreTestCase): Base class for courseware API tests """ MODULESTORE = TEST_DATA_SPLIT_MODULESTORE + @classmethod def setUpClass(cls): super().setUpClass() @@ -40,6 +36,10 @@ class BaseCoursewareTests(SharedModuleStoreTestCase): emit_signals=True, modulestore=cls.store, ) + cls.chapter = ItemFactory(parent=cls.course, category='chapter') + cls.sequence = ItemFactory(parent=cls.chapter, category='sequential', display_name='sequence') + cls.unit = ItemFactory.create(parent=cls.sequence, category='vertical', display_name="Vertical") + cls.user = UserFactory( username='student', email=u'user@example.com', @@ -63,6 +63,15 @@ class CourseApiTestViews(BaseCoursewareTests): """ Tests for the courseware REST API """ + @classmethod + def setUpClass(cls): + BaseCoursewareTests.setUpClass() + cls.course.tabs.append(ExternalLinkCourseTab.load('external_link', name='Zombo', link='http://zombo.com')) + cls.course.tabs.append( + ExternalLinkCourseTab.load('external_link', name='Hidden', link='http://hidden.com', is_hidden=True) + ) + cls.store.update_item(cls.course, cls.user.id) + @ddt.data( (True, None, ACCESS_DENIED), (True, 'audit', ACCESS_DENIED), @@ -85,7 +94,14 @@ class CourseApiTestViews(BaseCoursewareTests): enrollment = response.data['enrollment'] assert enrollment_mode == enrollment['mode'] assert enrollment['is_active'] - assert len(response.data['tabs']) == 4 + assert len(response.data['tabs']) == 5 + found = False + for tab in response.data['tabs']: + if tab['type'] == 'external_link': + assert tab['url'] != 'http://hidden.com', "Hidden tab is not hidden" + if tab['url'] == 'http://zombo.com': + found = True + assert found, 'external link not in course tabs' elif enable_anonymous and not logged_in: # multiple checks use this handler check_public_access.assert_called() @@ -102,9 +118,6 @@ class SequenceApiTestViews(BaseCoursewareTests): @classmethod def setUpClass(cls): super().setUpClass() - chapter = ItemFactory(parent=cls.course, category='chapter') - cls.sequence = ItemFactory(parent=chapter, category='sequential', display_name='sequence') - ItemFactory.create(parent=cls.sequence, category='vertical', display_name="Vertical") cls.url = '/api/courseware/sequence/{}'.format(cls.sequence.location) @classmethod @@ -113,9 +126,84 @@ class SequenceApiTestViews(BaseCoursewareTests): super().tearDownClass() def test_sequence_metadata(self): - print(self.url) - print(self.course.location) response = self.client.get(self.url) assert response.status_code == 200 assert response.data['display_name'] == 'sequence' assert len(response.data['items']) == 1 + + +class ResumeApiTestViews(BaseCoursewareTests, CompletionWaffleTestMixin): + """ + Tests for the resume API + """ + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.url = '/api/courseware/resume/{}'.format(cls.course.id) + + def test_resume_no_completion(self): + response = self.client.get(self.url) + assert response.status_code == 200 + assert response.data['block_id'] is None + assert response.data['unit_id'] is None + assert response.data['section_id'] is None + + def test_resume_with_completion(self): + self.override_waffle_switch(True) + submit_completions_for_testing(self.user, [self.unit.location]) + response = self.client.get(self.url) + assert response.status_code == 200 + assert response.data['block_id'] == str(self.unit.location) + assert response.data['unit_id'] == str(self.unit.location) + assert response.data['section_id'] == str(self.sequence.location) + + +@ddt.ddt +class CelebrationApiTestViews(BaseCoursewareTests): + """ + Tests for the celebration API + """ + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.url = '/api/courseware/celebration/{}'.format(cls.course.id) + + def setUp(self): + super().setUp() + self.enrollment = CourseEnrollment.enroll(self.user, self.course.id, 'verified') + + @ddt.data(True, False) + def test_happy_path(self, update): + if update: + CourseEnrollmentCelebrationFactory(enrollment=self.enrollment, celebrate_first_section=False) + + response = self.client.post(self.url, {'first_section': True}, content_type='application/json') + assert response.status_code == (200 if update else 201) + + celebration = CourseEnrollmentCelebration.objects.first() + assert celebration.celebrate_first_section + assert celebration.enrollment.id == self.enrollment.id + + def test_extra_data(self): + response = self.client.post(self.url, {'extra': True}, content_type='application/json') + assert response.status_code == 400 + + def test_no_data(self): + response = self.client.post(self.url, {}, content_type='application/json') + assert response.status_code == 200 + assert CourseEnrollmentCelebration.objects.count() == 0 + + def test_no_enrollment(self): + self.enrollment.delete() + response = self.client.post(self.url, {'first_section': True}, content_type='application/json') + assert response.status_code == 404 + + def test_no_login(self): + self.client.logout() + response = self.client.post(self.url, {'first_section': True}, content_type='application/json') + assert response.status_code == 401 + + def test_invalid_course(self): + response = self.client.post('/api/courseware/celebration/course-v1:does+not+exist', + {'first_section': True}, content_type='application/json') + assert response.status_code == 404 diff --git a/openedx/core/djangoapps/courseware_api/urls.py b/openedx/core/djangoapps/courseware_api/urls.py index 865955a6f1f72c929a9d94fc0afb07700b1b26a4..6175da19a1e970944684aa8d6e7b38dacbbfb4dd 100644 --- a/openedx/core/djangoapps/courseware_api/urls.py +++ b/openedx/core/djangoapps/courseware_api/urls.py @@ -15,4 +15,10 @@ urlpatterns = [ url(r'^sequence/{}'.format(settings.USAGE_KEY_PATTERN), views.SequenceMetadata.as_view(), name="sequence-api"), + url(r'^resume/{}'.format(settings.COURSE_KEY_PATTERN), + views.Resume.as_view(), + name="resume-api"), + url(r'^celebration/{}'.format(settings.COURSE_KEY_PATTERN), + views.Celebration.as_view(), + name="celebration-api"), ] diff --git a/openedx/core/djangoapps/courseware_api/views.py b/openedx/core/djangoapps/courseware_api/views.py index a75e454588c2d0265292c0dc3279623a2f8ac100..e7c35852a2e6034e1c57542c97cd2cd6a2b1e05d 100644 --- a/openedx/core/djangoapps/courseware_api/views.py +++ b/openedx/core/djangoapps/courseware_api/views.py @@ -4,25 +4,187 @@ Course API Views import json +from babel.numbers import get_currency_symbol +from completion.exceptions import UnavailableCompletionData +from completion.utilities import get_key_to_last_completed_block +from django.urls import reverse +from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication +from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser from opaque_keys.edx.keys import CourseKey, UsageKey from rest_framework.generics import RetrieveAPIView +from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView +from course_modes.models import CourseMode +from edxnotes.helpers import is_feature_enabled from lms.djangoapps.course_api.api import course_detail from lms.djangoapps.courseware.access import has_access from lms.djangoapps.courseware.courses import check_course_access +from lms.djangoapps.courseware.masquerade import is_masquerading +from lms.djangoapps.courseware.masquerade import is_masquerading_as_audit_enrollment +from lms.djangoapps.courseware.masquerade import is_masquerading_as_full_access +from lms.djangoapps.courseware.masquerade import is_masquerading_as_limited_access +from lms.djangoapps.courseware.masquerade import is_masquerading_as_non_audit_enrollment +from lms.djangoapps.courseware.masquerade import is_masquerading_as_staff +from lms.djangoapps.courseware.masquerade import setup_masquerade from lms.djangoapps.courseware.module_render import get_module_by_usage_id -from student.models import CourseEnrollment - +from lms.djangoapps.courseware.tabs import get_course_tab_list +from lms.djangoapps.courseware.utils import can_show_verified_upgrade +from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin from openedx.features.content_type_gating.models import ContentTypeGatingConfig from openedx.features.course_duration_limits.access import generate_course_expired_message -from xmodule.course_module import COURSE_VISIBILITY_PUBLIC +from openedx.features.discounts.utils import generate_offer_html +from student.models import CourseEnrollment, CourseEnrollmentCelebration +from xmodule.modulestore.django import modulestore +from xmodule.modulestore.search import path_to_location from .serializers import CourseInfoSerializer +class CoursewareMeta: + """ + Encapsulates courseware and enrollment metadata. + """ + def __init__(self, course_key, request, username=''): + self.overview = course_detail( + request, + username or request.user.username, + course_key, + ) + self.effective_user = self.overview.effective_user + # We need to memoize `is_staff` _before_ we configure masquerade. + self.is_staff = has_access(self.effective_user, 'staff', self.overview).has_access + self.course_key = course_key + self.enrollment_object = CourseEnrollment.get_enrollment(self.effective_user, self.course_key, + select_related=['celebration']) + course_masquerade, _user = setup_masquerade( + request, + course_key, + staff_access=self.is_staff, + ) + self.course_masquerade = course_masquerade + + def __getattr__(self, name): + return getattr(self.overview, name) + + @property + def enrollment(self): + """ + Return enrollment information. + """ + if self.effective_user.is_anonymous: + mode = None + is_active = False + else: + mode, is_active = CourseEnrollment.enrollment_mode_for_user( + self.effective_user, + self.course_key + ) + return {'mode': mode, 'is_active': is_active} + + @property + def course_expired_message(self): + # TODO: TNL-7185 Legacy: Refactor to return the expiration date and format the message in the MFE + return generate_course_expired_message(self.effective_user, self.overview) + + @property + def offer_html(self): + # TODO: TNL-7185 Legacy: Refactor to return the offer data and format the message in the MFE + return generate_offer_html(self.effective_user, self.overview) + + @property + def content_type_gating_enabled(self): + course_key = self.course_key + user = self.effective_user + is_enabled = None + course_masquerade = self.course_masquerade + if is_masquerading(user, course_key, course_masquerade): + if is_masquerading_as_staff(user, course_key): + is_enabled = False + elif is_masquerading_as_full_access(user, course_key, course_masquerade): + is_enabled = False + elif is_masquerading_as_non_audit_enrollment(user, course_key, course_masquerade): + is_enabled = False + elif is_masquerading_as_audit_enrollment(user, course_key, course_masquerade): + is_enabled = ContentTypeGatingConfig.enabled_for_course(course_key) + elif is_masquerading_as_limited_access(user, course_key, course_masquerade): + is_enabled = ContentTypeGatingConfig.enabled_for_course(course_key) + if is_enabled is None: + is_enabled = ContentTypeGatingConfig.enabled_for_enrollment( + user=user, + course_key=course_key, + ) + return is_enabled + + @property + def can_show_upgrade_sock(self): + can_show = can_show_verified_upgrade(self.effective_user, self.enrollment_object) + return can_show + + @property + def can_load_courseware(self): + return check_course_access( + self.overview, + self.effective_user, + 'load', + check_if_enrolled=True, + check_survey_complete=False, + check_if_authenticated=True, + ).to_json() + + @property + def tabs(self): + """ + Return course tab metadata. + """ + tabs = [] + for priority, tab in enumerate(get_course_tab_list(self.effective_user, self.overview)): + tabs.append({ + 'title': tab.title or tab.get('name', ''), + 'slug': tab.tab_id, + 'priority': priority, + 'type': tab.type, + 'url': tab.link_func(self.overview, reverse), + }) + return tabs + + @property + def verified_mode(self): + """ + Return verified mode information, or None. + """ + mode = CourseMode.verified_mode_for_course(self.course_key) + if mode: + return { + 'price': mode.min_price, + 'currency': mode.currency.upper(), + 'currency_symbol': get_currency_symbol(mode.currency.upper()), + 'sku': mode.sku, + 'upgrade_url': verified_upgrade_deadline_link(self.effective_user, self.overview), + } + + @property + def notes(self): + """ + Return whether edxnotes is enabled and visible. + """ + return { + 'enabled': is_feature_enabled(self.overview, self.effective_user), + 'visible': self.overview.edxnotes_visibility, + } + + @property + def celebrations(self): + """ + Returns a list of celebrations that should be performed. + """ + return { + 'first_section': CourseEnrollmentCelebration.should_celebrate_first_section(self.enrollment_object), + } + + class CoursewareInformation(RetrieveAPIView): """ **Use Cases** @@ -70,6 +232,7 @@ class CoursewareInformation(RetrieveAPIView): requested_fields (optional) comma separated list: If set, then only those fields will be returned. + username (optional) username to masquerade as (if requesting user is staff) **Returns** @@ -81,6 +244,11 @@ class CoursewareInformation(RetrieveAPIView): * 404 if the course is not available or cannot be seen. """ + authentication_classes = ( + JwtAuthentication, + SessionAuthenticationAllowInactiveUser, + ) + serializer_class = CourseInfoSerializer def get_object(self): @@ -88,41 +256,16 @@ class CoursewareInformation(RetrieveAPIView): Return the requested course object, if the user has appropriate permissions. """ - - overview = course_detail( - self.request, - self.request.user.username, + if self.request.user.is_staff: + username = self.request.GET.get('username', '') or self.request.user.username + else: + username = self.request.user.username + overview = CoursewareMeta( CourseKey.from_string(self.kwargs['course_key_string']), + self.request, + username=username, ) - if self.request.user.is_anonymous: - mode = None - is_active = False - else: - mode, is_active = CourseEnrollment.enrollment_mode_for_user( - overview.effective_user, - overview.id - ) - overview.enrollment = {'mode': mode, 'is_active': is_active} - - overview.is_staff = has_access(self.request.user, 'staff', overview).has_access - overview.can_load_courseware = check_course_access( - overview, - self.request.user, - 'load', - check_if_enrolled=True, - check_survey_complete=False, - check_if_authenticated=True, - ).to_json() - - # TODO: TNL-7185 Legacy: Refactor to return the expiration date and format the message in the MFE - overview.course_expired_message = generate_course_expired_message(self.request.user, overview) - - course_key = CourseKey.from_string(self.kwargs['course_key_string']) - overview.content_type_gating_enabled = ContentTypeGatingConfig.enabled_for_enrollment( - user=self.request.user, - course_key=course_key, - ) return overview def get_serializer_context(self): @@ -157,7 +300,13 @@ class SequenceMetadata(DeveloperErrorViewMixin, APIView): another user specifies a username other than their own. * 404 if the course is not available or cannot be seen. """ - def get(self, request, usage_key_string, *args, **kwargs): # pylint: disable=unused-argument + + authentication_classes = ( + JwtAuthentication, + SessionAuthenticationAllowInactiveUser, + ) + + def get(self, request, usage_key_string, *args, **kwargs): """ Return response to a GET request. """ @@ -169,3 +318,117 @@ class SequenceMetadata(DeveloperErrorViewMixin, APIView): str(usage_key), disable_staff_debug_info=True) return Response(json.loads(sequence.handle_ajax('metadata', None))) + + +class Resume(DeveloperErrorViewMixin, APIView): + """ + **Use Cases** + + Request the last completed block in a course + + **Example Requests** + + GET /api/courseware/resume/{course_key} + + **Response Values** + + Body consists of the following fields: + + * block: the last completed block key + * section: the key to the section + * unit: the key to the unit + If no completion data is available, the keys will be null + + **Returns** + + * 200 on success with above fields. + * 400 if an invalid parameter was sent. + * 403 if a user who does not have permission to masquerade as + another user specifies a username other than their own. + * 404 if the course is not available or cannot be seen. + """ + + authentication_classes = ( + JwtAuthentication, + SessionAuthenticationAllowInactiveUser, + ) + permission_classes = (IsAuthenticated, ) + + def get(self, request, course_key_string, *args, **kwargs): + """ + Return response to a GET request. + """ + course_id = CourseKey.from_string(course_key_string) + resp = { + 'block_id': None, + 'section_id': None, + 'unit_id': None, + } + + try: + block_key = get_key_to_last_completed_block(request.user, course_id) + path = path_to_location(modulestore(), block_key, request, full_path=True) + resp['section_id'] = str(path[2]) + resp['unit_id'] = str(path[3]) + resp['block_id'] = str(block_key) + + except UnavailableCompletionData: + pass + + return Response(resp) + + +class Celebration(DeveloperErrorViewMixin, APIView): + """ + **Use Cases** + + Marks a particular celebration as complete + + **Example Requests** + + POST /api/courseware/celebration/{course_key} + + **Request Parameters** + + Body consists of the following fields: + + * first_section (bool): whether we should celebrate when a user finishes their first section of a course + + **Returns** + + * 200 or 201 on success with above fields. + * 400 if an invalid parameter was sent. + * 404 if the course is not available or cannot be seen. + """ + + authentication_classes = ( + JwtAuthentication, + SessionAuthenticationAllowInactiveUser, + ) + permission_classes = (IsAuthenticated, ) + http_method_names = ['post'] + + def post(self, request, course_key_string, *args, **kwargs): + """ + Handle a POST request. + """ + course_key = CourseKey.from_string(course_key_string) + + data = dict(request.data) + first_section = data.pop('first_section', None) + if data: + return Response(status=400) # there were parameters we didn't recognize + + enrollment = CourseEnrollment.get_enrollment(request.user, course_key) + if not enrollment: + return Response(status=404) + + defaults = {} + if first_section is not None: + defaults['celebrate_first_section'] = first_section + + if defaults: + _, created = CourseEnrollmentCelebration.objects.update_or_create(enrollment=enrollment, defaults=defaults) + return Response(status=201 if created else 200) + else: + return Response(status=200) # just silently allow it diff --git a/openedx/core/djangoapps/credentials/management/commands/notify_credentials.py b/openedx/core/djangoapps/credentials/management/commands/notify_credentials.py index cd0bd9e9d3bb45e7e201b62bdae410a116d65746..ea8f90c8d1e021405a4b200cd515f226308e1bb3 100644 --- a/openedx/core/djangoapps/credentials/management/commands/notify_credentials.py +++ b/openedx/core/djangoapps/credentials/management/commands/notify_credentials.py @@ -212,6 +212,7 @@ class Command(BaseCommand): def send_notifications(self, certs, grades, site_config=None, delay=0, page_size=0, verbose=False): """ Run actual handler commands for the provided certs and grades. """ + course_cert_info = {} # First, do certs for i, cert in paged_query(certs, delay, page_size): if site_config and not site_config.has_org(cert.course_id.org): @@ -231,8 +232,14 @@ class Command(BaseCommand): 'status': cert.status, 'verbose': verbose, } + + data = { + 'mode': cert.mode, + 'status': cert.status + } + + course_cert_info[(cert.user.id, str(cert.course_id))] = data handle_course_cert_changed(**signal_args) - handle_cert_change(**signal_args) # Then do grades for i, grade in paged_query(grades, delay, page_size): @@ -246,11 +253,18 @@ class Command(BaseCommand): ) user = User.objects.get(id=grade.user_id) + + # Grab mode/status from cert call + key = (user.id, str(grade.course_id)) + cert_info = course_cert_info.get(key, {}) + mode = cert_info.get('mode', None) + status = cert_info.get('status', None) + send_grade_if_interesting( user, grade.course_id, - None, - None, + mode, + status, grade.letter_grade, grade.percent_grade, verbose=verbose diff --git a/openedx/core/djangoapps/credentials/management/commands/tests/test_notify_credentials.py b/openedx/core/djangoapps/credentials/management/commands/tests/test_notify_credentials.py index 63ed6e7101225a3913d8272f270663a3ba8fa5bc..a4d309561aece2a3f99459d3b4c226fea8305a5b 100644 --- a/openedx/core/djangoapps/credentials/management/commands/tests/test_notify_credentials.py +++ b/openedx/core/djangoapps/credentials/management/commands/tests/test_notify_credentials.py @@ -120,12 +120,10 @@ class TestNotifyCredentials(TestCase): call_command(Command(), '--dry-run', '--start-date', '2017-02-01') self.assertFalse(mock_send.called) - @mock.patch(COMMAND_MODULE + '.handle_cert_change') @mock.patch(COMMAND_MODULE + '.send_grade_if_interesting') @mock.patch(COMMAND_MODULE + '.handle_course_cert_changed') - def test_hand_off(self, mock_grade_cert_change, mock_grade_interesting, mock_program_changed): + def test_hand_off(self, mock_grade_interesting, mock_program_changed): call_command(Command(), '--start-date', '2017-02-01') - self.assertEqual(mock_grade_cert_change.call_count, 2) self.assertEqual(mock_grade_interesting.call_count, 2) self.assertEqual(mock_program_changed.call_count, 2) @@ -154,15 +152,13 @@ class TestNotifyCredentials(TestCase): self.assertEqual(len(connection.queries), baseline + 2) # one extra page query each for certs & grades @mock.patch(COMMAND_MODULE + '.send_grade_if_interesting') - @mock.patch(COMMAND_MODULE + '.handle_cert_change') - def test_site(self, mock_grade_interesting, mock_cert_change): + def test_site(self, mock_grade_interesting): site_config = SiteConfigurationFactory.create( site_values={'course_org_filter': ['testX']} ) call_command(Command(), '--site', site_config.site.domain, '--start-date', '2017-01-01') self.assertEqual(mock_grade_interesting.call_count, 1) - self.assertEqual(mock_cert_change.call_count, 1) @mock.patch(COMMAND_MODULE + '.Command.send_notifications') def test_args_from_database(self, mock_send): diff --git a/openedx/core/djangoapps/credit/email_utils.py b/openedx/core/djangoapps/credit/email_utils.py index c113ccbe31195944913f2e0ce440dc90ebaf6681..9433021ee8f9c814370a188de59431f8c0a6768a 100644 --- a/openedx/core/djangoapps/credit/email_utils.py +++ b/openedx/core/djangoapps/credit/email_utils.py @@ -6,6 +6,7 @@ This file contains utility functions which will responsible for sending emails. import logging import os import uuid +import html from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart @@ -106,8 +107,7 @@ def send_credit_notifications(username, course_key): cur_text = cur_file.read() # use html parser to unescape html characters which are changed # by the 'pynliner' while adding inline css to html content - html_parser = six.moves.html_parser.HTMLParser() - email_body_content = html_parser.unescape(with_inline_css(cur_text)) + email_body_content = html.unescape(with_inline_css(cur_text)) # cache the email body content before rendering it since the # email context will change for each user e.g., 'full_name' cache.set('credit.email.css-email-body', email_body_content, settings.CREDIT_NOTIFICATION_CACHE_TIMEOUT) diff --git a/openedx/core/djangoapps/django_comment_common/comment_client/settings.py b/openedx/core/djangoapps/django_comment_common/comment_client/settings.py index 4772e38c0da137953a0622ae810575540666814b..f64726335f6e44cc2a50264597b60743f0426e07 100644 --- a/openedx/core/djangoapps/django_comment_common/comment_client/settings.py +++ b/openedx/core/djangoapps/django_comment_common/comment_client/settings.py @@ -1,6 +1,3 @@ -# pylint: disable=missing-docstring - - from django.conf import settings if hasattr(settings, "COMMENTS_SERVICE_URL"): diff --git a/openedx/core/djangoapps/django_comment_common/migrations/0008_role_user_index.py b/openedx/core/djangoapps/django_comment_common/migrations/0008_role_user_index.py index eb224ab01db18a1b881a33d280034e5eaf7c882a..d1a766acc6c9bb5a39e51ca38b926526474a0bae 100644 --- a/openedx/core/djangoapps/django_comment_common/migrations/0008_role_user_index.py +++ b/openedx/core/djangoapps/django_comment_common/migrations/0008_role_user_index.py @@ -13,6 +13,5 @@ class Migration(migrations.Migration): operations = [ migrations.RunSQL( 'CREATE INDEX dcc_role_users_user_role_idx ON django_comment_client_role_users(user_id, role_id);', - reverse_sql=migrations.RunSQL.noop, - ), + reverse_sql='DROP INDEX dcc_role_users_user_role_idx ON django_comment_client_role_users;'), ] diff --git a/openedx/core/djangoapps/enrollments/api.py b/openedx/core/djangoapps/enrollments/api.py index 172803b465e3f3e8258661802560278ed068db0e..7e1b4d638f8cef6e199e84d69e809b53a08a8efe 100644 --- a/openedx/core/djangoapps/enrollments/api.py +++ b/openedx/core/djangoapps/enrollments/api.py @@ -266,7 +266,7 @@ def update_enrollment( enrollment = _data_api().update_course_enrollment(username, course_id, mode=mode, is_active=is_active) if enrollment is None: msg = u"Course Enrollment not found for user {user} in course {course}".format(user=username, course=course_id) - log.warn(msg) + log.warning(msg) raise errors.EnrollmentNotFoundError(msg) else: if enrollment_attributes is not None: @@ -455,7 +455,7 @@ def validate_course_mode(course_id, mode, is_active=None, include_expired=False) course_id=course_id, available=", ".join(available_modes) ) - log.warn(msg) + log.warning(msg) raise errors.CourseModeNotFoundError(msg, course_enrollment_info) diff --git a/openedx/core/djangoapps/enrollments/data.py b/openedx/core/djangoapps/enrollments/data.py index 029683918a193748889f00028b6d66b8869372c7..00fa315bf2412ea31f2f6770a7f6dc41b2255c0b 100644 --- a/openedx/core/djangoapps/enrollments/data.py +++ b/openedx/core/djangoapps/enrollments/data.py @@ -143,7 +143,7 @@ def create_course_enrollment(username, course_id, mode, is_active): user = User.objects.get(username=username) except User.DoesNotExist: msg = u"Not user with username '{username}' found.".format(username=username) - log.warn(msg) + log.warning(msg) raise UserNotFoundError(msg) try: @@ -181,7 +181,7 @@ def update_course_enrollment(username, course_id, mode=None, is_active=None): user = User.objects.get(username=username) except User.DoesNotExist: msg = u"Not user with username '{username}' found.".format(username=username) - log.warn(msg) + log.warning(msg) raise UserNotFoundError(msg) try: @@ -272,7 +272,7 @@ def _get_user(username): return User.objects.get(username=username) except User.DoesNotExist: msg = u"Not user with username '{username}' found.".format(username=username) - log.warn(msg) + log.warning(msg) raise UserNotFoundError(msg) @@ -295,17 +295,17 @@ def _invalid_attribute(attributes): for attribute in attributes: if "namespace" not in attribute: msg = u"'namespace' not in enrollment attribute" - log.warn(msg) + log.warning(msg) invalid_attributes.append("namespace") raise InvalidEnrollmentAttribute(msg) if "name" not in attribute: msg = u"'name' not in enrollment attribute" - log.warn(msg) + log.warning(msg) invalid_attributes.append("name") raise InvalidEnrollmentAttribute(msg) if "value" not in attribute: msg = u"'value' not in enrollment attribute" - log.warn(msg) + log.warning(msg) invalid_attributes.append("value") raise InvalidEnrollmentAttribute(msg) diff --git a/openedx/core/djangoapps/external_user_ids/apps.py b/openedx/core/djangoapps/external_user_ids/apps.py index cc29082b06e5ad97c8e287e3be071ffbf01738c3..abf154abc3fbd8e3fefd9d4c94d9e2f2dafe357a 100644 --- a/openedx/core/djangoapps/external_user_ids/apps.py +++ b/openedx/core/djangoapps/external_user_ids/apps.py @@ -13,4 +13,4 @@ class ExternalUserIDConfig(AppConfig): name = 'openedx.core.djangoapps.external_user_ids' def ready(self): - from . import signals # pylint: disable=unused-variable + from . import signals # pylint: disable=unused-import diff --git a/openedx/core/djangoapps/external_user_ids/migrations/0004_add_lti_type.py b/openedx/core/djangoapps/external_user_ids/migrations/0004_add_lti_type.py new file mode 100644 index 0000000000000000000000000000000000000000..ab8fc16751ed35f0924972cada1efff678b3046e --- /dev/null +++ b/openedx/core/djangoapps/external_user_ids/migrations/0004_add_lti_type.py @@ -0,0 +1,32 @@ +# Generated by Django 2.2.12 on 2020-04-28 15:47 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('external_user_ids', '0003_auto_20200224_1836'), + ] + + lti_type = 'lti' + + def create_lti_type(apps, schema_editor): + """ + Add a LTI type + """ + ExternalIdType = apps.get_model('external_user_ids', 'ExternalIdType') + ExternalIdType.objects.update_or_create(name=Migration.lti_type, description='LTI Xblock launches') + + def delete_lti_type(apps, schema_editor): + """ + Delete the LTI type + """ + ExternalIdType = apps.get_model('external_user_ids', 'ExternalIdType') + ExternalIdType.objects.filter( + name=Migration.lti_type + ).delete() + + operations = [ + migrations.RunPython(create_lti_type, reverse_code=delete_lti_type), + ] diff --git a/openedx/core/djangoapps/external_user_ids/models.py b/openedx/core/djangoapps/external_user_ids/models.py index 708385394d865c6739b6c16e126849945375be1c..043834930b36f8f7063abb0ee8f6e29c9c5e9719 100644 --- a/openedx/core/djangoapps/external_user_ids/models.py +++ b/openedx/core/djangoapps/external_user_ids/models.py @@ -3,7 +3,6 @@ Models for External User Ids that are sent out of Open edX """ import uuid as uuid_tools - from logging import getLogger from django.contrib.auth.models import User @@ -22,11 +21,15 @@ class ExternalIdType(TimeStampedModel): .. no_pii: """ MICROBACHELORS_COACHING = 'mb_coaching' + LTI = 'lti' name = models.CharField(max_length=32, blank=False, unique=True, db_index=True) description = models.TextField() history = HistoricalRecords() + class Meta: + app_label = 'external_user_ids' + def __str__(self): return self.name @@ -48,6 +51,7 @@ class ExternalId(TimeStampedModel): class Meta(object): unique_together = (('user', 'external_id_type'),) + app_label = 'external_user_ids' @classmethod def user_has_external_id(cls, user, type_name): @@ -86,7 +90,7 @@ class ExternalId(TimeStampedModel): type=type_name ) ) - return None + return None, False external_id, created = cls.objects.get_or_create( user=user, external_id_type=type_obj diff --git a/openedx/core/djangoapps/external_user_ids/signals.py b/openedx/core/djangoapps/external_user_ids/signals.py index 45f7f711dccaf9fd5150941135b1de2d6b74a7bf..166303d12becbe964445f7882fc0299636a3f3d9 100644 --- a/openedx/core/djangoapps/external_user_ids/signals.py +++ b/openedx/core/djangoapps/external_user_ids/signals.py @@ -8,6 +8,7 @@ from django.db.models.signals import post_save from django.dispatch import receiver from openedx.core.djangoapps.catalog.utils import get_programs + from .models import ExternalId, ExternalIdType LOGGER = getLogger(__name__) diff --git a/openedx/core/djangoapps/external_user_ids/tests/test_admin_generate_id.py b/openedx/core/djangoapps/external_user_ids/tests/test_admin_generate_id.py index fd48a8292b640bb26d873eeb611db2ba2e08ff2b..f0d8878e8dfa7bbc5e39a14b3e2a76e36b55e001 100644 --- a/openedx/core/djangoapps/external_user_ids/tests/test_admin_generate_id.py +++ b/openedx/core/djangoapps/external_user_ids/tests/test_admin_generate_id.py @@ -2,23 +2,17 @@ # Test the logic behind the Generate External IDs tools in Admin # """ import mock -from django.conf import settings from django.contrib.admin.sites import AdminSite from django.test import TestCase from student.tests.factories import UserFactory -from openedx.core.djangolib.testing.utils import skip_unless_lms +from openedx.core.djangoapps.external_user_ids.models import ( + ExternalId, +) +from openedx.core.djangoapps.external_user_ids.tests.factories import ExternalIDTypeFactory +from openedx.core.djangoapps.external_user_ids.admin import ExternalIdAdmin -# external_ids is not in CMS' INSTALLED_APPS so these imports will error during test collection -if settings.ROOT_URLCONF == 'lms.urls': - from openedx.core.djangoapps.external_user_ids.models import ( - ExternalId, - ) - from openedx.core.djangoapps.external_user_ids.tests.factories import ExternalIDTypeFactory - from openedx.core.djangoapps.external_user_ids.admin import ExternalIdAdmin - -@skip_unless_lms class TestGenerateExternalIds(TestCase): """ Test generating ExternalIDs for Users. diff --git a/openedx/core/djangoapps/external_user_ids/tests/test_signals.py b/openedx/core/djangoapps/external_user_ids/tests/test_signals.py index 74c1e6a6cd78d7551787316a5a866512bc00ceff..33ab1a9bc1df17fdf408d62ede7992713d107aa6 100644 --- a/openedx/core/djangoapps/external_user_ids/tests/test_signals.py +++ b/openedx/core/djangoapps/external_user_ids/tests/test_signals.py @@ -3,7 +3,6 @@ Signal Tests for External User Ids that are sent out of Open edX """ from opaque_keys.edx.keys import CourseKey -from django.conf import settings from django.core.cache import cache from edx_django_utils.cache import RequestCache @@ -18,19 +17,14 @@ from openedx.core.djangoapps.catalog.cache import ( COURSE_PROGRAMS_CACHE_KEY_TPL, PROGRAM_CACHE_KEY_TPL, ) +from openedx.core.djangoapps.external_user_ids.models import ExternalId, ExternalIdType from student.models import CourseEnrollment from course_modes.models import CourseMode -from openedx.core.djangolib.testing.utils import skip_unless_lms from openedx.core.djangolib.testing.utils import CacheIsolationTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -# external_ids is not in CMS' INSTALLED_APPS so these imports will error during test collection -if settings.ROOT_URLCONF == 'lms.urls': - from openedx.core.djangoapps.external_user_ids.models import ExternalId, ExternalIdType - -@skip_unless_lms class MicrobachelorsExternalIDTest(ModuleStoreTestCase, CacheIsolationTestCase): """ Test cases for Signals for External User Ids diff --git a/openedx/core/djangoapps/lang_pref/middleware.py b/openedx/core/djangoapps/lang_pref/middleware.py index c3c5fc1b173b828d490b14746833eae99b08d8e1..cef57cfc5643ce923cb34e3619efe03bd3c2404e 100644 --- a/openedx/core/djangoapps/lang_pref/middleware.py +++ b/openedx/core/djangoapps/lang_pref/middleware.py @@ -77,6 +77,7 @@ class LanguagePreferenceMiddleware(MiddlewareMixin): value=user_pref, domain=settings.SESSION_COOKIE_DOMAIN, max_age=COOKIE_DURATION, + secure=request.is_secure() ) else: response.delete_cookie( diff --git a/openedx/core/djangoapps/lang_pref/tests/test_middleware.py b/openedx/core/djangoapps/lang_pref/tests/test_middleware.py index dc78d5445aca4224f136314d6a557d0bea54aa13..0c699836dbf2f1b134ec5e38c9b0208e7af5f38a 100644 --- a/openedx/core/djangoapps/lang_pref/tests/test_middleware.py +++ b/openedx/core/djangoapps/lang_pref/tests/test_middleware.py @@ -75,6 +75,7 @@ class TestUserPreferenceMiddleware(CacheIsolationTestCase): value=lang_pref_out, domain=settings.SESSION_COOKIE_DOMAIN, max_age=COOKIE_DURATION, + secure=self.request.is_secure(), ) else: response.delete_cookie.assert_called_with( diff --git a/openedx/core/djangoapps/lang_pref/views.py b/openedx/core/djangoapps/lang_pref/views.py index bc85afe334c4146903485c78acb5d40533cbea1d..07077920d02a40241a02748023380e35611ac19c 100644 --- a/openedx/core/djangoapps/lang_pref/views.py +++ b/openedx/core/djangoapps/lang_pref/views.py @@ -31,6 +31,7 @@ def update_session_language(request): settings.LANGUAGE_COOKIE, language, domain=settings.SESSION_COOKIE_DOMAIN, - max_age=COOKIE_DURATION + max_age=COOKIE_DURATION, + secure=request.is_secure(), ) return response diff --git a/openedx/core/djangoapps/models/config/__init__.py b/openedx/core/djangoapps/models/config/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/core/djangoapps/models/config/waffle.py b/openedx/core/djangoapps/models/config/waffle.py new file mode 100644 index 0000000000000000000000000000000000000000..7db160b43bb10b1d3f94470c5b824b31689d8242 --- /dev/null +++ b/openedx/core/djangoapps/models/config/waffle.py @@ -0,0 +1,39 @@ +""" +This module contains various configuration settings via +waffle switches for the course_details view. +""" + + +from openedx.core.djangoapps.waffle_utils import ( + CourseWaffleFlag, + WaffleFlagNamespace, + WaffleSwitchNamespace +) + +COURSE_DETAIL_WAFFLE_NAMESPACE = 'course_detail' +COURSE_DETAIL_WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name=COURSE_DETAIL_WAFFLE_NAMESPACE) +WAFFLE_SWITCHES = WaffleSwitchNamespace(name=COURSE_DETAIL_WAFFLE_NAMESPACE) + +# Course Override Flag +COURSE_DETAIL_UPDATE_CERTIFICATE_DATE = u'course_detail_update_certificate_date' + + +def waffle_flags(): + """ + Returns the namespaced, cached, audited Waffle flags dictionary for course detail. + """ + return { + COURSE_DETAIL_UPDATE_CERTIFICATE_DATE: CourseWaffleFlag( + waffle_namespace=COURSE_DETAIL_WAFFLE_NAMESPACE, + flag_name=COURSE_DETAIL_UPDATE_CERTIFICATE_DATE, + flag_undefined_default=False, + ) + } + + +def enable_course_detail_update_certificate_date(course_id): + """ + Returns True if course_detail_update_certificate_date course override flag is enabled, + otherwise False. + """ + return waffle_flags()[COURSE_DETAIL_UPDATE_CERTIFICATE_DATE].is_enabled(course_id) diff --git a/openedx/core/djangoapps/models/course_details.py b/openedx/core/djangoapps/models/course_details.py index e3624f55cb04d402a3e387924c1990d5e76898a0..bdd8e207fbb14026b1b881c65e56266beaf082a1 100644 --- a/openedx/core/djangoapps/models/course_details.py +++ b/openedx/core/djangoapps/models/course_details.py @@ -6,8 +6,11 @@ CourseDetails import logging import re +import six from django.conf import settings +from openedx.core.djangoapps.models.config.waffle import enable_course_detail_update_certificate_date +from openedx.core.djangoapps.signals.signals import COURSE_CERT_DATE_CHANGE from openedx.core.djangolib.markup import HTML from openedx.core.lib.courses import course_image_url from xmodule.fields import Date @@ -243,6 +246,8 @@ class CourseDetails(object): if converted != descriptor.certificate_available_date: dirty = True descriptor.certificate_available_date = converted + if enable_course_detail_update_certificate_date(course_key): + COURSE_CERT_DATE_CHANGE.send_robust(sender=cls, course_key=six.text_type(course_key)) if 'course_image_name' in jsondict and jsondict['course_image_name'] != descriptor.course_image: descriptor.course_image = jsondict['course_image_name'] diff --git a/openedx/core/djangoapps/plugin_api/views.py b/openedx/core/djangoapps/plugin_api/views.py index 3ccd39f282d91ec5dcbd224cae0268dd060bcc72..d4ad82e2c16c6b62587b2176290191509d0ce81e 100644 --- a/openedx/core/djangoapps/plugin_api/views.py +++ b/openedx/core/djangoapps/plugin_api/views.py @@ -8,7 +8,7 @@ import logging from django.conf import settings from django.contrib.staticfiles.storage import staticfiles_storage from django.http import HttpResponse -from django.shortcuts import render_to_response +from django.shortcuts import render from web_fragments.views import FragmentView from edxmako.shortcuts import is_any_marketing_link_set, is_marketing_link_set, marketing_link @@ -21,6 +21,7 @@ class EdxFragmentView(FragmentView): The base class of all Open edX fragment views. """ page_title = None + _uses_pattern_library = True @staticmethod def get_css_dependencies(group): @@ -84,7 +85,8 @@ class EdxFragmentView(FragmentView): Creates the base context for rendering a fragment as a standalone page. """ return { - 'uses_pattern_library': True, + 'uses_pattern_library': self.uses_pattern_library, + 'uses_bootstrap': not self.uses_pattern_library, 'disable_accordion': True, 'allow_iframing': True, 'disable_header': True, @@ -139,4 +141,15 @@ class EdxFragmentView(FragmentView): else: template = 'fragments/standalone-page-v1.html' - return render_to_response(template, context) + return render( + request=request, + template_name=template, + context=context + ) + + @property + def uses_pattern_library(self): + """ + Returns true if this fragment is rendered with edx-pattern-library. + """ + return self._uses_pattern_library diff --git a/openedx/core/djangoapps/programs/docs/decisions/0001-sync-certificate-available-dates.rst b/openedx/core/djangoapps/programs/docs/decisions/0001-sync-certificate-available-dates.rst new file mode 100644 index 0000000000000000000000000000000000000000..dfe9fcb49264892d9fa5c5cb9f97d95e916a5224 --- /dev/null +++ b/openedx/core/djangoapps/programs/docs/decisions/0001-sync-certificate-available-dates.rst @@ -0,0 +1,46 @@ +Sync certificate_available_date and visible_date for certificates +================================================================= + +Status +------ + +Review + +Context +------- + +In the Credentials service, certificate_available_date is called visible_date. +Whenever a generatedCertificate is updated or saved the first time, it sets +the visible date to certificate available date (available in studio settings). + +There is a limitation in our code, if course team decides to change the +certificate_available_date it is not reflected in the credentials service +for all the certificates that were awarded before that change and have been +pushed to credentials service. The certificates' dates need to be in sync on +both places. + +This has caused problems when a learner is able to see the certificate on +their dashboard but the change is not reflected on their learner record in +credential service. + +Decision +-------- + +Whenever a CourseUpdate is made with change to the certificate_available_date, +the system updates the certificate visible_date on the credential service. + +To achieve this, a signal is created to listen to any course update signal that +contains change in certificate_available_date and start a task to compute all +certificates that have been issued. + +We will then reuse the award_course_certificate task for every certificate user +and get their visible_date updated on credential service to keep dates in sync +on both ends. + + +Consequences +------------ + +The system will have to process each issued user certificate and update the +visible_date for all of them individually as visible_date is an attribute for +every UserCredential object on credential service. diff --git a/openedx/core/djangoapps/programs/signals.py b/openedx/core/djangoapps/programs/signals.py index aea84fec2973e88b1164702052e5bbe434f3387e..27f53b085b89379f66f098209fd2cb624273e991 100644 --- a/openedx/core/djangoapps/programs/signals.py +++ b/openedx/core/djangoapps/programs/signals.py @@ -6,8 +6,12 @@ This module contains signals / handlers related to programs. import logging from django.dispatch import receiver - -from openedx.core.djangoapps.signals.signals import COURSE_CERT_AWARDED, COURSE_CERT_CHANGED +from openedx.core.djangoapps.signals.signals import ( + COURSE_CERT_AWARDED, + COURSE_CERT_CHANGED, + COURSE_CERT_DATE_CHANGE, + COURSE_CERT_REVOKED +) from openedx.core.djangoapps.site_configuration import helpers LOGGER = logging.getLogger(__name__) @@ -131,3 +135,79 @@ def handle_course_cert_changed(sender, user, course_key, mode, status, **kwargs) # import here, because signal is registered at startup, but items in tasks are not yet able to be loaded from openedx.core.djangoapps.programs.tasks.v1.tasks import award_course_certificate award_course_certificate.delay(user.username, str(course_key)) + + +@receiver(COURSE_CERT_REVOKED) +def handle_course_cert_revoked(sender, user, course_key, mode, status, **kwargs): # pylint: disable=unused-argument + """ + If programs is enabled and a learner's course certificate is revoked, + schedule a celery task to revoke any related program certificates. + + Args: + sender: + class of the object instance that sent this signal + user: + django.contrib.auth.User - the user for which a cert was revoked + course_key: + refers to the course run for which the cert was revoked + mode: + mode / certificate type, e.g. "verified" + status: + revoked + + Returns: + None + + """ + # Import here instead of top of file since this module gets imported before + # the credentials app is loaded, resulting in a Django deprecation warning. + from openedx.core.djangoapps.credentials.models import CredentialsApiConfig + + # Avoid scheduling new tasks if certification is disabled. + if not CredentialsApiConfig.current().is_learner_issuance_enabled: + return + + # schedule background task to process + LOGGER.info( + u'handling COURSE_CERT_REVOKED: username=%s, course_key=%s, mode=%s, status=%s', + user, + course_key, + mode, + status, + ) + # import here, because signal is registered at startup, but items in tasks are not yet able to be loaded + from openedx.core.djangoapps.programs.tasks.v1.tasks import revoke_program_certificates + revoke_program_certificates.delay(user.username, course_key) + + +@receiver(COURSE_CERT_DATE_CHANGE, dispatch_uid='course_certificate_date_change_handler') +def handle_course_cert_date_change(sender, course_key, **kwargs): + """ + If course is updated and the certificate_available_date is changed, + schedule a celery task to update visible_date for all certificates + within course. + + Args: + course_key: + refers to the course whose certificate_available_date was updated. + + Returns: + None + + """ + # Import here instead of top of file since this module gets imported before + # the credentials app is loaded, resulting in a Django deprecation warning. + from openedx.core.djangoapps.credentials.models import CredentialsApiConfig + + # Avoid scheduling new tasks if certification is disabled. + if not CredentialsApiConfig.current().is_learner_issuance_enabled: + return + + # schedule background task to process + LOGGER.info( + 'handling COURSE_CERT_DATE_CHANGE for course %s', + course_key, + ) + # import here, because signal is registered at startup, but items in tasks are not yet loaded + from openedx.core.djangoapps.programs.tasks.v1.tasks import update_certificate_visible_date_on_course_update + update_certificate_visible_date_on_course_update.delay(course_key) diff --git a/openedx/core/djangoapps/programs/tasks/v1/tasks.py b/openedx/core/djangoapps/programs/tasks/v1/tasks.py index 6b12824d9ffd13592c443a824a0bc801c167a4f2..913c5d41a89bba6beaecc3c6a94a7d140fd95cd2 100644 --- a/openedx/core/djangoapps/programs/tasks/v1/tasks.py +++ b/openedx/core/djangoapps/programs/tasks/v1/tasks.py @@ -52,6 +52,25 @@ def get_completed_programs(site, student): return meter.completed_programs_with_available_dates +def get_inverted_programs(student): + """ + Get programs keyed by course run ID. + + Args: + student (User): Representing the student whose programs to check for. + + Returns: + dict, programs keyed by course run ID + + """ + inverted_programs = {} + for site in Site.objects.all(): + meter = ProgramProgressMeter(site, student) + inverted_programs.update(meter.invert_programs()) + + return inverted_programs + + def get_certified_programs(student): """ Find the UUIDs of all the programs for which the student has already been awarded @@ -331,3 +350,211 @@ def award_course_certificate(self, username, course_run_key): except Exception as exc: LOGGER.exception(u'Failed to determine course certificates to be awarded for user %s', username) raise self.retry(exc=exc, countdown=countdown, max_retries=MAX_RETRIES) + + +def get_revokable_program_uuids(course_specific_programs, student): + """ + Get program uuids for which certificate to be revoked. + + Checks for existing learner certificates and filter out the program UUIDS + for which a certificate needs to be revoked. + + Args: + course_specific_programs (dict[]): list of programs specific to a course + student (User): Representing the student whose programs to check for. + + Returns: + list if program UUIDs for which certificates to be revoked + + """ + program_uuids_to_revoke = [] + existing_program_uuids = get_certified_programs(student) + for program in course_specific_programs: + if program['uuid'] in existing_program_uuids: + program_uuids_to_revoke.append(program['uuid']) + + return program_uuids_to_revoke + + +def revoke_program_certificate(client, username, program_uuid): + """ + Revoke a certificate of the given student for the given program. + + Args: + client: credentials API client (EdxRestApiClient) + username: The username of the student + program_uuid: uuid of the program + + Returns: + None + + """ + client.credentials.post({ + 'username': username, + 'status': 'revoked', + 'credential': { + 'type': PROGRAM_CERTIFICATE, + 'program_uuid': program_uuid + } + }) + + +@task(bind=True, ignore_result=True, routing_key=PROGRAM_CERTIFICATES_ROUTING_KEY) +def revoke_program_certificates(self, username, course_key): + """ + This task is designed to be called whenever a student's course certificate is + revoked. + + It will consult with a variety of APIs to determine whether or not the + specified user's certificate should be revoked in one or more programs, and + use the credentials service to revoke the said certificates if so. + + Args: + username (str): The username of the student + course_key (str|CourseKey): The course identifier + + Returns: + None + + """ + countdown = 2 ** self.request.retries + # If the credentials config model is disabled for this + # feature, it may indicate a condition where processing of such tasks + # has been temporarily disabled. Since this is a recoverable situation, + # mark this task for retry instead of failing it altogether. + + if not CredentialsApiConfig.current().is_learner_issuance_enabled: + LOGGER.warning( + 'Task revoke_program_certificates cannot be executed when credentials issuance is disabled in API config', + ) + raise self.retry(countdown=countdown, max_retries=MAX_RETRIES) + + try: + student = User.objects.get(username=username) + except User.DoesNotExist: + LOGGER.exception(u'Task revoke_program_certificates was called with invalid username %s', username) + # Don't retry for this case - just conclude the task. + return + + try: + inverted_programs = get_inverted_programs(student) + course_specific_programs = inverted_programs.get(str(course_key)) + if not course_specific_programs: + # No reason to continue beyond this point + LOGGER.info( + u'Task revoke_program_certificates was called for user %s and course %s with no engaged programs', + username, + course_key + ) + return + + # Determine which program certificates the user has already been awarded, if any. + program_uuids_to_revoke = get_revokable_program_uuids(course_specific_programs, student) + except Exception as exc: + LOGGER.exception( + u'Failed to determine program certificates to be revoked for user %s with course %s', + username, + course_key + ) + raise self.retry(exc=exc, countdown=countdown, max_retries=MAX_RETRIES) + + if program_uuids_to_revoke: + try: + credentials_client = get_credentials_api_client( + User.objects.get(username=settings.CREDENTIALS_SERVICE_USERNAME), + ) + except Exception as exc: + LOGGER.exception('Failed to create a credentials API client to revoke program certificates') + # Retry because a misconfiguration could be fixed + raise self.retry(exc=exc, countdown=countdown, max_retries=MAX_RETRIES) + + failed_program_certificate_revoke_attempts = [] + for program_uuid in program_uuids_to_revoke: + try: + revoke_program_certificate(credentials_client, username, program_uuid) + LOGGER.info(u'Revoked certificate for program %s for user %s', program_uuid, username) + except exceptions.HttpNotFoundError: + LOGGER.exception( + u"""Certificate for program {uuid} could not be found. Unable to revoke certificate for user + {username}.""".format(uuid=program_uuid, username=username) + ) + except exceptions.HttpClientError as exc: + # Grab the status code from the client error, because our API + # client handles all 4XX errors the same way. In the future, + # we may want to fork slumber, add 429 handling, and use that + # in edx_rest_api_client. + if exc.response.status_code == 429: # pylint: disable=no-member, no-else-raise + rate_limit_countdown = 60 + LOGGER.info( + u"""Rate limited. Retrying task to revoke certificates for user {username} in {countdown} + seconds""".format(username=username, countdown=rate_limit_countdown) + ) + # Retry after 60 seconds, when we should be in a new throttling window + raise self.retry(exc=exc, countdown=rate_limit_countdown, max_retries=MAX_RETRIES) + else: + LOGGER.exception( + u"Unable to revoke certificate for user {username} for program {uuid}.".format( + username=username, uuid=program_uuid + ) + ) + except Exception: # pylint: disable=broad-except + # keep trying to revoke other certs, but retry the whole task to fix any missing entries + LOGGER.warning(u'Failed to revoke certificate for program {uuid} of user {username}.'.format( + uuid=program_uuid, username=username)) + failed_program_certificate_revoke_attempts.append(program_uuid) + + if failed_program_certificate_revoke_attempts: + # N.B. This logic assumes that this task is idempotent + LOGGER.info(u'Retrying task to revoke failed certificates to user %s', username) + # The error message may change on each reattempt but will never be raised until + # the max number of retries have been exceeded. It is unlikely that this list + # will change by the time it reaches its maximimum number of attempts. + exception = MaxRetriesExceededError( + u"Failed to revoke certificate for user {} for programs {}".format( + username, failed_program_certificate_revoke_attempts)) + raise self.retry( + exc=exception, + countdown=countdown, + max_retries=MAX_RETRIES) + else: + LOGGER.info(u'There is no program certificates for user %s to revoke', username) + + LOGGER.info(u'Successfully completed the task revoke_program_certificates for username %s', username) + + +@task(bind=True, ignore_result=True, routing_key=PROGRAM_CERTIFICATES_ROUTING_KEY) +def update_certificate_visible_date_on_course_update(self, course_key): + """ + This task is designed to be called whenever a course is updated with + certificate_available_date so that visible_date is updated on credential + service as well. + + It will get all users within the course that have a certificate and call + the credentials API to update all these certificates visible_date value + to keep certificates in sync on both sides. + + Args: + course_key (str): The course identifier + + Returns: + None + + """ + countdown = 2 ** self.request.retries + # If the credentials config model is disabled for this + # feature, it may indicate a condition where processing of such tasks + # has been temporarily disabled. Since this is a recoverable situation, + # mark this task for retry instead of failing it altogether. + + if not CredentialsApiConfig.current().is_learner_issuance_enabled: + LOGGER.info( + 'Task update_certificate_visible_date_on_course_update cannot be executed when credentials issuance is ' + 'disabled in API config', + ) + raise self.retry(countdown=countdown, max_retries=MAX_RETRIES) + + users_with_certificates_in_course = GeneratedCertificate.eligible_available_certificates.filter( + course_id=course_key).values_list('user__username', flat=True) + + for user in users_with_certificates_in_course: + award_course_certificate.delay(user, str(course_key)) diff --git a/openedx/core/djangoapps/programs/tasks/v1/tests/test_tasks.py b/openedx/core/djangoapps/programs/tasks/v1/tests/test_tasks.py index 230dc13862a26cce90c104f526b15a6ef3405fed..ef3c80c6fbe82e4a950a688531b1d24476b932f5 100644 --- a/openedx/core/djangoapps/programs/tasks/v1/tests/test_tasks.py +++ b/openedx/core/djangoapps/programs/tasks/v1/tests/test_tasks.py @@ -591,3 +591,277 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase): tasks.award_course_certificate.delay(self.student.username, str(self.certificate.course_id)).get() self.assertFalse(mock_post_course_certificate.called) + + +@skip_unless_lms +class RevokeProgramCertificateTestCase(TestCase): + """ + Test the revoke_program_certificate function + """ + + @httpretty.activate + def test_revoke_program_certificate(self): + """ + Ensure the correct API call gets made + """ + test_username = 'test-username' + test_client = EdxRestApiClient('http://test-server', jwt='test-token') + + httpretty.register_uri( + httpretty.POST, + 'http://test-server/credentials/', + ) + + tasks.revoke_program_certificate(test_client, test_username, 123) + + expected_body = { + 'username': test_username, + 'status': 'revoked', + 'credential': { + 'program_uuid': 123, + 'type': tasks.PROGRAM_CERTIFICATE, + } + } + last_request_body = httpretty.last_request().body.decode('utf-8') + self.assertEqual(json.loads(last_request_body), expected_body) + + +@skip_unless_lms +@ddt.ddt +@mock.patch(TASKS_MODULE + '.revoke_program_certificate') +@mock.patch(TASKS_MODULE + '.get_certified_programs') +@mock.patch(TASKS_MODULE + '.get_inverted_programs') +@override_settings(CREDENTIALS_SERVICE_USERNAME='test-service-username') +class RevokeProgramCertificatesTestCase(CatalogIntegrationMixin, CredentialsApiConfigMixin, TestCase): + """ + Tests for the 'revoke_program_certificates' celery task. + """ + + def setUp(self): + super(RevokeProgramCertificatesTestCase, self).setUp() + + self.student = UserFactory.create(username='test-student') + self.course_key = 'course-v1:testX+test101+2T2020' + self.site = SiteFactory() + self.site_configuration = SiteConfigurationFactory(site=self.site) + ApplicationFactory.create(name='credentials') + UserFactory.create(username=settings.CREDENTIALS_SERVICE_USERNAME) + self.create_credentials_config() + + self.inverted_programs = {self.course_key: [{'uuid': 1}, {'uuid': 2}]} + + def test_inverted_programs( + self, + mock_get_inverted_programs, + mock_get_certified_programs, # pylint: disable=unused-argument + mock_revoke_program_certificate, # pylint: disable=unused-argument + ): + """ + Checks that the Programs API is used correctly to determine completed + programs. + """ + tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get() + mock_get_inverted_programs.assert_any_call(self.student) + + def test_revokinging_certificate( + self, + mock_get_inverted_programs, + mock_get_certified_programs, + mock_revoke_program_certificate, + ): + """ + Checks that the Credentials API is used to revoke certificates for + the proper programs. + """ + expected_program_uuid = 1 + mock_get_inverted_programs.return_value = { + self.course_key: [{'uuid': expected_program_uuid}] + } + mock_get_certified_programs.return_value = [expected_program_uuid] + + tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get() + + call_args, _ = mock_revoke_program_certificate.call_args + self.assertEqual(call_args[1], self.student.username) + self.assertEqual(call_args[2], expected_program_uuid) + + @ddt.data( + ('credentials', 'enable_learner_issuance'), + ) + @ddt.unpack + def test_retry_if_config_disabled( + self, + disabled_config_type, + disabled_config_attribute, + *mock_helpers + ): + """ + Checks that the task is aborted if any relevant api configs are + disabled. + """ + getattr(self, 'create_{}_config'.format(disabled_config_type))(**{disabled_config_attribute: False}) + with mock.patch(TASKS_MODULE + '.LOGGER.warning') as mock_warning: + with self.assertRaises(MaxRetriesExceededError): + tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get() + self.assertTrue(mock_warning.called) + for mock_helper in mock_helpers: + self.assertFalse(mock_helper.called) + + def test_abort_if_invalid_username(self, *mock_helpers): + """ + Checks that the task will be aborted and not retried if the username + passed was not found, and that an exception is logged. + """ + with mock.patch(TASKS_MODULE + '.LOGGER.exception') as mock_exception: + tasks.revoke_program_certificates.delay('nonexistent-username', self.course_key).get() + self.assertTrue(mock_exception.called) + for mock_helper in mock_helpers: + self.assertFalse(mock_helper.called) + + def test_abort_if_no_program( + self, + mock_get_inverted_programs, + mock_get_certified_programs, + mock_revoke_program_certificate, + ): + """ + Checks that the task will be aborted without further action if course is + not part of any program. + """ + mock_get_inverted_programs.return_value = {} + tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get() + self.assertTrue(mock_get_inverted_programs.called) + self.assertFalse(mock_get_certified_programs.called) + self.assertFalse(mock_revoke_program_certificate.called) + + def _make_side_effect(self, side_effects): + """ + DRY helper. Returns a side effect function for use with mocks that + will be called multiple times, permitting Exceptions to be raised + (or not) in a specified order. + + See Also: + http://www.voidspace.org.uk/python/mock/examples.html#multiple-calls-with-different-effects + http://www.voidspace.org.uk/python/mock/mock.html#mock.Mock.side_effect + + """ + + def side_effect(*_a): + if side_effects: + exc = side_effects.pop(0) + if exc: + raise exc + return mock.DEFAULT + + return side_effect + + def test_continue_revoking_certs_if_error( + self, + mock_get_inverted_programs, + mock_get_certified_programs, + mock_revoke_program_certificate, + ): + """ + Checks that a single failure to revoke one of several certificates + does not cause the entire task to fail. Also ensures that + successfully revoked certs are logged as INFO and warning is logged + for failed requests if there are retries available. + """ + mock_get_inverted_programs.return_value = self.inverted_programs + mock_get_certified_programs.side_effect = [[1], [1, 2]] + mock_revoke_program_certificate.side_effect = self._make_side_effect([Exception('boom'), None]) + + with mock.patch(TASKS_MODULE + '.LOGGER.info') as mock_info, \ + mock.patch(TASKS_MODULE + '.LOGGER.warning') as mock_warning: + tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get() + + self.assertEqual(mock_revoke_program_certificate.call_count, 3) + mock_warning.assert_called_once_with( + u'Failed to revoke certificate for program {uuid} of user {username}.'.format( + uuid=1, + username=self.student.username) + ) + mock_info.assert_any_call(mock.ANY, 1, self.student.username) + mock_info.assert_any_call(mock.ANY, 2, self.student.username) + + def test_retry_on_credentials_api_errors( + self, + mock_get_inverted_programs, + mock_get_certified_programs, + mock_revoke_program_certificate, + ): + """ + Ensures that any otherwise-unhandled errors that arise while trying + to get existing program credentials (e.g. network issues or other + transient API errors) will cause the task to be failed and queued for + retry. + """ + mock_get_inverted_programs.return_value = self.inverted_programs + mock_get_certified_programs.return_value = [1] + mock_get_certified_programs.side_effect = self._make_side_effect([Exception('boom'), None]) + tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get() + self.assertEqual(mock_get_certified_programs.call_count, 2) + self.assertEqual(mock_revoke_program_certificate.call_count, 1) + + def test_retry_on_credentials_api_429_error( + self, + mock_get_inverted_programs, + mock_get_certified_programs, + mock_revoke_program_certificate, + ): + """ + Verify that a 429 error causes the task to fail and then retry. + """ + exception = exceptions.HttpClientError() + exception.response = mock.Mock(status_code=429) + mock_get_inverted_programs.return_value = self.inverted_programs + mock_get_certified_programs.return_value = [1, 2] + mock_revoke_program_certificate.side_effect = self._make_side_effect( + [exception, None] + ) + + tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get() + + self.assertEqual(mock_revoke_program_certificate.call_count, 3) + + def test_no_retry_on_credentials_api_404_error( + self, + mock_get_inverted_programs, + mock_get_certified_programs, + mock_revoke_program_certificate, + ): + """ + Verify that a 404 error causes the task to fail but there is no retry. + """ + exception = exceptions.HttpNotFoundError() + exception.response = mock.Mock(status_code=404) + mock_get_inverted_programs.return_value = self.inverted_programs + mock_get_certified_programs.return_value = [1, 2] + mock_revoke_program_certificate.side_effect = self._make_side_effect( + [exception, None] + ) + + tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get() + + self.assertEqual(mock_revoke_program_certificate.call_count, 2) + + def test_no_retry_on_credentials_api_4XX_error( + self, + mock_get_inverted_programs, + mock_get_certified_programs, + mock_revoke_program_certificate, + ): + """ + Verify that other 4XX errors cause task to fail but there is no retry. + """ + exception = exceptions.HttpClientError() + exception.response = mock.Mock(status_code=418) + mock_get_inverted_programs.return_value = self.inverted_programs + mock_get_certified_programs.return_value = [1, 2] + mock_revoke_program_certificate.side_effect = self._make_side_effect( + [exception, None] + ) + + tasks.revoke_program_certificates.delay(self.student.username, self.course_key).get() + + self.assertEqual(mock_revoke_program_certificate.call_count, 2) diff --git a/openedx/core/djangoapps/programs/tests/factories.py b/openedx/core/djangoapps/programs/tests/factories.py index 9e1e3f483cef461f2aa897cc7cfd65e7600f816c..37a54aaa66465a01e1ffec675a1eefa7afa15b4a 100644 --- a/openedx/core/djangoapps/programs/tests/factories.py +++ b/openedx/core/djangoapps/programs/tests/factories.py @@ -13,4 +13,3 @@ class ProgressFactory(factory.Factory): completed = 0 in_progress = 0 not_started = 0 - grades = dict() diff --git a/openedx/core/djangoapps/programs/tests/test_signals.py b/openedx/core/djangoapps/programs/tests/test_signals.py index 364dc089f6325c44549ac8cd172eb0175e8236ce..828eb441886c304191677faf247ca06ff7021f96 100644 --- a/openedx/core/djangoapps/programs/tests/test_signals.py +++ b/openedx/core/djangoapps/programs/tests/test_signals.py @@ -6,9 +6,18 @@ This module contains tests for programs-related signals and signal handlers. import mock from django.test import TestCase from opaque_keys.edx.keys import CourseKey - -from openedx.core.djangoapps.programs.signals import handle_course_cert_awarded, handle_course_cert_changed -from openedx.core.djangoapps.signals.signals import COURSE_CERT_AWARDED, COURSE_CERT_CHANGED +from openedx.core.djangoapps.programs.signals import ( + handle_course_cert_awarded, + handle_course_cert_changed, + handle_course_cert_date_change, + handle_course_cert_revoked +) +from openedx.core.djangoapps.signals.signals import ( + COURSE_CERT_AWARDED, + COURSE_CERT_CHANGED, + COURSE_CERT_DATE_CHANGE, + COURSE_CERT_REVOKED +) from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfigurationFactory from openedx.core.djangolib.testing.utils import skip_unless_lms from student.tests.factories import UserFactory @@ -159,3 +168,120 @@ class CertChangedReceiverTest(TestCase): site_config.save() handle_course_cert_changed(**self.signal_kwargs) self.assertFalse(mock_task.called) + + +# The credentials app isn't installed for the CMS. +@skip_unless_lms +@mock.patch('openedx.core.djangoapps.programs.tasks.v1.tasks.revoke_program_certificates.delay') +@mock.patch( + 'openedx.core.djangoapps.credentials.models.CredentialsApiConfig.is_learner_issuance_enabled', + new_callable=mock.PropertyMock, + return_value=False, +) +class CertRevokedReceiverTest(TestCase): + """ + Tests for the `handle_course_cert_revoked` signal handler function. + """ + + @property + def signal_kwargs(self): + """ + DRY helper. + """ + return dict( + sender=self.__class__, + user=UserFactory.create(username=TEST_USERNAME), + course_key=TEST_COURSE_KEY, + mode='test-mode', + status='test-status', + ) + + def test_signal_received(self, mock_is_learner_issuance_enabled, mock_task): # pylint: disable=unused-argument + """ + Ensures the receiver function is invoked when COURSE_CERT_REVOKED is + sent. + + Suboptimal: because we cannot mock the receiver function itself (due + to the way django signals work), we mock a configuration call that is + known to take place inside the function. + """ + COURSE_CERT_REVOKED.send(**self.signal_kwargs) + self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1) + + def test_programs_disabled(self, mock_is_learner_issuance_enabled, mock_task): + """ + Ensures that the receiver function does nothing when the credentials API + configuration is not enabled. + """ + handle_course_cert_revoked(**self.signal_kwargs) + self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1) + self.assertEqual(mock_task.call_count, 0) + + def test_programs_enabled(self, mock_is_learner_issuance_enabled, mock_task): + """ + Ensures that the receiver function invokes the expected celery task + when the credentials API configuration is enabled. + """ + mock_is_learner_issuance_enabled.return_value = True + + handle_course_cert_revoked(**self.signal_kwargs) + + self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1) + self.assertEqual(mock_task.call_count, 1) + self.assertEqual(mock_task.call_args[0], (TEST_USERNAME, TEST_COURSE_KEY)) + + +@skip_unless_lms +@mock.patch('openedx.core.djangoapps.programs.tasks.v1.tasks.update_certificate_visible_date_on_course_update.delay') +@mock.patch( + 'openedx.core.djangoapps.credentials.models.CredentialsApiConfig.is_learner_issuance_enabled', + new_callable=mock.PropertyMock, + return_value=False, +) +class CourseCertAvailableDateChangedReceiverTest(TestCase): + """ + Tests for the `handle_course_cert_date_change` signal handler function. + """ + + @property + def signal_kwargs(self): + """ + DRY helper. + """ + return { + 'sender': self.__class__, + 'course_key': TEST_COURSE_KEY, + } + + def test_signal_received(self, mock_is_learner_issuance_enabled, mock_task): # pylint: disable=unused-argument + """ + Ensures the receiver function is invoked when COURSE_CERT_DATE_CHANGE is + sent. + + Suboptimal: because we cannot mock the receiver function itself (due + to the way django signals work), we mock a configuration call that is + known to take place inside the function. + """ + COURSE_CERT_DATE_CHANGE.send(**self.signal_kwargs) + self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1) + + def test_programs_disabled(self, mock_is_learner_issuance_enabled, mock_task): + """ + Ensures that the receiver function does nothing when the credentials API + configuration is not enabled. + """ + handle_course_cert_date_change(**self.signal_kwargs) + self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1) + self.assertEqual(mock_task.call_count, 0) + + def test_programs_enabled(self, mock_is_learner_issuance_enabled, mock_task): + """ + Ensures that the receiver function invokes the expected celery task + when the credentials API configuration is enabled. + """ + mock_is_learner_issuance_enabled.return_value = True + + handle_course_cert_date_change(**self.signal_kwargs) + + self.assertEqual(mock_is_learner_issuance_enabled.call_count, 1) + self.assertEqual(mock_task.call_count, 1) diff --git a/openedx/core/djangoapps/programs/tests/test_utils.py b/openedx/core/djangoapps/programs/tests/test_utils.py index 845a5db402e0411fde3f50802bf72f820d9d8a40..61acf1dbd9805cf8552e9e4988f36fd2eadc7605 100644 --- a/openedx/core/djangoapps/programs/tests/test_utils.py +++ b/openedx/core/djangoapps/programs/tests/test_utils.py @@ -151,7 +151,7 @@ class TestProgramProgressMeter(TestCase): self.assertEqual(meter.engaged_programs, [program]) self._assert_progress( meter, - ProgressFactory(uuid=program['uuid'], in_progress=1, grades={course_run_key: 0.0}) + ProgressFactory(uuid=program['uuid'], in_progress=1) ) self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), []) @@ -250,7 +250,6 @@ class TestProgramProgressMeter(TestCase): completed=[], in_progress=[program['courses'][0]], not_started=[], - grades={course_run_key: 0.0}, ) ] @@ -287,7 +286,6 @@ class TestProgramProgressMeter(TestCase): completed=[], in_progress=[program['courses'][0]], not_started=[], - grades={course_run_key: 0.0}, ) ] @@ -329,7 +327,6 @@ class TestProgramProgressMeter(TestCase): completed=0, in_progress=1 if offset in [None, 1] else 0, not_started=1 if offset in [-1] else 0, - grades={course_run_key: 0.0}, ) ] @@ -369,13 +366,9 @@ class TestProgramProgressMeter(TestCase): programs = data[:2] self.assertEqual(meter.engaged_programs, programs) - grades = { - newer_course_run_key: 0.0, - older_course_run_key: 0.0, - } self._assert_progress( meter, - *(ProgressFactory(uuid=program['uuid'], in_progress=1, grades=grades) for program in programs) + *(ProgressFactory(uuid=program['uuid'], in_progress=1) for program in programs) ) self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), []) @@ -441,14 +434,9 @@ class TestProgramProgressMeter(TestCase): programs = data[:3] self.assertEqual(meter.engaged_programs, programs) - grades = { - solo_course_run_key: 0.0, - shared_course_run_key: 0.0, - } - self._assert_progress( meter, - *(ProgressFactory(uuid=program['uuid'], in_progress=1, grades=grades) for program in programs) + *(ProgressFactory(uuid=program['uuid'], in_progress=1) for program in programs) ) self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), []) @@ -509,7 +497,7 @@ class TestProgramProgressMeter(TestCase): _, program_uuid = data[0], data[0]['uuid'] self._assert_progress( meter, - ProgressFactory(uuid=program_uuid, in_progress=1, not_started=1, grades={first_course_run_key: 0.0}) + ProgressFactory(uuid=program_uuid, in_progress=1, not_started=1) ) self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), []) @@ -521,10 +509,6 @@ class TestProgramProgressMeter(TestCase): ProgressFactory( uuid=program_uuid, in_progress=2, - grades={ - first_course_run_key: 0.0, - second_course_run_key: 0.0, - }, ) ) self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), []) @@ -538,10 +522,6 @@ class TestProgramProgressMeter(TestCase): uuid=program_uuid, completed=1, in_progress=1, - grades={ - first_course_run_key: 0.0, - second_course_run_key: 0.0, - } ) ) self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), []) @@ -556,10 +536,6 @@ class TestProgramProgressMeter(TestCase): uuid=program_uuid, completed=1, in_progress=1, - grades={ - first_course_run_key: 0.0, - second_course_run_key: 0.0, - } ) ) self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), []) @@ -573,10 +549,6 @@ class TestProgramProgressMeter(TestCase): ProgressFactory( uuid=program_uuid, completed=2, - grades={ - first_course_run_key: 0.0, - second_course_run_key: 0.0, - } ) ) self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [program_uuid]) @@ -607,7 +579,7 @@ class TestProgramProgressMeter(TestCase): _, program_uuid = data[0], data[0]['uuid'] self._assert_progress( meter, - ProgressFactory(uuid=program_uuid, completed=1, grades={course_run_key: 0.0}) + ProgressFactory(uuid=program_uuid, completed=1) ) self.assertEqual(list(meter.completed_programs_with_available_dates.keys()), [program_uuid]) @@ -725,38 +697,6 @@ class TestProgramProgressMeter(TestCase): mock_completed_course_runs.return_value = [{'course_run_id': course_run_key, 'type': CourseMode.VERIFIED}] self.assertEqual(meter._is_course_complete(course), True) - def test_course_grade_results(self, mock_get_programs): - grade_percent = .8 - with mock_passing_grade(percent=grade_percent): - course_run_key = generate_course_run_key() - data = [ - ProgramFactory( - courses=[ - CourseFactory(course_runs=[ - CourseRunFactory(key=course_run_key), - ]), - ] - ) - ] - mock_get_programs.return_value = data - - self._create_enrollments(course_run_key) - - meter = ProgramProgressMeter(self.site, self.user) - - program = data[0] - expected = [ - ProgressFactory( - uuid=program['uuid'], - completed=[], - in_progress=[program['courses'][0]], - not_started=[], - grades={course_run_key: grade_percent}, - ) - ] - - self.assertEqual(meter.progress(count_only=False), expected) - def test_detail_url_for_mobile_only(self, mock_get_programs): """ Verify that correct program detail url is returned for mobile. @@ -854,7 +794,7 @@ class TestProgramDataExtender(ModuleStoreTestCase): 'certificate_url': None, 'course_url': reverse('course_root', args=[self.course.id]), 'enrollment_open_date': strftime_localized(DEFAULT_ENROLLMENT_START_DATE, 'SHORT_DATE'), - 'is_course_ended': self.course.end < datetime.datetime.now(utc), + 'is_course_ended': self.course.has_ended(), 'is_enrolled': False, 'is_enrollment_open': True, 'upgrade_url': None, diff --git a/openedx/core/djangoapps/programs/utils.py b/openedx/core/djangoapps/programs/utils.py index 6f9b379605a1f0a01a3226647ad75b5c93be0959..2e0905f65d0e2128f38561b6dc2c7fadd852b213 100644 --- a/openedx/core/djangoapps/programs/utils.py +++ b/openedx/core/djangoapps/programs/utils.py @@ -26,7 +26,6 @@ from entitlements.models import CourseEntitlement from lms.djangoapps.certificates import api as certificate_api from lms.djangoapps.certificates.models import GeneratedCertificate from lms.djangoapps.commerce.utils import EcommerceService -from lms.djangoapps.grades.api import CourseGradeFactory from openedx.core.djangoapps.catalog.utils import get_fulfillable_course_runs_for_entitlement, get_programs from openedx.core.djangoapps.certificates.api import available_date_for_certificate from openedx.core.djangoapps.commerce.utils import ecommerce_api_client @@ -114,8 +113,6 @@ class ProgramProgressMeter(object): self.entitlements = list(CourseEntitlement.unexpired_entitlements_for_user(self.user)) self.course_uuids = [str(entitlement.course_uuid) for entitlement in self.entitlements] - self.course_grade_factory = CourseGradeFactory() - if uuid: self.programs = [get_programs(uuid=uuid)] else: @@ -270,17 +267,11 @@ class ProgramProgressMeter(object): else: not_started.append(course) - grades = {} - for run in self.course_run_ids: - grade = self.course_grade_factory.read(self.user, course_key=CourseKey.from_string(run)) - grades[run] = grade.percent - progress.append({ 'uuid': program_copy['uuid'], 'completed': len(completed) if count_only else completed, 'in_progress': len(in_progress) if count_only else in_progress, 'not_started': len(not_started) if count_only else not_started, - 'grades': grades, }) return progress diff --git a/openedx/core/djangoapps/schedules/admin.py b/openedx/core/djangoapps/schedules/admin.py index 5456b3d2534b6bb3c4626652e96c4c1cdaa1171e..0355f05744e29d28ae283562d22f680bbd40a869 100644 --- a/openedx/core/djangoapps/schedules/admin.py +++ b/openedx/core/djangoapps/schedules/admin.py @@ -7,11 +7,11 @@ from django import forms from django.contrib import admin from django.db.models import F from django.urls import reverse +from django.utils.html import format_html from django.utils.translation import ugettext_lazy as _ from opaque_keys.edx.keys import CourseKey from openedx.core.djangoapps.content.course_overviews.models import CourseOverview -from openedx.core.djangolib.markup import HTML from . import models @@ -151,23 +151,23 @@ class ScheduleAdmin(admin.ModelAdmin): experience_display.short_descriptions = _('Experience') def username(self, obj): - return HTML('<a href="{}">{}</a>').format( + return format_html( + '<a href="{}">{}</a>', reverse("admin:auth_user_change", args=(obj.enrollment.user.id,)), obj.enrollment.user.username ) - username.allow_tags = True username.short_description = _('Username') def course_id(self, obj): - return HTML('<a href="{}">{}</a>').format( + return format_html( + '<a href="{}">{}</a>', reverse("admin:course_overviews_courseoverview_change", args=( obj.enrollment.course_id, )), obj.enrollment.course_id ) - course_id.allow_tags = True course_id.short_description = _('Course ID') def get_queryset(self, request): diff --git a/openedx/core/djangoapps/schedules/content_highlights.py b/openedx/core/djangoapps/schedules/content_highlights.py index 424af077c5a4226d542416a66258dfb8d5cd41b2..f236c0a004e67494a02448344aedbda8a696e652 100644 --- a/openedx/core/djangoapps/schedules/content_highlights.py +++ b/openedx/core/djangoapps/schedules/content_highlights.py @@ -6,6 +6,7 @@ schedule experience built on the Schedules app. import logging +from openedx.core.djangoapps.course_date_signals.utils import spaced_out_sections from openedx.core.djangoapps.schedules.config import COURSE_UPDATE_WAFFLE_FLAG from openedx.core.djangoapps.schedules.exceptions import CourseUpdateDoesNotExist from openedx.core.lib.request_utils import get_request_or_stub @@ -62,6 +63,25 @@ def get_week_highlights(user, course_key, week_num): return highlights +def get_next_section_highlights(user, course_key, start_date, target_date): + """ + Get highlights (list of unicode strings) for a week, based upon the current date. + + Raises: + CourseUpdateDoeNotExist: if highlights do not exist for the requested date + """ + course_descriptor = _get_course_with_highlights(course_key) + course_module = _get_course_module(course_descriptor, user) + sections_with_highlights = _get_sections_with_highlights(course_module) + highlights = _get_highlights_for_next_section( + course_module, + sections_with_highlights, + start_date, + target_date + ) + return highlights + + def _get_course_with_highlights(course_key): # pylint: disable=missing-docstring if not COURSE_UPDATE_WAFFLE_FLAG.is_enabled(course_key): @@ -104,16 +124,20 @@ def _get_course_module(course_descriptor, user): field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_descriptor.id, user, course_descriptor, depth=1, read_only=True, ) - return get_module_for_descriptor( + course_module = get_module_for_descriptor( user, request, course_descriptor, field_data_cache, course_descriptor.id, course=course_descriptor, ) + if not course_module: + raise CourseUpdateDoesNotExist('Course module {} not found'.format(course_descriptor.id)) + return course_module + + +def _section_has_highlights(section): + return section.highlights and not section.hide_from_toc def _get_sections_with_highlights(course_module): - return [ - section for section in course_module.get_children() - if section.highlights and not section.hide_from_toc - ] + return list(filter(_section_has_highlights, course_module.get_children())) def _get_highlights_for_week(sections, week_num, course_key): @@ -128,3 +152,25 @@ def _get_highlights_for_week(sections, week_num, course_key): section = sections[week_num - 1] return section.highlights + + +def _get_highlights_for_next_section(course_module, sections, start_date, target_date): + for index, section, weeks_to_complete in spaced_out_sections(course_module): + if not _section_has_highlights(section): + continue + + # We calculate section due date ourselves (rather than grabbing the due attribute), + # since not every section has a real due date (i.e. not all are graded), but we still + # want to know when this section should have been completed by the learner. + section_due_date = start_date + weeks_to_complete + + if section_due_date.date() == target_date and index + 1 < len(sections): + # Return index + 2 for "week_num", since weeks start at 1 as opposed to indexes, + # and we want the next week, so +1 for index and +1 for next + return sections[index + 1].highlights, index + 2 + + raise CourseUpdateDoesNotExist( + u"No section found ending on {} for {}".format( + target_date, course_module.id + ) + ) diff --git a/openedx/core/djangoapps/schedules/management/commands/send_course_next_section_update.py b/openedx/core/djangoapps/schedules/management/commands/send_course_next_section_update.py new file mode 100644 index 0000000000000000000000000000000000000000..8805ebbcaf9b7a1815b51e2b2221731ef87dfb0c --- /dev/null +++ b/openedx/core/djangoapps/schedules/management/commands/send_course_next_section_update.py @@ -0,0 +1,33 @@ +""" +Management command to send Schedule course updates +""" + +import datetime +import pytz +from textwrap import dedent + +from django.contrib.sites.models import Site + +from openedx.core.djangoapps.schedules.management.commands import SendEmailBaseCommand +from openedx.core.djangoapps.schedules.tasks import ScheduleCourseNextSectionUpdate + + +class Command(SendEmailBaseCommand): + """ + Command to send Schedule course updates + """ + help = dedent(__doc__).strip() + async_send_task = ScheduleCourseNextSectionUpdate + log_prefix = 'Course Update' + + def handle(self, *args, ** options): + current_date = datetime.datetime( + *[int(x) for x in options['date'].split('-')], + tzinfo=pytz.UTC + ) + + site = Site.objects.get(domain__iexact=options['site_domain_name']) + override_recipient_email = options.get('override_recipient_email') + + # day_offset set to 1 as we'll always be looking for yesterday + self.async_send_task.enqueue(site, current_date, 1, override_recipient_email) diff --git a/openedx/core/djangoapps/schedules/resolvers.py b/openedx/core/djangoapps/schedules/resolvers.py index 6437e282385703f3abfd6d11c8a743f368b0b04b..cc092d6e272141b424234a9eafd0fa8158c665e1 100644 --- a/openedx/core/djangoapps/schedules/resolvers.py +++ b/openedx/core/djangoapps/schedules/resolvers.py @@ -13,12 +13,14 @@ from django.urls import reverse from edx_ace.recipient import Recipient from edx_ace.recipient_resolver import RecipientResolver from edx_django_utils.monitoring import function_trace, set_custom_metric +from edx_when.api import get_schedules_with_due_date +from opaque_keys.edx.keys import CourseKey -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, verified_upgrade_link_is_valid +from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, can_show_verified_upgrade from lms.djangoapps.discussion.notification_prefs.views import UsernameCipher from openedx.core.djangoapps.ace_common.template_context import get_base_template_context from openedx.core.djangoapps.schedules.config import COURSE_UPDATE_SHOW_UNSUBSCRIBE_WAFFLE_SWITCH -from openedx.core.djangoapps.schedules.content_highlights import get_week_highlights +from openedx.core.djangoapps.schedules.content_highlights import get_week_highlights, get_next_section_highlights from openedx.core.djangoapps.schedules.exceptions import CourseUpdateDoesNotExist from openedx.core.djangoapps.schedules.message_types import CourseUpdate, InstructorLedCourseUpdate from openedx.core.djangoapps.schedules.models import Schedule, ScheduleExperience @@ -343,7 +345,7 @@ def _get_upsell_information_for_schedule(user, schedule): def _get_verified_upgrade_link(user, schedule): enrollment = schedule.enrollment - if enrollment.dynamic_upgrade_deadline is not None and verified_upgrade_link_is_valid(enrollment): + if enrollment.dynamic_upgrade_deadline is not None and can_show_verified_upgrade(user, enrollment): return verified_upgrade_deadline_link(user, enrollment.course) @@ -417,6 +419,94 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver): yield (user, schedule.enrollment.course.closest_released_language, template_context, course.self_paced) +@attr.s +class CourseNextSectionUpdate(PrefixedDebugLoggerMixin, RecipientResolver): + """ + Send a message to all users whose schedule gives them a due date of yesterday. + """ + async_send_task = attr.ib() + site = attr.ib() + target_datetime = attr.ib() + course_id = attr.ib() + override_recipient_email = attr.ib(default=None) + + log_prefix = 'Next Section Course Update' + experience_filter = Q(experience__experience_type=ScheduleExperience.EXPERIENCES.course_updates) + + def send(self): + schedules = self.get_schedules() + for (user, language, context, is_self_paced) in schedules: + msg_type = CourseUpdate() if is_self_paced else InstructorLedCourseUpdate() + msg = msg_type.personalize( + Recipient( + user.username, + self.override_recipient_email or user.email, + ), + language, + context, + ) + LOG.info( + u'Sending email to user: {} for course-key: {}'.format( + user.username, + self.course_id + ) + ) + with function_trace('enqueue_send_task'): + self.async_send_task.apply_async((self.site.id, str(msg)), retry=False) + + def get_schedules(self): + course_key = CourseKey.from_string(self.course_id) + target_date = self.target_datetime.date() + schedules = get_schedules_with_due_date(course_key, target_date).filter( + self.experience_filter, + active=True, + enrollment__user__is_active=True, + ) + + template_context = get_base_template_context(self.site) + for schedule in schedules: + enrollment = schedule.enrollment + course = schedule.enrollment.course + user = enrollment.user + start_date = schedule.start_date + LOG.info(u'Received a schedule for user {} in course {} for date {}'.format( + user.username, + self.course_id, + target_date, + )) + + try: + week_highlights, week_num = get_next_section_highlights(user, course.id, start_date, target_date) + except CourseUpdateDoesNotExist: + LOG.warning( + u'Weekly highlights for user {} of course {} does not exist or is disabled'.format( + user, course.id + ) + ) + # continue to the next schedule, don't yield an email for this one + continue + unsubscribe_url = None + if (COURSE_UPDATE_SHOW_UNSUBSCRIBE_WAFFLE_SWITCH.is_enabled() and + 'bulk_email_optout' in settings.ACE_ENABLED_POLICIES): + unsubscribe_url = reverse('bulk_email_opt_out', kwargs={ + 'token': UsernameCipher.encrypt(user.username), + 'course_id': str(enrollment.course_id), + }) + + template_context.update({ + 'course_name': course.display_name, + 'course_url': _get_trackable_course_home_url(enrollment.course_id), + 'week_num': week_num, + 'week_highlights': week_highlights, + # This is used by the bulk email optout policy + 'course_ids': [str(enrollment.course_id)], + 'unsubscribe_url': unsubscribe_url, + }) + template_context.update(_get_upsell_information_for_schedule(user, schedule)) + + yield (user, enrollment.course.closest_released_language, template_context, course.self_paced) + + def _get_trackable_course_home_url(course_id): """ Get the home page URL for the course. diff --git a/openedx/core/djangoapps/schedules/tasks.py b/openedx/core/djangoapps/schedules/tasks.py index e3ff5631f0b9cd9de517321c0d896101881b561f..d8132e6aa97bb1ead7d846a24fdb55a351ff6875 100644 --- a/openedx/core/djangoapps/schedules/tasks.py +++ b/openedx/core/djangoapps/schedules/tasks.py @@ -20,6 +20,7 @@ from edx_django_utils.monitoring import set_custom_metric from eventtracking import tracker from opaque_keys.edx.keys import CourseKey +from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.schedules import message_types, resolvers from openedx.core.djangoapps.schedules.models import Schedule, ScheduleConfig from openedx.core.lib.celery.task_utils import emulate_http_request @@ -38,6 +39,7 @@ KNOWN_RETRY_ERRORS = ( # Errors we expect occasionally that could resolve on re RECURRING_NUDGE_LOG_PREFIX = 'Recurring Nudge' UPGRADE_REMINDER_LOG_PREFIX = 'Upgrade Reminder' COURSE_UPDATE_LOG_PREFIX = 'Course Update' +COURSE_NEXT_SECTION_UPDATE_LOG_PREFIX = 'Course Next Section Update' @task(base=LoggedPersistOnFailureTask, bind=True, default_retry_delay=30) @@ -59,12 +61,10 @@ def update_course_schedules(self, **kwargs): class ScheduleMessageBaseTask(LoggedTask): """ - Base class for top-level Schedule tasks that create subtasks - for each Bin. + Base class for top-level Schedule tasks that create subtasks. """ ignore_result = True routing_key = ROUTING_KEY - num_bins = resolvers.DEFAULT_NUM_BINS enqueue_config_var = None # define in subclass log_prefix = None resolver = None # define in subclass @@ -84,6 +84,20 @@ class ScheduleMessageBaseTask(LoggedTask): """ LOG.info(cls.log_prefix + ': ' + message, *args, **kwargs) + @classmethod + def is_enqueue_enabled(cls, site): + if cls.enqueue_config_var: + return getattr(ScheduleConfig.current(site), cls.enqueue_config_var) + return False + + +class BinnedScheduleMessageBaseTask(ScheduleMessageBaseTask): + """ + Base class for top-level Schedule tasks that create subtasks + for each Bin. + """ + num_bins = resolvers.DEFAULT_NUM_BINS + @classmethod def enqueue(cls, site, current_date, day_offset, override_recipient_email=None): current_date = resolvers._get_datetime_beginning_of_day(current_date) @@ -108,12 +122,6 @@ class ScheduleMessageBaseTask(LoggedTask): retry=False, ) - @classmethod - def is_enqueue_enabled(cls, site): - if cls.enqueue_config_var: - return getattr(ScheduleConfig.current(site), cls.enqueue_config_var) - return False - def run( self, site_id, target_day_str, day_offset, bin_num, override_recipient_email=None, ): @@ -164,7 +172,7 @@ def _course_update_schedule_send(site_id, msg_str): ) -class ScheduleRecurringNudge(ScheduleMessageBaseTask): +class ScheduleRecurringNudge(BinnedScheduleMessageBaseTask): num_bins = resolvers.RECURRING_NUDGE_NUM_BINS enqueue_config_var = 'enqueue_recurring_nudge' log_prefix = RECURRING_NUDGE_LOG_PREFIX @@ -175,7 +183,7 @@ class ScheduleRecurringNudge(ScheduleMessageBaseTask): return message_types.RecurringNudge(abs(day_offset)) -class ScheduleUpgradeReminder(ScheduleMessageBaseTask): +class ScheduleUpgradeReminder(BinnedScheduleMessageBaseTask): num_bins = resolvers.UPGRADE_REMINDER_NUM_BINS enqueue_config_var = 'enqueue_upgrade_reminder' log_prefix = UPGRADE_REMINDER_LOG_PREFIX @@ -186,7 +194,7 @@ class ScheduleUpgradeReminder(ScheduleMessageBaseTask): return message_types.UpgradeReminder() -class ScheduleCourseUpdate(ScheduleMessageBaseTask): +class ScheduleCourseUpdate(BinnedScheduleMessageBaseTask): num_bins = resolvers.COURSE_UPDATE_NUM_BINS enqueue_config_var = 'enqueue_course_update' log_prefix = COURSE_UPDATE_LOG_PREFIX @@ -197,6 +205,47 @@ class ScheduleCourseUpdate(ScheduleMessageBaseTask): return message_types.CourseUpdate() +class ScheduleCourseNextSectionUpdate(ScheduleMessageBaseTask): + enqueue_config_var = 'enqueue_course_update' + log_prefix = COURSE_NEXT_SECTION_UPDATE_LOG_PREFIX + resolver = resolvers.CourseNextSectionUpdate + async_send_task = _course_update_schedule_send + + @classmethod + def enqueue(cls, site, current_date, day_offset, override_recipient_email=None): + target_datetime = (current_date - datetime.timedelta(days=day_offset)) + + if not cls.is_enqueue_enabled(site): + cls.log_info(u'Message queuing disabled for site %s', site.domain) + return + + cls.log_info(u'Target date = %s', target_datetime.date().isoformat()) + for course_key in CourseOverview.get_all_course_keys(): + task_args = ( + site.id, + serialize(target_datetime), # Need to leave as a datetime for serialization purposes here + str(course_key), # Needs to be a string for celery to properly process + override_recipient_email, + ) + cls.log_info(u'Launching task with args = %r', task_args) + cls().apply_async( + task_args, + retry=False, + ) + + def run(self, site_id, target_day_str, course_key, override_recipient_email=None): + site = Site.objects.select_related('configuration').get(id=site_id) + with emulate_http_request(site=site): + _annotate_for_monitoring(message_types.CourseUpdate(), site, 0, target_day_str, -1) + return self.resolver( + self.async_send_task, + site, + deserialize(target_day_str), + str(course_key), + override_recipient_email, + ).send() + + def _schedule_send(msg_str, site_id, delivery_config_var, log_prefix): site = Site.objects.select_related('configuration').get(pk=site_id) if _is_delivery_enabled(site, delivery_config_var, log_prefix): @@ -253,18 +302,24 @@ def _is_delivery_enabled(site, delivery_config_var, log_prefix): LOG.info(u'%s: Message delivery disabled for site %s', log_prefix, site.domain) -def _annotate_for_monitoring(message_type, site, bin_num, target_day_str, day_offset): +def _annotate_for_monitoring(message_type, site, bin_num=None, target_day_str=None, day_offset=None, course_key=None): # This identifies the type of message being sent, for example: schedules.recurring_nudge3. set_custom_metric('message_name', '{0}.{1}'.format(message_type.app_label, message_type.name)) # The domain name of the site we are sending the message for. set_custom_metric('site', site.domain) # This is the "bin" of data being processed. We divide up the work into chunks so that we don't tie up celery # workers for too long. This could help us identify particular bins that are problematic. - set_custom_metric('bin', bin_num) + if bin_num: + set_custom_metric('bin', bin_num) # The date we are processing data for. - set_custom_metric('target_day', target_day_str) + if target_day_str: + set_custom_metric('target_day', target_day_str) # The number of days relative to the current date to process data for. - set_custom_metric('day_offset', day_offset) + if day_offset: + set_custom_metric('day_offset', day_offset) + # If we're processing these according to a course_key rather than bin we can use this to identify problematic keys. + if course_key: + set_custom_metric('course_key', course_key) # A unique identifier for this batch of messages being sent. set_custom_metric('send_uuid', message_type.uuid) diff --git a/openedx/core/djangoapps/schedules/templates/dropdown_filter.html b/openedx/core/djangoapps/schedules/templates/dropdown_filter.html index 61c6a2173737214a494fba1fd4c2e9df0ae2b16c..0b1a6e251353c688c200085f439dc384958c079e 100644 --- a/openedx/core/djangoapps/schedules/templates/dropdown_filter.html +++ b/openedx/core/djangoapps/schedules/templates/dropdown_filter.html @@ -1,5 +1,8 @@ {% load i18n %} -<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3> +<h3>{% filter force_escape %} + {% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %} + {% endfilter %} +</h3> <form method="GET"> {% for name, param in spec.unused_parameters.items %} <input type="hidden" name="{{ name }}" value="{{ param }}"/> diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/courseupdate/email/body.html b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/courseupdate/email/body.html index 545a165ba7af8026c34b36d6282e76e8e459d044..fd43f9933b8355d64bcc2858ebb94d61a7c3e2c3 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/courseupdate/email/body.html +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/courseupdate/email/body.html @@ -35,8 +35,10 @@ {% endblocktrans %} {% endfilter %} </p> - {# xss-lint: disable=django-trans-missing-escape #} - {% trans "Resume your course now" as course_cta_text %} + + {% filter force_escape %} + {% blocktrans asvar course_cta_text %}Resume your course now{% endblocktrans %} + {% endfilter %} {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text%} {% include "ace_common/edx_ace/common/upsell_cta.html"%} diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/instructorledcourseupdate/email/body.html b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/instructorledcourseupdate/email/body.html index d74c2847bbc9a24919f486dea259e6fc299f3032..e569348b777c3e9aa1ee72642883302304ed1c27 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/instructorledcourseupdate/email/body.html +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/instructorledcourseupdate/email/body.html @@ -34,8 +34,10 @@ {% endblocktrans %} {% endfilter %} </p> - {# xss-lint: disable=django-trans-missing-escape #} - {% trans "Resume your course now" as course_cta_text %} + + {% filter force_escape %} + {% blocktrans asvar course_cta_text %}Resume your course now{% endblocktrans %} + {% endfilter %} {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text%} {% include "ace_common/edx_ace/common/upsell_cta.html"%} diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.html b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.html index 4aafbc7a1dd4b89b1b9e2c1da721ebf7c59ffbf9..8dc820d6dda3c24e09f8fd189897683cdafed39c 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.html +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.html @@ -42,8 +42,10 @@ {% interpolate_html tmsg start_strong='<strong>'|safe end_strong='</strong>'|safe course_name=course_name|force_escape|safe platform_name=platform_name|force_escape|safe %} {% endif %} </p> - {# xss-lint: disable=django-trans-missing-escape #} - {% trans "Keep learning" as course_cta_text %} + + {% filter force_escape %} + {% blocktrans asvar course_cta_text %}Keep learning{% endblocktrans %} + {% endfilter %} {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text%} {% include "ace_common/edx_ace/common/upsell_cta.html"%} diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.html b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.html index 85a2076232fa1431ce97da21858a1f8035f78fc6..a936e911bfbbe382d5866e106823b7614343b3e0 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.html +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.html @@ -41,8 +41,10 @@ {% interpolate_html tmsg start_strong='<strong>'|safe end_strong='</strong>'|safe course_name=course_name|force_escape|safe platform_name=platform_name|force_escape|safe %} {% endif %} </p> - {# xss-lint: disable=django-trans-missing-escape #} - {% trans "Start learning now" as course_cta_text %} + + {% filter force_escape %} + {% blocktrans asvar course_cta_text %}Start learning now{% endblocktrans %} + {% endfilter %} {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text%} {% include "ace_common/edx_ace/common/upsell_cta.html"%} diff --git a/openedx/core/djangoapps/schedules/tests/test_content_highlights.py b/openedx/core/djangoapps/schedules/tests/test_content_highlights.py index 7cc9bc119fce629ea38878c07df0fc9e63bbd769..a98c0d070ab85712d6dff5910c36b07486898ce6 100644 --- a/openedx/core/djangoapps/schedules/tests/test_content_highlights.py +++ b/openedx/core/djangoapps/schedules/tests/test_content_highlights.py @@ -1,8 +1,13 @@ # -*- coding: utf-8 -*- +import datetime + +import mock from openedx.core.djangoapps.schedules.config import COURSE_UPDATE_WAFFLE_FLAG -from openedx.core.djangoapps.schedules.content_highlights import course_has_highlights, get_week_highlights +from openedx.core.djangoapps.schedules.content_highlights import ( + course_has_highlights, get_week_highlights, get_next_section_highlights, +) from openedx.core.djangoapps.schedules.exceptions import CourseUpdateDoesNotExist from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from openedx.core.djangolib.testing.utils import skip_unless_lms @@ -130,3 +135,41 @@ class TestContentHighlights(ModuleStoreTestCase): self.assertTrue(course_has_highlights(self.course_key)) with self.assertRaises(CourseUpdateDoesNotExist): get_week_highlights(self.user, self.course_key, week_num=1) + + @override_waffle_flag(COURSE_UPDATE_WAFFLE_FLAG, True) + @mock.patch('openedx.core.djangoapps.course_date_signals.utils.get_expected_duration') + def test_get_next_section_highlights(self, mock_duration): + mock_duration.return_value = datetime.timedelta(days=2) + yesterday = datetime.datetime.utcnow() - datetime.timedelta(days=1) + today = datetime.datetime.utcnow() + tomorrow = datetime.datetime.utcnow() + datetime.timedelta(days=1) + with self.store.bulk_operations(self.course_key): + self._create_chapter( # Week 1 + highlights=[u'a', u'b', u'á'], + ) + self._create_chapter( # Week 2 + highlights=[u'skipped a week'], + ) + + self.assertEqual( + get_next_section_highlights(self.user, self.course_key, yesterday, today.date()), + ([u'skipped a week'], 2), + ) + with self.assertRaises(CourseUpdateDoesNotExist): + get_next_section_highlights(self.user, self.course_key, yesterday, tomorrow.date()) + + @override_waffle_flag(COURSE_UPDATE_WAFFLE_FLAG, True) + @mock.patch('lms.djangoapps.courseware.module_render.get_module_for_descriptor') + def test_get_highlights_without_module(self, mock_get_module): + mock_get_module.return_value = None + + with self.store.bulk_operations(self.course_key): + self._create_chapter(highlights='Test highlight') + + with self.assertRaisesRegex(CourseUpdateDoesNotExist, 'Course module .* not found'): + get_week_highlights(self.user, self.course_key, 1) + + yesterday = datetime.datetime.utcnow() - datetime.timedelta(days=1) + today = datetime.datetime.utcnow() + with self.assertRaisesRegex(CourseUpdateDoesNotExist, 'Course module .* not found'): + get_next_section_highlights(self.user, self.course_key, yesterday, today.date()) diff --git a/openedx/core/djangoapps/schedules/tests/test_resolvers.py b/openedx/core/djangoapps/schedules/tests/test_resolvers.py index aa60ec7cab5cef183c700efb323d639ea8be5492..b38982a49293403375024b4ddc905d87456dd4b4 100644 --- a/openedx/core/djangoapps/schedules/tests/test_resolvers.py +++ b/openedx/core/djangoapps/schedules/tests/test_resolvers.py @@ -14,9 +14,11 @@ from mock import Mock, patch from waffle.testutils import override_switch from openedx.core.djangoapps.schedules.config import COURSE_UPDATE_WAFFLE_FLAG +from openedx.core.djangoapps.schedules.models import Schedule from openedx.core.djangoapps.schedules.resolvers import ( BinnedSchedulesBaseResolver, CourseUpdateResolver, + CourseNextSectionUpdate, ) from openedx.core.djangoapps.schedules.tests.factories import ScheduleConfigFactory from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfigurationFactory, SiteFactory @@ -167,3 +169,75 @@ class TestCourseUpdateResolver(SchedulesResolverTestMixin, ModuleStoreTestCase): self.user.save() schedules = resolver.get_schedules_with_target_date_by_bin_and_orgs() self.assertEqual(schedules.count(), 0) + + +@skip_unless_lms +@skipUnless('openedx.core.djangoapps.schedules.apps.SchedulesConfig' in settings.INSTALLED_APPS, + "Can't test schedules if the app isn't installed") +class TestCourseNextSectionUpdateResolver(SchedulesResolverTestMixin, ModuleStoreTestCase): + """ + Tests the TestCourseNextSectionUpdateResolver. + """ + def setUp(self): + super(TestCourseNextSectionUpdateResolver, self).setUp() + self.course = CourseFactory(highlights_enabled_for_messaging=True, self_paced=True) + self.yesterday = datetime.datetime.utcnow() - datetime.timedelta(days=1) + self.today = datetime.datetime.utcnow() + self.tomorrow = datetime.datetime.utcnow() + datetime.timedelta(days=1) + + with self.store.bulk_operations(self.course.id): + ItemFactory.create(parent=self.course, category='chapter', highlights=[u'good stuff 1'], due=self.yesterday) + ItemFactory.create(parent=self.course, category='chapter', highlights=[u'good stuff 2'], due=self.today) + ItemFactory.create(parent=self.course, category='chapter', highlights=[u'good stuff 3'], due=self.tomorrow) + + def create_resolver(self): + """ + Creates a CourseNextSectionUpdateResolver with an enrollment to schedule. + """ + with patch('openedx.core.djangoapps.schedules.signals.get_current_site') as mock_get_current_site: + mock_get_current_site.return_value = self.site_config.site + CourseEnrollmentFactory(course_id=self.course.id, user=self.user, mode=u'audit') + + return CourseNextSectionUpdate( + async_send_task=Mock(name='async_send_task'), + site=self.site_config.site, + target_datetime=self.yesterday, + course_key=self.course.id, + ) + + @override_settings(CONTACT_MAILING_ADDRESS='123 Sesame Street') + @override_waffle_flag(COURSE_UPDATE_WAFFLE_FLAG, True) + def test_schedule_context(self): + resolver = self.create_resolver() + # Mock the call to edx-when to just return all schedules + with patch('openedx.core.djangoapps.schedules.resolvers.get_schedules_with_due_date') as mock_get_schedules: + mock_get_schedules.return_value = Schedule.objects.all() + schedules = list(resolver.get_schedules()) + expected_context = { + 'contact_email': 'info@example.com', + 'contact_mailing_address': '123 Sesame Street', + 'course_ids': [str(self.course.id)], + 'course_name': self.course.display_name, + 'course_url': '/courses/{}/course/'.format(self.course.id), + 'dashboard_url': '/dashboard', + 'homepage_url': '/', + 'mobile_store_urls': {}, + 'platform_name': u'\xe9dX', + 'show_upsell': False, + 'social_media_urls': {}, + 'template_revision': 'release', + 'unsubscribe_url': None, + 'week_highlights': ['good stuff 2'], + 'week_num': 2, + } + self.assertEqual(schedules, [(self.user, None, expected_context, True)]) + + @override_waffle_flag(COURSE_UPDATE_WAFFLE_FLAG, True) + @override_switch('schedules.course_update_show_unsubscribe', True) + def test_schedule_context_show_unsubscribe(self): + resolver = self.create_resolver() + # Mock the call to edx-when to just return all schedules + with patch('openedx.core.djangoapps.schedules.resolvers.get_schedules_with_due_date') as mock_get_schedules: + mock_get_schedules.return_value = Schedule.objects.all() + schedules = list(resolver.get_schedules()) + self.assertIn('optout', schedules[0][2]['unsubscribe_url']) diff --git a/openedx/core/djangoapps/schedules/tests/test_tasks.py b/openedx/core/djangoapps/schedules/tests/test_tasks.py index 38a9b8e6551e7ebb77e985ddb0c062ff34bd5766..a4e9c6e7b2ba4e410a84612d618698d1ae76037c 100644 --- a/openedx/core/djangoapps/schedules/tests/test_tasks.py +++ b/openedx/core/djangoapps/schedules/tests/test_tasks.py @@ -11,7 +11,7 @@ from django.conf import settings from mock import DEFAULT, Mock, patch from openedx.core.djangoapps.schedules.resolvers import DEFAULT_NUM_BINS -from openedx.core.djangoapps.schedules.tasks import ScheduleMessageBaseTask +from openedx.core.djangoapps.schedules.tasks import BinnedScheduleMessageBaseTask from openedx.core.djangoapps.schedules.tests.factories import ScheduleConfigFactory from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms @@ -21,13 +21,13 @@ from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_un @skip_unless_lms @skipUnless('openedx.core.djangoapps.schedules.apps.SchedulesConfig' in settings.INSTALLED_APPS, "Can't test schedules if the app isn't installed") -class TestScheduleMessageBaseTask(CacheIsolationTestCase): +class TestBinnedScheduleMessageBaseTask(CacheIsolationTestCase): def setUp(self): - super(TestScheduleMessageBaseTask, self).setUp() + super(TestBinnedScheduleMessageBaseTask, self).setUp() self.site = SiteFactory.create() self.schedule_config = ScheduleConfigFactory.create(site=self.site) - self.basetask = ScheduleMessageBaseTask + self.basetask = BinnedScheduleMessageBaseTask def test_send_enqueue_disabled(self): send = Mock(name='async_send_task') diff --git a/openedx/core/djangoapps/schedules/tests/test_utils.py b/openedx/core/djangoapps/schedules/tests/test_utils.py index 70704948be9a234efe2f091e074941cef12a3098..3d2711c0a3400bd50d3ab6496e22490edb572f33 100644 --- a/openedx/core/djangoapps/schedules/tests/test_utils.py +++ b/openedx/core/djangoapps/schedules/tests/test_utils.py @@ -48,7 +48,7 @@ class ResetSelfPacedScheduleTests(SharedModuleStoreTestCase): self.create_schedule() original_start = self.schedule.start_date - with self.assertNumQueries(1): + with self.assertNumQueries(3): reset_self_paced_schedule(self.user, self.course.id, use_availability_date=False) self.schedule.refresh_from_db() @@ -63,7 +63,7 @@ class ResetSelfPacedScheduleTests(SharedModuleStoreTestCase): self.create_schedule(offset=offset) expected_start = self.course.start + datetime.timedelta(days=expected_offset) - with self.assertNumQueries(1): + with self.assertNumQueries(3): reset_self_paced_schedule(self.user, self.course.id, use_availability_date=True) self.schedule.refresh_from_db() diff --git a/openedx/core/djangoapps/schedules/utils.py b/openedx/core/djangoapps/schedules/utils.py index 3fd5f901ec32413006ea8a79b27a79749931b05b..282e91b84c5168a68b9959dfca6b35eae985bbd1 100644 --- a/openedx/core/djangoapps/schedules/utils.py +++ b/openedx/core/djangoapps/schedules/utils.py @@ -6,6 +6,7 @@ import logging import pytz from django.db.models import F, Subquery from django.db.models.functions import Greatest +from django.db import transaction from openedx.core.djangoapps.schedules.models import Schedule from student.models import CourseEnrollment @@ -48,25 +49,20 @@ def reset_self_paced_schedule(user, course_key, use_availability_date=False): course_key (CourseKey or str) use_availability_date (bool): if False, reset to now, else reset to when user got access to course material """ - schedule = Schedule.objects.filter( - enrollment__user=user, - enrollment__course__id=course_key, - enrollment__course__self_paced=True, - ) + with transaction.atomic(savepoint=False): + try: + schedule = Schedule.objects.select_related('enrollment', 'enrollment__course').get( + enrollment__user=user, + enrollment__course__id=course_key, + enrollment__course__self_paced=True, + ) + except Schedule.DoesNotExist: + return - if use_availability_date: - # Query enrollments to find availability date -- very similar to query above, but we can't reuse that query - # object because mysql doesn't like a subquery of an update to reference the same table being updated. - # Be careful attempting to remove this logic because you can't reproduce a problem locally -- in my own testing, - # I could not reproduce in devstack, but it was happening on prod databases. So implementations vary. - # See https://dev.mysql.com/doc/refman/8.0/en/subquery-restrictions.html - enrollments = CourseEnrollment.objects.filter( - user=user, - course__id=course_key, - course__self_paced=True, - ).annotate( - availability=Greatest(F('created'), F('course__start')), - ) - schedule.update(start_date=Subquery(enrollments.values('availability')[:1])) - else: - schedule.update(start_date=datetime.datetime.now(pytz.utc)) + if use_availability_date: + enrollment = schedule.enrollment + schedule.start_date = max(enrollment.created, enrollment.course.start) + schedule.save() + else: + schedule.start_date = datetime.datetime.now(pytz.utc) + schedule.save() diff --git a/openedx/core/djangoapps/signals/signals.py b/openedx/core/djangoapps/signals/signals.py index 06ef324aaf9b9a6f47d6accd31d9bf8858b7ae51..5bab209a541e2fb038e6b332404804c794b07791 100644 --- a/openedx/core/djangoapps/signals/signals.py +++ b/openedx/core/djangoapps/signals/signals.py @@ -13,6 +13,9 @@ COURSE_GRADE_CHANGED = Signal(providing_args=["user", "course_grade", "course_ke # rather than a User object; however, this will require changes to the milestones and badges APIs COURSE_CERT_CHANGED = Signal(providing_args=["user", "course_key", "mode", "status"]) COURSE_CERT_AWARDED = Signal(providing_args=["user", "course_key", "mode", "status"]) +COURSE_CERT_REVOKED = Signal(providing_args=["user", "course_key", "mode", "status"]) +COURSE_CERT_DATE_CHANGE = Signal(providing_args=["course_key"]) + # Signal that indicates that a user has passed a course. COURSE_GRADE_NOW_PASSED = Signal( diff --git a/openedx/core/djangoapps/site_configuration/helpers.py b/openedx/core/djangoapps/site_configuration/helpers.py index 45663497f3a9667f68ed2425e16882013e2ca2b3..9873a871b7bf28500034b840b2b6f7849759054c 100644 --- a/openedx/core/djangoapps/site_configuration/helpers.py +++ b/openedx/core/djangoapps/site_configuration/helpers.py @@ -4,8 +4,10 @@ Helpers methods for site configuration. from django.conf import settings +from openedx.core.lib.cache_utils import request_cached +@request_cached("site_config") def get_current_site_configuration(): """ Return configuration for the current site. diff --git a/openedx/core/djangoapps/site_configuration/management/commands/create_or_update_site_configuration.py b/openedx/core/djangoapps/site_configuration/management/commands/create_or_update_site_configuration.py index edcb0f19a417b2bd8e47e1bb8d529d0810f238b1..3fc92844b9fe974d1341d234bdb25f5d2c24a84e 100644 --- a/openedx/core/djangoapps/site_configuration/management/commands/create_or_update_site_configuration.py +++ b/openedx/core/djangoapps/site_configuration/management/commands/create_or_update_site_configuration.py @@ -17,7 +17,8 @@ LOG = logging.getLogger(__name__) def load_json_from_file(filename): - return json.load(codecs.open(filename, encoding='utf-8')) + with codecs.open(filename, encoding='utf-8') as file: + return json.load(file) class Command(BaseCommand): diff --git a/openedx/core/djangoapps/user_api/accounts/api.py b/openedx/core/djangoapps/user_api/accounts/api.py index f693c61682b54e4410f5f2be9cff2011b10fbd70..62d341c8a67daa8d45b01c525dfbf6ddb5160437 100644 --- a/openedx/core/djangoapps/user_api/accounts/api.py +++ b/openedx/core/djangoapps/user_api/accounts/api.py @@ -158,6 +158,7 @@ def update_account_settings(requesting_user, update, username=None): _notify_language_proficiencies_update_if_needed(update, user, user_profile, old_language_proficiencies) _store_old_name_if_needed(old_name, user_profile, requesting_user) _update_extended_profile_if_needed(update, user_profile) + _update_state_if_needed(update, user_profile) except PreferenceValidationError as err: raise AccountValidationError(err.preference_errors) @@ -290,6 +291,13 @@ def _update_extended_profile_if_needed(data, user_profile): user_profile.save() +def _update_state_if_needed(data, user_profile): + # If the country was changed to something other than US, remove the state. + if "country" in data and data['country'] != UserProfile.COUNTRY_WITH_STATES: + user_profile.state = None + user_profile.save() + + def _store_old_name_if_needed(old_name, user_profile, requesting_user): # If the name was changed, store information about the change operation. This is outside of the # serializer so that we can store who requested the change. diff --git a/openedx/core/djangoapps/user_api/accounts/serializers.py b/openedx/core/djangoapps/user_api/accounts/serializers.py index f22091416f99a4e39e9b8e5bca5d4d77f9238a46..7f197cb8b6e75ff93e8330175a6b719eb717d4cc 100644 --- a/openedx/core/djangoapps/user_api/accounts/serializers.py +++ b/openedx/core/djangoapps/user_api/accounts/serializers.py @@ -5,6 +5,7 @@ Django REST Framework serializers for the User API Accounts sub-application import json import logging +import re from django.conf import settings from django.contrib.auth.models import User @@ -16,7 +17,7 @@ from six import text_type from lms.djangoapps.badges.utils import badges_enabled from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.user_api import errors -from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled_for_user +from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled from openedx.core.djangoapps.user_api.models import RetirementState, UserPreference, UserRetirementStatus from openedx.core.djangoapps.user_api.serializers import ReadOnlyFieldsSerializerMixin from student.models import LanguageProficiency, SocialLink, UserProfile @@ -37,6 +38,15 @@ PROFILE_IMAGE_KEY_PREFIX = 'image_url' LOGGER = logging.getLogger(__name__) +class PhoneNumberSerializer(serializers.BaseSerializer): + """ + Class to serialize phone number into a digit only representation + """ + def to_internal_value(self, data): + """Remove all non numeric characters in phone number""" + return re.sub("[^0-9]", "", data) or None + + class LanguageProficiencySerializer(serializers.ModelSerializer): """ Class that serializes the LanguageProficiency model for account @@ -127,6 +137,7 @@ class UserReadOnlySerializer(serializers.Serializer): "is_active": user.is_active, "bio": None, "country": None, + "state": None, "profile_image": None, "language_proficiencies": None, "name": None, @@ -148,6 +159,7 @@ class UserReadOnlySerializer(serializers.Serializer): { "bio": AccountLegacyProfileSerializer.convert_empty_to_None(user_profile.bio), "country": AccountLegacyProfileSerializer.convert_empty_to_None(user_profile.country.code), + "state": AccountLegacyProfileSerializer.convert_empty_to_None(user_profile.state), "profile_image": AccountLegacyProfileSerializer.get_profile_image( user_profile, user, self.context.get('request') ), @@ -172,7 +184,7 @@ class UserReadOnlySerializer(serializers.Serializer): } ) - if is_secondary_email_feature_enabled_for_user(user): + if is_secondary_email_feature_enabled(): data.update( { "secondary_email": account_recovery.secondary_email if account_recovery else None, @@ -223,11 +235,12 @@ class AccountLegacyProfileSerializer(serializers.HyperlinkedModelSerializer, Rea requires_parental_consent = serializers.SerializerMethodField() language_proficiencies = LanguageProficiencySerializer(many=True, required=False) social_links = SocialLinkSerializer(many=True, required=False) + phone_number = PhoneNumberSerializer(required=False) class Meta(object): model = UserProfile fields = ( - "name", "gender", "goals", "year_of_birth", "level_of_education", "country", "social_links", + "name", "gender", "goals", "year_of_birth", "level_of_education", "country", "state", "social_links", "mailing_address", "bio", "profile_image", "requires_parental_consent", "language_proficiencies", "phone_number" ) diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_api.py b/openedx/core/djangoapps/user_api/accounts/tests/test_api.py index cc9b1de3f5a5840513df57fd3a683a23c263fcf5..f0eac87b1cf81d9ad02b13b20034f735873d3ec8 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_api.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_api.py @@ -481,6 +481,23 @@ class TestAccountApi(UserSettingsEventTestMixin, EmailTemplateTagMixin, CreateAc self.assertIsNot(account_recovery, None) self.assertEqual(account_recovery.secondary_email, test_email) + def test_change_country_removes_state(self): + ''' + Test that changing the country (to something other than a country with + states) removes the state + ''' + # First set the country and state + update_account_settings(self.user, {"country": UserProfile.COUNTRY_WITH_STATES, "state": "MA"}) + account_settings = get_account_settings(self.default_request)[0] + self.assertEqual(account_settings['country'], UserProfile.COUNTRY_WITH_STATES) + self.assertEqual(account_settings['state'], 'MA') + + # Change the country and check that state is removed + update_account_settings(self.user, {"country": ""}) + account_settings = get_account_settings(self.default_request)[0] + self.assertEqual(account_settings['country'], None) + self.assertEqual(account_settings['state'], None) + @patch('openedx.core.djangoapps.user_api.accounts.image_helpers._PROFILE_IMAGE_SIZES', [50, 10]) @patch.dict( @@ -521,6 +538,7 @@ class AccountSettingsOnCreationTest(CreateAccountMixin, TestCase): 'mailing_address': u'', 'year_of_birth': None, 'country': None, + 'state': None, 'social_links': [], 'bio': None, 'profile_image': { diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py index ac0155e36866a6b03d20ff16277f6c19d716b664..b9e17df87cee8b4ed3f4f43e58a1a62d2c95baf5 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py @@ -1320,6 +1320,7 @@ class TestAccountRetirementPost(RetirementTestCase): 'city': None, 'country': None, 'bio': None, + 'phone_number': None, } self.assertEqual(expected_user_profile_pii, USER_PROFILE_PII) diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_views.py index e6ff25201daef3908bd4dc388fc19a5219d1c32d..040e4fb59d73d51164c26eefcfaefad645b5aacf 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_views.py @@ -107,6 +107,7 @@ class UserAPITestCase(APITestCase): """ legacy_profile = UserProfile.objects.get(id=user.id) legacy_profile.country = "US" + legacy_profile.state = "MA" legacy_profile.level_of_education = "m" legacy_profile.year_of_birth = 2000 legacy_profile.goals = "world peace" @@ -266,7 +267,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): Verify that all account fields are returned (even those that are not shareable). """ data = response.data - self.assertEqual(24, len(data)) + self.assertEqual(25, len(data)) # public fields (3) expected_account_privacy = ( @@ -291,6 +292,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): # additional admin fields (10) self.assertEqual(self.user.email, data["email"]) self.assertIsNotNone(data["extended_profile"]) + self.assertEqual("MA", data["state"]) self.assertEqual("f", data["gender"]) self.assertEqual("world peace", data["goals"]) self.assertTrue(data["is_active"]) @@ -495,12 +497,13 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): with self.assertNumQueries(queries): response = self.send_get(self.client) data = response.data - self.assertEqual(24, len(data)) + self.assertEqual(25, len(data)) self.assertEqual(self.user.username, data["username"]) self.assertEqual(self.user.first_name + " " + self.user.last_name, data["name"]) for empty_field in ("year_of_birth", "level_of_education", "mailing_address", "bio"): self.assertIsNone(data[empty_field]) self.assertIsNone(data["country"]) + self.assertIsNone(data["state"]) self.assertEqual("m", data["gender"]) self.assertEqual("Learn a lot", data["goals"]) self.assertEqual(self.user.email, data["email"]) @@ -528,6 +531,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): """ legacy_profile = UserProfile.objects.get(id=self.user.id) legacy_profile.country = "" + legacy_profile.state = "" legacy_profile.level_of_education = "" legacy_profile.gender = "" legacy_profile.bio = "" @@ -536,7 +540,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): self.client.login(username=self.user.username, password=TEST_PASSWORD) with self.assertNumQueries(21): response = self.send_get(self.client) - for empty_field in ("level_of_education", "gender", "country", "bio"): + for empty_field in ("level_of_education", "gender", "country", "state", "bio",): self.assertIsNone(response.data[empty_field]) @ddt.data( @@ -572,6 +576,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): ("gender", "f", "not a gender", u'"not a gender" is not a valid choice.'), ("level_of_education", "none", u"ȻħȺÉłɇs", u'"ȻħȺÉłɇs" is not a valid choice.'), ("country", "GB", "XY", u'"XY" is not a valid choice.'), + ("state", "MA", "PY", u'"PY" is not a valid choice.'), ("year_of_birth", 2009, "not_an_int", u"A valid integer is required."), ("name", "bob", "z" * 256, u"Ensure this field has no more than 255 characters."), ("name", u"ȻħȺÉłɇs", " ", u"The name field must be at least 1 character long."), @@ -606,10 +611,15 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): if fails_validation_value: error_response = self.send_patch(client, {field: fails_validation_value}, expected_status=400) + expected_user_message = u'This value is invalid.' + if field == 'bio': + expected_user_message = u"The about me field must be at most 300 characters long." + self.assertEqual( - u'This value is invalid.', + expected_user_message, error_response.data["field_errors"][field]["user_message"] ) + self.assertEqual( u"Value '{value}' is not valid for field '{field}': {messages}".format( value=fails_validation_value, field=field, messages=[developer_validation_message] @@ -677,7 +687,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): Also verifies the behaviour when setting to None. """ self.client.login(username=self.user.username, password=TEST_PASSWORD) - for field_name in ["gender", "level_of_education", "country"]: + for field_name in ["gender", "level_of_education", "country", "state"]: response = self.send_patch(self.client, {field_name: ""}) # Although throwing a 400 might be reasonable, the default DRF behavior with ModelSerializer # is to convert to None, which also seems acceptable (and is difficult to override). @@ -906,12 +916,12 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): response = self.send_get(client) if has_full_access: data = response.data - self.assertEqual(24, len(data)) + self.assertEqual(25, len(data)) self.assertEqual(self.user.username, data["username"]) self.assertEqual(self.user.first_name + " " + self.user.last_name, data["name"]) self.assertEqual(self.user.email, data["email"]) self.assertEqual(year_of_birth, data["year_of_birth"]) - for empty_field in ("country", "level_of_education", "mailing_address", "bio"): + for empty_field in ("country", "level_of_education", "mailing_address", "bio", "state",): self.assertIsNone(data[empty_field]) self.assertEqual("m", data["gender"]) self.assertEqual("Learn a lot", data["goals"]) diff --git a/openedx/core/djangoapps/user_api/accounts/utils.py b/openedx/core/djangoapps/user_api/accounts/utils.py index 9b4667b9d8ea7627dfc30aae04b35d2083cd78a2..64fdd2bc0613d4df22cd4ddb8b713d71c00f6e25 100644 --- a/openedx/core/djangoapps/user_api/accounts/utils.py +++ b/openedx/core/djangoapps/user_api/accounts/utils.py @@ -111,7 +111,7 @@ def _is_valid_social_username(value): def retrieve_last_sitewide_block_completed(user): """ Completion utility - From a string 'username' or object User retrieve + From a given User object retrieve the last course block marked as 'completed' and construct a URL :param user: obj(User) @@ -192,18 +192,6 @@ def is_secondary_email_feature_enabled(): return waffle.switch_is_active(ENABLE_SECONDARY_EMAIL_FEATURE_SWITCH) -def is_secondary_email_feature_enabled_for_user(user): - """ - Checks to see if secondary email feature is enabled for the given user. - - Returns: - Boolean value representing the status of secondary email feature. - """ - # import is placed here to avoid cyclic import. - from openedx.features.enterprise_support.utils import is_enterprise_learner - return is_secondary_email_feature_enabled() and is_enterprise_learner(user) - - def is_multiple_user_enterprises_feature_enabled(): """ Checks to see if the django-waffle switch for enabling the multiple user enterprises feature is active diff --git a/openedx/core/djangoapps/user_api/accounts/views.py b/openedx/core/djangoapps/user_api/accounts/views.py index 2be29ba74b04c028945436b7a16ffc03ac14aff3..c319af66d69b7ffbb3ab32daee61aeee0fd3a956 100644 --- a/openedx/core/djangoapps/user_api/accounts/views.py +++ b/openedx/core/djangoapps/user_api/accounts/views.py @@ -94,6 +94,7 @@ USER_PROFILE_PII = { 'city': None, 'country': None, 'bio': None, + 'phone_number': None, } @@ -591,9 +592,11 @@ class AccountRetirementPartnerReportView(ViewSet): """ PUT /api/user/v1/accounts/retirement_partner_report/ + ``` { 'username': 'user_to_retire' } + ``` Creates a UserRetirementPartnerReportingStatus object for the given user as part of the retirement pipeline. @@ -778,11 +781,13 @@ class AccountRetirementStatusView(ViewSet): """ PATCH /api/user/v1/accounts/update_retirement_status/ + ``` { 'username': 'user_to_retire', 'new_state': 'LOCKING_COMPLETE', 'response': 'User account locked and logged out.' } + ``` Updates the RetirementStatus row for the given user to the new status, and append any messages to the message log. @@ -825,9 +830,11 @@ class AccountRetirementStatusView(ViewSet): """ POST /api/user/v1/accounts/retirement_cleanup/ + ``` { 'usernames': ['user1', 'user2', ...] } + ``` Deletes a batch of retirement requests by username. """ @@ -868,9 +875,11 @@ class LMSAccountRetirementView(ViewSet): """ POST /api/user/v1/accounts/retire_misc/ + ``` { 'username': 'user_to_retire' } + ``` Retires the user with the given username in the LMS. """ @@ -922,9 +931,11 @@ class AccountRetirementView(ViewSet): """ POST /api/user/v1/accounts/retire/ + ``` { 'username': 'user_to_retire' } + ``` Retires the user with the given username. This includes retiring this username, the associated email address, and @@ -1057,12 +1068,14 @@ class UsernameReplacementView(APIView): def post(self, request): """ POST /api/user/v1/accounts/replace_usernames/ + ``` { "username_mappings": [ {"current_username_1": "desired_username_1"}, {"current_username_2": "desired_username_2"} ] } + ``` **POST Parameters** @@ -1076,6 +1089,7 @@ class UsernameReplacementView(APIView): As long as data validation passes, the request will return a 200 with a new mapping of old usernames (key) to new username (value) + ``` { "successful_replacements": [ {"old_username_1": "new_username_1"} @@ -1084,6 +1098,8 @@ class UsernameReplacementView(APIView): {"old_username_2": "new_username_2"} ] } + ``` + """ # (model_name, column_name) diff --git a/openedx/core/djangoapps/user_api/admin.py b/openedx/core/djangoapps/user_api/admin.py index 66750d8d0faad20d40fea4f92d11bf6aeb0061c7..eb01bb24ffc4a893d6c951d3492c05300d25a088 100644 --- a/openedx/core/djangoapps/user_api/admin.py +++ b/openedx/core/djangoapps/user_api/admin.py @@ -115,7 +115,6 @@ class UserRetirementStatusAdmin(admin.ModelAdmin): return format_html('') retirement_actions.short_description = _('Actions') - retirement_actions.allow_tags = True def get_actions(self, request): """ diff --git a/openedx/core/djangoapps/user_api/management/commands/retire_user.py b/openedx/core/djangoapps/user_api/management/commands/retire_user.py new file mode 100644 index 0000000000000000000000000000000000000000..7851cf1af6fe31683dbb0a72c396e9eaf94c1366 --- /dev/null +++ b/openedx/core/djangoapps/user_api/management/commands/retire_user.py @@ -0,0 +1,99 @@ +import logging + +from django.contrib.auth import get_user_model, logout +from django.contrib.auth.models import User +from django.core.management.base import BaseCommand, CommandError +from django.db import transaction +from social_django.models import UserSocialAuth + +from student.models import AccountRecovery, Registration, get_retired_email_by_email +from openedx.core.djangolib.oauth2_retirement_utils import retire_dot_oauth2_models + +from ...models import UserRetirementStatus + + +logger = logging.getLogger(__name__) + + +class Command(BaseCommand): + """ + Manually move a user into the retirement queue, so that they can be + picked up by the user retirement pipeline. This should only be done in + the case that a user has tried and is unable to delete their account + via the UI. + + Most of this code has been lifted from openedx/core/djangoapps/user_api/accounts/views + + As this is a fairly sensitive operation, we want to make sure that human + error is accounted for. In order to make sure that something like a typo + during command invocation does not result in the retirement of a + different user, you must supply both the username and email address linked + to the user account. + """ + + def add_arguments(self, parser): + parser.add_argument( + '--username', + required=True, + type=str, + help='Username to be retired' + ) + parser.add_argument( + '--user_email', + required=True, + type=str, + help='User email address.' + ) + + def handle(self, *args, **options): + """ + Execute the command. + """ + + username = options['username'] + user_email = options['user_email'] + try: + user = User.objects.get(username=username, email=user_email) + except: + error_message = ( + 'Could not find a user with specified username and email ' + 'address. Make sure you have everything correct before ' + 'trying again' + ) + logger.error(error_message) + raise CommandError(error_message) + + user_model = get_user_model() + + try: + with transaction.atomic(): + # Add user to retirement queue. + UserRetirementStatus.create_retirement(user) + # Unlink LMS social auth accounts + UserSocialAuth.objects.filter(user_id=user.id).delete() + # Change LMS password & email + user.email = get_retired_email_by_email(user.email) + user.set_unusable_password() + user.save() + + # TODO: Unlink social accounts & change password on each IDA. + # Remove the activation keys sent by email to the user for account activation. + Registration.objects.filter(user=user).delete() + + # Delete OAuth tokens associated with the user. + retire_dot_oauth2_models(user) + AccountRecovery.retire_recovery_email(user.id) + except KeyError: + error_message = 'Username not specified {}'.format(user) + logger.error(error_message) + raise CommandError(error_message) + except user_model.DoesNotExist: + error_message = 'The user "{}" does not exist.'.format(user.username) + logger.error(error_message) + raise CommandError(error_message) + except Exception as exc: # pylint: disable=broad-except + error_message = '500 error deactivating account {}'.format(exc) + logger.error(error_message) + raise CommandError(error_message) + + logger.info("User succesfully moved to the retirment pipeline") diff --git a/openedx/core/djangoapps/user_api/management/tests/test_retire_user.py b/openedx/core/djangoapps/user_api/management/tests/test_retire_user.py new file mode 100644 index 0000000000000000000000000000000000000000..46e5dcfc39ea4bd63620075a155538ad1242fa66 --- /dev/null +++ b/openedx/core/djangoapps/user_api/management/tests/test_retire_user.py @@ -0,0 +1,41 @@ +""" +Test the retire_user management command +""" + + +import pytest +from django.contrib.auth.models import User +from django.core.management import CommandError, call_command + +from ...models import UserRetirementStatus +from openedx.core.djangoapps.user_api.accounts.tests.retirement_helpers import ( # pylint: disable=unused-import + setup_retirement_states +) +from openedx.core.djangolib.testing.utils import skip_unless_lms +from student.tests.factories import UserFactory + + +pytestmark = pytest.mark.django_db + + +@skip_unless_lms +def test_successful_retire(setup_retirement_states): + user = UserFactory() + username = user.username + user_email = user.email + call_command('retire_user', username=username, user_email=user_email) + user = User.objects.get(username=username) + retired_user_status = UserRetirementStatus.objects.all()[0] + assert retired_user_status.original_username == username + assert retired_user_status.original_email == user_email + # Make sure that we have changed the email address linked to the original user + assert user.email != user_email + + +@skip_unless_lms +def test_retire_user_with_usename_email_mismatch(setup_retirement_states): + user = UserFactory() + username = user.username + user_email = "other@edx.org" + with pytest.raises(CommandError, match=r'Could not find a user with specified username and email address'): + call_command('retire_user', username=username, user_email=user_email) diff --git a/openedx/core/djangoapps/user_api/partition_schemes.py b/openedx/core/djangoapps/user_api/partition_schemes.py index 2ab42ffd572684552f473d0da9ecd3a628a79d6d..eeb55faa1745bfb2cc9cc78747951e27aef1ee0b 100644 --- a/openedx/core/djangoapps/user_api/partition_schemes.py +++ b/openedx/core/djangoapps/user_api/partition_schemes.py @@ -65,7 +65,7 @@ class RandomUserPartitionScheme(object): group = user_partition.get_group(int(group_id)) except NoSuchUserPartitionGroupError: # jsa: we can turn off warnings here if this is an expected case. - log.warn( + log.warning( u"group not found in RandomUserPartitionScheme: %r", { "requested_partition_id": user_partition.id, diff --git a/openedx/core/djangoapps/user_authn/cookies.py b/openedx/core/djangoapps/user_authn/cookies.py index f6a6ffe7b524a63e5a480df57b02e5951bb7c7e5..159084b7ee04f7cc938d27ce3e6fab14b74d0646 100644 --- a/openedx/core/djangoapps/user_authn/cookies.py +++ b/openedx/core/djangoapps/user_authn/cookies.py @@ -12,7 +12,7 @@ from django.conf import settings from django.contrib.auth.models import User from django.dispatch import Signal from django.urls import NoReverseMatch, reverse -from django.utils.http import cookie_date +from django.utils.http import http_date from edx_rest_framework_extensions.auth.jwt import cookies as jwt_cookies from edx_rest_framework_extensions.auth.jwt.constants import JWT_DELIMITER from oauth2_provider.models import Application @@ -113,7 +113,7 @@ def _set_expires_in_cookie_settings(cookie_settings, expires_in): based on the value of expires_in. """ expires_time = time.time() + expires_in - expires = cookie_date(expires_time) + expires = http_date(expires_time) cookie_settings.update({ 'max_age': expires_in, diff --git a/openedx/core/djangoapps/user_authn/urls.py b/openedx/core/djangoapps/user_authn/urls.py index 6b15b052ca7205d17fbd57d345d2f6fff48b3c5d..61726b93523ff9c84c2fa1c815e4605558c62ced 100644 --- a/openedx/core/djangoapps/user_authn/urls.py +++ b/openedx/core/djangoapps/user_authn/urls.py @@ -20,4 +20,6 @@ urlpatterns += [ {'initial_mode': 'login'}, name='signin_user'), url(r'^register$', login_form.login_and_registration_form, {'initial_mode': 'register'}, name='register_user'), + url(r'^password_assistance', login_form.login_and_registration_form, + {'initial_mode': 'reset'}, name='password_assistance'), ] diff --git a/openedx/core/djangoapps/user_authn/urls_common.py b/openedx/core/djangoapps/user_authn/urls_common.py index f51c789a9b4359f9b72508460d9dab61e43e5ebc..20d0982eec8e69f466a792a4dfe96df0d26bd5b8 100644 --- a/openedx/core/djangoapps/user_authn/urls_common.py +++ b/openedx/core/djangoapps/user_authn/urls_common.py @@ -27,6 +27,10 @@ urlpatterns = [ url(r'^user_api/v1/account/registration/$', register.RegistrationView.as_view(), name="user_api_registration"), + # V2 is created to avoid backward compatibility issue with confirm_email + url(r'^user_api/v2/account/registration/$', register.RegistrationView.as_view(), + name="user_api_registration_v2"), + # Moved from user_api/urls.py # `api/user` prefix is preserved for backwards compatibility. url( diff --git a/openedx/core/djangoapps/user_authn/utils.py b/openedx/core/djangoapps/user_authn/utils.py index e9fddab58f41b6bc141f8d73471fd920bece01eb..2ed90062f136e62ed550dbebf6ee410cb1b8b9c1 100644 --- a/openedx/core/djangoapps/user_authn/utils.py +++ b/openedx/core/djangoapps/user_authn/utils.py @@ -58,3 +58,12 @@ def generate_password(length=12, chars=string.ascii_letters + string.digits): password += choice(string.ascii_letters) password += ''.join([choice(chars) for _i in range(length - 2)]) return password + + +def is_registration_api_v1(request): + """ + Checks if registration api is v1 + :param request: + :return: Bool + """ + return 'v1' in request.get_full_path() and 'register' not in request.get_full_path() diff --git a/openedx/core/djangoapps/user_authn/views/auto_auth.py b/openedx/core/djangoapps/user_authn/views/auto_auth.py index 4e24e3389fea26a3df7fae6d45e7bdac82581fe5..6e4a9a8bc35291e1023836b6801bcceb6f0a270e 100644 --- a/openedx/core/djangoapps/user_authn/views/auto_auth.py +++ b/openedx/core/djangoapps/user_authn/views/auto_auth.py @@ -189,7 +189,7 @@ def auto_auth(request): # pylint: disable=too-many-statements 'user_id': user.id, 'anonymous_id': anonymous_id_for_user(user, None), }) - response.set_cookie('csrftoken', csrf(request)['csrf_token']) + response.set_cookie('csrftoken', csrf(request)['csrf_token'], secure=request.is_secure()) return response diff --git a/openedx/core/djangoapps/user_authn/views/login.py b/openedx/core/djangoapps/user_authn/views/login.py index b8c712aca127e51c64ae80ac6f0b8a97829e7d8d..7d6068b3110e7ffcd9e41ea842b6bc043b70cf14 100644 --- a/openedx/core/djangoapps/user_authn/views/login.py +++ b/openedx/core/djangoapps/user_authn/views/login.py @@ -113,8 +113,21 @@ def _check_excessive_login_attempts(user): """ if user and LoginFailures.is_feature_enabled(): if LoginFailures.is_user_locked_out(user): - raise AuthFailedError(_('This account has been temporarily locked due ' - 'to excessive login failures. Try again later.')) + _generate_locked_out_error_message() + + +def _generate_locked_out_error_message(): + + locked_out_period_in_sec = settings.MAX_FAILED_LOGIN_ATTEMPTS_LOCKOUT_PERIOD_SECS + raise AuthFailedError(Text(_('To protect your account, it’s been temporarily ' + 'locked. Try again in {locked_out_period} minutes.' + '{li_start}To be on the safe side, you can reset your ' + 'password {link_start}here{link_end} before you try again.')).format( + link_start=HTML('<a "#login" class="form-toggle" data-type="password-reset">'), + link_end=HTML('</a>'), + li_start=HTML('<li>'), + li_end=HTML('</li>'), + locked_out_period=int(locked_out_period_in_sec / 60))) def _enforce_password_policy_compliance(request, user): @@ -230,6 +243,27 @@ def _handle_failed_authentication(user, authenticated_user): else: AUDIT_LOG.warning(u"Login failed - password for {0} is invalid".format(user.email)) + if user and LoginFailures.is_feature_enabled(): + blocked_threshold, failure_count = LoginFailures.check_user_reset_password_threshold(user) + if blocked_threshold: + if not LoginFailures.is_user_locked_out(user): + max_failures_allowed = settings.MAX_FAILED_LOGIN_ATTEMPTS_ALLOWED + remaining_attempts = max_failures_allowed - failure_count + raise AuthFailedError(Text(_('Email or password is incorrect.' + '{li_start}You have {remaining_attempts} more sign-in ' + 'attempts before your account is temporarily locked.{li_end}' + '{li_start}If you\'ve forgotten your password, click ' + '{link_start}here{link_end} to reset.{li_end}' + )) + .format( + link_start=HTML('<a http="#login" class="form-toggle" data-type="password-reset">'), + link_end=HTML('</a>'), + li_start=HTML('<li>'), + li_end=HTML('</li>'), + remaining_attempts=remaining_attempts)) + else: + _generate_locked_out_error_message() + raise AuthFailedError(_('Email or password is incorrect.')) diff --git a/openedx/core/djangoapps/user_authn/views/login_form.py b/openedx/core/djangoapps/user_authn/views/login_form.py index 0d850eae304f5232dd9b76f3c04c385da3da4592..adabf22f029a8b501393804a5daf89d2ac2faa0d 100644 --- a/openedx/core/djangoapps/user_authn/views/login_form.py +++ b/openedx/core/djangoapps/user_authn/views/login_form.py @@ -12,6 +12,7 @@ from django.urls import reverse from django.utils.translation import ugettext as _ from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.http import require_http_methods +from ratelimit.decorators import ratelimit import third_party_auth from edxmako.shortcuts import render_to_response @@ -28,7 +29,8 @@ from openedx.core.djangoapps.user_authn.views.registration_form import Registrat from openedx.features.enterprise_support.api import enterprise_customer_for_request from openedx.features.enterprise_support.utils import ( handle_enterprise_cookies_for_logistration, - update_logistration_context_for_enterprise + get_enterprise_slug_login_url, + update_logistration_context_for_enterprise, ) from student.helpers import get_next_url_for_login_page from third_party_auth import pipeline @@ -123,6 +125,12 @@ def get_login_session_form(request): @require_http_methods(['GET']) +@ratelimit( + key='openedx.core.djangoapps.util.ratelimit.real_ip', + rate=settings.LOGISTRATION_RATELIMIT_RATE, + method='GET', + block=True +) @ensure_csrf_cookie @xframe_allow_whitelisted def login_and_registration_form(request, initial_mode="login"): @@ -211,7 +219,8 @@ def login_and_registration_form(request, initial_mode="login"): 'account_creation_allowed': configuration_helpers.get_value( 'ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION', True)), 'is_account_recovery_feature_enabled': is_secondary_email_feature_enabled(), - 'is_multiple_user_enterprises_feature_enabled': is_multiple_user_enterprises_feature_enabled() + 'is_multiple_user_enterprises_feature_enabled': is_multiple_user_enterprises_feature_enabled(), + 'enterprise_slug_login_url': get_enterprise_slug_login_url() }, 'login_redirect_url': redirect_to, # This gets added to the query string of the "Sign In" button in header 'responsive': True, diff --git a/openedx/core/djangoapps/user_authn/views/password_reset.py b/openedx/core/djangoapps/user_authn/views/password_reset.py index 9715db635801575f6a0de6032c05561d33f3d57e..066ee2f47bda70ebc573cdb336f27c5a250a0ef8 100644 --- a/openedx/core/djangoapps/user_authn/views/password_reset.py +++ b/openedx/core/djangoapps/user_authn/views/password_reset.py @@ -43,7 +43,7 @@ from student.forms import send_account_recovery_email_for_user from student.models import AccountRecovery from util.json_request import JsonResponse from util.password_policy_validators import normalize_password, validate_password -from util.request_rate_limiter import BadRequestRateLimiter, PasswordResetEmailRateLimiter +from util.request_rate_limiter import PasswordResetEmailRateLimiter SETTING_CHANGE_INITIATED = 'edx.user.settings.change_initiated' @@ -242,11 +242,18 @@ def password_reset(request): """ Attempts to send a password reset e-mail. """ - # Add some rate limiting here by re-using the RateLimitMixin as a helper class - limiter = BadRequestRateLimiter() - if limiter.is_rate_limit_exceeded(request): - AUDIT_LOG.warning("Rate limit exceeded in password_reset") - return HttpResponseForbidden() + + password_reset_email_limiter = PasswordResetEmailRateLimiter() + + if password_reset_email_limiter.is_rate_limit_exceeded(request): + AUDIT_LOG.warning("Password reset rate limit exceeded") + return JsonResponse( + { + 'success': False, + 'value': _("Your previous request is in progress, please try again in a few moments.") + }, + status=403 + ) form = PasswordResetFormNoActive(request.POST) if form.is_valid(): @@ -269,7 +276,8 @@ def password_reset(request): else: # bad user? tick the rate limiter counter AUDIT_LOG.info("Bad password_reset user passed in.") - limiter.tick_request_counter(request) + + password_reset_email_limiter.tick_request_counter(request) return JsonResponse({ 'success': True, diff --git a/openedx/core/djangoapps/user_authn/views/register.py b/openedx/core/djangoapps/user_authn/views/register.py index e2dccbbf5142f1538fc2c1f389a87c50f01499d8..d9105f4702d23874b5f5c108a0d091f86933b4c7 100644 --- a/openedx/core/djangoapps/user_authn/views/register.py +++ b/openedx/core/djangoapps/user_authn/views/register.py @@ -48,7 +48,7 @@ from openedx.core.djangoapps.user_api.accounts.api import ( get_username_existence_validation_error, get_username_validation_error ) -from openedx.core.djangoapps.user_authn.utils import generate_password +from openedx.core.djangoapps.user_authn.utils import generate_password, is_registration_api_v1 from openedx.core.djangoapps.user_api.preferences import api as preferences_api from openedx.core.djangoapps.user_authn.cookies import set_logged_in_cookies from openedx.core.djangoapps.user_authn.views.registration_form import ( @@ -56,6 +56,7 @@ from openedx.core.djangoapps.user_authn.views.registration_form import ( AccountCreationForm, RegistrationFormFactory ) +from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace from student.helpers import ( authenticate_new_user, create_or_set_user_attribute_created_on_site, @@ -94,6 +95,24 @@ REGISTRATION_UTM_CREATED_AT = 'registration_utm_created_at' REGISTER_USER = Signal(providing_args=["user", "registration"]) +# .. feature_toggle_name: registration.enable_failure_logging +# .. feature_toggle_type: flag +# .. feature_toggle_default: False +# .. feature_toggle_description: Enable verbose logging of registration failure messages +# .. feature_toggle_category: registration +# .. feature_toggle_use_cases: monitored_rollout +# .. feature_toggle_creation_date: 2020-04-30 +# .. feature_toggle_expiration_date: 2020-06-01 +# .. feature_toggle_warnings: None +# .. feature_toggle_tickets: None +# .. feature_toggle_status: supported +REGISTRATION_FAILURE_LOGGING_FLAG = WaffleFlag( + waffle_namespace=WaffleFlagNamespace(name=u'registration'), + flag_name=u'enable_failure_logging', + flag_undefined_default=False +) + + @transaction.non_atomic_requests def create_account_with_params(request, params): """ @@ -138,6 +157,10 @@ def create_account_with_params(request, params): 'REGISTRATION_EXTRA_FIELDS', getattr(settings, 'REGISTRATION_EXTRA_FIELDS', {}) ) + if is_registration_api_v1(request): + if 'confirm_email' in extra_fields: + del extra_fields['confirm_email'] + # registration via third party (Google, Facebook) using mobile application # doesn't use social auth pipeline (no redirect uri(s) etc involved). # In this case all related info (required for account linking) @@ -463,7 +486,7 @@ class RegistrationView(APIView): data = request.POST.copy() self._handle_terms_of_service(data) - response = self._handle_duplicate_email_username(data) + response = self._handle_duplicate_email_username(request, data) if response: return response @@ -471,11 +494,11 @@ class RegistrationView(APIView): if response: return response - response = self._create_response({}, status_code=200) + response = self._create_response(request, {}, status_code=200) set_logged_in_cookies(request, response, user) return response - def _handle_duplicate_email_username(self, data): + def _handle_duplicate_email_username(self, request, data): # pylint: disable=no-member # TODO Verify whether this check is needed here - it may be duplicated in user_api. email = data.get('email') @@ -489,7 +512,7 @@ class RegistrationView(APIView): errors["username"] = [{"user_message": accounts_settings.USERNAME_CONFLICT_MSG.format(username=username)}] if errors: - return self._create_response(errors, status_code=409) + return self._create_response(request, errors, status_code=409) def _handle_terms_of_service(self, data): # Backwards compatibility: the student view expects both @@ -510,7 +533,7 @@ class RegistrationView(APIView): errors = { err.field: [{"user_message": text_type(err)}] } - response = self._create_response(errors, status_code=409) + response = self._create_response(request, errors, status_code=409) except ValidationError as err: # Should only get field errors from this exception assert NON_FIELD_ERRORS not in err.message_dict @@ -519,18 +542,39 @@ class RegistrationView(APIView): field: [{"user_message": error} for error in error_list] for field, error_list in err.message_dict.items() } - response = self._create_response(errors, status_code=400) + response = self._create_response(request, errors, status_code=400) except PermissionDenied: response = HttpResponseForbidden(_("Account creation not allowed.")) return response, user - def _create_response(self, response_dict, status_code): + def _create_response(self, request, response_dict, status_code): if status_code == 200: # keeping this `success` field in for now, as we have outstanding clients expecting this response_dict['success'] = True + else: + self._log_validation_errors(request, response_dict, status_code) + return JsonResponse(response_dict, status=status_code) + def _log_validation_errors(self, request, errors, status_code): + if not REGISTRATION_FAILURE_LOGGING_FLAG.is_enabled(): + return + + try: + for field_key, errors in errors.items(): + for error in errors: + log.info( + 'message=registration_failed, status_code=%d, agent="%s", field="%s", error="%s"', + status_code, + request.META.get('HTTP_USER_AGENT', ''), + field_key, + error['user_message'] + ) + except: # pylint: disable=bare-except + log.exception("Failed to log registration validation error") + pass + class RegistrationValidationThrottle(AnonRateThrottle): """ @@ -687,14 +731,16 @@ class RegistrationValidationView(APIView): POST /api/user/v1/validation/registration/ Expects request of the form - >>> { - >>> "name": "Dan the Validator", - >>> "username": "mslm", - >>> "email": "mslm@gmail.com", - >>> "confirm_email": "mslm@gmail.com", - >>> "password": "password123", - >>> "country": "PK" - >>> } + ``` + { + "name": "Dan the Validator", + "username": "mslm", + "email": "mslm@gmail.com", + "confirm_email": "mslm@gmail.com", + "password": "password123", + "country": "PK" + } + ``` where each key is the appropriate form field name and the value is user input. One may enter individual inputs if needed. Some inputs can get extra verification checks if entered along with others, diff --git a/openedx/core/djangoapps/user_authn/views/registration_form.py b/openedx/core/djangoapps/user_authn/views/registration_form.py index 6c29b4756d369d5216154e41d816f7156eb7de81..fbc7ce5344875a49d2195ade99e8977a746a0f71 100644 --- a/openedx/core/djangoapps/user_authn/views/registration_form.py +++ b/openedx/core/djangoapps/user_authn/views/registration_form.py @@ -2,7 +2,6 @@ Objects and utilities used to construct registration forms. """ - import copy from importlib import import_module import re @@ -24,6 +23,7 @@ from edxmako.shortcuts import marketing_link from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.user_api import accounts from openedx.core.djangoapps.user_api.helpers import FormDescription +from openedx.core.djangoapps.user_authn.utils import is_registration_api_v1 as is_api_v1 from openedx.core.djangolib.markup import HTML, Text from openedx.features.enterprise_support.api import enterprise_customer_for_request from student.models import ( @@ -42,6 +42,7 @@ class TrueCheckbox(widgets.CheckboxInput): """ A checkbox widget that only accepts "true" (case-insensitive) as true. """ + def value_from_datadict(self, data, files, name): value = data.get(name, '') return value.lower() == 'true' @@ -164,12 +165,12 @@ class AccountCreationForm(forms.Form): ) def __init__( - self, - data=None, - extra_fields=None, - extended_profile_fields=None, - do_third_party_auth=True, - tos_required=True + self, + data=None, + extra_fields=None, + extended_profile_fields=None, + do_third_party_auth=True, + tos_required=True ): super(AccountCreationForm, self).__init__(data) @@ -350,10 +351,11 @@ class RegistrationFormFactory(object): field_order = configuration_helpers.get_value('REGISTRATION_FIELD_ORDER') if not field_order: field_order = settings.REGISTRATION_FIELD_ORDER or valid_fields - - # Check that all of the valid_fields are in the field order and vice versa, if not set to the default order + # Check that all of the valid_fields are in the field order and vice versa, + # if not append missing fields at end of field order if set(valid_fields) != set(field_order): - field_order = valid_fields + difference = set(valid_fields).difference(set(field_order)) + field_order.extend(difference) self.field_order = field_order @@ -372,7 +374,7 @@ class RegistrationFormFactory(object): Returns: HttpResponse """ - form_desc = FormDescription("post", reverse("user_api_registration")) + form_desc = FormDescription("post", self._get_registration_submit_url(request)) self._apply_third_party_auth_overrides(request, form_desc) # Custom form fields can be added via the form set in settings.REGISTRATION_EXTENSION_FORM @@ -428,9 +430,17 @@ class RegistrationFormFactory(object): form_desc, required=self._is_field_required(field_name) ) - + # remove confirm_email form v1 registration form + if is_api_v1(request): + for index, field in enumerate(form_desc.fields): + if field['name'] == 'confirm_email': + del form_desc.fields[index] + break return form_desc + def _get_registration_submit_url(self, request): + return reverse("user_api_registration") if is_api_v1(request) else reverse("user_api_registration_v2") + def _add_email_field(self, form_desc, required=True): """Add an email field to a form description. Arguments: @@ -473,6 +483,7 @@ class RegistrationFormFactory(object): form_desc.add_field( "confirm_email", + field_type="email", label=email_label, required=required, error_messages={ @@ -951,7 +962,6 @@ class RegistrationFormFactory(object): field_type = 'checkbox' if not separate_honor_and_tos: - field_type = 'plaintext' pp_link = marketing_link("PRIVACY") @@ -1068,10 +1078,11 @@ class RegistrationFormFactory(object): field_name, default=field_overrides[field_name] ) - if (field_name not in ['terms_of_service', 'honor_code'] - and field_overrides[field_name] - and hide_registration_fields_except_tos): - + if ( + field_name not in ['terms_of_service', 'honor_code'] and + field_overrides[field_name] and + hide_registration_fields_except_tos + ): form_desc.override_field_properties( field_name, field_type="hidden", @@ -1079,6 +1090,17 @@ class RegistrationFormFactory(object): instructions="", ) + # Hide the confirm_email field + form_desc.override_field_properties( + "confirm_email", + default="", + field_type="hidden", + required=False, + label="", + instructions="", + restrictions={} + ) + # Hide the password field form_desc.override_field_properties( "password", diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_logistration.py b/openedx/core/djangoapps/user_authn/views/tests/test_logistration.py index 1e0c4612e87e6760ce7a24c0de4529bfdda7cfcd..e99e6afe519f35f1b084acf4aafa027542c49ff9 100644 --- a/openedx/core/djangoapps/user_authn/views/tests/test_logistration.py +++ b/openedx/core/djangoapps/user_authn/views/tests/test_logistration.py @@ -2,6 +2,7 @@ """ Tests for Logistration views. """ +from datetime import datetime, timedelta from http.cookies import SimpleCookie import ddt @@ -17,6 +18,8 @@ from django.test.client import RequestFactory from django.test.utils import override_settings from django.urls import reverse from django.utils.translation import ugettext as _ +from freezegun import freeze_time +from pytz import UTC from six.moves.urllib.parse import urlencode # pylint: disable=import-error from course_modes.models import CourseMode @@ -71,6 +74,25 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto expected_data = u'"initial_mode": "{mode}"'.format(mode=initial_mode) self.assertContains(response, expected_data) + def test_login_and_registration_form_ratelimited(self): + """ + Test that rate limiting for logistration enpoints works as expected. + """ + login_url = reverse('signin_user') + for i in range(5): + response = self.client.get(login_url) + self.assertEqual(response.status_code, 200) + + # then the rate limiter should kick in and give a HttpForbidden response + response = self.client.get(login_url) + self.assertEqual(response.status_code, 403) + + # now reset the time to 6 mins from now in future in order to unblock + reset_time = datetime.now(UTC) + timedelta(seconds=361) + with freeze_time(reset_time): + response = self.client.get(login_url) + self.assertEqual(response.status_code, 200) + @ddt.data("signin_user", "register_user") def test_login_and_registration_form_already_authenticated(self, url_name): # call the account registration api that sets the login cookies diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_register.py b/openedx/core/djangoapps/user_authn/views/tests/test_register.py index 614b8c746bef72c685f369bd46a7a5cec1f3f794..4a0d7f7a54f33fc0ed4394e672565d9e7a2fd2b5 100644 --- a/openedx/core/djangoapps/user_authn/views/tests/test_register.py +++ b/openedx/core/djangoapps/user_authn/views/tests/test_register.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """Tests for account creation""" - import json from unittest import skipIf, skipUnless from datetime import datetime @@ -50,7 +49,9 @@ from openedx.core.djangoapps.user_api.accounts.tests.retirement_helpers import ( from openedx.core.djangoapps.user_api.tests.test_helpers import TestCaseForm from openedx.core.djangoapps.user_api.tests.test_constants import SORTED_COUNTRIES from openedx.core.djangoapps.user_api.tests.test_views import UserAPITestCase -from openedx.core.djangoapps.user_authn.views.register import RegistrationValidationThrottle +from openedx.core.djangoapps.user_authn.views.register import RegistrationValidationThrottle, \ + REGISTRATION_FAILURE_LOGGING_FLAG +from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms from openedx.core.lib.api import test_utils from student.helpers import authenticate_new_user @@ -209,6 +210,42 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa } ) + @override_waffle_flag(REGISTRATION_FAILURE_LOGGING_FLAG, True) + def test_registration_failure_logging(self): + # Register a user + response = self.client.post(self.url, { + "email": self.EMAIL, + "name": self.NAME, + "username": self.USERNAME, + "password": self.PASSWORD, + "honor_code": "true", + }) + self.assertHttpOK(response) + + # Try to create a second user with the same email address + response = self.client.post(self.url, { + "email": self.EMAIL, + "name": "Someone Else", + "username": "someone_else", + "password": self.PASSWORD, + "honor_code": "true", + }) + self.assertEqual(response.status_code, 409) + response_json = json.loads(response.content.decode('utf-8')) + self.assertDictEqual( + response_json, + { + "email": [{ + "user_message": ( + u"It looks like {} belongs to an existing account. " + "Try again with a different email address." + ).format( + self.EMAIL + ) + }] + } + ) + def test_register_duplicate_username_account_validation_error(self): # Register the first user response = self.client.post(self.url, { @@ -290,7 +327,7 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa @ddt.ddt @skip_unless_lms -class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): +class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase): """Tests for the registration end-points of the User API. """ maxDiff = None @@ -354,7 +391,7 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): link_template = u"<a href='/honor' rel='noopener' target='_blank'>{link_label}</a>" def setUp(self): # pylint: disable=arguments-differ - super(RegistrationViewTest, self).setUp() + super(RegistrationViewTestV1, self).setUp() self.url = reverse("user_api_registration") @ddt.data("get", "post") @@ -456,7 +493,7 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): } ) - msg = u'Your password must contain at least 2 characters, including '\ + msg = u'Your password must contain at least 2 characters, including ' \ u'3 uppercase letters & 1 symbol.' self._assert_reg_field( no_extra_fields_setting, @@ -912,18 +949,7 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): ) def test_registration_form_confirm_email(self): - self._assert_reg_field( - {"confirm_email": "required"}, - { - "name": "confirm_email", - "type": "text", - "required": True, - "label": "Confirm Email", - "errorMessages": { - "required": "The email addresses do not match.", - } - } - ) + pass @override_settings( MKTG_URLS={"ROOT": "https://www.test.com/", "HONOR": "honor"}, @@ -1122,7 +1148,6 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): "password", "favorite_movie", "favorite_editor", - "confirm_email", "city", "state", "country", @@ -1183,7 +1208,6 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): "name", "username", "email", - "confirm_email", "password", "city", "state", @@ -1241,7 +1265,7 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): "password", "favorite_movie", "favorite_editor", - "confirm_email", + "city", "state", "country", @@ -1599,6 +1623,7 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): """ Test case to check user creation is forbidden when ALLOW_PUBLIC_ACCOUNT_CREATION feature flag is turned off """ + def _side_effect_for_get_value(value, default=None): """ returns a side_effect with given return value for a given value @@ -1697,6 +1722,188 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): }) +class RegistrationViewTestV2(RegistrationViewTestV1): + + def setUp(self): # pylint: disable=arguments-differ + super(RegistrationViewTestV1, self).setUp() + self.url = reverse("user_api_registration_v2") + + @override_settings( + REGISTRATION_EXTRA_FIELDS={ + "level_of_education": "optional", + "gender": "optional", + "year_of_birth": "optional", + "mailing_address": "optional", + "goals": "optional", + "city": "optional", + "state": "optional", + "country": "required", + "honor_code": "required", + "confirm_email": "required", + }, + REGISTRATION_EXTENSION_FORM='openedx.core.djangoapps.user_api.tests.test_helpers.TestCaseForm', + REGISTRATION_FIELD_ORDER=[ + "name", + "confirm_email", + "password", + "first_name", + "last_name", + "gender", + "year_of_birth", + "level_of_education", + "company", + "title", + "mailing_address", + "goals", + "honor_code", + "terms_of_service", + ], + ) + def test_field_order_invalid_override(self): + response = self.client.get(self.url) + self.assertHttpOK(response) + + # Verify that all fields render in the correct order + form_desc = json.loads(response.content.decode('utf-8')) + field_names = [field["name"] for field in form_desc["fields"]] + + self.assertEqual(field_names, [ + "email", + "name", + "username", + "password", + "favorite_movie", + "favorite_editor", + "confirm_email", + "city", + "state", + "country", + "gender", + "year_of_birth", + "level_of_education", + "mailing_address", + "goals", + "honor_code", + ]) + + @override_settings( + REGISTRATION_EXTRA_FIELDS={ + "level_of_education": "optional", + "gender": "optional", + "year_of_birth": "optional", + "mailing_address": "optional", + "goals": "optional", + "city": "optional", + "state": "optional", + "country": "required", + "honor_code": "required", + "confirm_email": "required", + }, + REGISTRATION_FIELD_ORDER=[ + "name", + "username", + "email", + "confirm_email", + "password", + "first_name", + "last_name", + "city", + "state", + "country", + "gender", + "year_of_birth", + "level_of_education", + "company", + "title", + "job_title", + "mailing_address", + "goals", + "honor_code", + "terms_of_service", + "specialty", + "profession", + ], + ) + def test_field_order_override(self): + response = self.client.get(self.url) + self.assertHttpOK(response) + + # Verify that all fields render in the correct order + form_desc = json.loads(response.content.decode('utf-8')) + field_names = [field["name"] for field in form_desc["fields"]] + self.assertEqual(field_names, [ + "name", + "username", + "email", + "confirm_email", + "password", + "city", + "state", + "country", + "gender", + "year_of_birth", + "level_of_education", + "mailing_address", + "goals", + "honor_code", + ]) + + @override_settings( + REGISTRATION_EXTRA_FIELDS={ + "level_of_education": "optional", + "gender": "optional", + "year_of_birth": "optional", + "mailing_address": "optional", + "goals": "optional", + "city": "optional", + "state": "optional", + "country": "required", + "honor_code": "required", + "confirm_email": "required", + }, + REGISTRATION_EXTENSION_FORM='openedx.core.djangoapps.user_api.tests.test_helpers.TestCaseForm', + ) + def test_field_order(self): + response = self.client.get(self.url) + self.assertHttpOK(response) + + # Verify that all fields render in the correct order + form_desc = json.loads(response.content.decode('utf-8')) + field_names = [field["name"] for field in form_desc["fields"]] + self.assertEqual(field_names, [ + "email", + "name", + "username", + "password", + "favorite_movie", + "favorite_editor", + "confirm_email", + "city", + "state", + "country", + "gender", + "year_of_birth", + "level_of_education", + "mailing_address", + "goals", + "honor_code", + ]) + + def test_registration_form_confirm_email(self): + self._assert_reg_field( + {"confirm_email": "required"}, + { + "name": "confirm_email", + "type": "email", + "required": True, + "label": "Confirm Email", + "errorMessages": { + "required": "The email addresses do not match.", + } + } + ) + + @httpretty.activate @ddt.ddt class ThirdPartyRegistrationTestMixin(ThirdPartyOAuthTestMixin, CacheIsolationTestCase): diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_reset_password.py b/openedx/core/djangoapps/user_authn/views/tests/test_reset_password.py index 3ea7d3c2a916c833d89cbdff3d5f5ca0ffe7e6cf..8450540a8b6830df5122457d20593a091c5ab154 100644 --- a/openedx/core/djangoapps/user_authn/views/tests/test_reset_password.py +++ b/openedx/core/djangoapps/user_authn/views/tests/test_reset_password.py @@ -85,6 +85,7 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase): """ bad_pwd_req = self.request_factory.post('/password_reset/', {'email': self.user_bad_passwd.email}) + bad_pwd_req.user = AnonymousUser() bad_pwd_resp = password_reset(bad_pwd_req) # If they've got an unusable password, we return a successful response code self.assertEqual(bad_pwd_resp.status_code, 200) @@ -105,6 +106,7 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase): """ bad_email_req = self.request_factory.post('/password_reset/', {'email': self.user.email + "makeItFail"}) + bad_email_req.user = AnonymousUser() bad_email_resp = password_reset(bad_email_req) # Note: even if the email is bad, we return a successful response code # This prevents someone potentially trying to "brute-force" find out which @@ -121,24 +123,87 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase): 'openedx.core.djangoapps.user_authn.views.password_reset.render_to_string', Mock(side_effect=mock_render_to_string, autospec=True) ) - def test_password_reset_ratelimited(self): + def test_password_reset_ratelimited_for_non_existing_user(self): """ - Try (and fail) resetting password 30 times in a row on an non-existant email address + Test that reset password endpoint only allow one request per minute + for non-existing user. """ - cache.clear() + self.assert_password_reset_ratelimitted('thisdoesnotexist@foo.com', AnonymousUser()) + self.assert_no_events_were_emitted() - for i in range(30): - good_req = self.request_factory.post('/password_reset/', { - 'email': 'thisdoesnotexist{0}@foo.com'.format(i) - }) - good_resp = password_reset(good_req) - self.assertEqual(good_resp.status_code, 200) + @patch( + 'openedx.core.djangoapps.user_authn.views.password_reset.render_to_string', + Mock(side_effect=mock_render_to_string, autospec=True) + ) + def test_password_reset_ratelimited_for_existing_user(self): + """ + Test that reset password endpoint only allow one request per minute + for existing user. + """ + self.assert_password_reset_ratelimitted(self.user.email, self.user) + self.assert_event_emission_count(SETTING_CHANGE_INITIATED, 1) + + def assert_password_reset_ratelimitted(self, email, user): + """ + Assert that password reset endpoint allow one request per minute per email. + """ + cache.clear() + password_reset_req = self.request_factory.post('/password_reset/', {'email': email}) + password_reset_req.user = user + password_reset_req.site = Mock(domain='example.com') + good_resp = password_reset(password_reset_req) + self.assertEqual(good_resp.status_code, 200) # then the rate limiter should kick in and give a HttpForbidden response - bad_req = self.request_factory.post('/password_reset/', {'email': 'thisdoesnotexist@foo.com'}) + bad_resp = password_reset(password_reset_req) + self.assertEqual(bad_resp.status_code, 403) + + cache.clear() + + def test_ratelimitted_from_same_ip_with_different_email(self): + """ + Test that password reset endpoint allow only one request per minute per IP. + """ + cache.clear() + good_req = self.request_factory.post('/password_reset/', {'email': 'thisdoesnotexist@foo.com'}) + good_req.user = AnonymousUser() + good_resp = password_reset(good_req) + self.assertEqual(good_resp.status_code, 200) + + # change the email ID and verify that the rate limiter should kick in and + # give a Forbidden response if the request is from same IP. + bad_req = self.request_factory.post('/password_reset/', {'email': 'thisdoesnotexist2@foo.com'}) + bad_req.user = AnonymousUser() bad_resp = password_reset(bad_req) self.assertEqual(bad_resp.status_code, 403) - self.assert_no_events_were_emitted() + + cache.clear() + + def test_ratelimited_from_different_ips_with_same_email(self): + """ + Test that password reset endpoint allow only one request per minute + per email address. + """ + cache.clear() + good_req = self.request_factory.post('/password_reset/', {'email': 'thisdoesnotexist@foo.com'}) + good_req.user = AnonymousUser() + good_resp = password_reset(good_req) + self.assertEqual(good_resp.status_code, 200) + + # change the IP and verify that the rate limiter should kick in and + # give a Forbidden response if the request is for same email address. + new_ip = "8.8.8.8" + self.assertNotEqual(good_req.META.get('REMOTE_ADDR'), new_ip) + + bad_req = self.request_factory.post( + '/password_reset/', + {'email': 'thisdoesnotexist@foo.com'}, + REMOTE_ADDR=new_ip + ) + bad_req.user = AnonymousUser() + bad_resp = password_reset(bad_req) + self.assertEqual(bad_resp.status_code, 403) + self.assertEqual(bad_req.META.get('REMOTE_ADDR'), new_ip) cache.clear() diff --git a/openedx/core/djangoapps/video_pipeline/admin.py b/openedx/core/djangoapps/video_pipeline/admin.py index 88711570615f3764f5da5215eb1c5304734eef3c..b04f9e45f4143b9bfee97057e318d1b32224c46c 100644 --- a/openedx/core/djangoapps/video_pipeline/admin.py +++ b/openedx/core/djangoapps/video_pipeline/admin.py @@ -2,15 +2,19 @@ Django admin for Video Pipeline models. """ -from config_models.admin import ConfigurationModelAdmin from django.contrib import admin +from config_models.admin import ConfigurationModelAdmin from openedx.core.djangoapps.video_config.admin import CourseSpecificEnabledFlagBaseAdmin -from openedx.core.djangoapps.video_pipeline.forms import CourseVideoUploadsEnabledByDefaultAdminForm +from openedx.core.djangoapps.video_pipeline.forms import ( + CourseVideoUploadsEnabledByDefaultAdminForm, + VEMPipelineIntegrationAdminForm +) from openedx.core.djangoapps.video_pipeline.models import ( - VideoPipelineIntegration, - VideoUploadsEnabledByDefault, CourseVideoUploadsEnabledByDefault, + VEMPipelineIntegration, + VideoPipelineIntegration, + VideoUploadsEnabledByDefault ) @@ -21,7 +25,16 @@ class CourseVideoUploadsEnabledByDefaultAdmin(CourseSpecificEnabledFlagBaseAdmin """ form = CourseVideoUploadsEnabledByDefaultAdminForm + +class VEMPipelineIntegrationAdmin(ConfigurationModelAdmin): + """ + Admin of VEM Pipeline integration config model. + """ + form = VEMPipelineIntegrationAdminForm + + admin.site.register(VideoPipelineIntegration, ConfigurationModelAdmin) +admin.site.register(VEMPipelineIntegration, VEMPipelineIntegrationAdmin) admin.site.register(VideoUploadsEnabledByDefault, ConfigurationModelAdmin) admin.site.register(CourseVideoUploadsEnabledByDefault, CourseVideoUploadsEnabledByDefaultAdmin) diff --git a/openedx/core/djangoapps/video_pipeline/api.py b/openedx/core/djangoapps/video_pipeline/api.py index 74a4c13bc62668ebfafc754863841a36632c6e80..dbff3408c7438f509c8cbcedd2ee143025b4c724 100644 --- a/openedx/core/djangoapps/video_pipeline/api.py +++ b/openedx/core/djangoapps/video_pipeline/api.py @@ -9,16 +9,56 @@ from django.core.exceptions import ObjectDoesNotExist from oauth2_provider.models import Application from slumber.exceptions import HttpClientError -from openedx.core.djangoapps.video_pipeline.models import VideoPipelineIntegration +from openedx.core.djangoapps.video_pipeline.config.waffle import ENABLE_VEM_PIPELINE, waffle_flags +from openedx.core.djangoapps.video_pipeline.models import VEMPipelineIntegration, VideoPipelineIntegration from openedx.core.djangoapps.video_pipeline.utils import create_video_pipeline_api_client - log = logging.getLogger(__name__) +def send_transcript_credentials(pipeline_integration, credentials_payload): + """ + Sends transcript credentials to video pipeline + """ + error_response, is_updated = {}, False + try: + oauth_client = Application.objects.get(name=pipeline_integration.client_name) + except ObjectDoesNotExist: + return error_response, is_updated + + client = create_video_pipeline_api_client( + oauth_client.client_id, + oauth_client.client_secret + ) + error_message = "Unable to update transcript credentials -- org={}, provider={}, response={}" + try: + response = client.request("POST", pipeline_integration.api_url, json=credentials_payload) + if response.ok: + is_updated = True + else: + is_updated = False + error_response = json.loads(response.text) + log.error(error_message.format( + credentials_payload.get('org'), + credentials_payload.get('provider'), + response.text + )) + except HttpClientError as ex: + is_updated = False + log.exception(error_message.format( + credentials_payload.get('org'), + credentials_payload.get('provider'), + ex.content + )) + error_response = json.loads(ex.content) + + return error_response, is_updated + + def update_3rd_party_transcription_service_credentials(**credentials_payload): """ - Updates the 3rd party transcription service's credentials. + Updates the 3rd party transcription service's credentials. Credentials are updated + for all the enabled pipelines. Arguments: credentials_payload(dict): A payload containing org, provider and its credentials. @@ -26,35 +66,29 @@ def update_3rd_party_transcription_service_credentials(**credentials_payload): Returns: A Boolean specifying whether the credentials were updated or not and an error response received from pipeline. + + Note: If one of the pipeline fails to update the credentials, False is returned, meaning + that credentials were not updated and both calls should be tried again. """ error_response, is_updated = {}, False - pipeline_integration = VideoPipelineIntegration.current() - if pipeline_integration.enabled: - try: - video_pipeline_user = pipeline_integration.get_service_user() - oauth_client = Application.objects.get(name=pipeline_integration.client_name) - except ObjectDoesNotExist: - return error_response, is_updated - client = create_video_pipeline_api_client( - user=video_pipeline_user, - api_client_id=oauth_client.client_id, - api_client_secret=oauth_client.client_secret, - api_url=pipeline_integration.api_url - ) + vem_pipeline_integration = VEMPipelineIntegration.current() + veda_pipeline_integration = VideoPipelineIntegration.current() - try: - client.transcript_credentials.post(credentials_payload) - is_updated = True - except HttpClientError as ex: - is_updated = False - log.exception( - ('[video-pipeline-service] Unable to update transcript credentials ' - u'-- org=%s -- provider=%s -- response=%s.'), - credentials_payload.get('org'), - credentials_payload.get('provider'), - ex.content, - ) - error_response = json.loads(ex.content) + if vem_pipeline_integration.enabled: + log.info('Sending transcript credentials to VEM for org: {} and provider: {}'.format( + credentials_payload.get('org'), credentials_payload.get('provider') + )) + error_response, is_updated = send_transcript_credentials(vem_pipeline_integration, credentials_payload) + # If credentials update fail for VEM, return proper error message and discontinue to + # send credentials to VEDA because we are going to try it next time anyway + if not is_updated: + return error_response, is_updated + + if veda_pipeline_integration.enabled: + log.info('Sending transcript credentials to VEDA for org: {} and provider: {}'.format( + credentials_payload.get('org'), credentials_payload.get('provider') + )) + error_response, is_updated = send_transcript_credentials(veda_pipeline_integration, credentials_payload) return error_response, is_updated diff --git a/openedx/core/djangoapps/video_pipeline/config/waffle.py b/openedx/core/djangoapps/video_pipeline/config/waffle.py index 43e26759f6409e9947b653bf5a42d0b360fd2759..78e9bd5a953b548377b8a99893ee3b046cd46436 100644 --- a/openedx/core/djangoapps/video_pipeline/config/waffle.py +++ b/openedx/core/djangoapps/video_pipeline/config/waffle.py @@ -11,7 +11,7 @@ WAFFLE_NAMESPACE = 'videos' # Waffle flag telling whether youtube is deprecated. DEPRECATE_YOUTUBE = 'deprecate_youtube' ENABLE_DEVSTACK_VIDEO_UPLOADS = 'enable_devstack_video_uploads' -SAVE_CREDENTIALS_IN_VAL = 'save_credentials_in_val' +ENABLE_VEM_PIPELINE = 'enable_vem_pipeline' def waffle_flags(): @@ -29,9 +29,9 @@ def waffle_flags(): flag_name=ENABLE_DEVSTACK_VIDEO_UPLOADS, flag_undefined_default=False ), - SAVE_CREDENTIALS_IN_VAL: CourseWaffleFlag( + ENABLE_VEM_PIPELINE: CourseWaffleFlag( waffle_namespace=namespace, - flag_name=SAVE_CREDENTIALS_IN_VAL, + flag_name=ENABLE_VEM_PIPELINE, flag_undefined_default=False ) } diff --git a/openedx/core/djangoapps/video_pipeline/forms.py b/openedx/core/djangoapps/video_pipeline/forms.py index b35d16b9df4c3ee339cc54e35fb2f68a028e0e6b..5704bfe62de352cfe4f12d17edf703d03451567e 100644 --- a/openedx/core/djangoapps/video_pipeline/forms.py +++ b/openedx/core/djangoapps/video_pipeline/forms.py @@ -1,6 +1,7 @@ """ Defines a form to provide validations for course-specific configuration. """ +from django import forms from openedx.core.djangoapps.video_config.forms import CourseSpecificFlagAdminBaseForm from openedx.core.djangoapps.video_pipeline.models import CourseVideoUploadsEnabledByDefault @@ -14,3 +15,18 @@ class CourseVideoUploadsEnabledByDefaultAdminForm(CourseSpecificFlagAdminBaseFor class Meta(object): model = CourseVideoUploadsEnabledByDefault fields = '__all__' + + +class VEMPipelineIntegrationAdminForm(forms.ModelForm): + """ + Form for VEM Pipeline Integration Admin class + """ + + def clean_vem_enabled_courses_percentage(self): + """ + Validates that vem_enabled_courses_percentage lies between 0 to 100. + """ + vem_enabled_courses_percentage = self.cleaned_data['vem_enabled_courses_percentage'] + if vem_enabled_courses_percentage < 0 or vem_enabled_courses_percentage > 100: + raise forms.ValidationError('Invalid percentage, the value must be between 0 and 100') + return vem_enabled_courses_percentage diff --git a/openedx/core/djangoapps/video_pipeline/migrations/0004_vempipelineintegration.py b/openedx/core/djangoapps/video_pipeline/migrations/0004_vempipelineintegration.py new file mode 100644 index 0000000000000000000000000000000000000000..1655ddcbb1447d95fb2ffa1ba48bc69ef9d60316 --- /dev/null +++ b/openedx/core/djangoapps/video_pipeline/migrations/0004_vempipelineintegration.py @@ -0,0 +1,32 @@ +# Generated by Django 2.2.12 on 2020-05-29 12:15 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('video_pipeline', '0003_coursevideouploadsenabledbydefault_videouploadsenabledbydefault'), + ] + + operations = [ + migrations.CreateModel( + name='VEMPipelineIntegration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), + ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('client_name', models.CharField(default='VEM-Prod', help_text='Oauth client name of VEM service.', max_length=100)), + ('api_url', models.URLField(help_text='video encode manager API URL.', verbose_name='Internal API URL')), + ('service_username', models.CharField(default='vem_service_user', help_text='Username created for VEM Integration, e.g. vem_service_user.', max_length=100)), + ('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')), + ], + options={ + 'ordering': ('-change_date',), + 'abstract': False, + }, + ), + ] diff --git a/openedx/core/djangoapps/video_pipeline/migrations/0005_add_vem_course_percentage.py b/openedx/core/djangoapps/video_pipeline/migrations/0005_add_vem_course_percentage.py new file mode 100644 index 0000000000000000000000000000000000000000..cd934bb96c6eb40fa9ab96b7769e6fa6fc9ebd71 --- /dev/null +++ b/openedx/core/djangoapps/video_pipeline/migrations/0005_add_vem_course_percentage.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-06-22 11:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('video_pipeline', '0004_vempipelineintegration'), + ] + + operations = [ + migrations.AddField( + model_name='vempipelineintegration', + name='vem_enabled_courses_percentage', + field=models.IntegerField(default=0, help_text='Percentage of courses allowed to use VEM pipeline'), + ), + ] diff --git a/openedx/core/djangoapps/video_pipeline/models.py b/openedx/core/djangoapps/video_pipeline/models.py index fb312c3c42f6b8ec429ea92b9f7d4160ea4d0f97..84a6f2074aeca111e3bce6f7b44373417e946120 100644 --- a/openedx/core/djangoapps/video_pipeline/models.py +++ b/openedx/core/djangoapps/video_pipeline/models.py @@ -45,6 +45,43 @@ class VideoPipelineIntegration(ConfigurationModel): return User.objects.get(username=self.service_username) +class VEMPipelineIntegration(ConfigurationModel): + """ + Manages configuration for connecting to the video encode manager service and using its API. + + .. no_pii: + """ + client_name = models.CharField( + max_length=100, + default='VEM-Prod', + null=False, + blank=False, + help_text=_('Oauth client name of VEM service.') + ) + + api_url = models.URLField( + verbose_name=_('Internal API URL'), + help_text=_('video encode manager API URL.') + ) + + service_username = models.CharField( + max_length=100, + default='vem_service_user', + null=False, + blank=False, + help_text=_('Username created for VEM Integration, e.g. vem_service_user.') + ) + + vem_enabled_courses_percentage = models.IntegerField( + default=0, + help_text=_('Percentage of courses allowed to use VEM pipeline') + ) + + def get_service_user(self): + User = get_user_model() # pylint: disable=invalid-name + return User.objects.get(username=self.service_username) + + @python_2_unicode_compatible class VideoUploadsEnabledByDefault(ConfigurationModel): """ diff --git a/openedx/core/djangoapps/video_pipeline/tests/mixins.py b/openedx/core/djangoapps/video_pipeline/tests/mixins.py index f0ebe0d33ef0ffaf98d884a70204bb24e8276b97..37c6f2f00881e7e9fe5d87dbb2c82a9f062456d4 100644 --- a/openedx/core/djangoapps/video_pipeline/tests/mixins.py +++ b/openedx/core/djangoapps/video_pipeline/tests/mixins.py @@ -4,43 +4,61 @@ Mixins to test video pipeline integration. from oauth2_provider.models import Application -from openedx.core.djangoapps.video_pipeline.models import VideoPipelineIntegration +from openedx.core.djangoapps.video_pipeline.models import VEMPipelineIntegration, VideoPipelineIntegration -class VideoPipelineIntegrationMixin(object): +class VideoPipelineMixin(object): """ - Utility for working with the video pipeline service during testing. + Utility for working with the video pipelines (VEDA and VEM) service during testing. """ - video_pipeline_integration_defaults = { + veda_pipeline_integration_defaults = { 'enabled': True, 'api_url': 'https://video-pipeline.example.com/api/v1/', - 'service_username': u'cms_video_pipeline_service_user', - 'client_name': 'video_pipeline' + 'service_username': 'cms_veda_pipeline_service_user', + 'client_name': 'veda_pipeline' } - request_uris = 'https://video-pipeline.example.com/api/v1/logout' - request_uris += ' https://video-pipeline.example.com/api/v1/redirect' - video_pipelien_oauth_client_defaults = { - 'name': 'video_pipeline', - 'redirect_uris': request_uris, - 'client_id': 'video_pipeline_client_id', - 'client_secret': 'video_pipeline_client_secret', - 'client_type': Application.CLIENT_CONFIDENTIAL + vem_pipeline_integration_defaults = { + 'enabled': True, + 'api_url': 'https://video-encode-manager.example.com/api/v1/', + 'service_username': 'cms_vem_pipeline_service_user', + 'client_name': 'vem_pipeline' } + request_uris = 'https://video-pipeline.example.com/api/v1/logout ' \ + 'https://video-pipeline.example.com/api/v1/redirect ' \ + 'https://video-encode-manager.example.com/api/v1/logout ' \ + 'https://video-encode-manager.example.com/api/v1/redirect' + def create_video_pipeline_integration(self, **kwargs): """ - Creates a new `VideoPipelineIntegration` record with `video_pipeline_integration_defaults`, + Creates a new `VideoPipelineIntegration` record with `veda_pipeline_integration_defaults`, and it can be updated with any provided overrides. """ - fields = dict(self.video_pipeline_integration_defaults, **kwargs) + fields = dict(self.veda_pipeline_integration_defaults, **kwargs) return VideoPipelineIntegration.objects.create(**fields) - def create_video_pipeline_oauth_client(self, user, **kwargs): + def create_vem_pipeline_integration(self, **kwargs): + """ + Creates a new `VEMPipelineIntegration` record with `vem_pipeline_integration_defaults`, + and it can be updated with any provided overrides + """ + fields = dict(self.vem_pipeline_integration_defaults, **kwargs) + return VEMPipelineIntegration.objects.create(**fields) + + def create_video_pipeline_oauth_client(self, user, vem_enabled=False, **kwargs): """ - Creates a new `Client` record with `video_pipelien_oauth_client_defaults`, + Creates a new `Client` record with `video_pipeline_oauth_client_defaults`, and it can be updated with any provided overrides. """ - fields = dict(self.video_pipelien_oauth_client_defaults, **kwargs) + video_pipeline_oauth_client_defaults = { + 'name': 'vem_pipeline' if vem_enabled else 'veda_pipeline', + 'redirect_uris': self.request_uris, + 'client_id': 'vem_client_id' if vem_enabled else 'video_pipeline_client_id', + 'client_secret': 'video_pipeline_client_secret', + 'client_type': Application.CLIENT_CONFIDENTIAL + } + + fields = dict(video_pipeline_oauth_client_defaults, **kwargs) fields['user'] = user return Application.objects.create(**fields) diff --git a/openedx/core/djangoapps/video_pipeline/tests/test_api.py b/openedx/core/djangoapps/video_pipeline/tests/test_api.py index d93ea3df30447593a2957ea3fc4639d1e570e117..7ef781b5653a5d891f17b3840737e4a75d588242 100644 --- a/openedx/core/djangoapps/video_pipeline/tests/test_api.py +++ b/openedx/core/djangoapps/video_pipeline/tests/test_api.py @@ -2,53 +2,91 @@ Tests for Video Pipeline api utils. """ -import ddt import json -from mock import Mock, patch +import ddt from django.test.testcases import TestCase +from mock import Mock, patch +from opaque_keys.edx.locations import CourseLocator from slumber.exceptions import HttpClientError - from student.tests.factories import UserFactory from openedx.core.djangoapps.video_pipeline.api import update_3rd_party_transcription_service_credentials -from openedx.core.djangoapps.video_pipeline.tests.mixins import VideoPipelineIntegrationMixin +from openedx.core.djangoapps.video_pipeline.config.waffle import ENABLE_VEM_PIPELINE, waffle_flags +from openedx.core.djangoapps.video_pipeline.tests.mixins import VideoPipelineMixin +from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag @ddt.ddt -class TestAPIUtils(VideoPipelineIntegrationMixin, TestCase): +class TestAPIUtils(VideoPipelineMixin, TestCase): """ Tests for API Utils. """ def setUp(self): - self.pipeline_integration = self.create_video_pipeline_integration() - self.user = UserFactory(username=self.pipeline_integration.service_username) - self.oauth_client = self.create_video_pipeline_oauth_client(user=self.user) + """ + Setup VEDA and VEM oauth clients. + """ + self.add_veda_client() + self.add_vem_client() - def test_update_transcription_service_credentials_with_integration_disabled(self): + def add_veda_client(self): """ - Test updating the credentials when service integration is disabled. + Creates a VEDA oauth client """ - self.pipeline_integration.enabled = False - self.pipeline_integration.save() - __, is_updated = update_3rd_party_transcription_service_credentials() - self.assertFalse(is_updated) + self.veda_pipeline_integration = self.create_video_pipeline_integration() + self.veda_user = UserFactory(username=self.veda_pipeline_integration.service_username) + self.veda_oauth_client = self.create_video_pipeline_oauth_client(user=self.veda_user) + + def add_vem_client(self): + """ + Creates a VEM oauth client + """ + self.vem_pipeline_integration = self.create_vem_pipeline_integration() + self.vem_user = UserFactory(username=self.vem_pipeline_integration.service_username) + self.vem_oauth_client = self.create_video_pipeline_oauth_client(user=self.vem_user, vem_enabled=True) - def test_update_transcription_service_credentials_with_unknown_user(self): + @patch('openedx.core.djangoapps.video_pipeline.api.log') + @patch('openedx.core.djangoapps.video_pipeline.utils.OAuthAPIClient') + def test_update_transcription_service_credentials_with_one_integration_disabled(self, mock_client, mock_logger): """ - Test updating the credentials when expected service user is not registered. + Test that updating the credentials when one of the service integration is disabled, allows + the credentials to be updated for other pipeline. """ - self.pipeline_integration.service_username = 'non_existent_user' - self.pipeline_integration.save() + mock_client.request.return_value.ok = True + credentials_payload = { + 'org': 'mit', 'provider': 'ABC Provider', 'api_key': '61c56a8d0' + } + + self.veda_pipeline_integration.enabled = False + self.veda_pipeline_integration.save() + __, is_updated = update_3rd_party_transcription_service_credentials(**credentials_payload) + mock_logger.info.assert_called_with('Sending transcript credentials to VEM for org: {} and provider: {}'.format( + credentials_payload.get('org'), credentials_payload.get('provider') + )) + self.assertTrue(is_updated) + + def test_update_transcription_service_credentials_with_both_integration_disabled(self): + """ + Test updating the credentials when both service integration are disabled. + """ + # Disabling VEDA + self.veda_pipeline_integration.enabled = False + self.veda_pipeline_integration.save() + + # Disabling VEM + self.vem_pipeline_integration.enabled = False + self.vem_pipeline_integration.save() + __, is_updated = update_3rd_party_transcription_service_credentials() self.assertFalse(is_updated) - def test_update_transcription_service_credentials_with_unknown_oauth_client(self): + def test_update_transcription_service_credentials_when_one_service_fails(self): """ - Test updating the credentials when expected oauth cleint is not present. + Test that if one of the transcription service fails to update credentials, + response from `update_3rd_party_transcription_service_credentials` is False. """ - self.pipeline_integration.client_name = 'non_existent_client' - self.pipeline_integration.save() + self.vem_pipeline_integration.client_name = 'non_existent_client' + self.vem_pipeline_integration.save() __, is_updated = update_3rd_party_transcription_service_credentials() self.assertFalse(is_updated) @@ -63,33 +101,38 @@ class TestAPIUtils(VideoPipelineIntegrationMixin, TestCase): } ) @patch('openedx.core.djangoapps.video_pipeline.api.log') - @patch('openedx.core.djangoapps.video_pipeline.utils.EdxRestApiClient') + @patch('openedx.core.djangoapps.video_pipeline.utils.OAuthAPIClient') def test_update_transcription_service_credentials(self, credentials_payload, mock_client, mock_logger): """ Tests that the update transcription service credentials api util works as expected. """ - # Mock the post request - mock_credentials_endpoint = mock_client.return_value.transcript_credentials + mock_client.request.return_value.ok = True + # Try updating the transcription service credentials error_response, is_updated = update_3rd_party_transcription_service_credentials(**credentials_payload) - mock_credentials_endpoint.post.assert_called_with(credentials_payload) # Making sure log.exception is not called. self.assertDictEqual(error_response, {}) self.assertFalse(mock_logger.exception.called) self.assertTrue(is_updated) + mock_logger.info.assert_any_call('Sending transcript credentials to VEM for org: {} and provider: {}'.format( + credentials_payload.get('org'), credentials_payload.get('provider') + )) + mock_logger.info.assert_any_call('Sending transcript credentials to VEDA for org: {} and provider: {}'.format( + credentials_payload.get('org'), credentials_payload.get('provider') + )) + @patch('openedx.core.djangoapps.video_pipeline.api.log') - @patch('openedx.core.djangoapps.video_pipeline.utils.EdxRestApiClient') + @patch('openedx.core.djangoapps.video_pipeline.utils.OAuthAPIClient') def test_update_transcription_service_credentials_exceptions(self, mock_client, mock_logger): """ Tests that the update transcription service credentials logs the exception occurring during communication with edx-video-pipeline. """ error_content = '{"error_type": "1"}' - # Mock the post request - mock_credentials_endpoint = mock_client.return_value.transcript_credentials - mock_credentials_endpoint.post = Mock(side_effect=HttpClientError(content=error_content)) + mock_client.return_value.request = Mock(side_effect=HttpClientError(content=error_content)) + # try updating the transcription service credentials credentials_payload = { 'org': 'mit', @@ -98,13 +141,13 @@ class TestAPIUtils(VideoPipelineIntegrationMixin, TestCase): } error_response, is_updated = update_3rd_party_transcription_service_credentials(**credentials_payload) - mock_credentials_endpoint.post.assert_called_with(credentials_payload) # Assert the results. self.assertFalse(is_updated) self.assertDictEqual(error_response, json.loads(error_content)) mock_logger.exception.assert_called_with( - u'[video-pipeline-service] Unable to update transcript credentials -- org=%s -- provider=%s -- response=%s.', - credentials_payload['org'], - credentials_payload['provider'], - error_content + 'Unable to update transcript credentials -- org={}, provider={}, response={}'.format( + credentials_payload['org'], + credentials_payload['provider'], + error_content + ) ) diff --git a/openedx/core/djangoapps/video_pipeline/utils.py b/openedx/core/djangoapps/video_pipeline/utils.py index 72850943fd03832e4d002e2b3d5942380612e209..b76026927b6eb058284eefad5002a87c72c21db0 100644 --- a/openedx/core/djangoapps/video_pipeline/utils.py +++ b/openedx/core/djangoapps/video_pipeline/utils.py @@ -1,21 +1,17 @@ """ Utils for video_pipeline app. """ +from django.conf import settings -from edx_rest_api_client.client import EdxRestApiClient +from edx_rest_api_client.client import OAuthAPIClient -from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user - -def create_video_pipeline_api_client(user, api_client_id, api_client_secret, api_url): +def create_video_pipeline_api_client(api_client_id, api_client_secret): """ Returns an API client which can be used to make Video Pipeline API requests. Arguments: - user(User): A requesting user. api_client_id(unicode): Video pipeline client id. api_client_secret(unicode): Video pipeline client secret. - api_url(unicode): It is video pipeline's API URL. """ - jwt_token = create_jwt_for_user(user, secret=api_client_secret, aud=api_client_id) - return EdxRestApiClient(api_url, jwt=jwt_token) + return OAuthAPIClient(settings.LMS_ROOT_URL, api_client_id, api_client_secret) diff --git a/openedx/core/djangoapps/waffle_utils/__init__.py b/openedx/core/djangoapps/waffle_utils/__init__.py index d563a4261170b16741c179019104a959f40eaba0..0bb3872f8f178b4050bad460c2320716b466fbf9 100644 --- a/openedx/core/djangoapps/waffle_utils/__init__.py +++ b/openedx/core/djangoapps/waffle_utils/__init__.py @@ -6,7 +6,7 @@ Includes namespacing, caching, and course overrides for waffle flags. Usage: For Waffle Flags, first set up the namespace, and then create flags using the -namespace. For example: +namespace. For example:: WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='course_experience') @@ -15,7 +15,7 @@ namespace. For example: # Use WaffleFlag when outside the context of a course. HIDE_SEARCH_FLAG = WaffleFlag(WAFFLE_FLAG_NAMESPACE, 'hide_search') -You can check these flags in code using the following: +You can check these flags in code using the following:: HIDE_SEARCH_FLAG.is_enabled() UNIFIED_COURSE_TAB_FLAG.is_enabled(course_key) @@ -29,13 +29,13 @@ You could also use the Django Admin "waffle_utils" section to configure a course override for this same flag (e.g. course_experience.unified_course_tab). For Waffle Switches, first set up the namespace, and then create the flag name. -For example: +For example:: WAFFLE_SWITCHES = WaffleSwitchNamespace(name=WAFFLE_NAMESPACE) ESTIMATE_FIRST_ATTEMPTED = 'estimate_first_attempted' -You can then use the switch as follows: +You can then use the switch as follows:: WAFFLE_SWITCHES.is_enabled(waffle.ESTIMATE_FIRST_ATTEMPTED) @@ -44,29 +44,24 @@ To test WaffleSwitchNamespace, use the provided context managers. For example: with WAFFLE_SWITCHES.override(waffle.ESTIMATE_FIRST_ATTEMPTED, active=True): ... -For long-lived flags, you may want to change the default for the flag from "off" -to "on", so that it is "on" by default in devstack, sandboxes, or new Open edX -releases, more closely matching what is in Production. This is for flags that -can't yet be deleted, for example if there are straggling course overrides. +For long-lived flags, you may want to change the default for devstack, sandboxes, +or new Open edX releases. For help with this, see: +openedx/core/djangoapps/waffle_utils/docs/decisions/0001-refactor-waffle-flag-default.rst - * WaffleFlag has a DEPRECATED argument flag_undefined_default that we don't - recommend you use any more. Although this can work, it is proven not ideal to - have a value that isn't immediately obvious via Django admin. - - * At this time, the proper alternative has not been fully designed. The - following food-for-thought could provide ideas for this design when needed: - using migrations, using app-level configuration, using management commands, - and/or creating records up front so all toggle defaults are explicit rather - than implicit. +Also see ``WAFFLE_FLAG_CUSTOM_METRICS`` and docstring for _set_waffle_flag_metric +for temporarily instrumenting/monitoring waffle flag usage. """ import logging +import warnings from abc import ABCMeta from contextlib import contextmanager import crum import six +from django.conf import settings +from edx_django_utils.monitoring import set_custom_metric from opaque_keys.edx.keys import CourseKey from waffle import flag_is_active, switch_is_active @@ -253,11 +248,18 @@ class WaffleFlagNamespace(six.with_metaclass(ABCMeta, WaffleNamespace)): used. DEPRECATED flag_undefined_default (Boolean): A default value to be returned if the waffle flag is to be checked, but doesn't exist. - See docs for alternatives. + See module docstring for alternative. """ # Import is placed here to avoid model import at project startup. from waffle.models import Flag + if flag_undefined_default: + warnings.warn( + # NOTE: This will be removed once ARCHBOM-132, currently in-progress, is complete. + 'flag_undefined_default has been deprecated. For existing uses this is already actively being fixed.', + DeprecationWarning + ) + # validate arguments namespaced_flag_name = self._namespaced_name(flag_name) value = None @@ -275,6 +277,10 @@ class WaffleFlagNamespace(six.with_metaclass(ABCMeta, WaffleNamespace)): try: Flag.objects.get(name=namespaced_flag_name) except Flag.DoesNotExist: + if flag_undefined_default: + # This metric will go away once this has been fully retired with ARCHBOM-132. + # Also, even though the value will only track the last flag, that should be enough. + set_custom_metric('temp_flag_default_used', namespaced_flag_name) value = flag_undefined_default if value is None: @@ -283,16 +289,90 @@ class WaffleFlagNamespace(six.with_metaclass(ABCMeta, WaffleNamespace)): value = flag_is_active(request, namespaced_flag_name) else: log.warning(u"%sFlag '%s' accessed without a request", self.log_prefix, namespaced_flag_name) + set_custom_metric('warn_flag_no_request', True) # Return the default value if not in a request context. # Note: this skips the cache as the value might be different # in a normal request context. This case seems to occur when # a page redirects to a 404. In this case, we'll just return # the default value. - return bool(flag_undefined_default) + value = bool(flag_undefined_default) + self._set_waffle_flag_metric(namespaced_flag_name, value) + return value self._cached_flags[namespaced_flag_name] = value + + self._set_waffle_flag_metric(namespaced_flag_name, value) return value + def _set_waffle_flag_metric(self, name, value): + """ + For any flag name in _WAFFLE_FLAG_CUSTOM_METRIC_SET, add name/value + to cached values and set custom metric if the value changed. + + The name of the custom metric will have the prefix ``flag_`` and the + suffix will match the name of the flag. + The value of the custom metric could be False, True, or Both. + + The value Both would mean that the flag had both a True and False + value at different times during the transaction. This is most + likely due to having a check_before_waffle_callback, as is the + case with CourseWaffleFlag. + + An example NewRelic query to see the values of a flag in different + environments, if your waffle flag was named ``my.waffle.flag`` might + look like:: + + SELECT count(*) FROM Transaction + WHERE flag_my.waffle.flag IS NOT NULL + FACET appName, flag_my.waffle.flag + + Important: Remember to configure ``WAFFLE_FLAG_CUSTOM_METRICS`` for + LMS, Studio and Workers in order to see waffle flag usage in all + edx-platform environments. + + """ + if name not in _WAFFLE_FLAG_CUSTOM_METRIC_SET: + return + + flag_metric_data = self._get_request_cache().setdefault('flag_metric', {}) + is_value_change = False + if name not in flag_metric_data: + flag_metric_data[name] = str(value) + is_value_change = True + else: + if flag_metric_data[name] != str(value): + flag_metric_data[name] = 'Both' + is_value_change = True + + if is_value_change: + metric_name = 'flag_{}'.format(name) + set_custom_metric(metric_name, flag_metric_data[name]) + + +def _get_waffle_flag_custom_metrics_set(): + """ + Returns a set based on the Django setting WAFFLE_FLAG_CUSTOM_METRICS (list). + """ + waffle_flag_custom_metrics = getattr(settings, _WAFFLE_FLAG_CUSTOM_METRICS, None) + waffle_flag_custom_metrics = waffle_flag_custom_metrics if waffle_flag_custom_metrics else [] + return set(waffle_flag_custom_metrics) + + # .. toggle_name: WAFFLE_FLAG_CUSTOM_METRICS + # .. toggle_implementation: DjangoSetting + # .. toggle_default: False + # .. toggle_description: A list of waffle flag to track with custom metrics having values of (True, False, or Both). + # .. toggle_category: monitoring + # .. toggle_use_cases: opt_in + # .. toggle_creation_date: 2020-06-17 + # .. toggle_expiration_date: None + # .. toggle_tickets: None + # .. toggle_status: supported + # .. toggle_warnings: Intent is for temporary research (1 day - several weeks) of a flag's usage. +_WAFFLE_FLAG_CUSTOM_METRICS = 'WAFFLE_FLAG_CUSTOM_METRICS' + +# set of waffle flags that should be instrumented with custom metrics +_WAFFLE_FLAG_CUSTOM_METRIC_SET = _get_waffle_flag_custom_metrics_set() + class WaffleFlag(object): """ @@ -306,8 +386,9 @@ class WaffleFlag(object): Arguments: waffle_namespace (WaffleFlagNamespace | String): Namespace for this flag. flag_name (String): The name of the flag (without namespacing). - flag_undefined_default (Boolean): A default value to be returned if - the waffle flag is to be checked, but doesn't exist. + DEPRECATED flag_undefined_default (Boolean): A default value to be returned + if the waffle flag is to be checked, but doesn't exist. See module + docstring for alternative. """ if isinstance(waffle_namespace, six.string_types): waffle_namespace = WaffleFlagNamespace(name=waffle_namespace) diff --git a/openedx/core/djangoapps/waffle_utils/docs/decisions/0001-refactor-waffle-flag-default.rst b/openedx/core/djangoapps/waffle_utils/docs/decisions/0001-refactor-waffle-flag-default.rst new file mode 100644 index 0000000000000000000000000000000000000000..d38ce65273afc024cc129b8cdaec6d01b855e849 --- /dev/null +++ b/openedx/core/djangoapps/waffle_utils/docs/decisions/0001-refactor-waffle-flag-default.rst @@ -0,0 +1,38 @@ +Refactor Waffle Flag Default +**************************** + +Status +====== + +Accepted + +Context +======= + +While working on the toggle reports, it became clear that the value for WaffleFlags (and derivatives like CourseWaffleFlag) in all environments was difficult to determine, and difficult to reason about. + +By default, the original waffle flag values are False, unless a record is created to turn it on under certain circumstances. Having the ability to make the default True in code was confusing when looking in Admin and trying to determine the current value of the flag. It also would have been complex to have the report have to investigate code to try to determine this value. + +Decision +======== + +* Retire the ``flag_undefined_default`` argument for WaffleFlag and CourseWaffleFlag that allowed you to change the default to True in code. +* Do not introduce any new ability to adjust the default in code. +* Teams can use any of the following alternatives instead: + + * The flag can simply be removed at this time if it was meant to be temporary. + * The flag could be replaced with a Django Setting, if the features of a flag are not needed for the permanent toggle. + * You could add a migration that adds an active (True) waffle flag database record if a record doesn't already exist. + * You could introduce and replace an *enable* flag with a new *disable* flag. This might be useful when a permanent toggle is desired that requires features of a waffle flag, and where disabling would now be the exceptional case, since the default would be inactive (False). + +Consequences +============ + +* We will need to implement one of the alternate solutions for each flag currently using ``flag_undefined_default=True``, and then finally remove the deprecated ``flag_undefined_default`` argument. + +Rejected Alternatives +===================== + +We are clearly rejecting the ``flag_undefined_default`` argument. + +We are also rejecting any other alternative that would separate this default from the normal usage of the waffle flag record. diff --git a/openedx/core/djangoapps/waffle_utils/tests/test_init.py b/openedx/core/djangoapps/waffle_utils/tests/test_init.py index 3cc1d6c6e2f7fcdf1079188e72c867698470733a..f29b16e40fdf17e62d43ff56f067129475259612 100644 --- a/openedx/core/djangoapps/waffle_utils/tests/test_init.py +++ b/openedx/core/djangoapps/waffle_utils/tests/test_init.py @@ -6,12 +6,19 @@ import crum import ddt from django.test import TestCase from django.test.client import RequestFactory +from django.test.utils import override_settings from edx_django_utils.cache import RequestCache -from mock import patch +from mock import call, patch from opaque_keys.edx.keys import CourseKey from waffle.testutils import override_flag -from .. import CourseWaffleFlag, WaffleFlagNamespace, WaffleSwitchNamespace, WaffleSwitch +from .. import ( + _get_waffle_flag_custom_metrics_set, + CourseWaffleFlag, + WaffleFlagNamespace, + WaffleSwitchNamespace, + WaffleSwitch, +) from ..models import WaffleFlagCourseOverrideModel @@ -24,6 +31,8 @@ class TestCourseWaffleFlag(TestCase): NAMESPACE_NAME = "test_namespace" FLAG_NAME = "test_flag" NAMESPACED_FLAG_NAME = NAMESPACE_NAME + "." + FLAG_NAME + FLAG_2_NAME = "test_flag_2" + NAMESPACED_FLAG_2_NAME = NAMESPACE_NAME + "." + FLAG_2_NAME TEST_COURSE_KEY = CourseKey.from_string("edX/DemoX/Demo_Course") TEST_COURSE_2_KEY = CourseKey.from_string("edX/DemoX/Demo_Course_2") @@ -37,44 +46,60 @@ class TestCourseWaffleFlag(TestCase): crum.set_current_request(request) RequestCache.clear_all_namespaces() + @override_settings(WAFFLE_FLAG_CUSTOM_METRICS=[NAMESPACED_FLAG_NAME]) + @patch('openedx.core.djangoapps.waffle_utils.set_custom_metric') @ddt.data( {'course_override': WaffleFlagCourseOverrideModel.ALL_CHOICES.on, 'waffle_enabled': False, 'result': True}, {'course_override': WaffleFlagCourseOverrideModel.ALL_CHOICES.off, 'waffle_enabled': True, 'result': False}, {'course_override': WaffleFlagCourseOverrideModel.ALL_CHOICES.unset, 'waffle_enabled': True, 'result': True}, {'course_override': WaffleFlagCourseOverrideModel.ALL_CHOICES.unset, 'waffle_enabled': False, 'result': False}, ) - def test_course_waffle_flag(self, data): + def test_course_waffle_flag(self, data, mock_set_custom_metric): """ Tests various combinations of a flag being set in waffle and overridden for a course. """ - with patch.object(WaffleFlagCourseOverrideModel, 'override_value', return_value=data['course_override']): - with override_flag(self.NAMESPACED_FLAG_NAME, active=data['waffle_enabled']): - # check twice to test that the result is properly cached - self.assertEqual(self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_KEY), data['result']) - self.assertEqual(self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_KEY), data['result']) - # result is cached, so override check should happen once - WaffleFlagCourseOverrideModel.override_value.assert_called_once_with( - self.NAMESPACED_FLAG_NAME, - self.TEST_COURSE_KEY - ) - - # check flag for a second course - if data['course_override'] == WaffleFlagCourseOverrideModel.ALL_CHOICES.unset: - # When course override wasn't set for the first course, the second course will get the same - # cached value from waffle. - self.assertEqual(self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_2_KEY), data['waffle_enabled']) - else: - # When course override was set for the first course, it should not apply to the second - # course which should get the default value of False. - self.assertEqual(self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_2_KEY), False) - + with patch( + 'openedx.core.djangoapps.waffle_utils._WAFFLE_FLAG_CUSTOM_METRIC_SET', + _get_waffle_flag_custom_metrics_set(), + ): + with patch.object(WaffleFlagCourseOverrideModel, 'override_value', return_value=data['course_override']): + with override_flag(self.NAMESPACED_FLAG_NAME, active=data['waffle_enabled']): + # check twice to test that the result is properly cached + self.assertEqual(self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_KEY), data['result']) + self.assertEqual(self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_KEY), data['result']) + # result is cached, so override check should happen once + WaffleFlagCourseOverrideModel.override_value.assert_called_once_with( + self.NAMESPACED_FLAG_NAME, + self.TEST_COURSE_KEY + ) + + self._assert_waffle_flag_metric(mock_set_custom_metric, expected_flag_value=str(data['result'])) + mock_set_custom_metric.reset_mock() + + # check flag for a second course + if data['course_override'] == WaffleFlagCourseOverrideModel.ALL_CHOICES.unset: + # When course override wasn't set for the first course, the second course will get the same + # cached value from waffle. + second_value = data['waffle_enabled'] + self.assertEqual(self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_2_KEY), second_value) + else: + # When course override was set for the first course, it should not apply to the second + # course which should get the default value of False. + second_value = False + self.assertEqual(self.TEST_COURSE_FLAG.is_enabled(self.TEST_COURSE_2_KEY), second_value) + + expected_flag_value = None if second_value == data['result'] else 'Both' + self._assert_waffle_flag_metric(mock_set_custom_metric, expected_flag_value=expected_flag_value) + + @override_settings(WAFFLE_FLAG_CUSTOM_METRICS=[NAMESPACED_FLAG_NAME]) + @patch('openedx.core.djangoapps.waffle_utils.set_custom_metric') @ddt.data( {'flag_undefined_default': None, 'result': False}, {'flag_undefined_default': False, 'result': False}, {'flag_undefined_default': True, 'result': True}, ) - def test_undefined_waffle_flag(self, data): + def test_undefined_waffle_flag(self, data, mock_set_custom_metric): """ Test flag with various defaults provided for undefined waffle flags. """ @@ -84,19 +109,29 @@ class TestCourseWaffleFlag(TestCase): flag_undefined_default=data['flag_undefined_default'] ) - with patch.object( - WaffleFlagCourseOverrideModel, - 'override_value', - return_value=WaffleFlagCourseOverrideModel.ALL_CHOICES.unset + with patch( + 'openedx.core.djangoapps.waffle_utils._WAFFLE_FLAG_CUSTOM_METRIC_SET', + _get_waffle_flag_custom_metrics_set(), ): - # check twice to test that the result is properly cached - self.assertEqual(test_course_flag.is_enabled(self.TEST_COURSE_KEY), data['result']) - self.assertEqual(test_course_flag.is_enabled(self.TEST_COURSE_KEY), data['result']) - # result is cached, so override check should happen once - WaffleFlagCourseOverrideModel.override_value.assert_called_once_with( - self.NAMESPACED_FLAG_NAME, - self.TEST_COURSE_KEY - ) + with patch.object( + WaffleFlagCourseOverrideModel, + 'override_value', + return_value=WaffleFlagCourseOverrideModel.ALL_CHOICES.unset + ): + # check twice to test that the result is properly cached + self.assertEqual(test_course_flag.is_enabled(self.TEST_COURSE_KEY), data['result']) + self.assertEqual(test_course_flag.is_enabled(self.TEST_COURSE_KEY), data['result']) + # result is cached, so override check should happen once + WaffleFlagCourseOverrideModel.override_value.assert_called_once_with( + self.NAMESPACED_FLAG_NAME, + self.TEST_COURSE_KEY + ) + + self._assert_waffle_flag_metric( + mock_set_custom_metric, + expected_flag_value=str(data['result']), + flag_undefined_default=data['flag_undefined_default'], + ) @ddt.data( {'flag_undefined_default': None, 'result': False}, @@ -115,6 +150,35 @@ class TestCourseWaffleFlag(TestCase): ) self.assertEqual(test_course_flag.is_enabled(self.TEST_COURSE_KEY), data['result']) + @ddt.data( + {'expected_count': 0, 'waffle_flag_metric_setting': None}, + {'expected_count': 1, 'waffle_flag_metric_setting': [NAMESPACED_FLAG_NAME]}, + {'expected_count': 2, 'waffle_flag_metric_setting': [NAMESPACED_FLAG_NAME, NAMESPACED_FLAG_2_NAME]}, + ) + @patch('openedx.core.djangoapps.waffle_utils.set_custom_metric') + def test_waffle_flag_metric_for_various_settings(self, data, mock_set_custom_metric): + with override_settings(WAFFLE_FLAG_CUSTOM_METRICS=data['waffle_flag_metric_setting']): + with patch( + 'openedx.core.djangoapps.waffle_utils._WAFFLE_FLAG_CUSTOM_METRIC_SET', + _get_waffle_flag_custom_metrics_set(), + ): + test_course_flag = CourseWaffleFlag(self.TEST_NAMESPACE, self.FLAG_NAME) + test_course_flag.is_enabled(self.TEST_COURSE_KEY) + test_course_flag_2 = CourseWaffleFlag(self.TEST_NAMESPACE, self.FLAG_2_NAME) + test_course_flag_2.is_enabled(self.TEST_COURSE_KEY) + + self.assertEqual(mock_set_custom_metric.call_count, data['expected_count']) + + def _assert_waffle_flag_metric(self, mock_set_custom_metric, expected_flag_value=None, flag_undefined_default=None): + if expected_flag_value: + expected_flag_name = 'flag_{}'.format(self.NAMESPACED_FLAG_NAME) + expected_calls = [call(expected_flag_name, expected_flag_value)] + mock_set_custom_metric.assert_has_calls(expected_calls) + expected_call_count = 2 if flag_undefined_default else 1 + self.assertEqual(mock_set_custom_metric.call_count, expected_call_count) + else: + self.assertEqual(mock_set_custom_metric.call_count, 0) + class TestWaffleSwitch(TestCase): """ diff --git a/openedx/core/djangoapps/xblock/api.py b/openedx/core/djangoapps/xblock/api.py index a3449a198f310e43bc88a324e700d3fcd9c87600..496219b6c63dc1c12f331c885873e9b5b716524f 100644 --- a/openedx/core/djangoapps/xblock/api.py +++ b/openedx/core/djangoapps/xblock/api.py @@ -9,6 +9,7 @@ Studio APIs cover use cases like adding/deleting/editing blocks. """ import logging +import threading from django.urls import reverse from django.utils.translation import ugettext as _ @@ -38,15 +39,24 @@ def get_runtime_system(): keep application startup faster, it's only initialized when first accessed via this method. """ - # pylint: disable=protected-access - if not hasattr(get_runtime_system, '_system'): + # The runtime system should not be shared among threads, as there is currently a race condition when parsing XML + # that can lead to duplicate children. + # (In BlockstoreXBlockRuntime.get_block(), has_cached_definition(def_id) returns false so parse_xml is called, but + # meanwhile another thread parses the XML and caches the definition; then when parse_xml gets to XML nodes for + # child blocks, it appends them to the children already cached by the other thread and saves the doubled list of + # children; this happens only occasionally but is very difficult to avoid in a clean way due to the API of parse_xml + # and XBlock field data in general [does not distinguish between setting initial values during parsing and changing + # values at runtime due to user interaction], and how it interacts with BlockstoreFieldData. Keeping the caches + # local to each thread completely avoids this problem.) + cache_name = '_system_{}'.format(threading.get_ident()) + if not hasattr(get_runtime_system, cache_name): params = dict( handler_url=get_handler_url, runtime_class=BlockstoreXBlockRuntime, ) params.update(get_xblock_app_config().get_runtime_system_params()) - get_runtime_system._system = XBlockRuntimeSystem(**params) - return get_runtime_system._system + setattr(get_runtime_system, cache_name, XBlockRuntimeSystem(**params)) + return getattr(get_runtime_system, cache_name) def load_block(usage_key, user): @@ -79,16 +89,47 @@ def load_block(usage_key, user): return runtime.get_block(usage_key) -def get_block_metadata(block): +def get_block_metadata(block, includes=()): """ - Get metadata about the specified XBlock + Get metadata about the specified XBlock. + + This metadata is the same for all users. Any data which varies per-user must + be served from a different API. + + Optionally provide a list or set of metadata keys to include. Valid keys are: + index_dictionary: a dictionary of data used to add this XBlock's content + to a search index. + student_view_data: data needed to render the XBlock on mobile or in + custom frontends. + children: list of usage keys of the XBlock's children + editable_children: children in the same bundle, as opposed to linked + children in other bundles. """ - return { + data = { "block_id": six.text_type(block.scope_ids.usage_id), "block_type": block.scope_ids.block_type, "display_name": get_block_display_name(block), } + if "index_dictionary" in includes: + data["index_dictionary"] = block.index_dictionary() + + if "student_view_data" in includes: + data["student_view_data"] = block.student_view_data() if hasattr(block, 'student_view_data') else None + + if "children" in includes: + data["children"] = block.children if hasattr(block, 'children') else [] # List of usage keys of children + + if "editable_children" in includes: + # "Editable children" means children in the same bundle, as opposed to linked children in other bundles. + data["editable_children"] = [] + child_includes = block.runtime.child_includes_of(block) + for idx, include in enumerate(child_includes): + if include.link_id is None: + data["editable_children"].append(block.children[idx]) + + return data + def resolve_definition(block_or_key): """ diff --git a/openedx/core/djangoapps/xblock/rest_api/views.py b/openedx/core/djangoapps/xblock/rest_api/views.py index 939c663b7b8fca59763c1f9d35015022372b6a92..fbabcec2a1513741b5830b519cf667d8dd79b0b8 100644 --- a/openedx/core/djangoapps/xblock/rest_api/views.py +++ b/openedx/core/djangoapps/xblock/rest_api/views.py @@ -34,10 +34,18 @@ User = get_user_model() def block_metadata(request, usage_key_str): """ Get metadata about the specified block. + + Accepts an "include" query parameter which must be a comma separated list of keys to include. Valid keys are + "index_dictionary" and "student_view_data". """ usage_key = UsageKey.from_string(usage_key_str) block = load_block(usage_key, request.user) - metadata_dict = get_block_metadata(block) + includes = request.GET.get("include", "").split(",") + metadata_dict = get_block_metadata(block, includes=includes) + if 'children' in metadata_dict: + metadata_dict['children'] = [str(key) for key in metadata_dict['children']] + if 'editable_children' in metadata_dict: + metadata_dict['editable_children'] = [str(key) for key in metadata_dict['editable_children']] return Response(metadata_dict) diff --git a/openedx/core/djangoapps/xblock/runtime/shims.py b/openedx/core/djangoapps/xblock/runtime/shims.py index c9c172b4d9289c6ac56380cc11290e7333651aea..edf1d56951fd40750e6167c9a7a5e03b4e4f88ae 100644 --- a/openedx/core/djangoapps/xblock/runtime/shims.py +++ b/openedx/core/djangoapps/xblock/runtime/shims.py @@ -11,6 +11,7 @@ from django.core.cache import cache from django.template import TemplateDoesNotExist from django.utils.functional import cached_property from fs.memoryfs import MemoryFS +from openedx.core.djangoapps.xblock.apps import get_xblock_app_config import six from edxmako.shortcuts import render_to_string @@ -270,7 +271,12 @@ class RuntimeShim(object): Seems only to be used by capa. Remove this if capa can be refactored. """ # TODO: Refactor capa to access this directly, don't bother the runtime. Then remove it from here. - return settings.STATIC_URL + static_url = settings.STATIC_URL + if static_url.startswith('/') and not static_url.startswith('//'): + # This is not a full URL - should start with https:// to support loading assets from an iframe sandbox + site_root_url = get_xblock_app_config().get_site_root_url() + static_url = site_root_url + static_url + return static_url @cached_property def user_is_staff(self): diff --git a/openedx/core/djangoapps/zendesk_proxy/v1/views.py b/openedx/core/djangoapps/zendesk_proxy/v1/views.py index 0899a3a79717437e7dc82806582960da8c1dd161..25f5640e271b8773d89facac08c7caab6aba5e64 100644 --- a/openedx/core/djangoapps/zendesk_proxy/v1/views.py +++ b/openedx/core/djangoapps/zendesk_proxy/v1/views.py @@ -1,6 +1,7 @@ """ Define request handlers used by the zendesk_proxy djangoapp """ +import logging from rest_framework import status from rest_framework.parsers import JSONParser @@ -10,6 +11,7 @@ from rest_framework.views import APIView from openedx.core.djangoapps.zendesk_proxy.utils import create_zendesk_ticket +logger = logging.getLogger(__name__) REQUESTS_PER_HOUR = 50 @@ -62,7 +64,8 @@ class ZendeskPassthroughView(APIView): custom_fields=request.data['custom_fields'], tags=request.data['tags'] ) - except KeyError: + except KeyError as key: + logger.error('Zendesk Proxy Bad Request KeyError: %s', key) return Response(status=status.HTTP_400_BAD_REQUEST) return Response( diff --git a/openedx/core/djangolib/blockstore_cache.py b/openedx/core/djangolib/blockstore_cache.py index 9beeaf60713c7e341354fcbfba0fa0ce4434d7c3..bbd482e9e58adfed4420f0298eb2745206dc11a8 100644 --- a/openedx/core/djangolib/blockstore_cache.py +++ b/openedx/core/djangolib/blockstore_cache.py @@ -81,7 +81,7 @@ class BundleCache(object): """ assert isinstance(key_parts, (list, tuple)) full_key = _get_versioned_cache_key(self.bundle_uuid, self.draft_name, key_parts) - return cache.set(full_key, value) + return cache.set(full_key, value, timeout=None) def clear(self): """ @@ -101,6 +101,14 @@ class BundleCache(object): cache.delete(cache_key) +def _construct_versioned_cache_key(bundle_uuid, version_num, key_parts, draft_name=None): + cache_key = str(bundle_uuid) + if draft_name: + cache_key += ":" + draft_name + cache_key += ":" + str(version_num) + ":" + ":".join(key_parts) + return cache_key + + def _get_versioned_cache_key(bundle_uuid, draft_name, key_parts): """ Generate a cache key string that can be used to store data about the current @@ -112,7 +120,7 @@ def _get_versioned_cache_key(bundle_uuid, draft_name, key_parts): """ assert isinstance(bundle_uuid, UUID) version_num = get_bundle_version_number(bundle_uuid, draft_name) - return str(bundle_uuid) + ":" + str(version_num) + ":" + ":".join(key_parts) + return _construct_versioned_cache_key(bundle_uuid, version_num, key_parts, draft_name) def get_bundle_version_number(bundle_uuid, draft_name=None): @@ -135,6 +143,11 @@ def get_bundle_version_number(bundle_uuid, draft_name=None): # Convert the 'updated_at' datetime info an integer value with microsecond accuracy. updated_at_timestamp = (draft_metadata.updated_at - datetime(1970, 1, 1, tzinfo=UTC)).total_seconds() version = int(updated_at_timestamp * 1e6) + # Cache the draft files using the version. This saves an API call when the draft is first retrieved. + draft_files = list(draft_metadata.files.values()) + draft_files_cache_key = _construct_versioned_cache_key( + bundle_uuid, version, ('bundle_draft_files', ), draft_name) + cache.set(draft_files_cache_key, draft_files) # If we're not using a draft or the draft does not exist [anymore], fall # back to the bundle version, if any versions have been published: if version == 0 and bundle_metadata.latest_version: diff --git a/openedx/core/djangolib/tests/test_js_utils.py b/openedx/core/djangolib/tests/test_js_utils.py index 024a11c89bedc1fc2d85e9cfff33555d6c7338cb..f427335cab8da8caaa514d9c3d8a02b64f6da6c5 100644 --- a/openedx/core/djangolib/tests/test_js_utils.py +++ b/openedx/core/djangolib/tests/test_js_utils.py @@ -6,6 +6,7 @@ Tests for js_utils.py import json import re +import html from unittest import TestCase import six @@ -184,9 +185,8 @@ class TestJSUtils(TestCase): should be parseable into a near equivalent to test_dict. """ - html_parser = six.moves.html_parser.HTMLParser() - expected_json = html_parser.unescape(expected_json_for_html_string) + expected_json = html.unescape(expected_json_for_html_string) parsed_expected_dict = json.loads(expected_json) # tuples become arrays in json, so it is parsed to a list that is # switched back to a tuple before comparing diff --git a/openedx/core/lib/api/tests/test_authentication.py b/openedx/core/lib/api/tests/test_authentication.py index 0c973e94c32d1599dd2cdf94ab8edd52fed372c3..61a627958c8d95ec8d0929100c2e8c5af3b988e4 100644 --- a/openedx/core/lib/api/tests/test_authentication.py +++ b/openedx/core/lib/api/tests/test_authentication.py @@ -45,7 +45,6 @@ class MockView(APIView): # pylint: disable=missing-docstring urlpatterns = [ - url(r'^oauth2/', include(('provider.oauth2.urls', 'oauth2'), namespace='oauth2')), url( r'^oauth2-inactive-test/$', MockView.as_view(authentication_classes=[authentication.BearerAuthenticationAllowInactiveUser]) diff --git a/openedx/core/lib/api/view_utils.py b/openedx/core/lib/api/view_utils.py index b776cbc5e16d7088a753bddb91b43eadc8f4355f..e4c35b02a6121d182c56b7bc243ac9c673f61eb6 100644 --- a/openedx/core/lib/api/view_utils.py +++ b/openedx/core/lib/api/view_utils.py @@ -23,6 +23,7 @@ from rest_framework.views import APIView from six import text_type, iteritems from openedx.core.djangoapps.content.course_overviews.models import CourseOverview +from openedx.core.djangoapps.user_api.accounts import BIO_MAX_LENGTH from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser from openedx.core.lib.api.permissions import IsUserInUrl @@ -154,11 +155,16 @@ def add_serializer_errors(serializer, data, field_errors): errors = serializer.errors for key, error in iteritems(errors): error = clean_errors(error) + if key == 'bio': + user_message = _(u"The about me field must be at most {} characters long.".format(BIO_MAX_LENGTH)) + else: + user_message = _(u"This value is invalid.") + field_errors[key] = { 'developer_message': u"Value '{field_value}' is not valid for field '{field_name}': {error}".format( field_value=data.get(key, ''), field_name=key, error=error ), - 'user_message': _(u"This value is invalid."), + 'user_message': user_message, } return field_errors diff --git a/openedx/core/lib/blockstore_api/methods.py b/openedx/core/lib/blockstore_api/methods.py index 7a3fa49ecf2a458863e275ccd527096c26d2849f..a9735aace216e44eb80f6ee2980cb6cc1854076d 100644 --- a/openedx/core/lib/blockstore_api/methods.py +++ b/openedx/core/lib/blockstore_api/methods.py @@ -264,7 +264,7 @@ def get_bundle_version_links(bundle_uuid, version_number): Get a dictionary of the links in the specified bundle version """ if version_number == 0: - return [] + return {} version_url = api_url('bundle_versions', str(bundle_uuid) + ',' + str(version_number)) version_info = api_request('get', version_url) return { diff --git a/openedx/core/lib/cache_utils.py b/openedx/core/lib/cache_utils.py index 9a71acc791a91eb1f61bd7139e1bf489f523e26d..eebe87f75c63788b776d9371fce6e9136e5d9315 100644 --- a/openedx/core/lib/cache_utils.py +++ b/openedx/core/lib/cache_utils.py @@ -159,6 +159,7 @@ class CacheInvalidationManager: To use, instantiate with a namespace or django model class: `manager = CacheInvalidationManager(model=User)` + One of namespace or model should be specified, but not both. Then use it as a decorator on functions with no arguments `@manager @@ -173,7 +174,7 @@ class CacheInvalidationManager: if model: post_save.connect(self.invalidate, sender=model) post_delete.connect(self.invalidate, sender=model) - namespace = str(model) + namespace = "{}.{}".format(model.__module__, model.__qualname__) self.namespace = namespace self.cache_time = cache_time self.keys = set() diff --git a/openedx/core/lib/dynamic_partitions_generators.py b/openedx/core/lib/dynamic_partitions_generators.py new file mode 100644 index 0000000000000000000000000000000000000000..d7b7f6accef118e408aaca26b5af97e9a4aea57c --- /dev/null +++ b/openedx/core/lib/dynamic_partitions_generators.py @@ -0,0 +1,9 @@ +""" +A plugin manager to retrieve the dynamic course partitions generators. +""" + +from openedx.core.lib.plugins import PluginManager + + +class DynamicPartitionGeneratorsPluginManager(PluginManager): + NAMESPACE = 'openedx.dynamic_partition_generator' diff --git a/openedx/core/lib/teams_config.py b/openedx/core/lib/teams_config.py index 8a292a10116be5a1c61efc1d82dc17e037a352b2..ea785b1e2a79a1a742f50edbdf48abdb6df09b16 100644 --- a/openedx/core/lib/teams_config.py +++ b/openedx/core/lib/teams_config.py @@ -84,21 +84,6 @@ class TeamsConfig(object): ] } - @cached_property - def cleaned_data_old_format(self): - """ - JSON-friendly dictionary containing cleaned data from this TeamsConfig, - excluding newly added fields. - - Here for backwards compatibility; to be removed (TODO MST-40). - """ - return { - 'max_team_size': self.default_max_team_size, - 'topics': [ - teamset.cleaned_data_old_format for teamset in self.teamsets - ] - } - @property def is_enabled(self): """ @@ -246,20 +231,6 @@ class TeamsetConfig(object): 'type': self.teamset_type.value, } - @cached_property - def cleaned_data_old_format(self): - """ - JSON-friendly dictionary containing cleaned data from this TeamsConfig, - excluding newly added fields. - - Here for backwards compatibility; to be removed (TODO MST-40). - """ - return { - 'id': self.teamset_id, - 'name': self.name, - 'description': self.description, - } - @cached_property def teamset_id(self): """ diff --git a/openedx/core/lib/tests/assertions/events.py b/openedx/core/lib/tests/assertions/events.py index f8f113ff25cf02cede9f4e608c6cf8349f56c34f..1293eb627185a36e9ef13b38886913afff30b7b8 100644 --- a/openedx/core/lib/tests/assertions/events.py +++ b/openedx/core/lib/tests/assertions/events.py @@ -190,15 +190,16 @@ def block_indent(text, spaces=4): def parse_event_payload(event): """ - Given an event, parse the "event" field as a JSON string. + Given an event, parse the 'event' field, if found otherwise 'data' field as a JSON string. Note that this may simply return the same event unchanged, or return a new copy of the event with the payload parsed. It will never modify the event in place. """ - if 'event' in event and isinstance(event['event'], six.string_types): + payload_key = 'event' if 'event' in event else 'data' + if payload_key in event and isinstance(event[payload_key], six.string_types): event = event.copy() try: - event['event'] = json.loads(event['event']) + event[payload_key] = json.loads(event[payload_key]) except ValueError: pass return event diff --git a/openedx/core/lib/xblock_pipeline/finder.py b/openedx/core/lib/xblock_pipeline/finder.py index 2cb3eb3ce3603b4592f9a13715ab95a1aca3d03c..aad79b8d441c695e04a08036751659586de120d4 100644 --- a/openedx/core/lib/xblock_pipeline/finder.py +++ b/openedx/core/lib/xblock_pipeline/finder.py @@ -9,6 +9,7 @@ from django.contrib.staticfiles import utils from django.contrib.staticfiles.finders import BaseFinder from django.contrib.staticfiles.storage import FileSystemStorage from django.core.files.storage import Storage +from django.utils import timezone from pkg_resources import resource_exists, resource_filename, resource_isdir, resource_listdir from xblock.core import XBlock @@ -80,19 +81,19 @@ class XBlockPackageStorage(Storage): """ Returns a URL to the package resource. """ - return datetime.fromtimestamp(os.path.getatime(self.path(name))) + return datetime.fromtimestamp(os.path.getatime(self.path(name)), timezone.utc) def get_created_time(self, name): """ Returns the created time of the package resource. """ - return datetime.fromtimestamp(os.path.getctime(self.path(name))) + return datetime.fromtimestamp(os.path.getctime(self.path(name)), timezone.utc) def get_modified_time(self, name): """ Returns the modified time of the resource. """ - return datetime.fromtimestamp(os.path.getmtime(self.path(name))) + return datetime.fromtimestamp(os.path.getmtime(self.path(name)), timezone.utc) def url(self, name): """ diff --git a/openedx/core/lib/xblock_utils/__init__.py b/openedx/core/lib/xblock_utils/__init__.py index 00423da4bc9cd7a2e474c8730d00e039eb894fdf..c8c205f2e2f48ff026d38fb3276b9bd28eb4f500 100644 --- a/openedx/core/lib/xblock_utils/__init__.py +++ b/openedx/core/lib/xblock_utils/__init__.py @@ -323,23 +323,7 @@ def add_staff_markup(user, disable_staff_debug_info, block, view, frag, context) return frag # TODO: make this more general, eg use an XModule attribute instead if isinstance(block, VerticalBlock) and (not context or not context.get('child_of_vertical', False)): - # check that the course is a mongo backed Studio course before doing work - is_studio_course = block.course_edit_method == "Studio" - - if is_studio_course: - # build edit link to unit in CMS. Can't use reverse here as lms doesn't load cms's urls.py - edit_link = "//" + settings.CMS_BASE + '/container/' + text_type(block.location) - - # return edit link in rendered HTML for display - return wrap_fragment( - frag, - render_to_string( - "edit_unit_link.html", - {'frag_content': frag.content, 'edit_link': edit_link} - ) - ) - else: - return frag + return frag if isinstance(block, SequenceModule) or getattr(block, 'HIDDEN', False): return frag diff --git a/openedx/core/process_warnings.py b/openedx/core/process_warnings.py index 6c749e76f17e850effb4649ebb50af1fd19fd32d..e0b0fd37f85fd2f4a881cca2c0b3c5c18542db73 100644 --- a/openedx/core/process_warnings.py +++ b/openedx/core/process_warnings.py @@ -6,10 +6,10 @@ from __future__ import print_function import json import os import io +import itertools import re import argparse from collections import Counter -import pandas as pd from write_to_html import ( HtmlOutlineWriter, @@ -156,16 +156,29 @@ def process_warnings_json(dir_path): return compressed_warnings_data -def group_and_sort_by_sumof(dataframe, group, sort_by): - groups_by = dataframe.groupby(group) - temp_list_to_sort = [(key, value, value[sort_by].sum()) for key, value in groups_by] +def group_and_sort_by_sumof(data, group, sort_by): + """ + Group and sort data. + + Return + List of tuples. Each tuple has: + - Group key + - Iterable of warnings that belongs to that group + - Count of warnings that belong to that group + """ + sorted_data = sorted(data, key=lambda x: x[columns.index(group)]) + groups_by = itertools.groupby(sorted_data, lambda x: x[columns_index_dict[group]]) + temp_list_to_sort = [] + for key, generator in groups_by: + value = list(generator) + temp_list_to_sort.append((key, value, sum([item[columns_index_dict[sort_by]] for item in value]))) # sort by count return sorted(temp_list_to_sort, key=lambda x: -x[2]) -def write_html_report(warnings_dataframe, html_path): +def write_html_report(warnings_data, html_path): """ - converts from panda dataframe to our html + converts from list of lists data to our html """ html_path = os.path.expanduser(html_path) if "/" in html_path: @@ -175,7 +188,7 @@ def write_html_report(warnings_dataframe, html_path): with io.open(html_path, "w") as fout: html_writer = HtmlOutlineWriter(fout) category_sorted_by_count = group_and_sort_by_sumof( - warnings_dataframe, "category", "num" + warnings_data, "category", "num" ) for category, group_in_category, category_count in category_sorted_by_count: # xss-lint: disable=python-wrap-html @@ -211,20 +224,20 @@ def write_html_report(warnings_dataframe, html_path): ) html_writer.start_section(html, klass=u"warning_text") # warnings_object[location][warning_text] is a list - for _, warning in message_group.iterrows(): + for warning in message_group: # xss-lint: disable=python-wrap-html html = u'<span class="count">{warning_file_path}</span> '.format( - warning_file_path=warning["filename"] + warning_file_path=warning[columns_index_dict["filename"]] ) html_writer.start_section(html, klass=u"warning") # xss-lint: disable=python-wrap-html html = u'<p class="lineno">lineno: {lineno}</p> '.format( - lineno=warning["lineno"] + lineno=warning[columns_index_dict["lineno"]] ) html_writer.write(html) # xss-lint: disable=python-wrap-html html = u'<p class="num">num_occur: {num}</p> '.format( - num=warning["num"] + num=warning[columns_index_dict["num"]] ) html_writer.write(html) @@ -242,5 +255,4 @@ if __name__ == "__main__": parser.add_argument("--html-path", default="test_html.html") args = parser.parse_args() data_output = process_warnings_json(args.dir_path) - data_dataframe = pd.DataFrame(data=data_output, columns=columns) - write_html_report(data_dataframe, args.html_path) + write_html_report(data_output, args.html_path) diff --git a/openedx/core/tests/test_admin_view.py b/openedx/core/tests/test_admin_view.py index c1d45e69113156ac01869e9903243023f906b847..7362a8c14610aa7b377ddae336d315242a2c8d5c 100644 --- a/openedx/core/tests/test_admin_view.py +++ b/openedx/core/tests/test_admin_view.py @@ -41,3 +41,6 @@ class TestAdminView(TestCase): response = self.client.get(reverse('admin:login')) assert response.url == '/login?next=/admin' assert response.status_code == 302 + with ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY.override(False): + response = self.client.get(reverse('admin:login')) + assert response.template_name == ['admin/login.html'] diff --git a/openedx/features/calendar_sync/docs/decisions/0001-calendar-sync-emails-using-ses.rst b/openedx/features/calendar_sync/docs/decisions/0001-calendar-sync-emails-using-ses.rst new file mode 100644 index 0000000000000000000000000000000000000000..3491383abf619e501af09a6098f8b3174c5ab80f --- /dev/null +++ b/openedx/features/calendar_sync/docs/decisions/0001-calendar-sync-emails-using-ses.rst @@ -0,0 +1,24 @@ +1. Amazon SES for calendar sync emails +================================================ + +Status +------ + +Proposed + +Context +------- + +For calendar sync functionality, we would like to send users +emails with .ics file attachments, which will in turn allow the user +to easily add/update course deadline dates on their personal calendars. + +Decision +-------- + +We will use Amazon SES to send these emails. Originally, we had hoped to use +Sailthru, but found that file attachments were not supported. While emails +with attachments are not currently sent from platform at the time this doc is +being written, they are however sent from other services such as +enterprise-data using Amazon SES. We will use a similar approach for our +calendar sync feature. diff --git a/openedx/features/calendar_sync/message_types.py b/openedx/features/calendar_sync/message_types.py deleted file mode 100644 index 72af6e8009233008628429eb95d69b1fc07e100a..0000000000000000000000000000000000000000 --- a/openedx/features/calendar_sync/message_types.py +++ /dev/null @@ -1,13 +0,0 @@ -""" -ACE message types for the calendar_sync module. -""" - - -from openedx.core.djangoapps.ace_common.message import BaseMessageType - - -class CalendarSync(BaseMessageType): - def __init__(self, *args, **kwargs): - super(CalendarSync, self).__init__(*args, **kwargs) - - self.options['transactional'] = True diff --git a/openedx/features/calendar_sync/tasks.py b/openedx/features/calendar_sync/tasks.py deleted file mode 100644 index 834d4e5c01fdf02a4a60595cb7f03e76186ed610..0000000000000000000000000000000000000000 --- a/openedx/features/calendar_sync/tasks.py +++ /dev/null @@ -1,71 +0,0 @@ -""" -This file contains celery tasks for sending email -""" - - -import logging - -from celery.exceptions import MaxRetriesExceededError -from celery.task import task -from django.conf import settings -from django.contrib.auth.models import User -from django.contrib.sites.models import Site -from edx_ace import ace -from edx_ace.errors import RecoverableChannelDeliveryError -from edx_ace.message import Message -from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.lib.celery.task_utils import emulate_http_request - -log = logging.getLogger('edx.celery.task') - - -@task(bind=True) -def send_calendar_sync_email(self, msg_string, from_address=None): - """ - Sending calendar sync email to the user. - """ - msg = Message.from_string(msg_string) - - max_retries = settings.RETRY_CALENDAR_SYNC_EMAIL_MAX_ATTEMPTS - retries = self.request.retries - - if from_address is None: - from_address = configuration_helpers.get_value('ACTIVATION_EMAIL_FROM_ADDRESS') or ( - configuration_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL) - ) - msg.options['from_address'] = from_address - - dest_addr = msg.recipient.email_address - - site = Site.objects.get_current() - user = User.objects.get(username=msg.recipient.username) - - try: - with emulate_http_request(site=site, user=user): - ace.send(msg) - # Log that the Activation Email has been sent to user without an exception - log.info("Calendar Sync Email has been sent to User {user_email}".format( - user_email=dest_addr - )) - except RecoverableChannelDeliveryError: - log.info('Retrying sending email to user {dest_addr}, attempt # {attempt} of {max_attempts}'.format( - dest_addr=dest_addr, - attempt=retries, - max_attempts=max_retries - )) - try: - self.retry(countdown=settings.RETRY_ACTIVATION_EMAIL_TIMEOUT, max_retries=max_retries) - except MaxRetriesExceededError: - log.error( - 'Unable to send calendar sync email to user from "%s" to "%s"', - from_address, - dest_addr, - exc_info=True - ) - except Exception: - log.exception( - 'Unable to send calendar sync email to user from "%s" to "%s"', - from_address, - dest_addr, - ) - raise Exception diff --git a/openedx/features/calendar_sync/tests/test_ics.py b/openedx/features/calendar_sync/tests/test_ics.py index 8fa356fba29eecad04b376b9c67b18d4a56bf210..bd0892ce36584adcd614e69d101f44088225a2ee 100644 --- a/openedx/features/calendar_sync/tests/test_ics.py +++ b/openedx/features/calendar_sync/tests/test_ics.py @@ -31,9 +31,12 @@ class TestIcsGeneration(TestCase): self.request.site = SiteFactory() self.request.user = self.user - def make_assigment(self, block_key=None, title=None, url=None, date=None, requires_file_access=False): + def make_assigment( + self, block_key=None, title=None, url=None, date=None, contains_gated_content=False, complete=False, + past_due=False, assignment_type=None + ): """ Bundles given info into a namedtupled like get_course_assignments returns """ - return _Assignment(block_key, title, url, date, requires_file_access) + return _Assignment(block_key, title, url, date, contains_gated_content, complete, past_due, assignment_type) def expected_ics(self, *assignments): """ Returns hardcoded expected ics strings for given assignments """ diff --git a/openedx/features/calendar_sync/tests/test_tasks.py b/openedx/features/calendar_sync/tests/test_tasks.py deleted file mode 100644 index 787e68f5484599043e208ba7ef5e8fec53354add..0000000000000000000000000000000000000000 --- a/openedx/features/calendar_sync/tests/test_tasks.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -Tests for the Sending activation email celery tasks -""" - - -import mock -from django.conf import settings -from django.test import TestCase -from six.moves import range - -from edx_ace.errors import ChannelError, RecoverableChannelDeliveryError -from lms.djangoapps.courseware.tests.factories import UserFactory -from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory -from openedx.features.calendar_sync.tasks import send_calendar_sync_email -from openedx.features.calendar_sync.views.management import compose_calendar_sync_email - - -class SendCalendarSyncEmailTestCase(TestCase): - """ - Test for send activation email to user - """ - def setUp(self): - """ Setup components used by each test.""" - super(SendCalendarSyncEmailTestCase, self).setUp() - self.user = UserFactory() - self.course_overview = CourseOverviewFactory() - self.msg = compose_calendar_sync_email(self.user, self.course_overview) - - @mock.patch('time.sleep', mock.Mock(return_value=None)) - @mock.patch('openedx.features.calendar_sync.tasks.log') - @mock.patch( - 'openedx.features.calendar_sync.tasks.ace.send', - mock.Mock(side_effect=RecoverableChannelDeliveryError(None, None)) - ) - def test_RetrySendUntilFail(self, mock_log): - """ - Tests retries when the activation email doesn't send - """ - from_address = 'task_testing@example.com' - email_max_attempts = settings.RETRY_ACTIVATION_EMAIL_MAX_ATTEMPTS - - send_calendar_sync_email.delay(str(self.msg), from_address=from_address) - - # Asserts sending email retry logging. - for attempt in range(email_max_attempts): - mock_log.info.assert_any_call( - 'Retrying sending email to user {dest_addr}, attempt # {attempt} of {max_attempts}'.format( - dest_addr=self.user.email, - attempt=attempt, - max_attempts=email_max_attempts - )) - self.assertEqual(mock_log.info.call_count, 6) - - # Asserts that the error was logged on crossing max retry attempts. - mock_log.error.assert_called_with( - 'Unable to send calendar sync email to user from "%s" to "%s"', - from_address, - self.user.email, - exc_info=True - ) - self.assertEqual(mock_log.error.call_count, 1) - - @mock.patch('openedx.features.calendar_sync.tasks.log') - @mock.patch('openedx.features.calendar_sync.tasks.ace.send', mock.Mock(side_effect=ChannelError)) - def test_UnrecoverableSendError(self, mock_log): - """ - Tests that a major failure of the send is logged - """ - from_address = 'task_testing@example.com' - - send_calendar_sync_email.delay(str(self.msg), from_address=from_address) - - # Asserts that the error was logged - mock_log.exception.assert_called_with( - 'Unable to send calendar sync email to user from "%s" to "%s"', - from_address, - self.user.email - ) - - # Assert that nothing else was logged - self.assertEqual(mock_log.info.call_count, 0) - self.assertEqual(mock_log.error.call_count, 0) - self.assertEqual(mock_log.exception.call_count, 1) diff --git a/openedx/features/calendar_sync/tests/test_views.py b/openedx/features/calendar_sync/tests/test_views.py index 85d730105b620733382d963cb41f1961376fb7a8..d9892c050d02e4fa37d836a2d10ba3c80eb64a1d 100644 --- a/openedx/features/calendar_sync/tests/test_views.py +++ b/openedx/features/calendar_sync/tests/test_views.py @@ -8,10 +8,7 @@ import ddt from django.test import TestCase from django.urls import reverse -from lms.djangoapps.courseware.tests.factories import UserFactory -from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory from openedx.features.calendar_sync.api import SUBSCRIBE, UNSUBSCRIBE -from openedx.features.calendar_sync.views.management import compose_calendar_sync_email from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory @@ -52,39 +49,3 @@ class TestCalendarSyncView(SharedModuleStoreTestCase, TestCase): response = self.client.post(self.calendar_sync_url, data) self.assertEqual(response.status_code, expected_status_code) self.assertIn(contained_text, str(response.content)) - - -@ddt.ddt -class CalendarSyncEmailTestCase(TestCase): - """ - Test for send activation email to user - """ - - @ddt.data(False, True) - def test_compose_calendar_sync_email(self, is_update): - """ - Tests that attributes of the message are being filled correctly in compose_activation_email - """ - user = UserFactory() - course_overview = CourseOverviewFactory() - course_name = course_overview.display_name - if is_update: - calendar_sync_subject = 'Updates for Your {course} Schedule'.format(course=course_name) - calendar_sync_headline = 'Update Your Calendar' - calendar_sync_body = ('Your assignment due dates for {course} were recently adjusted. Update your calendar' - 'with your new schedule to ensure that you stay on track!').format(course=course_name) - else: - calendar_sync_subject = 'Stay on Track' - calendar_sync_headline = 'Mark Your Calendar' - calendar_sync_body = ( - 'Sticking to a schedule is the best way to ensure that you successfully complete your ' - 'self-paced course. This schedule of assignment due dates for {course} will help you ' - 'stay on track!'.format(course=course_name)) - - msg = compose_calendar_sync_email(user, course_overview, is_update) - - self.assertEqual(msg.context['calendar_sync_subject'], calendar_sync_subject) - self.assertEqual(msg.context['calendar_sync_headline'], calendar_sync_headline) - self.assertEqual(msg.context['calendar_sync_body'], calendar_sync_body) - self.assertEqual(msg.recipient.username, user.username) - self.assertEqual(msg.recipient.email_address, user.email) diff --git a/openedx/features/calendar_sync/utils.py b/openedx/features/calendar_sync/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..7bade9b7fd8c48d1e39458ba3a5af1926bbfb25c --- /dev/null +++ b/openedx/features/calendar_sync/utils.py @@ -0,0 +1,79 @@ +import logging +from email.mime.application import MIMEApplication +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from django.conf import settings +from django.utils.html import format_html +from django.utils.translation import ugettext_lazy as _ +import os + +import boto3 + +logger = logging.getLogger(__name__) + + +def calendar_sync_initial_email_content(course_name): + subject = _('Stay on Track') + body_text = _('Sticking to a schedule is the best way to ensure that you successfully complete your self-paced ' + 'course. This schedule of assignment due dates for {course} will help you stay on track!' + ).format(course=course_name) + body = format_html('<div>{text}</div>', text=body_text) + return subject, body + + +def calendar_sync_update_email_content(course_name): + subject = _('Updates for Your {course} Schedule').format(course=course_name) + body_text = _('Your assignment due dates for {course} were recently adjusted. Update your calendar with your new ' + 'schedule to ensure that you stay on track!').format(course=course_name) + body = format_html('<div>{text}</div>', text=body_text) + return subject, body + + +def prepare_attachments(attachment_data): + """ + Helper function to create a list contain file attachment objects + for use with MIMEMultipart + Returns a list of MIMEApplication objects + """ + + attachments = [] + for filename, data in attachment_data.items(): + msg_attachment = MIMEApplication(data) + msg_attachment.add_header( + 'Content-Disposition', + 'attachment', + filename=os.path.basename(filename) + ) + msg_attachment.set_type('text/calendar') + attachments.append(msg_attachment) + + return attachments + + +def send_email_with_attachment(to_emails, attachment_data, course_name, is_update=False): + # connect to SES + client = boto3.client('ses', region_name=settings.AWS_SES_REGION_NAME) + + subject, body = (calendar_sync_update_email_content(course_name) if is_update else + calendar_sync_initial_email_content(course_name)) + + # build email body as html + msg_body = MIMEText(body, 'html') + + attachments = prepare_attachments(attachment_data) + + # iterate over each email in the list to send emails independently + for email in to_emails: + msg = MIMEMultipart() + msg['Subject'] = str(subject) + msg['From'] = settings.BULK_EMAIL_DEFAULT_FROM_EMAIL + msg['To'] = email + + # attach the message body and attachment + msg.attach(msg_body) + for msg_attachment in attachments: + msg.attach(msg_attachment) + + # send the email + result = client.send_raw_email(Source=msg['From'], Destinations=[email], RawMessage={'Data': msg.as_string()}) + logger.debug(result) diff --git a/openedx/features/calendar_sync/views/management.py b/openedx/features/calendar_sync/views/management.py deleted file mode 100644 index 9e4527c796418ff27ca55fe13710fa89bff40638..0000000000000000000000000000000000000000 --- a/openedx/features/calendar_sync/views/management.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -Calendar Sync Email Management -""" - - -from django.utils.translation import ugettext_lazy as _ - -from edx_ace.recipient import Recipient -from student.models import CourseEnrollment, CourseOverview -from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY -from openedx.core.djangoapps.user_api.preferences import api as preferences_api -from openedx.features.calendar_sync.message_types import CalendarSync -from openedx.features.calendar_sync.tasks import send_calendar_sync_email - - -def compose_calendar_sync_email(user, course: CourseOverview, is_update=False): - """ - Construct all the required params for the calendar - sync email through celery task - """ - - course_name = course.display_name - if is_update: - calendar_sync_subject = _('Updates for Your {course} Schedule').format(course=course_name) - calendar_sync_headline = _('Update Your Calendar') - calendar_sync_body = _('Your assignment due dates for {course} were recently adjusted. Update your calendar' - 'with your new schedule to ensure that you stay on track!').format(course=course_name) - else: - calendar_sync_subject = _('Stay on Track') - calendar_sync_headline = _('Mark Your Calendar') - calendar_sync_body = _('Sticking to a schedule is the best way to ensure that you successfully complete your ' - 'self-paced course. This schedule of assignment due dates for {course} will help you ' - 'stay on track!').format(course=course_name) - email_context = { - 'calendar_sync_subject': calendar_sync_subject, - 'calendar_sync_headline': calendar_sync_headline, - 'calendar_sync_body': calendar_sync_body, - } - - msg = CalendarSync().personalize( - recipient=Recipient(user.username, user.email), - language=preferences_api.get_user_preference(user, LANGUAGE_KEY), - user_context=email_context, - ) - - return msg - - -def compose_and_send_calendar_sync_email(user, course: CourseOverview, is_update=False): - """ - Construct all the required params and send the activation email - through celery task - - Arguments: - user: current logged-in user - course: course overview object - is_update: if this should be an 'update' email - """ - if not CourseEnrollment.objects.filter(user=user, course=course).exists(): - return - - msg = compose_calendar_sync_email(user, course, is_update) - - send_calendar_sync_email.delay(str(msg)) diff --git a/openedx/features/content_type_gating/block_transformers.py b/openedx/features/content_type_gating/block_transformers.py index ffec502345219567d4c7406dae7f38299b2dd8e7..db88164f75e9cf2277b4d006184ce9fbd287eb90 100644 --- a/openedx/features/content_type_gating/block_transformers.py +++ b/openedx/features/content_type_gating/block_transformers.py @@ -35,6 +35,18 @@ class ContentTypeGateTransformer(BlockStructureTransformer): """ block_structure.request_xblock_fields('group_access', 'graded', 'has_score', 'weight') + def _set_contains_gated_content_on_parents(self, block_structure, block_key): + """ + This will recursively set a field on all the parents of a block if one of the problems + inside of it is content gated. `contains_gated_content` can then be used to indicate something + in the blocks subtree is gated. + """ + for parent_block_key in block_structure.get_parents(block_key): + if block_structure.get_xblock_field(parent_block_key, 'contains_gated_content'): + continue + block_structure.override_xblock_field(parent_block_key, 'contains_gated_content', True) + self._set_contains_gated_content_on_parents(block_structure, parent_block_key) + def transform(self, usage_info, block_structure): if not ContentTypeGatingConfig.enabled_for_enrollment( user=usage_info.user, @@ -56,3 +68,5 @@ class ContentTypeGateTransformer(BlockStructureTransformer): [settings.CONTENT_TYPE_GATE_GROUP_IDS['full_access']] ) block_structure.override_xblock_field(block_key, 'group_access', current_access) + if current_access[CONTENT_GATING_PARTITION_ID] == [settings.CONTENT_TYPE_GATE_GROUP_IDS['full_access']]: + self._set_contains_gated_content_on_parents(block_structure, block_key) diff --git a/openedx/features/content_type_gating/models.py b/openedx/features/content_type_gating/models.py index ce6026c505036025adac14cf486de19205e06178..1a402de9f7ffaa0f74f716de072c3226f10c7c43 100644 --- a/openedx/features/content_type_gating/models.py +++ b/openedx/features/content_type_gating/models.py @@ -96,7 +96,6 @@ class ContentTypeGatingConfig(StackedConfigurationModel): ``enabled_as_of`` before the enrollment was created. Arguments: - enrollment: The enrollment being queried. user: The user being queried. course_key: The CourseKey of the course being queried. """ diff --git a/openedx/features/course_duration_limits/access.py b/openedx/features/course_duration_limits/access.py index ea43617e4da27f387c65c54cbfd47573b90d1db8..8696d21561522176dc4b2d4cc44858833ed387fe 100644 --- a/openedx/features/course_duration_limits/access.py +++ b/openedx/features/course_duration_limits/access.py @@ -67,6 +67,10 @@ def get_user_course_duration(user, course): if enrollment is None or enrollment.mode != CourseMode.AUDIT: return None + verified_mode = CourseMode.verified_mode_for_course(course=course, include_expired=True) + if not verified_mode: + return None + return get_expected_duration(course) @@ -87,26 +91,10 @@ def get_user_course_expiration_date(user, course): if enrollment is None or enrollment.mode != CourseMode.AUDIT: return None - try: - # Content availability date is equivalent to max(enrollment date, course start date) - # for most people. Using the schedule date will provide flexibility to deal with - # more complex business rules in the future. - content_availability_date = enrollment.schedule.start_date - # We have anecdotally observed a case where the schedule.start_date was - # equal to the course start, but should have been equal to the enrollment start - # https://openedx.atlassian.net/browse/PROD-58 - # This section is meant to address that case - if enrollment.created and course.start: - if (content_availability_date.date() == course.start.date() and - course.start < enrollment.created < timezone.now()): - content_availability_date = enrollment.created - # If course teams change the course start date, set the content_availability_date - # to max of enrollment or course start date - elif (content_availability_date.date() < course.start.date() and - content_availability_date.date() < enrollment.created.date()): - content_availability_date = max(enrollment.created, course.start) - except CourseEnrollment.schedule.RelatedObjectDoesNotExist: - content_availability_date = max(enrollment.created, course.start) + # We reset schedule.start in order to change a user's computed deadlines. + # But their expiration date shouldn't change when we adjust their schedule (they don't + # get additional time), so we need to based the expiration date on a fixed start date. + content_availability_date = max(enrollment.created, course.start) return content_availability_date + access_duration diff --git a/openedx/features/course_experience/__init__.py b/openedx/features/course_experience/__init__.py index c84d302e2a947dd35d2b832afe7c3090c5d4d8fb..a038208310be60ed3a9e281c753dd7194766e71f 100644 --- a/openedx/features/course_experience/__init__.py +++ b/openedx/features/course_experience/__init__.py @@ -72,9 +72,6 @@ UPGRADE_DEADLINE_MESSAGE = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'upgrade_dead # .. toggle_status: supported LATEST_UPDATE_FLAG = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'latest_update') -# Waffle flag to enable the use of Bootstrap for course experience pages -USE_BOOTSTRAP_FLAG = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'use_bootstrap', flag_undefined_default=True) - # Waffle flag to enable anonymous access to a course SEO_WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='seo') COURSE_ENABLE_UNENROLLED_ACCESS_FLAG = CourseWaffleFlag(SEO_WAFFLE_FLAG_NAMESPACE, 'enable_anonymous_courseware_access') @@ -85,9 +82,6 @@ RELATIVE_DATES_FLAG = ExperimentWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'relative_date # Waffle flag to enable user calendar syncing CALENDAR_SYNC_FLAG = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'calendar_sync') -# Waffle flag to ellipsize course welcome messages if they are too long -SHORTEN_WELCOME_MESSAGE_FLAG = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'shorten_welcome_message') - def course_home_page_title(course): # pylint: disable=unused-argument """ diff --git a/openedx/features/course_experience/api/__init__.py b/openedx/features/course_experience/api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/features/course_experience/api/v1/__init__.py b/openedx/features/course_experience/api/v1/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/features/course_experience/api/v1/tests/test_views.py b/openedx/features/course_experience/api/v1/tests/test_views.py new file mode 100644 index 0000000000000000000000000000000000000000..adcf340aa01521dbacb57efaba504f979bd1774f --- /dev/null +++ b/openedx/features/course_experience/api/v1/tests/test_views.py @@ -0,0 +1,31 @@ +""" +Tests for reset deadlines endpoint. +""" +import ddt + +from django.urls import reverse + +from course_modes.models import CourseMode +from lms.djangoapps.course_home_api.tests.utils import BaseCourseHomeTests +from student.models import CourseEnrollment + + +@ddt.ddt +class ResetCourseDeadlinesViewTests(BaseCourseHomeTests): + """ + Tests for reset deadlines endpoint. + """ + @ddt.data(CourseMode.VERIFIED) + def test_reset_deadlines(self, enrollment_mode): + CourseEnrollment.enroll(self.user, self.course.id, enrollment_mode) + # Test correct post body + response = self.client.post(reverse('course-experience-reset-course-deadlines'), {'course_key': self.course.id}) + self.assertEqual(response.status_code, 200) + # Test body with incorrect body param + response = self.client.post(reverse('course-experience-reset-course-deadlines'), {'course': self.course.id}) + self.assertEqual(response.status_code, 400) + # Test body with additional incorrect body param + response = self.client.post( + reverse('course-experience-reset-course-deadlines'), {'course_key': self.course.id, 'invalid': 'value'} + ) + self.assertEqual(response.status_code, 400) diff --git a/openedx/features/course_experience/api/v1/urls.py b/openedx/features/course_experience/api/v1/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..66ca7c43c2ce7e70969d8543a6d46557de188fae --- /dev/null +++ b/openedx/features/course_experience/api/v1/urls.py @@ -0,0 +1,19 @@ +""" +Contains URLs for the Course Experience API +""" + + +from django.urls import re_path + +from openedx.features.course_experience.api.v1.views import reset_course_deadlines + +urlpatterns = [] + +# URL for resetting course deadlines +urlpatterns += [ + re_path( + r'v1/reset_course_deadlines', + reset_course_deadlines, + name='course-experience-reset-course-deadlines' + ), +] diff --git a/openedx/features/course_experience/api/v1/views.py b/openedx/features/course_experience/api/v1/views.py new file mode 100644 index 0000000000000000000000000000000000000000..52871acdd4fca25971ba3b42a6ce27cae20c1146 --- /dev/null +++ b/openedx/features/course_experience/api/v1/views.py @@ -0,0 +1,32 @@ +from rest_framework.decorators import api_view, permission_classes +from rest_framework.exceptions import APIException, ParseError +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response + +from openedx.core.djangoapps.schedules.utils import reset_self_paced_schedule + + +class UnableToResetDeadlines(APIException): + status_code = 400 + default_detail = 'Unable to reset deadlines.' + default_code = 'unable_to_reset_deadlines' + + +@permission_classes((IsAuthenticated,)) +@api_view(['POST']) +def reset_course_deadlines(request): + course_key = request.data.get('course_key', None) + + # If body doesnt contain 'course_key', return 400 to client. + if not course_key: + raise ParseError("'course_key' is required.") + + # If body contains params other than 'course_key', return 400 to client. + if len(request.data) > 1: + raise ParseError("Only 'course_key' is expected.") + + try: + reset_self_paced_schedule(request.user, course_key) + return Response({'message': 'Deadlines successfully reset.'}) + except Exception: + raise UnableToResetDeadlines diff --git a/openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js b/openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js index d0a3683f1d10227e6ed3deb250d263ede33b3695..e865563f85b09fbc5ee80ec8095af7f0814fe222 100644 --- a/openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js +++ b/openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js @@ -42,7 +42,7 @@ export class WelcomeMessage { // eslint-disable-line import/prefer-default-expo // "Show More" support for welcome messages const messageContent = document.querySelector('#welcome-message-content'); const fullText = messageContent.innerHTML; - if (options.shortenWelcomeMessage && clampHtmlByWords(messageContent, 100) < 0) { + if (clampHtmlByWords(messageContent, 100) < 0) { const showMoreButton = document.querySelector('#welcome-message-show-more'); const shortText = messageContent.innerHTML; diff --git a/openedx/features/course_experience/static/course_experience/js/spec/WelcomeMessage_spec.js b/openedx/features/course_experience/static/course_experience/js/spec/WelcomeMessage_spec.js index 9f5595a5c0647d4f072be59422e1e09d675422e1..daea7536a3802c40582ad9cc0b39245cafc035b8 100644 --- a/openedx/features/course_experience/static/course_experience/js/spec/WelcomeMessage_spec.js +++ b/openedx/features/course_experience/static/course_experience/js/spec/WelcomeMessage_spec.js @@ -90,7 +90,6 @@ describe('Welcome Message factory', () => { loadFixtures('course_experience/fixtures/welcome-message-fragment.html'); new WelcomeMessage({ // eslint-disable-line no-new dismissUrl: endpointUrl, - shortenWelcomeMessage: true, }); }); diff --git a/openedx/features/course_experience/templates/course_experience/course-dates-fragment.html b/openedx/features/course_experience/templates/course_experience/course-dates-fragment.html index 2464682db75b19e8f16f8ee6ae12f24aea57e296..2ca2de015496ee25e82d107a71e70b7881732585 100644 --- a/openedx/features/course_experience/templates/course_experience/course-dates-fragment.html +++ b/openedx/features/course_experience/templates/course_experience/course-dates-fragment.html @@ -13,6 +13,9 @@ from django.utils.translation import ugettext as _ % for course_date_block in course_date_blocks: <%include file="dates-summary.html" args="course_date=course_date_block" /> % endfor + <div class="dates-tab-link"> + <a href="${dates_tab_link}">View all course dates</a> + </div> % endif <%static:require_module_async module_name="js/dateutil_factory" class_name="DateUtilFactory"> diff --git a/openedx/features/course_experience/templates/course_experience/course-outline-fragment.html b/openedx/features/course_experience/templates/course_experience/course-outline-fragment.html index 4f9ac1641505651c82033545e820abfda25b2057..8c46cd589702a0ed2ef8bfb60a4c311682cd2a3b 100644 --- a/openedx/features/course_experience/templates/course_experience/course-outline-fragment.html +++ b/openedx/features/course_experience/templates/course_experience/course-outline-fragment.html @@ -13,15 +13,20 @@ from django.utils import timezone from django.utils.translation import gettext as _ from django.utils.translation import ngettext +from lms.djangoapps.courseware.access import has_access from openedx.core.djangolib.markup import HTML, Text +from openedx.features.course_experience import RELATIVE_DATES_FLAG %> <% course_sections = blocks.get('children') self_paced = context.get('self_paced', False) -reset_deadlines_banner_displayed = False +relative_dates_flag_is_enabled = RELATIVE_DATES_FLAG.is_enabled(str(course_key)) +is_course_staff = bool(user and course and has_access(user, 'staff', course, course.id)) +dates_banner_displayed = False %> <main role="main" class="course-outline" id="main" tabindex="-1"> + <%include file="/dates_banner.html" /> % if course_sections is not None: <button class="btn btn-primary" id="expand-collapse-outline-all-button" @@ -60,15 +65,7 @@ reset_deadlines_banner_displayed = False scored = 'scored' if subsection.get('scored', False) else '' graded = 'graded' if subsection.get('graded') else '' num_graded_problems = subsection.get('num_graded_problems', 0) - due_date = subsection.get('due') - overdue = due_date is not None and due_date < timezone.now() and not subsection.get('complete', True) %> - % if overdue and not reset_deadlines_banner_displayed: - <% reset_deadlines_banner_displayed = True %> - <script type="text/javascript"> - $('.reset-deadlines-banner').css('display', 'flex'); - </script> - % endif <li class="subsection accordion ${ 'current' if subsection.get('resume_block') else '' } ${graded} ${scored}"> <a % if enable_links: @@ -79,7 +76,7 @@ reset_deadlines_banner_displayed = False class="subsection-text outline-button" id="${ subsection['id'] }" > - % if num_graded_problems and not (subsection.get('format') or 'special_exam_info' in subsection): + % if graded and scored and 'special_exam_info' not in subsection: <span class="icon fa fa-pencil-square-o" aria-hidden="true"></span> % endif <h4 class="subsection-title"> diff --git a/openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html b/openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html index 5e2568a8248f77e519d8f335ad864895ef700eeb..596b5e437723826e17d5d17ce4e2a42fe5ff9cfa 100644 --- a/openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html +++ b/openedx/features/course_experience/templates/course_experience/welcome-message-fragment.html @@ -37,6 +37,5 @@ from openedx.core.djangolib.markup import HTML <%static:webpack entry="WelcomeMessage"> new WelcomeMessage({ dismissUrl: "${dismiss_url | n, js_escaped_string}", - shortenWelcomeMessage: ${shorten_welcome_message | n, dump_js_escaped_json}, }); </%static:webpack> diff --git a/openedx/features/course_experience/tests/views/test_course_home.py b/openedx/features/course_experience/tests/views/test_course_home.py index 6e56952bd154b7435b2760a6755022baba630595..0374233b06527737efd641b83d1052ce756b4879 100644 --- a/openedx/features/course_experience/tests/views/test_course_home.py +++ b/openedx/features/course_experience/tests/views/test_course_home.py @@ -588,7 +588,9 @@ class TestCourseHomePageAccess(CourseHomePageTestCase): audit_user = UserFactory(password=self.TEST_PASSWORD) self.client.login(username=audit_user.username, password=self.TEST_PASSWORD) audit_enrollment = CourseEnrollment.enroll(audit_user, course.id, mode=CourseMode.AUDIT) - ScheduleFactory(start_date=THREE_YEARS_AGO + timedelta(days=1), enrollment=audit_enrollment) + audit_enrollment.created = THREE_YEARS_AGO + timedelta(days=1) + audit_enrollment.save() + ScheduleFactory(enrollment=audit_enrollment) response = self.client.get(url) @@ -1022,10 +1024,3 @@ class CourseHomeFragmentViewTests(ModuleStoreTestCase): response = self.client.get(self.url) self.assertContains(response, "<span>DISCOUNT_PRICE</span>") - - @RELATIVE_DATES_FLAG.override(active=True) - def test_reset_deadline_banner_is_present_on_course_tab(self): - CourseEnrollment.enroll(self.user, self.course.id, CourseMode.VERIFIED) # pylint: disable=no-member - response = self.client.get(self.url) - - self.assertContains(response, '<div class="reset-deadlines-banner">') diff --git a/openedx/features/course_experience/tests/views/test_course_outline.py b/openedx/features/course_experience/tests/views/test_course_outline.py index 81fe5701518e4bfa9d354fd39fe6a6abd611327f..0690a63cd7a96629d7e92c147132309962e43b59 100644 --- a/openedx/features/course_experience/tests/views/test_course_outline.py +++ b/openedx/features/course_experience/tests/views/test_course_outline.py @@ -7,12 +7,13 @@ import datetime import json import re +import ddt import six from completion import waffle from completion.models import BlockCompletion from completion.test_utils import CompletionWaffleTestMixin from django.contrib.sites.models import Site -from django.test import override_settings +from django.test import override_settings, RequestFactory from django.urls import reverse from django.utils import timezone from milestones.tests.utils import MilestonesTestCaseMixin @@ -23,13 +24,18 @@ from six import text_type from waffle.models import Switch from waffle.testutils import override_switch +from course_modes.models import CourseMode +from course_modes.tests.factories import CourseModeFactory from lms.djangoapps.courseware.tests.factories import StaffFactory from lms.urls import RESET_COURSE_DEADLINES_NAME from gating import api as lms_gating_api from lms.djangoapps.course_api.blocks.transformers.milestones import MilestonesAndSpecialExamsTransformer from openedx.core.djangoapps.schedules.models import Schedule from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory +from openedx.core.djangoapps.course_date_signals.models import SelfPacedRelativeDatesConfig from openedx.core.lib.gating import api as gating_api +from openedx.features.course_experience import RELATIVE_DATES_FLAG +from openedx.features.content_type_gating.models import ContentTypeGatingConfig from openedx.features.course_experience.views.course_outline import ( DEFAULT_COMPLETION_TRACKING_START, CourseOutlineFragmentView @@ -40,21 +46,29 @@ from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from ...utils import get_course_outline_block_tree + from .test_course_home import course_home_url TEST_PASSWORD = 'test' GATING_NAMESPACE_QUALIFIER = '.gating' +@ddt.ddt class TestCourseOutlinePage(SharedModuleStoreTestCase): """ Test the course outline view. """ + + ENABLED_SIGNALS = ['course_published'] + @classmethod def setUpClass(cls): """ Set up an array of various courses to be tested. """ + SelfPacedRelativeDatesConfig.objects.create(enabled=True) + # setUpClassAndTestData() already calls setUpClass on SharedModuleStoreTestCase # pylint: disable=super-method-not-called with super(TestCourseOutlinePage, cls).setUpClassAndTestData(): @@ -62,11 +76,13 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase): course = CourseFactory.create(self_paced=True) with cls.store.bulk_operations(course.id): chapter = ItemFactory.create(category='chapter', parent_location=course.location) - sequential = ItemFactory.create(category='sequential', parent_location=chapter.location) + sequential = ItemFactory.create(category='sequential', parent_location=chapter.location, graded=True, format="Homework") vertical = ItemFactory.create(category='vertical', parent_location=sequential.location) + problem = ItemFactory.create(category='problem', parent_location=vertical.location) course.children = [chapter] chapter.children = [sequential] sequential.children = [vertical] + vertical.children = [problem] cls.courses.append(course) course = CourseFactory.create() @@ -111,7 +127,11 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase): """Set up and enroll our fake user in the course.""" cls.user = UserFactory(password=TEST_PASSWORD) for course in cls.courses: - CourseEnrollment.enroll(cls.user, course.id) + enrollment = CourseEnrollment.enroll(cls.user, course.id) + ScheduleFactory.create( + start_date=timezone.now() - datetime.timedelta(days=1), + enrollment=enrollment + ) def setUp(self): """ @@ -120,21 +140,32 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase): super(TestCourseOutlinePage, self).setUp() self.client.login(username=self.user.username, password=TEST_PASSWORD) + @RELATIVE_DATES_FLAG.override(active=True) def test_outline_details(self): for course in self.courses: url = course_home_url(course) + + request_factory = RequestFactory() + request = request_factory.get(url) + request.user = self.user + + course_block_tree = get_course_outline_block_tree( + request, str(course.id), self.user + ) + response = self.client.get(url) self.assertTrue(course.children) - for chapter in course.children: - self.assertContains(response, chapter.display_name) - self.assertTrue(chapter.children) - for sequential in chapter.children: - self.assertContains(response, sequential.display_name) - if sequential.graded: - self.assertContains(response, sequential.due.strftime(u'%Y-%m-%d %H:%M:%S')) - self.assertContains(response, sequential.format) - self.assertTrue(sequential.children) + for chapter in course_block_tree['children']: + self.assertContains(response, chapter['display_name']) + self.assertTrue(chapter['children']) + for sequential in chapter['children']: + self.assertContains(response, sequential['display_name']) + if sequential['graded']: + print(sequential) + self.assertContains(response, sequential['due'].strftime(u'%Y-%m-%d %H:%M:%S')) + self.assertContains(response, sequential['format']) + self.assertTrue(sequential['children']) def test_num_graded_problems(self): course = CourseFactory.create() @@ -164,28 +195,61 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase): self.assertRegex(content, sequential2.display_name + r'\s*\(1 Question\)\s*</h4>') self.assertRegex(content, sequential3.display_name + r'\s*\(2 Questions\)\s*</h4>') + @RELATIVE_DATES_FLAG.override(active=True) + @ddt.data( + ([CourseMode.AUDIT, CourseMode.VERIFIED], CourseMode.AUDIT, False, True), + ([CourseMode.AUDIT, CourseMode.VERIFIED], CourseMode.VERIFIED, False, True), + ([CourseMode.AUDIT, CourseMode.VERIFIED, CourseMode.MASTERS], CourseMode.MASTERS, False, True), + ([CourseMode.PROFESSIONAL], CourseMode.PROFESSIONAL, False, True), + ([CourseMode.AUDIT, CourseMode.VERIFIED], CourseMode.VERIFIED, True, False), + ) + @ddt.unpack + def test_reset_course_deadlines_banner_shows_for_self_paced_course( + self, + course_modes, + enrollment_mode, + is_course_staff, + should_display + ): + ContentTypeGatingConfig.objects.create( + enabled=True, + enabled_as_of=datetime.datetime(2017, 1, 1), + ) + course = self.courses[0] + for mode in course_modes: + CourseModeFactory.create(course_id=course.id, mode_slug=mode) + + enrollment = CourseEnrollment.objects.get(course_id=course.id, user=self.user) + enrollment.mode = enrollment_mode + enrollment.save() + enrollment.schedule.start_date = timezone.now() - datetime.timedelta(days=30) + enrollment.schedule.save() + self.user.is_staff = is_course_staff + self.user.save() + + url = course_home_url(course) + response = self.client.get(url) + + if should_display: + self.assertContains(response, '<div class="dates-banner-text"') + else: + self.assertNotContains(response, '<div class="dates-banner-text"') + + @RELATIVE_DATES_FLAG.override(active=True) def test_reset_course_deadlines(self): course = self.courses[0] enrollment = CourseEnrollment.objects.get(course_id=course.id) - ScheduleFactory( - start_date=timezone.now() - datetime.timedelta(1), - enrollment=enrollment - ) + enrollment.schedule.start_date = timezone.now() - datetime.timedelta(days=30) + enrollment.schedule.save() post_dict = {'reset_deadlines_redirect_url_id_dict': json.dumps({'course_id': str(course.id)})} - self.client.post(reverse(RESET_COURSE_DEADLINES_NAME), post_dict) - updated_schedule = Schedule.objects.get(enrollment=enrollment) - self.assertEqual(updated_schedule.start_date.date(), datetime.datetime.today().date()) - - def test_reset_course_deadlines_masquerade_specific_student(self): course = self.courses[0] - student_schedule = ScheduleFactory( - start_date=timezone.now() - datetime.timedelta(1), - enrollment=CourseEnrollment.objects.get(course_id=course.id, user=self.user), - ) + student_schedule = CourseEnrollment.objects.get(course_id=course.id, user=self.user).schedule + student_schedule.start_date = timezone.now() - datetime.timedelta(days=30) + student_schedule.save() staff = StaffFactory(course_key=course.id) staff_schedule = ScheduleFactory( - start_date=timezone.now() - datetime.timedelta(1), + start_date=timezone.now() - datetime.timedelta(days=30), enrollment__course__id=course.id, enrollment__user=staff, ) @@ -212,16 +276,17 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase): updated_staff_schedule = Schedule.objects.get(id=staff_schedule.id) self.assertEqual(updated_staff_schedule.start_date, staff_schedule.start_date) + @RELATIVE_DATES_FLAG.override(active=True) def test_reset_course_deadlines_masquerade_generic_student(self): course = self.courses[0] - student_schedule = ScheduleFactory( - start_date=timezone.now() - datetime.timedelta(1), - enrollment=CourseEnrollment.objects.get(course_id=course.id, user=self.user), - ) + student_schedule = CourseEnrollment.objects.get(course_id=course.id, user=self.user).schedule + student_schedule.start_date = timezone.now() - datetime.timedelta(days=30) + student_schedule.save() + staff = StaffFactory(course_key=course.id) staff_schedule = ScheduleFactory( - start_date=timezone.now() - datetime.timedelta(1), + start_date=timezone.now() - datetime.timedelta(days=30), enrollment__course__id=course.id, enrollment__user=staff, ) @@ -246,7 +311,7 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase): updated_student_schedule = Schedule.objects.get(id=student_schedule.id) self.assertEqual(updated_student_schedule.start_date, student_schedule.start_date) updated_staff_schedule = Schedule.objects.get(id=staff_schedule.id) - self.assertEqual(updated_staff_schedule.start_date.date(), datetime.datetime.today().date()) + self.assertEqual(updated_staff_schedule.start_date.date(), datetime.date.today()) class TestCourseOutlinePageWithPrerequisites(SharedModuleStoreTestCase, MilestonesTestCaseMixin): diff --git a/openedx/features/course_experience/tests/views/test_masquerade.py b/openedx/features/course_experience/tests/views/test_masquerade.py new file mode 100644 index 0000000000000000000000000000000000000000..57be7fe5f4ccaa7ff86981a6e0f903130514e6ad --- /dev/null +++ b/openedx/features/course_experience/tests/views/test_masquerade.py @@ -0,0 +1,127 @@ +""" +Tests for masquerading functionality on course_experience +""" + + +import json + +import six +from django.urls import reverse + +from lms.djangoapps.commerce.models import CommerceConfiguration +from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag +from openedx.features.course_experience import DISPLAY_COURSE_SOCK_FLAG, SHOW_UPGRADE_MSG_ON_COURSE_HOME +from student.roles import CourseStaffRole +from student.tests.factories import CourseEnrollmentFactory, UserFactory +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory +from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID +from xmodule.partitions.partitions_service import PartitionService + +from .helpers import add_course_mode +from .test_course_home import TEST_UPDATE_MESSAGE, course_home_url +from .test_course_sock import TEST_VERIFICATION_SOCK_LOCATOR + +TEST_PASSWORD = 'test' +UPGRADE_MESSAGE_CONTAINER = 'section-upgrade' + + +class MasqueradeTestBase(SharedModuleStoreTestCase): + """ + Base test class for masquerading functionality on course_experience + """ + @classmethod + def setUpClass(cls): + super(MasqueradeTestBase, cls).setUpClass() + + # Create two courses + cls.verified_course = CourseFactory.create() + cls.masters_course = CourseFactory.create() + # Create a verifiable course mode with an upgrade deadline in each course + add_course_mode(cls.verified_course, upgrade_deadline_expired=False) + add_course_mode(cls.masters_course, upgrade_deadline_expired=False) + add_course_mode(cls.masters_course, mode_slug='masters', mode_display_name='Masters') + + def setUp(self): + super(MasqueradeTestBase, self).setUp() + self.course_staff = UserFactory.create() + CourseStaffRole(self.verified_course.id).add_users(self.course_staff) + CourseStaffRole(self.masters_course.id).add_users(self.course_staff) + + # Enroll the user in the two courses + CourseEnrollmentFactory.create(user=self.course_staff, course_id=self.verified_course.id) + CourseEnrollmentFactory.create(user=self.course_staff, course_id=self.masters_course.id) + + # Log the staff user in + self.client.login(username=self.course_staff.username, password=TEST_PASSWORD) + + def get_group_id_by_course_mode_name(self, course_id, mode_name): + """ + Get the needed group_id from the Enrollment_Track partition for the specific masquerading track. + """ + partition_service = PartitionService(course_id) + enrollment_track_user_partition = partition_service.get_user_partition(ENROLLMENT_TRACK_PARTITION_ID) + for group in enrollment_track_user_partition.groups: + if group.name == mode_name: + return group.id + return None + + def update_masquerade(self, role, course, username=None, group_id=None): + """ + Toggle masquerade state. + """ + masquerade_url = reverse( + 'masquerade_update', + kwargs={ + 'course_key_string': six.text_type(course.id), + } + ) + response = self.client.post( + masquerade_url, + json.dumps({ + "role": role, + "group_id": group_id, + "user_name": username, + "user_partition_id": ENROLLMENT_TRACK_PARTITION_ID + }), + "application/json" + ) + self.assertEqual(response.status_code, 200) + return response + + +class TestVerifiedUpgradesWithMasquerade(MasqueradeTestBase): + """ + Tests for the course verification upgrade messages while the user is being masqueraded. + """ + + @override_waffle_flag(DISPLAY_COURSE_SOCK_FLAG, active=True) + @override_waffle_flag(SHOW_UPGRADE_MSG_ON_COURSE_HOME, active=True) + def test_masquerade_as_student(self): + # Elevate the staff user to be student + self.update_masquerade(role='student', course=self.verified_course) + response = self.client.get(course_home_url(self.verified_course)) + self.assertContains(response, TEST_VERIFICATION_SOCK_LOCATOR, html=False) + self.assertContains(response, UPGRADE_MESSAGE_CONTAINER, html=False) + + @override_waffle_flag(DISPLAY_COURSE_SOCK_FLAG, active=True) + def test_masquerade_as_verified_student(self): + user_group_id = self.get_group_id_by_course_mode_name( + self.verified_course.id, + 'Verified Certificate' + ) + self.update_masquerade(role='student', course=self.verified_course, group_id=user_group_id) + response = self.client.get(course_home_url(self.verified_course)) + self.assertNotContains(response, TEST_VERIFICATION_SOCK_LOCATOR, html=False) + self.assertNotContains(response, UPGRADE_MESSAGE_CONTAINER, html=False) + + @override_waffle_flag(DISPLAY_COURSE_SOCK_FLAG, active=True) + def test_masquerade_as_masters_student(self): + user_group_id = self.get_group_id_by_course_mode_name( + self.masters_course.id, + 'Masters' + ) + self.update_masquerade(role='student', course=self.masters_course, group_id=user_group_id) + response = self.client.get(course_home_url(self.masters_course)) + self.assertNotContains(response, TEST_VERIFICATION_SOCK_LOCATOR, html=False) + self.assertNotContains(response, UPGRADE_MESSAGE_CONTAINER, html=False) diff --git a/openedx/features/course_experience/urls.py b/openedx/features/course_experience/urls.py index eca0e988ea315a6f8ef959271c69d5de9688a7db..ddcd3adadb612fd279753886ee9c5df779aa4cf2 100644 --- a/openedx/features/course_experience/urls.py +++ b/openedx/features/course_experience/urls.py @@ -58,11 +58,6 @@ urlpatterns = [ LatestUpdateFragmentView.as_view(), name='openedx.course_experience.latest_update_fragment_view', ), - url( - r'course_sock_fragment$', - CourseSockFragmentView.as_view(), - name='openedx.course_experience.course_sock_fragment_view', - ), url( r'^dismiss_welcome_message$', dismiss_welcome_message, diff --git a/openedx/features/course_experience/utils.py b/openedx/features/course_experience/utils.py index 1c2978db03c29e8c283957cae101d57c0142bc86..9e5085e370bd1af8724ebadec892ad06517fedb6 100644 --- a/openedx/features/course_experience/utils.py +++ b/openedx/features/course_experience/utils.py @@ -6,24 +6,31 @@ Common utilities for the course experience, including course outline. from datetime import timedelta from completion.models import BlockCompletion +from django.db.models import Q from django.utils import timezone from opaque_keys.edx.keys import CourseKey from six.moves import range from course_modes.models import CourseMode from lms.djangoapps.course_api.blocks.api import get_blocks +from lms.djangoapps.course_blocks.api import get_course_blocks from lms.djangoapps.course_blocks.utils import get_student_module_as_dict from lms.djangoapps.courseware.access import has_access from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.lib.cache_utils import request_cached +from openedx.features.course_experience import RELATIVE_DATES_FLAG from student.models import CourseEnrollment from xmodule.modulestore.django import modulestore @request_cached() -def get_course_outline_block_tree(request, course_id, user=None): +def get_course_outline_block_tree(request, course_id, user=None, allow_start_dates_in_future=False): """ Returns the root block of the course outline, with children as blocks. + + allow_start_dates_in_future (bool): When True, will allow blocks to be + returned that can bypass the StartDateTransformer's filter to show + blocks with start dates in the future. """ assert user is None or user.is_authenticated @@ -149,8 +156,10 @@ def get_course_outline_block_tree(request, course_id, user=None): """ is_scored = block.get('has_score') and block.get('weight', 1) > 0 is_graded = block.get('graded') + is_countable = block.get('type') not in ('lti', 'lti_consumer') + is_graded_problem = is_scored and is_graded and is_countable - num_graded_problems = 1 if is_scored and is_graded else 0 + num_graded_problems = 1 if is_graded_problem else 0 num_graded_problems += sum(recurse_num_graded_problems(child) for child in block.get('children', [])) block['num_graded_problems'] = num_graded_problems @@ -186,17 +195,21 @@ def get_course_outline_block_tree(request, course_id, user=None): 'discussion', 'drag-and-drop-v2', 'poll', - 'word_cloud' + 'word_cloud', + 'lti', + 'lti_consumer', ] all_blocks = get_blocks( request, course_usage_key, - user=request.user, + user=user, nav_depth=3, requested_fields=[ 'children', 'display_name', 'type', + 'start', + 'contains_gated_content', 'due', 'graded', 'has_score', @@ -205,7 +218,8 @@ def get_course_outline_block_tree(request, course_id, user=None): 'show_gated_sections', 'format' ], - block_types_filter=block_types_filter + block_types_filter=block_types_filter, + allow_start_dates_in_future=allow_start_dates_in_future, ) course_outline_root_block = all_blocks['blocks'].get(all_blocks['root'], None) @@ -218,7 +232,7 @@ def get_course_outline_block_tree(request, course_id, user=None): set_last_accessed_default(course_outline_root_block) mark_blocks_completed( block=course_outline_root_block, - user=request.user, + user=user, course_key=course_key ) return course_outline_root_block @@ -241,33 +255,58 @@ def get_resume_block(block): return block -def reset_deadlines_banner_should_display(course_key, request): +def dates_banner_should_display(course_key, user): """ Return whether or not the reset banner should display, determined by whether or not a course has any past-due, - incomplete sequentials + incomplete sequentials and which enrollment mode is being + dealt with for the current user and course. + + Returns: + (missed_deadlines, missed_gated_content): + missed_deadlines is True if the user has missed any graded content deadlines + missed_gated_content is True if the first content that the user missed was gated content """ - display_reset_dates_banner = False + if not RELATIVE_DATES_FLAG.is_enabled(course_key): + return False, False + course_overview = CourseOverview.objects.get(id=str(course_key)) course_end_date = getattr(course_overview, 'end_date', None) is_self_paced = getattr(course_overview, 'self_paced', False) + + # Only display the banner for self-paced courses + if not is_self_paced: + return False, False + + # Only display the banner for enrolled users + if not CourseEnrollment.is_enrolled(user, course_key): + return False, False + + # Don't display the banner for course staff is_course_staff = bool( - request.user and course_overview and has_access(request.user, 'staff', course_overview, course_overview.id) + user and course_overview and has_access(user, 'staff', course_overview, course_overview.id) ) - if is_self_paced and (not is_course_staff) and (not course_end_date or timezone.now() < course_end_date): - if (CourseEnrollment.objects.filter( - course=course_overview, user=request.user, mode=CourseMode.VERIFIED - ).exists()): - course_block_tree = get_course_outline_block_tree( - request, str(course_key), request.user - ) - course_sections = course_block_tree.get('children', []) - for section in course_sections: - if display_reset_dates_banner: - break - for subsection in section.get('children', []): - if (not subsection.get('complete', True) - and subsection.get('due', timezone.now() + timedelta(1)) < timezone.now()): - display_reset_dates_banner = True - break - return display_reset_dates_banner + if is_course_staff: + return False, False + + # Don't display the banner if the course has ended + if course_end_date and course_end_date < timezone.now(): + return False, False + + store = modulestore() + course_usage_key = store.make_course_usage_key(course_key) + block_data = get_course_blocks(user, course_usage_key, include_completion=True) + for section_key in block_data.get_children(course_usage_key): + for subsection_key in block_data.get_children(section_key): + subsection_due_date = block_data.get_xblock_field(subsection_key, 'due', None) + if subsection_due_date and ( + not block_data.get_xblock_field(subsection_key, 'complete', False) + and block_data.get_xblock_field(subsection_key, 'graded', False) + and subsection_due_date < timezone.now() + ): + # Display the banner if the due date for an incomplete graded subsection + # has passed + return True, block_data.get_xblock_field(subsection_key, 'contains_gated_content', False) + + # Don't display the banner if there were no missed deadlines + return False, False diff --git a/openedx/features/course_experience/views/course_dates.py b/openedx/features/course_experience/views/course_dates.py index aa31068c89598d99ab6ac9aa4f58ffda08740095..f241ba8a8318204f5298aa8c6af24cb2754fed71 100644 --- a/openedx/features/course_experience/views/course_dates.py +++ b/openedx/features/course_experience/views/course_dates.py @@ -5,6 +5,7 @@ Fragment for rendering the course dates sidebar. from django.http import Http404 from django.template.loader import render_to_string +from django.urls import reverse from django.utils.translation import get_language_bidi from opaque_keys.edx.keys import CourseKey from web_fragments.fragment import Fragment @@ -25,10 +26,11 @@ class CourseDatesFragmentView(EdxFragmentView): """ course_key = CourseKey.from_string(course_id) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) - course_date_blocks = get_course_date_blocks(course, request.user, request, num_assignments=2) + course_date_blocks = get_course_date_blocks(course, request.user, request, num_assignments=1) context = { - 'course_date_blocks': [block for block in course_date_blocks if block.title != 'current_datetime'] + 'course_date_blocks': [block for block in course_date_blocks if block.title != 'current_datetime'], + 'dates_tab_link': reverse('dates', args=[course.id]), } html = render_to_string(self.template_name, context) dates_fragment = Fragment(html) @@ -47,6 +49,7 @@ class CourseDatesFragmentMobileView(CourseDatesFragmentView): mechanism to automatically create/recreate session with the server for all authenticated requests if the server returns 404. """ + _uses_pattern_library = False template_name = 'course_experience/mobile/course-dates-fragment.html' def get(self, request, *args, **kwargs): diff --git a/openedx/features/course_experience/views/course_home.py b/openedx/features/course_experience/views/course_home.py index 38eb8bdb823ce52b91f68e250ed7f6888e479bae..446fb22fa1361e6428c9177d22a18b7c8bc52301 100644 --- a/openedx/features/course_experience/views/course_home.py +++ b/openedx/features/course_experience/views/course_home.py @@ -24,6 +24,7 @@ from lms.djangoapps.course_goals.api import ( has_course_goal_permission ) from lms.djangoapps.courseware.exceptions import CourseAccessRedirect +from lms.djangoapps.courseware.utils import can_show_verified_upgrade, verified_upgrade_deadline_link from lms.djangoapps.courseware.views.views import CourseTabView from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.plugin_api.views import EdxFragmentView @@ -40,7 +41,6 @@ from .. import ( COURSE_ENABLE_UNENROLLED_ACCESS_FLAG, LATEST_UPDATE_FLAG, SHOW_UPGRADE_MSG_ON_COURSE_HOME, - USE_BOOTSTRAP_FLAG ) from ..utils import get_course_outline_block_tree, get_resume_block from .course_dates import CourseDatesFragmentView @@ -70,9 +70,9 @@ class CourseHomeView(CourseTabView): def uses_bootstrap(self, request, course, tab): """ - Returns true if the USE_BOOTSTRAP Waffle flag is enabled. + Always render this tab with bootstrap. """ - return USE_BOOTSTRAP_FLAG.is_enabled(course.id) + return True def render_to_fragment(self, request, course=None, tab=None, **kwargs): course_id = six.text_type(course.id) @@ -165,7 +165,7 @@ class CourseHomeFragmentView(EdxFragmentView): request, course_id=course_id, **kwargs ) course_sock_fragment = CourseSockFragmentView().render_to_fragment( - request, course=course_overview, **kwargs + request, course=course, **kwargs ) has_visited_course, resume_course_url, resume_course_title = self._get_resume_course_info( request, course_id @@ -222,8 +222,12 @@ class CourseHomeFragmentView(EdxFragmentView): has_discount = False # TODO Add switch to control deployment - if SHOW_UPGRADE_MSG_ON_COURSE_HOME.is_enabled(course_key) and enrollment and enrollment.upgrade_deadline: - upgrade_url = EcommerceService().upgrade_url(request.user, course_key) + if SHOW_UPGRADE_MSG_ON_COURSE_HOME.is_enabled(course_key) and can_show_verified_upgrade( + request.user, + enrollment, + course + ): + upgrade_url = verified_upgrade_deadline_link(request.user, course_id=course_key) upgrade_price, has_discount = format_strikeout_price(request.user, course_overview) show_search = ( diff --git a/openedx/features/course_experience/views/course_home_messages.py b/openedx/features/course_experience/views/course_home_messages.py index e60ab6e7d189b3006c0126dcd7a793b793d6cf73..d1c32b761d4eb5ce13785c5cdf15b3b589c8c69c 100644 --- a/openedx/features/course_experience/views/course_home_messages.py +++ b/openedx/features/course_experience/views/course_home_messages.py @@ -74,7 +74,7 @@ class CourseHomeMessageFragmentView(EdxFragmentView): _register_course_home_messages(request, course, user_access, course_start_data) # Register course date alerts - for course_date_block in get_course_date_blocks(course, request.user): + for course_date_block in get_course_date_blocks(course, request.user, request): course_date_block.register_alerts(request, course) # Register a course goal message, if appropriate diff --git a/openedx/features/course_experience/views/course_outline.py b/openedx/features/course_experience/views/course_outline.py index 61abbc926b6dd3100bfa7ddcf69322a0104ee409..f6baf4d021dfc4ec9093652aa1f3b8c81a39accb 100644 --- a/openedx/features/course_experience/views/course_outline.py +++ b/openedx/features/course_experience/views/course_outline.py @@ -9,10 +9,12 @@ import six from completion import waffle as completion_waffle from django.contrib.auth.models import User +from django.db.models import Q from django.shortcuts import redirect from django.template.context_processors import csrf from django.template.loader import render_to_string from django.urls import reverse +from django.utils import timezone from django.views.decorators.csrf import ensure_csrf_cookie import edx_when.api as edx_when_api from opaque_keys.edx.keys import CourseKey @@ -20,11 +22,18 @@ from pytz import UTC from waffle.models import Switch from web_fragments.fragment import Fragment +from course_modes.models import CourseMode from lms.djangoapps.courseware.access import has_access from lms.djangoapps.courseware.courses import get_course_overview_with_access +from lms.djangoapps.courseware.date_summary import verified_upgrade_deadline_link from lms.djangoapps.courseware.masquerade import setup_masquerade +from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.core.djangoapps.schedules.utils import reset_self_paced_schedule +from openedx.features.course_experience import RELATIVE_DATES_FLAG +from openedx.features.course_experience.utils import dates_banner_should_display +from openedx.features.content_type_gating.models import ContentTypeGatingConfig +from student.models import CourseEnrollment from util.milestones_helpers import get_course_content_milestones from xmodule.course_module import COURSE_VISIBILITY_PUBLIC from xmodule.modulestore.django import modulestore @@ -38,11 +47,15 @@ class CourseOutlineFragmentView(EdxFragmentView): """ Course outline fragment to be shown in the unified course view. """ + _uses_pattern_library = False def render_to_fragment(self, request, course_id, user_is_enrolled=True, **kwargs): # pylint: disable=arguments-differ """ Renders the course outline as a fragment. """ + from lms.urls import RESET_COURSE_DEADLINES_NAME + from openedx.features.course_experience.urls import COURSE_HOME_VIEW_NAME + course_key = CourseKey.from_string(course_id) course_overview = get_course_overview_with_access( request.user, 'load', course_key, check_if_enrolled=user_is_enrolled @@ -55,14 +68,6 @@ class CourseOutlineFragmentView(EdxFragmentView): if not course_block_tree: return None - context = { - 'csrf': csrf(request)['csrf_token'], - 'course': course_overview, - 'due_date_display_format': course.due_date_display_format, - 'blocks': course_block_tree, - 'enable_links': user_is_enrolled or course.course_visibility == COURSE_VISIBILITY_PUBLIC, - } - resume_block = get_resume_block(course_block_tree) if user_is_enrolled else None if not resume_block: @@ -71,16 +76,34 @@ class CourseOutlineFragmentView(EdxFragmentView): xblock_display_names = self.create_xblock_id_and_name_dict(course_block_tree) gated_content = self.get_content_milestones(request, course_key) - context['gated_content'] = gated_content - context['xblock_display_names'] = xblock_display_names + missed_deadlines, missed_gated_content = dates_banner_should_display(course_key, request.user) - page_context = kwargs.get('page_context', None) - if page_context: - context['self_paced'] = page_context.get('pacing_type', 'instructor_paced') == 'self_paced' + reset_deadlines_url = reverse(RESET_COURSE_DEADLINES_NAME) + reset_deadlines_redirect_url_base = COURSE_HOME_VIEW_NAME - # We're using this flag to prevent old self-paced dates from leaking out on courses not - # managed by edx-when. - context['in_edx_when'] = edx_when_api.is_enabled_for_course(course_key) + context = { + 'csrf': csrf(request)['csrf_token'], + 'course': course_overview, + 'due_date_display_format': course.due_date_display_format, + 'blocks': course_block_tree, + 'enable_links': user_is_enrolled or course.course_visibility == COURSE_VISIBILITY_PUBLIC, + 'course_key': course_key, + 'gated_content': gated_content, + 'xblock_display_names': xblock_display_names, + 'self_paced': course.self_paced, + + # We're using this flag to prevent old self-paced dates from leaking out on courses not + # managed by edx-when. + 'in_edx_when': edx_when_api.is_enabled_for_course(course_key), + 'reset_deadlines_url': reset_deadlines_url, + 'reset_deadlines_redirect_url_base': reset_deadlines_redirect_url_base, + 'reset_deadlines_redirect_url_id_dict': {'course_id': str(course.id)}, + 'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course), + 'on_course_outline_page': True, + 'missed_deadlines': missed_deadlines, + 'missed_gated_content': missed_gated_content, + 'has_ended': course.has_ended(), + } html = render_to_string('course_experience/course-outline-fragment.html', context) return Fragment(html) diff --git a/openedx/features/course_experience/views/course_reviews.py b/openedx/features/course_experience/views/course_reviews.py index 8428a834fa7d1a87df1f26d80fdde397019a3535..9956e29098aa5db3a223517dc82554d7202e364e 100644 --- a/openedx/features/course_experience/views/course_reviews.py +++ b/openedx/features/course_experience/views/course_reviews.py @@ -19,8 +19,6 @@ from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.features.course_experience import default_course_url_name from student.models import CourseEnrollment -from .. import USE_BOOTSTRAP_FLAG - class CourseReviewsView(CourseTabView): """ @@ -36,9 +34,9 @@ class CourseReviewsView(CourseTabView): def uses_bootstrap(self, request, course, tab): """ - Returns true if the USE_BOOTSTRAP Waffle flag is enabled. + Always render this tab with bootstrap. """ - return USE_BOOTSTRAP_FLAG.is_enabled(course.id) + return True def render_to_fragment(self, request, course=None, tab=None, **kwargs): course_id = six.text_type(course.id) diff --git a/openedx/features/course_experience/views/course_sock.py b/openedx/features/course_experience/views/course_sock.py index a41d9b8f819e59b4100a96c9ce6a841f66e6a6bd..ae06fd2995830e66ba5f766276c8adc374e70081 100644 --- a/openedx/features/course_experience/views/course_sock.py +++ b/openedx/features/course_experience/views/course_sock.py @@ -2,11 +2,13 @@ Fragment for rendering the course's sock and associated toggle button. """ - from django.template.loader import render_to_string from web_fragments.fragment import Fragment -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, verified_upgrade_link_is_valid +from lms.djangoapps.courseware.utils import ( + can_show_verified_upgrade, + verified_upgrade_deadline_link +) from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.features.discounts.utils import format_strikeout_price from student.models import CourseEnrollment @@ -27,7 +29,7 @@ class CourseSockFragmentView(EdxFragmentView): @staticmethod def get_verification_context(request, course): enrollment = CourseEnrollment.get_enrollment(request.user, course.id) - show_course_sock = verified_upgrade_link_is_valid(enrollment) + show_course_sock = can_show_verified_upgrade(request.user, enrollment, course) if show_course_sock: upgrade_url = verified_upgrade_deadline_link(request.user, course=course) course_price, _ = format_strikeout_price(request.user, course) diff --git a/openedx/features/course_experience/views/course_updates.py b/openedx/features/course_experience/views/course_updates.py index 7ce5779ddd3190b582d35fa8664dff9b8f1a4e94..4640da9d612ad42fd32a10dd92ef608034dc782b 100644 --- a/openedx/features/course_experience/views/course_updates.py +++ b/openedx/features/course_experience/views/course_updates.py @@ -20,8 +20,6 @@ from lms.djangoapps.courseware.views.views import CourseTabView from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.features.course_experience import default_course_url_name -from .. import USE_BOOTSTRAP_FLAG - STATUS_VISIBLE = 'visible' STATUS_DELETED = 'deleted' @@ -68,9 +66,9 @@ class CourseUpdatesView(CourseTabView): def uses_bootstrap(self, request, course, tab): """ - Returns true if the USE_BOOTSTRAP Waffle flag is enabled. + Always render this tab with bootstrap. """ - return USE_BOOTSTRAP_FLAG.is_enabled(course.id) + return True def render_to_fragment(self, request, course=None, tab=None, **kwargs): course_id = six.text_type(course.id) @@ -82,6 +80,8 @@ class CourseUpdatesFragmentView(EdxFragmentView): """ A fragment to render the updates page for a course. """ + _uses_pattern_library = False + def render_to_fragment(self, request, course_id=None, **kwargs): """ Renders the course's home page as a fragment. diff --git a/openedx/features/course_experience/views/latest_update.py b/openedx/features/course_experience/views/latest_update.py index c2a6bb46e8a034751eddf4be5db8a502c00bdd3e..b2d5a28f5e43cea046e2160d67f05a9d85e5f3fc 100644 --- a/openedx/features/course_experience/views/latest_update.py +++ b/openedx/features/course_experience/views/latest_update.py @@ -21,6 +21,8 @@ class LatestUpdateFragmentView(EdxFragmentView): """ A fragment that displays the latest course update. """ + _uses_pattern_library = False + def render_to_fragment(self, request, course_id=None, **kwargs): """ Renders the latest update message fragment for the specified course. diff --git a/openedx/features/course_experience/views/welcome_message.py b/openedx/features/course_experience/views/welcome_message.py index ce5636059d48dc4fa8bc77bf42c87f9bba2e9ba2..e4d414344dc5d1199291273f105a47e5b93670b3 100644 --- a/openedx/features/course_experience/views/welcome_message.py +++ b/openedx/features/course_experience/views/welcome_message.py @@ -14,7 +14,6 @@ from web_fragments.fragment import Fragment from lms.djangoapps.courseware.courses import get_course_with_access from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.core.djangoapps.user_api.course_tag.api import get_course_tag, set_course_tag -from openedx.features.course_experience import SHORTEN_WELCOME_MESSAGE_FLAG from .course_updates import get_ordered_updates @@ -25,6 +24,8 @@ class WelcomeMessageFragmentView(EdxFragmentView): """ A fragment that displays a course's welcome message. """ + _uses_pattern_library = False + def render_to_fragment(self, request, course_id=None, **kwargs): """ Renders the welcome message fragment for the specified course. @@ -44,7 +45,6 @@ class WelcomeMessageFragmentView(EdxFragmentView): context = { 'dismiss_url': dismiss_url, 'welcome_message_html': welcome_message_html, - 'shorten_welcome_message': SHORTEN_WELCOME_MESSAGE_FLAG.is_enabled(course_key), } if get_course_tag(request.user, course_key, PREFERENCE_KEY) == 'False': diff --git a/openedx/features/discounts/applicability.py b/openedx/features/discounts/applicability.py index 3c25813b0dc3ec39ef29247627fc043a6f414769..a63adddd85cb71a04abf5e04f36f121f4f122990 100644 --- a/openedx/features/discounts/applicability.py +++ b/openedx/features/discounts/applicability.py @@ -136,18 +136,23 @@ def can_receive_discount(user, course, discount_expiration_date=None): if is_enterprise_learner(user): return False + # Turn holdback on + if _is_in_holdback_and_bucket(user): + return False + return True -def _is_in_holdback(user): +def _is_in_holdback_and_bucket(user): """ Return whether the specified user is in the first-purchase-discount holdback group. + This will also stable bucket the user. """ if datetime(2020, 8, 1, tzinfo=pytz.UTC) <= datetime.now(tz=pytz.UTC): return False - # Holdback is 50/50 - bucket = stable_bucketing_hash_group(DISCOUNT_APPLICABILITY_HOLDBACK, 2, user.username) + # Holdback is 10% + bucket = stable_bucketing_hash_group(DISCOUNT_APPLICABILITY_HOLDBACK, 10, user.username) request = get_current_request() if hasattr(request, 'session') and DISCOUNT_APPLICABILITY_HOLDBACK not in request.session: diff --git a/openedx/features/discounts/tests/test_applicability.py b/openedx/features/discounts/tests/test_applicability.py index 0a611e1005d3ce74a4651ded2a88538220179534..30660750fd6e5c038a338c7de6f5669bf7568f7f 100644 --- a/openedx/features/discounts/tests/test_applicability.py +++ b/openedx/features/discounts/tests/test_applicability.py @@ -23,7 +23,7 @@ from student.tests.factories import CourseEnrollmentFactory, UserFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory -from ..applicability import DISCOUNT_APPLICABILITY_FLAG, _is_in_holdback, can_receive_discount +from ..applicability import DISCOUNT_APPLICABILITY_FLAG, _is_in_holdback_and_bucket, can_receive_discount @ddt.ddt @@ -44,7 +44,9 @@ class TestApplicability(ModuleStoreTestCase): user=self.user, experiment_id=REV1008_EXPERIMENT_ID, key=str(self.course), value=now_time ) - holdback_patcher = patch('openedx.features.discounts.applicability._is_in_holdback', return_value=False) + holdback_patcher = patch( + 'openedx.features.discounts.applicability._is_in_holdback_and_bucket', return_value=False + ) self.mock_holdback = holdback_patcher.start() self.addCleanup(holdback_patcher.stop) @@ -165,7 +167,7 @@ class TestApplicability(ModuleStoreTestCase): @ddt.unpack def test_holdback_group_ids(self, group_number, in_holdback): with patch('openedx.features.discounts.applicability.stable_bucketing_hash_group', return_value=group_number): - assert _is_in_holdback(self.user) == in_holdback + assert _is_in_holdback_and_bucket(self.user) == in_holdback def test_holdback_expiry(self): with patch('openedx.features.discounts.applicability.stable_bucketing_hash_group', return_value=0): @@ -173,4 +175,4 @@ class TestApplicability(ModuleStoreTestCase): 'openedx.features.discounts.applicability.datetime', Mock(now=Mock(return_value=datetime(2020, 8, 1, 0, 1, tzinfo=pytz.UTC)), wraps=datetime), ): - assert not _is_in_holdback(self.user) + assert not _is_in_holdback_and_bucket(self.user) diff --git a/openedx/features/discounts/views.py b/openedx/features/discounts/views.py index 35a2387717f36353be8167a2ded27ee0d7d4b756..7946276c7aaec0e97a353395ed0431d08db0a6d3 100644 --- a/openedx/features/discounts/views.py +++ b/openedx/features/discounts/views.py @@ -5,6 +5,8 @@ The Discount API Views should return information about discounts that apply to t # -*- coding: utf-8 -*- +import logging + from django.contrib.auth.models import User from django.utils.decorators import method_decorator from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication @@ -24,6 +26,8 @@ from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin from .applicability import can_receive_discount, discount_percentage, REV1008_EXPERIMENT_ID +log = logging.getLogger(__name__) + class CourseUserDiscount(DeveloperErrorViewMixin, APIView): """ @@ -77,12 +81,15 @@ class CourseUserDiscount(DeveloperErrorViewMixin, APIView): payload = {'discount_applicable': discount_applicable, 'discount_percent': discount_percent} # Record whether the last basket loaded for this course had a discount - ExperimentData.objects.update_or_create( - user=request.user, - experiment_id=REV1008_EXPERIMENT_ID, - key='discount_' + str(course), - value=discount_applicable - ) + try: + ExperimentData.objects.update_or_create( + user=request.user, + experiment_id=REV1008_EXPERIMENT_ID, + key='discount_' + str(course), + value=discount_applicable + ) + except Exception as e: # pylint: disable=broad-except + log.exception(str(e)) return Response({ 'discount_applicable': discount_applicable, diff --git a/openedx/features/enterprise_support/admin/__init__.py b/openedx/features/enterprise_support/admin/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/openedx/features/enterprise_support/admin/forms.py b/openedx/features/enterprise_support/admin/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..65f017964724921cc5e948082d5adcab99486e93 --- /dev/null +++ b/openedx/features/enterprise_support/admin/forms.py @@ -0,0 +1,21 @@ +""" +Enterprise support admin forms. +""" + +from django import forms +from django.utils.translation import ugettext_lazy as _ +from enterprise.admin.utils import validate_csv + + +class CSVImportForm(forms.Form): + csv_file = forms.FileField( + required=True, + label=_('CSV File'), + help_text=_('CSV file should have 3 columns having names lms_user_id, course_id, opportunity_id') + ) + + def clean_csv_file(self): + csv_file = self.cleaned_data['csv_file'] + csv_reader = validate_csv(csv_file, expected_columns=['lms_user_id', 'course_id', 'opportunity_id']) + + return csv_reader diff --git a/openedx/features/enterprise_support/admin/views.py b/openedx/features/enterprise_support/admin/views.py new file mode 100644 index 0000000000000000000000000000000000000000..838d22fbc3811d8f42176d61bab6201e1e7bfaa1 --- /dev/null +++ b/openedx/features/enterprise_support/admin/views.py @@ -0,0 +1,71 @@ +""" +Enterprise support admin views. +""" + +from django.contrib import admin, messages +from django.urls import reverse +from django.utils.translation import ugettext as _ +from django.views.generic.edit import FormView +from enterprise.models import EnterpriseCourseEnrollment + +from openedx.features.enterprise_support.admin.forms import CSVImportForm +from student.models import CourseEnrollment, CourseEnrollmentAttribute + + +class EnrollmentAttributeOverrideView(FormView): + """ + Learner Enrollment Attribute Override View. + """ + template_name = 'enterprise_support/admin/enrollment_attributes_override.html' + form_class = CSVImportForm + + @staticmethod + def _get_admin_context(request): + admin_context = {'opts': EnterpriseCourseEnrollment._meta} + return admin_context + + def get_success_url(self): + return reverse('admin:enterprise_override_attributes') + + def get_context_data(self, **kwargs): + context = super(EnrollmentAttributeOverrideView, self).get_context_data(**kwargs) + context.update(self._get_admin_context(self.request)) + return context + + def form_valid(self, form): + total_records = 0 + error_line_numbers = [] + csv_reader = form.cleaned_data['csv_file'] + for index, record in enumerate(csv_reader): + total_records += 1 + try: + course_enrollment = CourseEnrollment.objects.get( + user_id=record['lms_user_id'], + course_id=record['course_id'], + ) + except CourseEnrollment.DoesNotExist: + error_line_numbers.append(str(index + 1)) + else: + CourseEnrollmentAttribute.objects.update_or_create( + enrollment=course_enrollment, + namespace='salesforce', + name='opportunity_id', + defaults={ + 'value': record['opportunity_id'], + } + ) + + # if for some reason not a single enrollment updated than do not show success message. + if len(error_line_numbers) != total_records: + messages.success(self.request, 'Successfully updated learner enrollment opportunity ids.') + + if error_line_numbers: + messages.error( + self.request, + _( + 'Enrollment attributes were not updated for records at following line numbers ' + 'in csv because no enrollment found for these records: {error_line_numbers}' + ).format(error_line_numbers=', '.join(error_line_numbers)) + ) + + return super(EnrollmentAttributeOverrideView, self).form_valid(form) diff --git a/openedx/features/enterprise_support/api.py b/openedx/features/enterprise_support/api.py index b481312dbf69b087ba5be3d87c658a314aa7de31..33976f4f4ea5f4fdcbc95ba287edf79f956f397f 100644 --- a/openedx/features/enterprise_support/api.py +++ b/openedx/features/enterprise_support/api.py @@ -17,8 +17,7 @@ from django.template.loader import render_to_string from django.urls import reverse from django.utils.http import urlencode from django.utils.translation import ugettext as _ -from edx_django_utils.cache import TieredCache -from edx_django_utils.cache.utils import get_cache_key +from edx_django_utils.cache import TieredCache, get_cache_key from edx_rest_api_client.client import EdxRestApiClient from slumber.exceptions import HttpClientError, HttpNotFoundError, HttpServerError diff --git a/openedx/features/enterprise_support/apps.py b/openedx/features/enterprise_support/apps.py index 515f931173561361fdcf2cf61284d1fa998343b2..af8ee2539b603fc7f99db2aadb4a244c87abcaf8 100644 --- a/openedx/features/enterprise_support/apps.py +++ b/openedx/features/enterprise_support/apps.py @@ -14,4 +14,4 @@ class EnterpriseSupportConfig(AppConfig): def ready(self): # Import signals to activate signal handler for enterprise. - from . import signals # pylint: disable=unused-variable + from . import signals # pylint: disable=unused-import diff --git a/openedx/features/enterprise_support/templates/enterprise_support/admin/enrollment_attributes_override.html b/openedx/features/enterprise_support/templates/enterprise_support/admin/enrollment_attributes_override.html new file mode 100644 index 0000000000000000000000000000000000000000..7d10a8298b672f77c64738b4ad654437ecf572a3 --- /dev/null +++ b/openedx/features/enterprise_support/templates/enterprise_support/admin/enrollment_attributes_override.html @@ -0,0 +1,33 @@ +{% extends "admin/base_site.html" %} +{% load i18n static admin_urls %} + +{% block extrastyle %} + <link rel="stylesheet" type="text/css" href="{% static 'enterprise/bundles/main-admin.style.css' %}"/> + <link rel="stylesheet" type="text/css" href="{% static 'admin/css/changelists.css' %}"/> +{% endblock %} + +{% block extrahead %} +<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script> +{% endblock %} + +{% block breadcrumbs %} +<div class="breadcrumbs"> + <a href="{% url 'admin:index' %}">{% trans "Home" as tmsg %}{{ tmsg | force_escape }}</a> + › <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a> + › <a href="{% url opts|admin_urlname:'changelist' %}">{% trans "Enterprise Course Enrollments" as tmsg %}{{ tmsg | force_escape }}</a> + › {% trans "Override Enrollment Attributes" as tmsg %}{{ tmsg | force_escape }} +</div> +{% endblock %} + +{% block content %} +<div id="content-main"> + <div class="forms-panel"> + <h1>{% trans "Upload CSV to override enrollment attributes for learners" as tmsg %}{{ tmsg | force_escape }}</h1> + <form action="" method="post" enctype="multipart/form-data" id="enrollment-attribute-update-form"> + {% csrf_token %} + {{ form.as_p }} + <input type="submit" value="Submit"/> + </form> + </div> +</div> +{% endblock %} diff --git a/openedx/features/enterprise_support/tests/test_admin.py b/openedx/features/enterprise_support/tests/test_admin.py new file mode 100644 index 0000000000000000000000000000000000000000..d47dd29fc69d840c843ecf416b12d1c8defdd882 --- /dev/null +++ b/openedx/features/enterprise_support/tests/test_admin.py @@ -0,0 +1,145 @@ +""" +Enterprise support admin tests. +""" + +import csv +import os +import tempfile + +from django.contrib.messages import get_messages +from django.test import Client +from django.urls import reverse + +from openedx.core.djangoapps.catalog.tests.factories import CourseRunFactory +from openedx.features.enterprise_support.admin.forms import CSVImportForm +from student.models import CourseEnrollment, CourseEnrollmentAttribute +from student.tests.factories import TEST_PASSWORD, AdminFactory, CourseEnrollmentFactory, UserFactory +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase + + +class EnrollmentAttributeOverrideViewTest(ModuleStoreTestCase): + """ + Tests for course creator admin. + """ + + def setUp(self): + """ Test case setup """ + super(EnrollmentAttributeOverrideViewTest, self).setUp() + + self.client = Client() + user = AdminFactory() + self.view_url = reverse('admin:enterprise_override_attributes') + self.client.login(username=user.username, password=TEST_PASSWORD) + + self.users = [] + for _ in range(3): + self.users.append(UserFactory()) + + self.course = CourseRunFactory() + self.course_id = self.course.get('key') + self.csv_data = [ + [self.users[0].id, self.course_id, 'OP_4321'], + [self.users[1].id, self.course_id, 'OP_8765'], + [self.users[2].id, self.course_id, 'OP_2109'], + ] + self.csv_data_for_existing_attributes = [ + [self.users[0].id, self.course_id, 'OP_1234'], + [self.users[1].id, self.course_id, 'OP_5678'], + [self.users[2].id, self.course_id, 'OP_9012'], + ] + + for user in self.users: + CourseEnrollmentFactory( + course_id=self.course_id, + user=user + ) + + def create_csv(self, header=None, data=None): + """Create csv""" + header = header or ['lms_user_id', 'course_id', 'opportunity_id'] + data = data or self.csv_data + tmp_csv_path = os.path.join(tempfile.gettempdir(), 'data.csv') + with open(tmp_csv_path, 'w') as csv_file: + csv_writer = csv.writer(csv_file) + csv_writer.writerow(header) + csv_writer.writerows(data) + + return tmp_csv_path + + def verify_enrollment_attributes(self, data=None): + """ + Verify that data from csv is imported correctly and tables have correct data. + """ + data = data or self.csv_data + for user_id, course_id, opportunity_id in data: + enrollment = CourseEnrollment.objects.get(user_id=user_id, course_id=course_id) + enrollment_attribute = CourseEnrollmentAttribute.objects.get( + enrollment=enrollment, + namespace='salesforce', + name='opportunity_id' + ) + assert enrollment_attribute.value == opportunity_id + + def test_get(self): + """ + Tests that HTTP GET is working as expected. + """ + response = self.client.get(self.view_url) + assert response.status_code == 200 + assert isinstance(response.context['form'], CSVImportForm) + + def test_post(self): + """ + Tests that HTTP POST is working as expected when creating new attributes and updating. + """ + csv_path = self.create_csv() + post_data = {'csv_file': open(csv_path)} + response = self.client.post(self.view_url, data=post_data) + assert response.status_code == 302 + self.verify_enrollment_attributes() + + # override existing + csv_path = self.create_csv(data=self.csv_data_for_existing_attributes) + post_data = {'csv_file': open(csv_path)} + response = self.client.post(self.view_url, data=post_data) + assert response.status_code == 302 + self.verify_enrollment_attributes(data=self.csv_data_for_existing_attributes) + + def test_post_with_no_csv(self): + """ + Tests that HTTP POST without out csv file is working as expected. + """ + response = self.client.post(self.view_url) + assert response.context['form'].errors == {'csv_file': ['This field is required.']} + + def test_post_with_incorrect_csv_header(self): + """ + Tests that HTTP POST with incorrect csv header is working as expected. + """ + csv_path = self.create_csv(header=['a', 'b']) + post_data = {'csv_file': open(csv_path)} + response = self.client.post(self.view_url, data=post_data) + assert response.context['form'].errors == { + 'csv_file': [ + 'Expected a CSV file with [lms_user_id, course_id, opportunity_id] ' + 'columns, but found [a, b] columns instead.' + ] + } + + def test_post_with_no_enrollment_error(self): + """ + Tests that HTTP POST is working as expected when for some records there is no enrollment. + """ + csv_data = self.csv_data + [[999, self.course_id, 'NOPE'], [1000, self.course_id, 'NONE']] + csv_path = self.create_csv(data=csv_data) + post_data = {'csv_file': open(csv_path)} + response = self.client.post(self.view_url, data=post_data) + assert response.status_code == 302 + messages = [] + for msg in get_messages(response.wsgi_request): + messages.append(str(msg)) + assert messages == [ + 'Successfully updated learner enrollment opportunity ids.', + 'Enrollment attributes were not updated for records at following line numbers ' + 'in csv because no enrollment found for these records: 4, 5' + ] diff --git a/openedx/features/enterprise_support/tests/test_api.py b/openedx/features/enterprise_support/tests/test_api.py index d141ce3a5581e46e74c2f45135372b9633426fdb..882d22c31eaa4cdcc4795c7f847ac3e3b2cf8268 100644 --- a/openedx/features/enterprise_support/tests/test_api.py +++ b/openedx/features/enterprise_support/tests/test_api.py @@ -13,7 +13,7 @@ from django.core.cache import cache from django.http import HttpResponseRedirect from django.test.utils import override_settings from django.urls import reverse -from edx_django_utils.cache.utils import get_cache_key +from edx_django_utils.cache import get_cache_key from six.moves.urllib.parse import parse_qs from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory diff --git a/openedx/features/enterprise_support/tests/test_utils.py b/openedx/features/enterprise_support/tests/test_utils.py index 1e674088f175c269bdbe4e34518436b161ef204b..e3cf2cfda3fc185d9f3edfbcc72d1c0c46361fa5 100644 --- a/openedx/features/enterprise_support/tests/test_utils.py +++ b/openedx/features/enterprise_support/tests/test_utils.py @@ -30,7 +30,6 @@ class TestEnterpriseUtils(TestCase): @ddt.data( ('notfoundpage', 0), - (reverse('dashboard'), 1), ) @ddt.unpack def test_enterprise_customer_for_request_called_on_404(self, resource, expected_calls): diff --git a/openedx/features/enterprise_support/utils.py b/openedx/features/enterprise_support/utils.py index 077e655af646b25fa8ec077bd2922f17207a0e8b..b58d16492515d74bcce65db546d995cebf1df4f9 100644 --- a/openedx/features/enterprise_support/utils.py +++ b/openedx/features/enterprise_support/utils.py @@ -7,9 +7,9 @@ import json from crum import get_current_request from django.conf import settings +from django.urls import NoReverseMatch, reverse from django.utils.translation import ugettext as _ -from edx_django_utils.cache import TieredCache -from edx_django_utils.cache.utils import get_cache_key +from edx_django_utils.cache import TieredCache, get_cache_key from enterprise.models import EnterpriseCustomerUser from social_django.models import UserSocialAuth @@ -18,6 +18,7 @@ from lms.djangoapps.branding.api import get_privacy_url from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.user_authn.cookies import standard_cookie_settings from openedx.core.djangolib.markup import HTML, Text +from student.helpers import get_next_url_for_login_page def get_data_consent_share_cache_key(user_id, course_id): @@ -316,3 +317,28 @@ def is_enterprise_learner(user): (bool): True if given user is an enterprise learner. """ return EnterpriseCustomerUser.objects.filter(user_id=user.id).exists() + + +def get_enterprise_slug_login_url(): + """ + Return the enterprise slug login's URL (enterprise/login) if it exists otherwise None + """ + try: + return reverse('enterprise_slug_login') + except NoReverseMatch: + return None + + +def get_provider_login_url(request, provider_id, redirect_url=None): + """ + Return the given provider's login URL. + + This method is here to avoid the importing of pipeline and student app in enterprise. + """ + + provider_login_url = third_party_auth.pipeline.get_login_url( + provider_id, + third_party_auth.pipeline.AUTH_ENTRY_LOGIN, + redirect_url=redirect_url if redirect_url else get_next_url_for_login_page(request) + ) + return provider_login_url diff --git a/openedx/features/learner_profile/static/learner_profile/js/views/badge_view.js b/openedx/features/learner_profile/static/learner_profile/js/views/badge_view.js index cb68d8595c95f7558bc973fabe1be4a179a1b385..854324916985e2ab3704a86c87124cecf1421605 100644 --- a/openedx/features/learner_profile/static/learner_profile/js/views/badge_view.js +++ b/openedx/features/learner_profile/static/learner_profile/js/views/badge_view.js @@ -5,9 +5,10 @@ [ 'gettext', 'jquery', 'underscore', 'backbone', 'moment', 'text!learner_profile/templates/badge.underscore', - 'learner_profile/js/views/share_modal_view' + 'learner_profile/js/views/share_modal_view', + 'edx-ui-toolkit/js/utils/html-utils' ], - function(gettext, $, _, Backbone, Moment, badgeTemplate, ShareModalView) { + function(gettext, $, _, Backbone, Moment, badgeTemplate, ShareModalView, HtmlUtils) { var BadgeView = Backbone.View.extend({ initialize: function(options) { this.options = _.extend({}, options); @@ -35,7 +36,7 @@ modal.$el.fadeIn('short', 'swing', _.bind(modal.ready, modal)); }, render: function() { - this.$el.html(this.template(this.context)); + this.$el.html(HtmlUtils.HTML(this.template(this.context)).toString()); this.shareButton = this.$el.find('.share-button'); return this; } diff --git a/openedx/features/learner_profile/static/learner_profile/js/views/section_two_tab.js b/openedx/features/learner_profile/static/learner_profile/js/views/section_two_tab.js index 03e675db3c605c86c0f2bdb27b28c7c943d440ae..23064c9e6b6877af9ec84c0f7d05df16a3887348 100644 --- a/openedx/features/learner_profile/static/learner_profile/js/views/section_two_tab.js +++ b/openedx/features/learner_profile/static/learner_profile/js/views/section_two_tab.js @@ -3,9 +3,10 @@ define( [ - 'gettext', 'jquery', 'underscore', 'backbone', 'text!learner_profile/templates/section_two.underscore' + 'gettext', 'jquery', 'underscore', 'backbone', 'text!learner_profile/templates/section_two.underscore', + 'edx-ui-toolkit/js/utils/html-utils' ], - function(gettext, $, _, Backbone, sectionTwoTemplate) { + function(gettext, $, _, Backbone, sectionTwoTemplate, HtmlUtils) { var SectionTwoTab = Backbone.View.extend({ attributes: { class: 'wrapper-profile-section-two' @@ -17,10 +18,7 @@ render: function() { var self = this; var showFullProfile = this.options.showFullProfile(); - this.$el.html(this.template({ - ownProfile: self.options.ownProfile, - showFullProfile: showFullProfile - })); + this.$el.html(HtmlUtils.HTML(this.template({ownProfile: self.options.ownProfile, showFullProfile: showFullProfile})).toString()); // eslint-disable-line max-len if (showFullProfile) { _.each(this.options.viewList, function(fieldView) { self.$el.find('.field-container').append(fieldView.render().el); diff --git a/openedx/features/learner_profile/static/learner_profile/js/views/share_modal_view.js b/openedx/features/learner_profile/static/learner_profile/js/views/share_modal_view.js index 0e8f4884909088e427a384e363960208bae8a535..c018c3479ba042ea27e304bd14bf06294a544dd5 100644 --- a/openedx/features/learner_profile/static/learner_profile/js/views/share_modal_view.js +++ b/openedx/features/learner_profile/static/learner_profile/js/views/share_modal_view.js @@ -4,9 +4,10 @@ define( [ 'gettext', 'jquery', 'underscore', 'backbone', 'moment', - 'text!learner_profile/templates/share_modal.underscore' + 'text!learner_profile/templates/share_modal.underscore', + 'edx-ui-toolkit/js/utils/html-utils' ], - function(gettext, $, _, Backbone, Moment, badgeModalTemplate) { + function(gettext, $, _, Backbone, Moment, badgeModalTemplate, HtmlUtils) { var ShareModalView = Backbone.View.extend({ attributes: { class: 'badges-overlay' @@ -45,7 +46,7 @@ this.$el.find('.badges-modal').focus(); }, render: function() { - this.$el.html(this.template(this.model.toJSON())); + this.$el.html(HtmlUtils.HTML(this.template(this.model.toJSON())).toString()); return this; } }); diff --git a/openedx/features/learner_profile/views/learner_profile.py b/openedx/features/learner_profile/views/learner_profile.py index f4e91337eda77ca7a5558985ac2e1403400e6ac6..97e64807641acf7cc29719b761e4de0e33f82126 100644 --- a/openedx/features/learner_profile/views/learner_profile.py +++ b/openedx/features/learner_profile/views/learner_profile.py @@ -6,7 +6,7 @@ from django.contrib.auth.decorators import login_required from django.contrib.staticfiles.storage import staticfiles_storage from django.core.exceptions import ObjectDoesNotExist from django.http import Http404 -from django.shortcuts import redirect, render_to_response +from django.shortcuts import redirect, render from django.urls import reverse from django.utils.translation import ugettext as _ from django.views.decorators.http import require_http_methods @@ -51,9 +51,10 @@ def learner_profile(request, username): try: context = learner_profile_context(request, username, request.user.is_staff) - return render_to_response( - 'learner_profile/learner_profile.html', - context + return render( + request=request, + template_name='learner_profile/learner_profile.html', + context=context ) except (UserNotAuthorized, UserNotFound, ObjectDoesNotExist): raise Http404 diff --git a/openedx/tests/settings.py b/openedx/tests/settings.py index 7eb499b348e86654b71f6f36ffb797c9aa5c7020..950150edccaf00d31a4c75a8bc41bd4030582c0f 100644 --- a/openedx/tests/settings.py +++ b/openedx/tests/settings.py @@ -87,6 +87,8 @@ INSTALLED_APPS = ( 'openedx.core.djangoapps.self_paced', 'openedx.core.djangoapps.schedules.apps.SchedulesConfig', 'openedx.core.djangoapps.theming.apps.ThemingConfig', + 'openedx.core.djangoapps.external_user_ids', + 'experiments', 'openedx.features.content_type_gating', 'openedx.features.course_duration_limits', diff --git a/openedx/tests/xblock_integration/xblock_testcase.py b/openedx/tests/xblock_integration/xblock_testcase.py index 7b6c2cb875690e81e4d8936ce20a86b537391f23..961d0d8b8b7525986d9ea12e24007a1f30396717 100644 --- a/openedx/tests/xblock_integration/xblock_testcase.py +++ b/openedx/tests/xblock_integration/xblock_testcase.py @@ -41,6 +41,7 @@ import json import sys import unittest from datetime import datetime, timedelta +import html import mock import pytz @@ -449,7 +450,7 @@ class XBlockTestCase(XBlockStudentTestCaseMixin, ''' usage_id = self.xblocks[urlname].scope_ids.usage_id # First, we get out our <div> - soup_html = BeautifulSoup(content) + soup_html = BeautifulSoup(markup=content, features="lxml") xblock_html = six.text_type(soup_html.find(id="seq_contents_0")) # Now, we get out the text of the <div> try: @@ -466,7 +467,7 @@ class XBlockTestCase(XBlockStudentTestCaseMixin, print("Dice 2", repr(xblock_html.split('<')[1].split('>')[1]), file=sys.stderr) raise # Finally, we unescape the contents - decoded_html = six.moves.html_parser.HTMLParser().unescape(escaped_html).strip() + decoded_html = html.unescape(escaped_html).strip() return decoded_html diff --git a/package-lock.json b/package-lock.json index 791906b93366daccd79baceeeb75e42189c6df9f..d4c3534a7e710f340d363cdde3b17f318cbb8742 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,31 +66,6 @@ "resolved": "https://registry.npmjs.org/@edx/edx-proctoring/-/edx-proctoring-1.5.0.tgz", "integrity": "sha512-RiNjAgh8ZMX0D5gfN2R09a0RBs/R/Blfs/DiqhLmvCSvyCoeMDGANrDDQXv1w5blxxSJbz8a2awSZkwpv6gWNQ==" }, - "@edx/frontend-auth": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@edx/frontend-auth/-/frontend-auth-9.0.2.tgz", - "integrity": "sha512-b4rK4PBqODR9TCL9+/0W4xRI7NM4we71Yw7LAcF52ZA4QdKfnCQWNSrciFQuY17h2yQNc+5eXHHXCa9lfg/41g==", - "requires": { - "axios": "0.18.1", - "jwt-decode": "2.2.0", - "lodash.camelcase": "4.3.0", - "lodash.snakecase": "4.1.1", - "universal-cookie": "3.0.4" - }, - "dependencies": { - "universal-cookie": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-3.0.4.tgz", - "integrity": "sha512-3rhx6RAIuRmCWJttnbgzMrp2TbHhUmgQ2GrpY/US03Siv5T28iXr2qYw1m3YqmluBxEyrvZaloVemkLSId+Oyg==", - "requires": { - "@types/cookie": "^0.3.1", - "@types/object-assign": "^4.0.30", - "cookie": "^0.3.1", - "object-assign": "^4.1.0" - } - } - } - }, "@edx/frontend-component-cookie-policy-banner": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@edx/frontend-component-cookie-policy-banner/-/frontend-component-cookie-policy-banner-1.0.0.tgz", @@ -162,16 +137,6 @@ } } }, - "@edx/frontend-enterprise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@edx/frontend-enterprise/-/frontend-enterprise-4.0.0.tgz", - "integrity": "sha512-2FxQsnWf4Aw3As0Xh4ARXcDBPvAfppmMI8KnDHywLgQLZ6at1ceHE4rkOrHOT9QXsMoTvmY+uItAwpPnyXcSOw==" - }, - "@edx/frontend-logging": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@edx/frontend-logging/-/frontend-logging-3.0.1.tgz", - "integrity": "sha512-kRDsPbTUxNfZdnC4KN5HratS/7bkCYv/gyvUnBcuPbiONXwSuriNIVAKCepldvhg1DTwLqQMXh+Qw6vo2r048A==" - }, "@edx/mockprock": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@edx/mockprock/-/mockprock-1.0.2.tgz", @@ -306,22 +271,12 @@ "resolved": "https://registry.npmjs.org/@sambego/storybook-styles/-/storybook-styles-1.0.0.tgz", "integrity": "sha512-n0SqZwDewUDRaStEcoNMiYy9qovaLVStsh4Gb2dc2LLiG3IIK0UXdeR1N7puVuRihJq/192uOyGPCjZ/NAteuA==" }, - "@types/cookie": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", - "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==" - }, "@types/node": { "version": "10.5.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.2.tgz", "integrity": "sha512-m9zXmifkZsMHZBOyxZWilMwmTlpC8x5Ty360JKTiXvlXZfBWYpsg9ZZvP/Ye+iZUh+Q+MxDLjItVTWIsfwz+8Q==", "dev": true }, - "@types/object-assign": { - "version": "4.0.30", - "resolved": "https://registry.npmjs.org/@types/object-assign/-/object-assign-4.0.30.tgz", - "integrity": "sha1-iUk3HVqZ9Dge4PHfCpt6GH4H5lI=" - }, "abab": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", @@ -950,22 +905,6 @@ "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", "dev": true }, - "axios": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", - "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", - "requires": { - "follow-redirects": "1.5.10", - "is-buffer": "^2.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" - } - } - }, "axobject-query": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-0.1.0.tgz", @@ -5253,24 +5192,6 @@ "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=" }, - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } - } - }, "font-awesome": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", @@ -8398,11 +8319,6 @@ "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", "dev": true }, - "jwt-decode": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", - "integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk=" - }, "karma": { "version": "0.13.22", "resolved": "https://registry.npmjs.org/karma/-/karma-0.13.22.tgz", @@ -8903,11 +8819,6 @@ "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" }, - "lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=" - }, "lodash.some": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", diff --git a/package.json b/package.json index af31b630519b33cdc2044bac9542293d945a6e98..b3a737ef6cced6f7e4acc87b73242101e17564b1 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,7 @@ "dependencies": { "@edx/edx-bootstrap": "1.0.4", "@edx/edx-proctoring": "^1.5.0", - "@edx/frontend-auth": "^9.0.2", "@edx/frontend-component-cookie-policy-banner": "1.0.0", - "@edx/frontend-enterprise": "^4.0.0", - "@edx/frontend-logging": "^3.0.1", "@edx/paragon": "2.6.4", "@edx/studio-frontend": "^1.16.19", "babel-core": "6.26.0", diff --git a/pavelib/assets.py b/pavelib/assets.py index 61d3f52f2f4aff41e560bbeea912d2a9626e1825..3fa812da19bc5e4cf1ad79d8353c12989ffade91 100644 --- a/pavelib/assets.py +++ b/pavelib/assets.py @@ -11,7 +11,6 @@ from datetime import datetime from functools import wraps from threading import Timer -import six from paver import tasks from paver.easy import call_task, cmdopts, consume_args, needs, no_help, path, sh, task from watchdog.events import PatternMatchingEventHandler @@ -89,7 +88,7 @@ SASS_LOOKUP_DEPENDENCIES = { COLLECTSTATIC_LOG_DIR_ARG = 'collect_log_dir' # Webpack command -WEBPACK_COMMAND = u'STATIC_ROOT_LMS={static_root_lms} STATIC_ROOT_CMS={static_root_cms} $(npm bin)/webpack {options}' +WEBPACK_COMMAND = 'STATIC_ROOT_LMS={static_root_lms} STATIC_ROOT_CMS={static_root_cms} $(npm bin)/webpack {options}' def get_sass_directories(system, theme_dir=None): @@ -110,7 +109,7 @@ def get_sass_directories(system, theme_dir=None): :param theme_dir: absolute path of theme for which to compile sass files. """ if system not in SYSTEMS: - raise ValueError(u"'system' must be one of ({allowed_values})".format( + raise ValueError("'system' must be one of ({allowed_values})".format( allowed_values=', '.join(list(SYSTEMS.keys()))) ) system = SYSTEMS[system] @@ -285,11 +284,11 @@ def debounce(seconds=1): seconds. Waits until calls stop coming in before calling the decorated function. """ - def decorator(func): # pylint: disable=missing-docstring + def decorator(func): func.timer = None @wraps(func) - def wrapper(*args, **kwargs): # pylint: disable=missing-docstring + def wrapper(*args, **kwargs): def call(): func(*args, **kwargs) func.timer = None @@ -455,7 +454,7 @@ def compile_sass(options): for system in systems: for theme in themes: - print(u"Started compiling '{system}' Sass for '{theme}'.".format(system=system, theme=theme or 'system')) + print("Started compiling '{system}' Sass for '{theme}'.".format(system=system, theme=theme or 'system')) # Compile sass files is_successful = _compile_sass( @@ -467,18 +466,18 @@ def compile_sass(options): ) if is_successful: - print(u"Finished compiling '{system}' Sass for '{theme}'.".format( + print("Finished compiling '{system}' Sass for '{theme}'.".format( system=system, theme=theme or 'system' )) - compilation_results['success' if is_successful else 'failure'].append(u'{system} sass for {theme}.'.format( + compilation_results['success' if is_successful else 'failure'].append('{system} sass for {theme}.'.format( system=system, theme=theme or 'system', )) print("\t\tFinished compiling Sass:") if not dry_run: for sass_dir, css_dir, duration in timing_info: - print(u">> {} -> {} in {}s".format(sass_dir, css_dir, duration)) + print(">> {} -> {} in {}s".format(sass_dir, css_dir, duration)) if compilation_results['success']: print("\033[92m\nSuccessful compilations:\n--- " + "\n--- ".join(compilation_results['success']) + "\n\033[00m") @@ -524,7 +523,7 @@ def _compile_sass(system, theme, debug, force, timing_info): lookup_paths = dirs['lookup_paths'] if not sass_source_dir.isdir(): - print(u"\033[91m Sass dir '{dir}' does not exists, skipping sass compilation for '{theme}' \033[00m".format( + print("\033[91m Sass dir '{dir}' does not exists, skipping sass compilation for '{theme}' \033[00m".format( dir=sass_dirs, theme=theme or system, )) # theme doesn't override sass directory, so skip it @@ -532,14 +531,14 @@ def _compile_sass(system, theme, debug, force, timing_info): if force: if dry_run: - tasks.environment.info(u"rm -rf {css_dir}/*.css".format( + tasks.environment.info("rm -rf {css_dir}/*.css".format( css_dir=css_dir, )) else: - sh(u"rm -rf {css_dir}/*.css".format(css_dir=css_dir)) + sh("rm -rf {css_dir}/*.css".format(css_dir=css_dir)) if dry_run: - tasks.environment.info(u"libsass {sass_dir}".format( + tasks.environment.info("libsass {sass_dir}".format( sass_dir=sass_source_dir, )) else: @@ -556,7 +555,7 @@ def _compile_sass(system, theme, debug, force, timing_info): if should_generate_rtl_css_file(sass_file): source_css_file = sass_file.replace(sass_source_dir, css_dir).replace('.scss', '.css') target_css_file = source_css_file.replace('.css', '-rtl.css') - sh(u"rtlcss {source_file} {target_file}".format( + sh("rtlcss {source_file} {target_file}".format( source_file=source_css_file, target_file=target_css_file, )) @@ -606,19 +605,19 @@ def process_npm_assets(): else: vendor_dir = NPM_JS_VENDOR_DIRECTORY if os.path.exists(library_path): - sh(u'/bin/cp -rf {library_path} {vendor_dir}'.format( + sh('/bin/cp -rf {library_path} {vendor_dir}'.format( library_path=library_path, vendor_dir=vendor_dir, )) elif not skip_if_missing: - raise Exception(u'Missing vendor file {library_path}'.format(library_path=library_path)) + raise Exception('Missing vendor file {library_path}'.format(library_path=library_path)) def copy_vendor_library_dir(library_dir, skip_if_missing=False): """ Copies all vendor libraries in directory to the shared vendor directory. """ library_dir_path = 'node_modules/{library_dir}'.format(library_dir=library_dir) - print(u'Copying vendor library dir: {}'.format(library_dir_path)) + print('Copying vendor library dir: {}'.format(library_dir_path)) if os.path.exists(library_dir_path): for dirpath, _, filenames in os.walk(library_dir_path): for filename in filenames: @@ -697,16 +696,16 @@ def collect_assets(systems, settings, **kwargs): ] ignore_args = " ".join( - u'--ignore "{}"'.format(pattern) for pattern in ignore_patterns + '--ignore "{}"'.format(pattern) for pattern in ignore_patterns ) for sys in systems: collectstatic_stdout_str = _collect_assets_cmd(sys, **kwargs) - sh(django_cmd(sys, settings, u"collectstatic {ignore_args} --noinput {logfile_str}".format( + sh(django_cmd(sys, settings, "collectstatic {ignore_args} --noinput {logfile_str}".format( ignore_args=ignore_args, logfile_str=collectstatic_stdout_str ))) - print(u"\t\tFinished collecting {} assets.".format(sys)) + print("\t\tFinished collecting {} assets.".format(sys)) def _collect_assets_cmd(system, **kwargs): @@ -719,7 +718,7 @@ def _collect_assets_cmd(system, **kwargs): if kwargs[COLLECTSTATIC_LOG_DIR_ARG] is None: collectstatic_stdout_str = "" else: - collectstatic_stdout_str = u"> {output_dir}/{sys}-collectstatic.log".format( + collectstatic_stdout_str = "> {output_dir}/{sys}-collectstatic.log".format( output_dir=kwargs[COLLECTSTATIC_LOG_DIR_ARG], sys=system ) @@ -745,7 +744,7 @@ def execute_compile_sass(args): django_cmd( sys, args.settings, - u"compile_sass {system} {options}".format( + "compile_sass {system} {options}".format( system='cms' if sys == 'studio' else sys, options=options, ), @@ -766,31 +765,15 @@ def webpack(options): settings = getattr(options, 'settings', Env.DEVSTACK_SETTINGS) static_root_lms = Env.get_django_setting("STATIC_ROOT", "lms", settings=settings) static_root_cms = Env.get_django_setting("STATIC_ROOT", "cms", settings=settings) - lms_root_url = Env.get_django_setting("LMS_ROOT_URL", "lms", settings=settings) - jwt_auth_cookie_header_payload_name = Env.get_nested_django_setting( - "JWT_AUTH", - "JWT_AUTH_COOKIE_HEADER_PAYLOAD", - "lms", - settings=settings, - ) - user_info_cookie_name = Env.get_django_setting("EDXMKTG_USER_INFO_COOKIE_NAME", "lms", settings=settings) config_path = Env.get_django_setting("WEBPACK_CONFIG_PATH", "lms", settings=settings) - environment = u"NODE_ENV={node_env} " \ - u"STATIC_ROOT_LMS={static_root_lms} " \ - u"STATIC_ROOT_CMS={static_root_cms} " \ - u"LMS_ROOT_URL={lms_root_url} " \ - u"JWT_AUTH_COOKIE_HEADER_PAYLOAD={jwt_auth_cookie_header_payload_name} " \ - u"EDXMKTG_USER_INFO_COOKIE_NAME={user_info_cookie_name}".format( - node_env="development" if config_path == 'webpack.dev.config.js' else "production", - static_root_lms=static_root_lms, - static_root_cms=static_root_cms, - lms_root_url=lms_root_url, - jwt_auth_cookie_header_payload_name=jwt_auth_cookie_header_payload_name, - user_info_cookie_name=user_info_cookie_name, - ) + environment = 'NODE_ENV={node_env} STATIC_ROOT_LMS={static_root_lms} STATIC_ROOT_CMS={static_root_cms}'.format( + node_env="development" if config_path == 'webpack.dev.config.js' else "production", + static_root_lms=static_root_lms, + static_root_cms=static_root_cms + ) sh( cmd( - u'{environment} $(npm bin)/webpack --config={config_path}'.format( + '{environment} $(npm bin)/webpack --config={config_path}'.format( environment=environment, config_path=config_path ) @@ -806,8 +789,8 @@ def execute_webpack_watch(settings=None): # not all JS files, so we use its own watcher instead of subclassing # from Watchdog like the other watchers do. run_background_process( - u'STATIC_ROOT_LMS={static_root_lms} STATIC_ROOT_CMS={static_root_cms} $(npm bin)/webpack {options}'.format( - options=u'--watch --config={config_path}'.format( + 'STATIC_ROOT_LMS={static_root_lms} STATIC_ROOT_CMS={static_root_cms} $(npm bin)/webpack {options}'.format( + options='--watch --config={config_path}'.format( config_path=Env.get_django_setting("WEBPACK_CONFIG_PATH", "lms", settings=settings) ), static_root_lms=Env.get_django_setting("STATIC_ROOT", "lms", settings=settings), @@ -840,7 +823,7 @@ def listfy(data): data: data structure to be converted. """ - if isinstance(data, six.string_types): + if isinstance(data, str): data = data.split(',') elif not isinstance(data, list): data = [data] @@ -870,7 +853,7 @@ def watch_assets(options): themes = get_parsed_option(options, 'themes') theme_dirs = get_parsed_option(options, 'theme_dirs', []) - default_wait = [six.text_type(DEFAULT_OBSERVER_TIMEOUT)] + default_wait = [str(DEFAULT_OBSERVER_TIMEOUT)] wait = float(get_parsed_option(options, 'wait', default_wait)[0]) if not theme_dirs and themes: diff --git a/pavelib/bok_choy.py b/pavelib/bok_choy.py index fd5cd6436a765530406f4a74bdda3a6c40d222c3..46357cb0eba2b48b96f7d14ae5d3c47e441fc8ef 100644 --- a/pavelib/bok_choy.py +++ b/pavelib/bok_choy.py @@ -109,7 +109,7 @@ def run_bokchoy(options, passthrough_options): test_suite = BokChoyTestSuite('bok-choy', passthrough_options=passthrough_options, **options) msg = colorize( 'green', - u'Running tests using {default_store} modulestore.'.format( + 'Running tests using {default_store} modulestore.'.format( default_store=test_suite.default_store, ) ) @@ -126,14 +126,14 @@ def parse_coverage(report_dir, coveragerc): msg = colorize('green', "Combining coverage reports") print(msg) - sh(u"coverage combine --rcfile={}".format(coveragerc)) + sh("coverage combine --rcfile={}".format(coveragerc)) msg = colorize('green', "Generating coverage reports") print(msg) - sh(u"coverage html --rcfile={}".format(coveragerc)) - sh(u"coverage xml --rcfile={}".format(coveragerc)) - sh(u"coverage report --rcfile={}".format(coveragerc)) + sh("coverage html --rcfile={}".format(coveragerc)) + sh("coverage xml --rcfile={}".format(coveragerc)) + sh("coverage report --rcfile={}".format(coveragerc)) @task diff --git a/pavelib/database.py b/pavelib/database.py index 30938e91a7301e127186a098fc2ed44631e8f463..1249329085ce2e0ae4026d63b3341b5f863940c9 100644 --- a/pavelib/database.py +++ b/pavelib/database.py @@ -108,7 +108,7 @@ def update_local_bokchoy_db_from_s3(options): reset_test_db(BOKCHOY_DB_FILES, update_cache_files=False, use_existing_db=True) else: - msg = u"{} {} {}".format( + msg = "{} {} {}".format( "Did not find updated bokchoy db files at S3.", "Loading the bokchoy db files from disk", "and running migrations." @@ -121,7 +121,7 @@ def update_local_bokchoy_db_from_s3(options): if not is_fingerprint_in_bucket(fingerprint, CACHE_BUCKET_NAME): upload_db_cache_to_s3(fingerprint, BOKCHOY_DB_FILES, CACHE_BUCKET_NAME) else: - msg = u"{} {}. {}".format( + msg = "{} {}. {}".format( "Found a matching fingerprint in bucket ", CACHE_BUCKET_NAME, "Not pushing to s3" diff --git a/pavelib/docs.py b/pavelib/docs.py index f7db8d510da92a0797dac4b4b1fe49e718aa1975..c2075e10daa1853e1af8ff1d0e377f8d8a595c96 100644 --- a/pavelib/docs.py +++ b/pavelib/docs.py @@ -40,8 +40,8 @@ def doc_path(options, allow_default=True): if doc_type == 'default' and not allow_default: print( - u"You must specify a documentation type using '--type'. " - u"Valid options are: {options}".format( + "You must specify a documentation type using '--type'. " + "Valid options are: {options}".format( options=valid_doc_types() ) ) @@ -49,8 +49,8 @@ def doc_path(options, allow_default=True): if path is None: print( - u"Invalid documentation type '{doc_type}'. " - u"Valid options are: {options}".format( + "Invalid documentation type '{doc_type}'. " + "Valid options are: {options}".format( doc_type=doc_type, options=valid_doc_types() ) ) @@ -73,7 +73,7 @@ def build_docs(options): """ verbose = getattr(options, 'verbose', False) - cmd = u"cd {dir}; make html quiet={quiet}".format( + cmd = "cd {dir}; make html quiet={quiet}".format( dir=doc_path(options), quiet="false" if verbose else "true" ) diff --git a/pavelib/i18n.py b/pavelib/i18n.py index 0d8d2cc15782bf9ad424f3aa5c5fed7121a8b9e1..b269a9faf7a6deaf682fce1485b58c8f712ab7ca 100644 --- a/pavelib/i18n.py +++ b/pavelib/i18n.py @@ -9,7 +9,6 @@ import sys from path import Path as path from paver.easy import cmdopts, needs, sh, task -from six.moves import input from .utils.cmd import django_cmd from .utils.envs import Env @@ -139,9 +138,9 @@ def i18n_validate_transifex_config(): if not config.isfile or config.getsize == 0: msg = colorize( 'red', - u"Cannot connect to Transifex, config file is missing" - u" or empty: {config} \nSee " - u"http://help.transifex.com/features/client/#transifexrc \n".format( + "Cannot connect to Transifex, config file is missing" + " or empty: {config} \nSee " + "http://help.transifex.com/features/client/#transifexrc \n".format( config=config, ) ) diff --git a/pavelib/js_test.py b/pavelib/js_test.py index 3de8fcf0766419f53f02809f5cf17760f9a34925..1a76bce2983169a66fa689cbfcdb0b7e8212783c 100644 --- a/pavelib/js_test.py +++ b/pavelib/js_test.py @@ -50,7 +50,7 @@ def test_js(options): if (suite != 'all') and (suite not in Env.JS_TEST_ID_KEYS): sys.stderr.write( - u"Unknown test suite. Please choose from ({suites})\n".format( + "Unknown test suite. Please choose from ({suites})\n".format( suites=", ".join(Env.JS_TEST_ID_KEYS) ) ) diff --git a/pavelib/paver_tests/test_assets.py b/pavelib/paver_tests/test_assets.py index f170e59a54b824f974658d0277c6eb4fc30fd29d..2d416d4ffa8d1ac906ae5198df2406856d3ff326 100644 --- a/pavelib/paver_tests/test_assets.py +++ b/pavelib/paver_tests/test_assets.py @@ -6,7 +6,6 @@ from unittest import TestCase import ddt import paver.tasks -import six from mock import patch from paver.easy import call_task, path from watchdog.observers import Observer @@ -58,27 +57,27 @@ class TestPaverAssetTasks(PaverTestCase): if "lms" in system: if force: - expected_messages.append(u'rm -rf lms/static/css/*.css') - expected_messages.append(u'libsass lms/static/sass') + expected_messages.append('rm -rf lms/static/css/*.css') + expected_messages.append('libsass lms/static/sass') expected_messages.append( - u'rtlcss lms/static/css/bootstrap/lms-main.css lms/static/css/bootstrap/lms-main-rtl.css' + 'rtlcss lms/static/css/bootstrap/lms-main.css lms/static/css/bootstrap/lms-main-rtl.css' ) expected_messages.append( - u'rtlcss lms/static/css/discussion/lms-discussion-bootstrap.css' - u' lms/static/css/discussion/lms-discussion-bootstrap-rtl.css' + 'rtlcss lms/static/css/discussion/lms-discussion-bootstrap.css' + ' lms/static/css/discussion/lms-discussion-bootstrap-rtl.css' ) if force: - expected_messages.append(u'rm -rf lms/static/certificates/css/*.css') - expected_messages.append(u'libsass lms/static/certificates/sass') + expected_messages.append('rm -rf lms/static/certificates/css/*.css') + expected_messages.append('libsass lms/static/certificates/sass') if "studio" in system: if force: - expected_messages.append(u'rm -rf cms/static/css/*.css') - expected_messages.append(u'libsass cms/static/sass') + expected_messages.append('rm -rf cms/static/css/*.css') + expected_messages.append('libsass cms/static/sass') expected_messages.append( - u'rtlcss cms/static/css/bootstrap/studio-main.css cms/static/css/bootstrap/studio-main-rtl.css' + 'rtlcss cms/static/css/bootstrap/studio-main.css cms/static/css/bootstrap/studio-main-rtl.css' ) - six.assertCountEqual(self, self.task_messages, expected_messages) + self.assertCountEqual(self.task_messages, expected_messages) @ddt.ddt @@ -125,77 +124,77 @@ class TestPaverThemeAssetTasks(PaverTestCase): ) expected_messages = [] if force: - expected_messages.append(u'rm -rf common/static/css/*.css') - expected_messages.append(u'libsass common/static/sass') + expected_messages.append('rm -rf common/static/css/*.css') + expected_messages.append('libsass common/static/sass') if 'lms' in system: - expected_messages.append(u'mkdir_p ' + repr(TEST_THEME_DIR / 'lms/static/css')) + expected_messages.append('mkdir_p ' + repr(TEST_THEME_DIR / 'lms/static/css')) if force: expected_messages.append( - u'rm -rf {test_theme_dir}/lms/static/css/*.css'.format(test_theme_dir=str(TEST_THEME_DIR)) + 'rm -rf {test_theme_dir}/lms/static/css/*.css'.format(test_theme_dir=str(TEST_THEME_DIR)) ) expected_messages.append("libsass lms/static/sass") expected_messages.append( - u'rtlcss {test_theme_dir}/lms/static/css/bootstrap/lms-main.css' - u' {test_theme_dir}/lms/static/css/bootstrap/lms-main-rtl.css'.format( + 'rtlcss {test_theme_dir}/lms/static/css/bootstrap/lms-main.css' + ' {test_theme_dir}/lms/static/css/bootstrap/lms-main-rtl.css'.format( test_theme_dir=str(TEST_THEME_DIR), ) ) expected_messages.append( - u'rtlcss {test_theme_dir}/lms/static/css/discussion/lms-discussion-bootstrap.css' - u' {test_theme_dir}/lms/static/css/discussion/lms-discussion-bootstrap-rtl.css'.format( + 'rtlcss {test_theme_dir}/lms/static/css/discussion/lms-discussion-bootstrap.css' + ' {test_theme_dir}/lms/static/css/discussion/lms-discussion-bootstrap-rtl.css'.format( test_theme_dir=str(TEST_THEME_DIR), ) ) if force: expected_messages.append( - u'rm -rf {test_theme_dir}/lms/static/css/*.css'.format(test_theme_dir=str(TEST_THEME_DIR)) + 'rm -rf {test_theme_dir}/lms/static/css/*.css'.format(test_theme_dir=str(TEST_THEME_DIR)) ) expected_messages.append( - u'libsass {test_theme_dir}/lms/static/sass'.format(test_theme_dir=str(TEST_THEME_DIR)) + 'libsass {test_theme_dir}/lms/static/sass'.format(test_theme_dir=str(TEST_THEME_DIR)) ) if force: - expected_messages.append(u'rm -rf lms/static/css/*.css') - expected_messages.append(u'libsass lms/static/sass') + expected_messages.append('rm -rf lms/static/css/*.css') + expected_messages.append('libsass lms/static/sass') expected_messages.append( - u'rtlcss lms/static/css/bootstrap/lms-main.css lms/static/css/bootstrap/lms-main-rtl.css' + 'rtlcss lms/static/css/bootstrap/lms-main.css lms/static/css/bootstrap/lms-main-rtl.css' ) expected_messages.append( - u'rtlcss lms/static/css/discussion/lms-discussion-bootstrap.css' - u' lms/static/css/discussion/lms-discussion-bootstrap-rtl.css' + 'rtlcss lms/static/css/discussion/lms-discussion-bootstrap.css' + ' lms/static/css/discussion/lms-discussion-bootstrap-rtl.css' ) if force: - expected_messages.append(u'rm -rf lms/static/certificates/css/*.css') - expected_messages.append(u'libsass lms/static/certificates/sass') + expected_messages.append('rm -rf lms/static/certificates/css/*.css') + expected_messages.append('libsass lms/static/certificates/sass') if "studio" in system: - expected_messages.append(u'mkdir_p ' + repr(TEST_THEME_DIR / 'cms/static/css')) + expected_messages.append('mkdir_p ' + repr(TEST_THEME_DIR / 'cms/static/css')) if force: expected_messages.append( - u'rm -rf {test_theme_dir}/cms/static/css/*.css'.format(test_theme_dir=str(TEST_THEME_DIR)) + 'rm -rf {test_theme_dir}/cms/static/css/*.css'.format(test_theme_dir=str(TEST_THEME_DIR)) ) - expected_messages.append(u'libsass cms/static/sass') + expected_messages.append('libsass cms/static/sass') expected_messages.append( - u'rtlcss {test_theme_dir}/cms/static/css/bootstrap/studio-main.css' - u' {test_theme_dir}/cms/static/css/bootstrap/studio-main-rtl.css'.format( + 'rtlcss {test_theme_dir}/cms/static/css/bootstrap/studio-main.css' + ' {test_theme_dir}/cms/static/css/bootstrap/studio-main-rtl.css'.format( test_theme_dir=str(TEST_THEME_DIR), ) ) if force: expected_messages.append( - u'rm -rf {test_theme_dir}/cms/static/css/*.css'.format(test_theme_dir=str(TEST_THEME_DIR)) + 'rm -rf {test_theme_dir}/cms/static/css/*.css'.format(test_theme_dir=str(TEST_THEME_DIR)) ) expected_messages.append( - u'libsass {test_theme_dir}/cms/static/sass'.format(test_theme_dir=str(TEST_THEME_DIR)) + 'libsass {test_theme_dir}/cms/static/sass'.format(test_theme_dir=str(TEST_THEME_DIR)) ) if force: - expected_messages.append(u'rm -rf cms/static/css/*.css') - expected_messages.append(u'libsass cms/static/sass') + expected_messages.append('rm -rf cms/static/css/*.css') + expected_messages.append('libsass cms/static/sass') expected_messages.append( - u'rtlcss cms/static/css/bootstrap/studio-main.css cms/static/css/bootstrap/studio-main-rtl.css' + 'rtlcss cms/static/css/bootstrap/studio-main.css cms/static/css/bootstrap/studio-main-rtl.css' ) - six.assertCountEqual(self, self.task_messages, expected_messages) + self.assertCountEqual(self.task_messages, expected_messages) class TestPaverWatchAssetTasks(TestCase): @@ -221,11 +220,11 @@ class TestPaverWatchAssetTasks(TestCase): if 'pavelib.assets.watch_assets' in paver.tasks.environment.options: del paver.tasks.environment.options['pavelib.assets.watch_assets'] - super(TestPaverWatchAssetTasks, self).setUp() + super().setUp() def tearDown(self): self.expected_sass_directories = [] - super(TestPaverWatchAssetTasks, self).tearDown() + super().tearDown() def test_watch_assets(self): """ @@ -245,7 +244,7 @@ class TestPaverWatchAssetTasks(TestCase): self.assertIsInstance(sass_watcher_args[0], Observer) self.assertIsInstance(sass_watcher_args[1], list) - six.assertCountEqual(self, sass_watcher_args[1], self.expected_sass_directories) + self.assertCountEqual(sass_watcher_args[1], self.expected_sass_directories) def test_watch_theme_assets(self): """ @@ -275,7 +274,7 @@ class TestPaverWatchAssetTasks(TestCase): sass_watcher_args = mock_register.call_args_list[0][0] self.assertIsInstance(sass_watcher_args[0], Observer) self.assertIsInstance(sass_watcher_args[1], list) - six.assertCountEqual(self, sass_watcher_args[1], self.expected_sass_directories) + self.assertCountEqual(sass_watcher_args[1], self.expected_sass_directories) @ddt.ddt @@ -347,7 +346,7 @@ class TestCollectAssets(PaverTestCase): """ for i, sys in enumerate(systems): msg = self.task_messages[i] - self.assertTrue(msg.startswith(u'python manage.py {}'.format(sys))) + self.assertTrue(msg.startswith('python manage.py {}'.format(sys))) self.assertIn(' collectstatic ', msg) self.assertIn('--settings={}'.format(Env.DEVSTACK_SETTINGS), msg) self.assertTrue(msg.endswith(' {}'.format(log_location))) @@ -374,7 +373,7 @@ class TestUpdateAssetsTask(PaverTestCase): call_task('pavelib.assets.update_assets', args=cmd_args) self.assertTrue( self._is_substring_in_list(self.task_messages, expected_substring), - msg=u"{substring} not found in messages".format(substring=expected_substring) + msg="{substring} not found in messages".format(substring=expected_substring) ) def _is_substring_in_list(self, messages_list, expected_substring): diff --git a/pavelib/paver_tests/test_database.py b/pavelib/paver_tests/test_database.py index 0c6e9b74360f6173abe58af69b163580f058a262..3bf88f5d624d45f4aefa4e6de36fa1c6ce61a617 100644 --- a/pavelib/paver_tests/test_database.py +++ b/pavelib/paver_tests/test_database.py @@ -43,7 +43,7 @@ class TestPaverDbUtils(TestCase): extracted_file = os.path.join(output_dir, 'test.txt') assert os.path.isfile(extracted_file) - with open(extracted_file, 'r') as test_file: + with open(extracted_file) as test_file: data = test_file.read() assert data == 'Test file content' @@ -65,7 +65,7 @@ class TestPaverDatabaseTasks(PaverTestCase): """ def setUp(self): - super(TestPaverDatabaseTasks, self).setUp() + super().setUp() # This value is the actual sha1 fingerprint calculated for the dummy # files used in these tests self.expected_fingerprint = 'ccaa8d8dcc7d030cd6a6768db81f90d0ef976c3d' @@ -94,8 +94,8 @@ class TestPaverDatabaseTasks(PaverTestCase): # Make sure that the local cache files are used - NOT downloaded from s3 self.assertFalse(_mock_get_file.called) calls = [ - call(u'{}/scripts/reset-test-db.sh --calculate_migrations'.format(Env.REPO_ROOT)), - call(u'{}/scripts/reset-test-db.sh --use-existing-db'.format(Env.REPO_ROOT)) + call('{}/scripts/reset-test-db.sh --calculate_migrations'.format(Env.REPO_ROOT)), + call('{}/scripts/reset-test-db.sh --use-existing-db'.format(Env.REPO_ROOT)) ] _mock_sh.assert_has_calls(calls) @@ -137,8 +137,8 @@ class TestPaverDatabaseTasks(PaverTestCase): ) calls = [ - call(u'{}/scripts/reset-test-db.sh --calculate_migrations'.format(Env.REPO_ROOT)), - call(u'{}/scripts/reset-test-db.sh --use-existing-db'.format(Env.REPO_ROOT)) + call('{}/scripts/reset-test-db.sh --calculate_migrations'.format(Env.REPO_ROOT)), + call('{}/scripts/reset-test-db.sh --use-existing-db'.format(Env.REPO_ROOT)) ] _mock_sh.assert_has_calls(calls) @@ -165,8 +165,8 @@ class TestPaverDatabaseTasks(PaverTestCase): database.update_local_bokchoy_db_from_s3() # pylint: disable=no-value-for-parameter calls = [ - call(u'{}/scripts/reset-test-db.sh --calculate_migrations'.format(Env.REPO_ROOT)), - call(u'{}/scripts/reset-test-db.sh --rebuild_cache --use-existing-db'.format(Env.REPO_ROOT)) + call('{}/scripts/reset-test-db.sh --calculate_migrations'.format(Env.REPO_ROOT)), + call('{}/scripts/reset-test-db.sh --rebuild_cache --use-existing-db'.format(Env.REPO_ROOT)) ] _mock_sh.assert_has_calls(calls) diff --git a/pavelib/paver_tests/test_eslint.py b/pavelib/paver_tests/test_eslint.py index 06433e0aa1b6f6cf8295530e622194781bb098ef..86917b4dbc6de7ce62512fc6db417aa46addc930 100644 --- a/pavelib/paver_tests/test_eslint.py +++ b/pavelib/paver_tests/test_eslint.py @@ -17,7 +17,7 @@ class TestPaverESLint(unittest.TestCase): """ def setUp(self): - super(TestPaverESLint, self).setUp() + super().setUp() # Mock the paver @needs decorator self._mock_paver_needs = patch.object(pavelib.quality.run_eslint, 'needs').start() diff --git a/pavelib/paver_tests/test_extract_and_generate.py b/pavelib/paver_tests/test_extract_and_generate.py index 88c784b40c9a7fa37b910a41b8a90377e38785f6..81ed8a356180fa51abb7047cc1094be657c31e53 100644 --- a/pavelib/paver_tests/test_extract_and_generate.py +++ b/pavelib/paver_tests/test_extract_and_generate.py @@ -15,7 +15,6 @@ from unittest import TestCase from i18n import config, dummy, extract, generate from polib import pofile from pytz import UTC -from six.moves import range class TestGenerate(TestCase): @@ -26,7 +25,7 @@ class TestGenerate(TestCase): @classmethod def setUpClass(cls): - super(TestGenerate, cls).setUpClass() + super().setUpClass() sys.stderr.write( "\nThis test tests that i18n extraction (`paver i18n_extract`) works properly. " @@ -50,10 +49,10 @@ class TestGenerate(TestCase): sys.stderr.flush() returncode = subprocess.call(cmd, shell=True) assert returncode == 0 - super(TestGenerate, cls).tearDownClass() + super().tearDownClass() def setUp(self): - super(TestGenerate, self).setUp() + super().setUp() self.configuration = config.Configuration() @@ -87,11 +86,11 @@ class TestGenerate(TestCase): mofile = filename + '.mo' path = os.path.join(self.configuration.get_messages_dir(locale), mofile) exists = os.path.exists(path) - self.assertTrue(exists, msg=u'Missing file in locale %s: %s' % (locale, mofile)) + self.assertTrue(exists, msg='Missing file in locale %s: %s' % (locale, mofile)) self.assertGreaterEqual( datetime.fromtimestamp(os.path.getmtime(path), UTC), self.start_time, - msg=u'File not recently modified: %s' % path + msg='File not recently modified: %s' % path ) # Segmenting means that the merge headers don't work they way they # used to, so don't make this check for now. I'm not sure if we'll @@ -116,7 +115,7 @@ class TestGenerate(TestCase): self.assertEqual( len(match), 3, - msg=u"Found %s (should be 3) merge comments in the header for %s" % (len(match), path) + msg="Found %s (should be 3) merge comments in the header for %s" % (len(match), path) ) diff --git a/pavelib/paver_tests/test_i18n.py b/pavelib/paver_tests/test_i18n.py index d17ee145ddeba3c41b38fe269d52781460b6b9fa..d6cb38278bc2bebfef7c0f65d6c158c1c35908cd 100644 --- a/pavelib/paver_tests/test_i18n.py +++ b/pavelib/paver_tests/test_i18n.py @@ -141,7 +141,7 @@ class TestI18nDummy(PaverTestCase): Test the Paver i18n_dummy task. """ def setUp(self): - super(TestI18nDummy, self).setUp() + super().setUp() # Mock the paver @needs decorator for i18n_extract self._mock_paver_needs = patch.object(pavelib.i18n.i18n_extract, 'needs').start() @@ -160,9 +160,9 @@ class TestI18nDummy(PaverTestCase): self.assertEqual( self.task_messages, [ - u'i18n_tool extract', - u'i18n_tool dummy', - u'i18n_tool generate', + 'i18n_tool extract', + 'i18n_tool dummy', + 'i18n_tool generate', ] ) @@ -172,7 +172,7 @@ class TestI18nCompileJS(PaverTestCase): Test the Paver i18n_compilejs task. """ def setUp(self): - super(TestI18nCompileJS, self).setUp() + super().setUp() # Mock the paver @needs decorator for i18n_extract self._mock_paver_needs = patch.object(pavelib.i18n.i18n_extract, 'needs').start() @@ -193,7 +193,7 @@ class TestI18nCompileJS(PaverTestCase): self.assertEqual( self.task_messages, [ - u'python manage.py lms --settings={} compilejsi18n'.format(Env.TEST_SETTINGS), - u'python manage.py cms --settings={} compilejsi18n'.format(Env.TEST_SETTINGS), + 'python manage.py lms --settings={} compilejsi18n'.format(Env.TEST_SETTINGS), + 'python manage.py cms --settings={} compilejsi18n'.format(Env.TEST_SETTINGS), ] ) diff --git a/pavelib/paver_tests/test_js_test.py b/pavelib/paver_tests/test_js_test.py index 26413a340a6f8294f7e0dc2e028bc118ddd590d7..78a431da259495a246d706b6785e4739c223628f 100644 --- a/pavelib/paver_tests/test_js_test.py +++ b/pavelib/paver_tests/test_js_test.py @@ -17,30 +17,30 @@ class TestPaverJavaScriptTestTasks(PaverTestCase): Test the Paver JavaScript testing tasks. """ - EXPECTED_DELETE_JAVASCRIPT_REPORT_COMMAND = u'find {platform_root}/reports/javascript -type f -delete' - EXPECTED_INSTALL_NPM_ASSETS_COMMAND = u'install npm_assets' + EXPECTED_DELETE_JAVASCRIPT_REPORT_COMMAND = 'find {platform_root}/reports/javascript -type f -delete' + EXPECTED_INSTALL_NPM_ASSETS_COMMAND = 'install npm_assets' EXPECTED_KARMA_OPTIONS = ( - u"{config_file} " - u"--single-run={single_run} " - u"--capture-timeout=60000 " - u"--junitreportpath=" - u"{platform_root}/reports/javascript/javascript_xunit-{suite}.xml " - u"--browsers={browser}" + "{config_file} " + "--single-run={single_run} " + "--capture-timeout=60000 " + "--junitreportpath=" + "{platform_root}/reports/javascript/javascript_xunit-{suite}.xml " + "--browsers={browser}" ) EXPECTED_COVERAGE_OPTIONS = ( - u' --coverage --coveragereportpath={platform_root}/reports/javascript/coverage-{suite}.xml' + ' --coverage --coveragereportpath={platform_root}/reports/javascript/coverage-{suite}.xml' ) EXPECTED_COMMANDS = [ - u"make report_dir", - u'git clean -fqdx test_root/logs test_root/data test_root/staticfiles test_root/uploads', - u"find . -name '.git' -prune -o -name '*.pyc' -exec rm {} \\;", - u'rm -rf test_root/log/auto_screenshots/*', - u"rm -rf /tmp/mako_[cl]ms", + "make report_dir", + 'git clean -fqdx test_root/logs test_root/data test_root/staticfiles test_root/uploads', + "find . -name '.git' -prune -o -name '*.pyc' -exec rm {} \\;", + 'rm -rf test_root/log/auto_screenshots/*', + "rm -rf /tmp/mako_[cl]ms", ] def setUp(self): - super(TestPaverJavaScriptTestTasks, self).setUp() + super().setUp() # Mock the paver @needs decorator self._mock_paver_needs = patch.object(pavelib.js_test.test_js, 'needs').start() @@ -119,7 +119,7 @@ class TestPaverJavaScriptTestTasks(PaverTestCase): expected_messages.append(self.EXPECTED_INSTALL_NPM_ASSETS_COMMAND) command_template = ( - u'nodejs --max_old_space_size=4096 node_modules/.bin/karma start {options}' + 'nodejs --max_old_space_size=4096 node_modules/.bin/karma start {options}' ) for suite in suites: @@ -141,9 +141,9 @@ class TestPaverJavaScriptTestTasks(PaverTestCase): suite=suite ) if port: - expected_test_tool_command += u" --port={port}".format(port=port) + expected_test_tool_command += " --port={port}".format(port=port) else: - expected_test_tool_command = u'jest' + expected_test_tool_command = 'jest' expected_messages.append(expected_test_tool_command) diff --git a/pavelib/paver_tests/test_paver_bok_choy_cmds.py b/pavelib/paver_tests/test_paver_bok_choy_cmds.py index 07a9274809d2ab2ed244affe90d5cb5c02149e2e..12352f19c59b21750792293178ad527cdd5aa11a 100644 --- a/pavelib/paver_tests/test_paver_bok_choy_cmds.py +++ b/pavelib/paver_tests/test_paver_bok_choy_cmds.py @@ -6,12 +6,8 @@ Run just this test with: paver test_lib -t pavelib/paver_tests/test_paver_bok_ch import os import unittest -import six -if six.PY2: - from test.test_support import EnvironmentVarGuard -else: - from test.support import EnvironmentVarGuard # pylint: disable=import-error,no-name-in-module +from test.support import EnvironmentVarGuard from pavelib.utils.test.suites import BokChoyTestSuite @@ -53,7 +49,7 @@ class TestPaverBokChoyCmd(unittest.TestCase): return expected_statement def setUp(self): - super(TestPaverBokChoyCmd, self).setUp() + super().setUp() self.shard = os.environ.get('SHARD') self.env_var_override = EnvironmentVarGuard() @@ -147,7 +143,7 @@ class TestPaverBokChoyCmd(unittest.TestCase): repo_dir=REPO_DIR, shard_str='/shard_' + self.shard if self.shard else '', ), - u"-n {}".format(process_count), + "-n {}".format(process_count), "--color=no", "--verbose", ] @@ -164,7 +160,7 @@ class TestPaverBokChoyCmd(unittest.TestCase): repo_dir=REPO_DIR, shard_str='/shard_' + self.shard if self.shard else '', ), - u"-n {}".format(process_count), + "-n {}".format(process_count), "--color=no", "--verbose", ] diff --git a/pavelib/paver_tests/test_paver_quality.py b/pavelib/paver_tests/test_paver_quality.py index 9615990ccd5f52c278ab7689bd15915ff4de6922..b038f0fe2949c40fbfc7c1c23e956d43a2b89d45 100644 --- a/pavelib/paver_tests/test_paver_quality.py +++ b/pavelib/paver_tests/test_paver_quality.py @@ -9,7 +9,6 @@ import tempfile import textwrap import unittest -import six from ddt import data, ddt, file_data, unpack from mock import MagicMock, mock_open, patch from path import Path as path @@ -18,10 +17,7 @@ from paver.easy import BuildFailure import pavelib.quality from pavelib.paver_tests.utils import PaverTestCase, fail_on_eslint -if six.PY2: - OPEN_BUILTIN = '__builtin__.open' -else: - OPEN_BUILTIN = 'builtins.open' +OPEN_BUILTIN = 'builtins.open' @ddt @@ -30,7 +26,7 @@ class TestPaverQualityViolations(unittest.TestCase): For testing the paver violations-counting tasks """ def setUp(self): - super(TestPaverQualityViolations, self).setUp() + super().setUp() self.f = tempfile.NamedTemporaryFile(delete=False) self.f.close() self.addCleanup(os.remove, self.f.name) @@ -84,7 +80,7 @@ class TestPaverQualityOptions(unittest.TestCase): ) @unpack def test_pylint_parser_other_string(self, options, expected_values): - class PaverOptions(object): + class PaverOptions: """ Simple options class to mimick paver's Namespace object. """ @@ -102,7 +98,7 @@ class TestPaverReportViolationsCounts(unittest.TestCase): """ def setUp(self): - super(TestPaverReportViolationsCounts, self).setUp() + super().setUp() # Temporary file infrastructure self.f = tempfile.NamedTemporaryFile(delete=False) @@ -258,7 +254,7 @@ class TestPrepareReportDir(unittest.TestCase): """ def setUp(self): - super(TestPrepareReportDir, self).setUp() + super().setUp() self.test_dir = tempfile.mkdtemp() self.test_file = tempfile.NamedTemporaryFile(delete=False, dir=self.test_dir) self.addCleanup(os.removedirs, self.test_dir) @@ -280,7 +276,7 @@ class TestPaverRunQuality(PaverTestCase): """ def setUp(self): - super(TestPaverRunQuality, self).setUp() + super().setUp() # mock the @needs decorator to skip it patcher = patch('pavelib.quality.sh') @@ -325,7 +321,6 @@ class TestPaverRunQuality(PaverTestCase): with patch('pavelib.quality._get_pylint_violations', _mock_pylint_violations): with self.assertRaises(SystemExit): pavelib.quality.run_quality("") - self.assertRaises(BuildFailure) print(self._mock_paver_sh.mock_calls) # Test that pylint is called @@ -344,7 +339,6 @@ class TestPaverRunQuality(PaverTestCase): self._mock_paver_sh.side_effect = [Exception('unrecognized failure!'), 0] with self.assertRaises(SystemExit): pavelib.quality.run_quality("") - self.assertRaises(Exception) # Test that pylint is NOT called by counting calls self.assertEqual(self._mock_paver_sh.call_count, 1) @@ -357,3 +351,37 @@ class TestPaverRunQuality(PaverTestCase): # 1 for diff_quality for pylint # 1 for diff_quality for eslint self.assertEqual(self._mock_paver_sh.call_count, 8) + + +class TestPaverRunDiffQuality(PaverTestCase): + """ + For testing the paver run_diff_quality task + + Note: Although diff_quality is tested as part of quality, some + cases weren't tested properly. + """ + def setUp(self): + super().setUp() + + # mock the @needs decorator to skip it + patcher = patch('pavelib.quality.sh') + self._mock_paver_sh = patcher.start() + self.addCleanup(patcher.stop) + + @patch(OPEN_BUILTIN, mock_open()) + def test_percentage_failure(self): + """ + When diff_quality is run with a threshold percentage, it ends with an exit code of 1. + This bubbles up to paver with a subprocess return code error and should return False. + """ + self._mock_paver_sh.side_effect = [BuildFailure('Subprocess return code: 1')] + self.assertEqual(pavelib.quality.run_diff_quality(""), False) + + @patch(OPEN_BUILTIN, mock_open()) + def test_other_failures(self): + """ + Run diff_quality with an exception that is not a percentage failure. + """ + self._mock_paver_sh.side_effect = [BuildFailure('Some failure.')] + with self.assertRaisesRegex(BuildFailure, '.*Diff Quality Report.*Some failure.'): + pavelib.quality.run_diff_quality("") diff --git a/pavelib/paver_tests/test_pii_check.py b/pavelib/paver_tests/test_pii_check.py index 7fb1a8c26fc5e8395d03fa1b6a8201e386a889ec..3be3b26620d8b18a342a3dc9c1314ac1f98a6e6b 100644 --- a/pavelib/paver_tests/test_pii_check.py +++ b/pavelib/paver_tests/test_pii_check.py @@ -2,13 +2,10 @@ Tests for Paver's PII checker task. """ - -import io import shutil import tempfile import unittest -import six from mock import patch from path import Path as path from paver.easy import call_task, BuildFailure @@ -22,7 +19,7 @@ class TestPaverPIICheck(unittest.TestCase): For testing the paver run_pii_check task """ def setUp(self): - super(TestPaverPIICheck, self).setUp() + super().setUp() self.report_dir = path(tempfile.mkdtemp()) self.addCleanup(shutil.rmtree, self.report_dir) @@ -39,14 +36,14 @@ class TestPaverPIICheck(unittest.TestCase): lms_stdout_report.write_lines(['Coverage found 66 uncovered models:\n']) mock_needs.return_value = 0 - call_task('pavelib.quality.run_pii_check', options={"report_dir": six.text_type(self.report_dir)}) - mock_calls = [six.text_type(call) for call in mock_paver_sh.mock_calls] + call_task('pavelib.quality.run_pii_check', options={"report_dir": str(self.report_dir)}) + mock_calls = [str(call) for call in mock_paver_sh.mock_calls] assert len(mock_calls) == 2 assert any(['lms.envs.test' in call for call in mock_calls]) assert any(['cms.envs.test' in call for call in mock_calls]) - assert all([six.text_type(self.report_dir) in call for call in mock_calls]) + assert all([str(self.report_dir) in call for call in mock_calls]) metrics_file = Env.METRICS_DIR / 'pii' - assert io.open(metrics_file, 'r').read() == 'Number of PII Annotation violations: 66\n' + assert open(metrics_file, 'r').read() == 'Number of PII Annotation violations: 66\n' @patch.object(pavelib.quality.run_pii_check, 'needs') @patch('pavelib.quality.sh') @@ -65,12 +62,12 @@ class TestPaverPIICheck(unittest.TestCase): mock_needs.return_value = 0 with self.assertRaises(SystemExit): - call_task('pavelib.quality.run_pii_check', options={"report_dir": six.text_type(self.report_dir)}) + call_task('pavelib.quality.run_pii_check', options={"report_dir": str(self.report_dir)}) self.assertRaises(BuildFailure) - mock_calls = [six.text_type(call) for call in mock_paver_sh.mock_calls] + mock_calls = [str(call) for call in mock_paver_sh.mock_calls] assert len(mock_calls) == 2 assert any(['lms.envs.test' in call for call in mock_calls]) assert any(['cms.envs.test' in call for call in mock_calls]) - assert all([six.text_type(self.report_dir) in call for call in mock_calls]) + assert all([str(self.report_dir) in call for call in mock_calls]) metrics_file = Env.METRICS_DIR / 'pii' - assert io.open(metrics_file, 'r').read() == 'Number of PII Annotation violations: 66\n' + assert open(metrics_file, 'r').read() == 'Number of PII Annotation violations: 66\n' diff --git a/pavelib/paver_tests/test_prereqs.py b/pavelib/paver_tests/test_prereqs.py index 669ab6bed86229da94036fc7da6f051bd4c15e25..5f416a884c590c4dd7b3231772eccada3b067c78 100644 --- a/pavelib/paver_tests/test_prereqs.py +++ b/pavelib/paver_tests/test_prereqs.py @@ -32,7 +32,7 @@ class TestPaverPrereqInstall(unittest.TestCase): self.assertEqual( pavelib.prereqs.no_prereq_install(), expected_val, - u'NO_PREREQ_INSTALL is set to {}, but we read it as {}'.format( + 'NO_PREREQ_INSTALL is set to {}, but we read it as {}'.format( set_val, expected_val), ) @@ -83,7 +83,7 @@ class TestPaverNodeInstall(PaverTestCase): """ def setUp(self): - super(TestPaverNodeInstall, self).setUp() + super().setUp() # Ensure prereqs will be run os.environ['NO_PREREQ_INSTALL'] = 'false' diff --git a/pavelib/paver_tests/test_servers.py b/pavelib/paver_tests/test_servers.py index 8e94fd655f7a50f9f15c488e339219e1b6a483c0..fc3e3f8a680c6223f47c17ac6c6c263e033b6d21 100644 --- a/pavelib/paver_tests/test_servers.py +++ b/pavelib/paver_tests/test_servers.py @@ -8,54 +8,49 @@ from ..utils.envs import Env from .utils import PaverTestCase EXPECTED_SASS_COMMAND = ( - u"libsass {sass_directory}" + "libsass {sass_directory}" ) EXPECTED_COMMON_SASS_DIRECTORIES = [ - u"common/static/sass", + "common/static/sass", ] EXPECTED_LMS_SASS_DIRECTORIES = [ - u"lms/static/sass", - u"lms/static/certificates/sass", + "lms/static/sass", + "lms/static/certificates/sass", ] EXPECTED_CMS_SASS_DIRECTORIES = [ - u"cms/static/sass", + "cms/static/sass", ] EXPECTED_LMS_SASS_COMMAND = [ - u"python manage.py lms --settings={asset_settings} compile_sass lms ", + "python manage.py lms --settings={asset_settings} compile_sass lms ", ] EXPECTED_CMS_SASS_COMMAND = [ - u"python manage.py cms --settings={asset_settings} compile_sass cms ", + "python manage.py cms --settings={asset_settings} compile_sass cms ", ] EXPECTED_COLLECT_STATIC_COMMAND = ( - u'python manage.py {system} --settings={asset_settings} collectstatic ' - u'--ignore "fixtures" --ignore "karma_*.js" --ignore "spec" ' - u'--ignore "spec_helpers" --ignore "spec-helpers" --ignore "xmodule_js" ' - u'--ignore "geoip" --ignore "sass" ' - u'--noinput {log_string}' + 'python manage.py {system} --settings={asset_settings} collectstatic ' + '--ignore "fixtures" --ignore "karma_*.js" --ignore "spec" ' + '--ignore "spec_helpers" --ignore "spec-helpers" --ignore "xmodule_js" ' + '--ignore "geoip" --ignore "sass" ' + '--noinput {log_string}' ) EXPECTED_CELERY_COMMAND = ( - u"DJANGO_SETTINGS_MODULE=lms.envs.{settings} celery worker " - u"--app=lms.celery:APP --beat --loglevel=INFO --pythonpath=." + "DJANGO_SETTINGS_MODULE=lms.envs.{settings} celery worker " + "--app=lms.celery:APP --beat --loglevel=INFO --pythonpath=." ) EXPECTED_RUN_SERVER_COMMAND = ( - u"python manage.py {system} --settings={settings} runserver --traceback --pythonpath=. 0.0.0.0:{port}" + "python manage.py {system} --settings={settings} runserver --traceback --pythonpath=. 0.0.0.0:{port}" ) EXPECTED_INDEX_COURSE_COMMAND = ( - u"python manage.py {system} --settings={settings} reindex_course --setup" + "python manage.py {system} --settings={settings} reindex_course --setup" ) EXPECTED_PRINT_SETTINGS_COMMAND = [ - u"python manage.py lms --settings={settings} print_setting STATIC_ROOT 2>{log_file}", - u"python manage.py cms --settings={settings} print_setting STATIC_ROOT 2>{log_file}", - u"python manage.py lms --settings={settings} print_setting LMS_ROOT_URL 2>{log_file}", - u"python manage.py lms --settings={settings} print_setting JWT_AUTH 2>{log_file}", - u"python manage.py lms --settings={settings} print_setting EDXMKTG_USER_INFO_COOKIE_NAME 2>{log_file}", - u"python manage.py lms --settings={settings} print_setting WEBPACK_CONFIG_PATH 2>{log_file}" + "python manage.py lms --settings={settings} print_setting STATIC_ROOT 2>{log_file}", + "python manage.py cms --settings={settings} print_setting STATIC_ROOT 2>{log_file}", + "python manage.py lms --settings={settings} print_setting WEBPACK_CONFIG_PATH 2>{log_file}" ] EXPECTED_WEBPACK_COMMAND = ( - u"NODE_ENV={node_env} STATIC_ROOT_LMS={static_root_lms} STATIC_ROOT_CMS={static_root_cms} " - u"LMS_ROOT_URL={lms_root_url} JWT_AUTH_COOKIE_HEADER_PAYLOAD={jwt_auth_cookie_header_payload_name} " - u"EDXMKTG_USER_INFO_COOKIE_NAME={user_info_cookie_name} " - u"$(npm bin)/webpack --config={webpack_config_path}" + "NODE_ENV={node_env} STATIC_ROOT_LMS={static_root_lms} STATIC_ROOT_CMS={static_root_cms} " + "$(npm bin)/webpack --config={webpack_config_path}" ) @@ -174,7 +169,7 @@ class TestPaverServerTasks(PaverTestCase): settings = options.get("settings", Env.DEVSTACK_SETTINGS) call_task("pavelib.servers.update_db", options=options) # pylint: disable=line-too-long - db_command = u"NO_EDXAPP_SUDO=1 EDX_PLATFORM_SETTINGS_OVERRIDE={settings} /edx/bin/edxapp-migrate-{server} --traceback --pythonpath=. " + db_command = "NO_EDXAPP_SUDO=1 EDX_PLATFORM_SETTINGS_OVERRIDE={settings} /edx/bin/edxapp-migrate-{server} --traceback --pythonpath=. " self.assertEqual( self.task_messages, [ @@ -199,8 +194,8 @@ class TestPaverServerTasks(PaverTestCase): self.assertEqual( self.task_messages, [ - u"echo 'import {system}.envs.{settings}' " - u"| python manage.py {system} --settings={settings} shell --plain --pythonpath=.".format( + "echo 'import {system}.envs.{settings}' " + "| python manage.py {system} --settings={settings} shell --plain --pythonpath=.".format( system=system, settings=settings ), ] @@ -247,8 +242,8 @@ class TestPaverServerTasks(PaverTestCase): expected_asset_settings = "test_static_optimized" expected_collect_static = not is_fast and expected_settings != Env.DEVSTACK_SETTINGS if not is_fast: - expected_messages.append(u"xmodule_assets common/static/xmodule") - expected_messages.append(u"install npm_assets") + expected_messages.append("xmodule_assets common/static/xmodule") + expected_messages.append("install npm_assets") expected_messages.extend( [c.format(settings=expected_asset_settings, log_file=Env.PRINT_SETTINGS_LOG_FILE) for c in EXPECTED_PRINT_SETTINGS_COMMAND] @@ -257,9 +252,6 @@ class TestPaverServerTasks(PaverTestCase): node_env="production", static_root_lms=None, static_root_cms=None, - lms_root_url=None, - jwt_auth_cookie_header_payload_name=None, - user_info_cookie_name=None, webpack_config_path=None )) expected_messages.extend(self.expected_sass_commands(system=system, asset_settings=expected_asset_settings)) @@ -296,8 +288,8 @@ class TestPaverServerTasks(PaverTestCase): expected_collect_static = not is_fast and expected_settings != Env.DEVSTACK_SETTINGS expected_messages = [] if not is_fast: - expected_messages.append(u"xmodule_assets common/static/xmodule") - expected_messages.append(u"install npm_assets") + expected_messages.append("xmodule_assets common/static/xmodule") + expected_messages.append("install npm_assets") expected_messages.extend( [c.format(settings=expected_asset_settings, log_file=Env.PRINT_SETTINGS_LOG_FILE) for c in EXPECTED_PRINT_SETTINGS_COMMAND] @@ -306,9 +298,6 @@ class TestPaverServerTasks(PaverTestCase): node_env="production", static_root_lms=None, static_root_cms=None, - lms_root_url=None, - jwt_auth_cookie_header_payload_name=None, - user_info_cookie_name=None, webpack_config_path=None )) expected_messages.extend(self.expected_sass_commands(asset_settings=expected_asset_settings)) @@ -336,7 +325,7 @@ class TestPaverServerTasks(PaverTestCase): expected_messages.append(EXPECTED_CELERY_COMMAND.format(settings="devstack_with_worker")) self.assertEqual(self.task_messages, expected_messages) - def expected_sass_commands(self, system=None, asset_settings=u"test_static_optimized"): + def expected_sass_commands(self, system=None, asset_settings="test_static_optimized"): """ Returns the expected SASS commands for the specified system. """ diff --git a/pavelib/paver_tests/test_timer.py b/pavelib/paver_tests/test_timer.py index 753a66920fc6c1c0757d39e1f91952a35cd2ebe4..5304bfce6bd529f62b4572b9a2b3e97c4b03f33e 100644 --- a/pavelib/paver_tests/test_timer.py +++ b/pavelib/paver_tests/test_timer.py @@ -28,7 +28,7 @@ class TimedDecoratorTests(TestCase): Tests of the pavelib.utils.timer:timed decorator. """ def setUp(self): - super(TimedDecoratorTests, self).setUp() + super().setUp() patch_dumps = patch.object(timer.json, 'dump', autospec=True) self.mock_dump = patch_dumps.start() diff --git a/pavelib/paver_tests/test_utils.py b/pavelib/paver_tests/test_utils.py index f450cf0cd4a383804df1ec21754f8a90464f60bc..8323269db771a2827ae41b6576d50441b1516f25 100644 --- a/pavelib/paver_tests/test_utils.py +++ b/pavelib/paver_tests/test_utils.py @@ -20,7 +20,7 @@ class TestUtils(unittest.TestCase): @patch('subprocess.check_output') def test_firefox_version_ok(self, _mock_subprocesss): test_version = MINIMUM_FIREFOX_VERSION - _mock_subprocesss.return_value = u"Mozilla Firefox {version}".format( + _mock_subprocesss.return_value = "Mozilla Firefox {version}".format( version=str(test_version) ) # No exception should be raised @@ -29,7 +29,7 @@ class TestUtils(unittest.TestCase): @patch('subprocess.check_output') def test_firefox_version_below_expected(self, _mock_subprocesss): test_version = MINIMUM_FIREFOX_VERSION - 1 - _mock_subprocesss.return_value = u"Mozilla Firefox {version}".format( + _mock_subprocesss.return_value = "Mozilla Firefox {version}".format( version=test_version ) with self.assertRaises(Exception): diff --git a/pavelib/paver_tests/test_xsscommitlint.py b/pavelib/paver_tests/test_xsscommitlint.py index 4e504428aceffcb950b86d01494552176b3fe348..ca769f12893c1620c3a9820b00dcd287f267b12c 100644 --- a/pavelib/paver_tests/test_xsscommitlint.py +++ b/pavelib/paver_tests/test_xsscommitlint.py @@ -19,7 +19,7 @@ class PaverXSSCommitLintTest(PaverTestCase): """ def setUp(self): - super(PaverXSSCommitLintTest, self).setUp() + super().setUp() self.reset_task_messages() @patch.object(pavelib.quality, '_write_metric') diff --git a/pavelib/paver_tests/test_xsslint.py b/pavelib/paver_tests/test_xsslint.py index ded36433d6f307db5e28527052e4bf1b3c7acb2b..686004f9db47453bf90dbb438daaa4359b241b33 100644 --- a/pavelib/paver_tests/test_xsslint.py +++ b/pavelib/paver_tests/test_xsslint.py @@ -17,7 +17,7 @@ class PaverXSSLintTest(PaverTestCase): """ def setUp(self): - super(PaverXSSLintTest, self).setUp() + super().setUp() self.reset_task_messages() @patch.object(pavelib.quality, '_write_metric') diff --git a/pavelib/paver_tests/utils.py b/pavelib/paver_tests/utils.py index 3262917d5ce407fdb6e9fa303838f9fb60c857f9..8f7fb69eaaa683fd96e310cef642b19c5d2837d9 100644 --- a/pavelib/paver_tests/utils.py +++ b/pavelib/paver_tests/utils.py @@ -5,7 +5,6 @@ import os from unittest import TestCase from uuid import uuid4 -import six from paver import tasks from paver.easy import BuildFailure @@ -15,7 +14,7 @@ class PaverTestCase(TestCase): Base class for Paver test cases. """ def setUp(self): - super(PaverTestCase, self).setUp() + super().setUp() # Show full length diffs upon test failure self.maxDiff = None # pylint: disable=invalid-name @@ -27,7 +26,7 @@ class PaverTestCase(TestCase): os.environ['NO_PREREQ_INSTALL'] = 'true' def tearDown(self): - super(PaverTestCase, self).tearDown() + super().tearDown() tasks.environment = tasks.Environment() del os.environ['NO_PREREQ_INSTALL'] @@ -51,7 +50,7 @@ class MockEnvironment(tasks.Environment): Mock environment that collects information about Paver commands. """ def __init__(self): - super(MockEnvironment, self).__init__() + super().__init__() self.dry_run = True self.messages = [] @@ -62,7 +61,7 @@ class MockEnvironment(tasks.Environment): else: output = message if not output.startswith("--->"): - self.messages.append(six.text_type(output)) + self.messages.append(str(output)) def fail_on_eslint(*args, **kwargs): diff --git a/pavelib/prereqs.py b/pavelib/prereqs.py index 9a1b4ad9cc3141bfc7a3591680fa37f9ce85f0a9..f44da6eaa514b6f9a81cf8a383e00f3105b6f49d 100644 --- a/pavelib/prereqs.py +++ b/pavelib/prereqs.py @@ -4,16 +4,13 @@ Install Python and Node prerequisites. import hashlib -import io import os import re import subprocess import sys from distutils import sysconfig -import six from paver.easy import BuildFailure, sh, task -from six.moves import range from .utils.envs import Env from .utils.timer import timed @@ -84,7 +81,7 @@ def compute_fingerprint(path_list): # For files, hash the contents of the file if os.path.isfile(path_item): - with io.open(path_item, "rb") as file_handle: + with open(path_item, "rb") as file_handle: hasher.update(file_handle.read()) return hasher.hexdigest() @@ -103,7 +100,7 @@ def prereq_cache(cache_name, paths, install_func): cache_file_path = os.path.join(PREREQS_STATE_DIR, "{}.sha1".format(cache_filename)) old_hash = None if os.path.isfile(cache_file_path): - with io.open(cache_file_path, "r") as cache_file: + with open(cache_file_path, "r") as cache_file: old_hash = cache_file.read() # Compare the old hash to the new hash @@ -117,13 +114,13 @@ def prereq_cache(cache_name, paths, install_func): # If the code executed within the context fails (throws an exception), # then this step won't get executed. create_prereqs_cache_dir() - with io.open(cache_file_path, "wb") as cache_file: + with open(cache_file_path, "wb") as cache_file: # Since the pip requirement files are modified during the install # process, we need to store the hash generated AFTER the installation post_install_hash = compute_fingerprint(paths) cache_file.write(post_install_hash.encode('utf-8')) else: - print(u'{cache} unchanged, skipping...'.format(cache=cache_name)) + print('{cache} unchanged, skipping...'.format(cache=cache_name)) def node_prereqs_installation(): @@ -138,11 +135,9 @@ def node_prereqs_installation(): npm_log_file_path = '{}/npm-install.{}.log'.format(Env.GEN_LOG_DIR, shard_str) else: npm_log_file_path = '{}/npm-install.log'.format(Env.GEN_LOG_DIR) - npm_log_file = io.open(npm_log_file_path, 'wb') + npm_log_file = open(npm_log_file_path, 'wb') npm_command = 'npm install --verbose'.split() - cb_error_text = "Subprocess return code: 1" - # The implementation of Paver's `sh` function returns before the forked # actually returns. Using a Popen object so that we can ensure that # the forked process has returned @@ -156,7 +151,7 @@ def node_prereqs_installation(): proc = subprocess.Popen(npm_command, stderr=npm_log_file) retcode = proc.wait() if retcode == 1: - raise Exception("npm install failed") + raise Exception("npm install failed: See {}".format(npm_log_file_path)) print("Successfully installed NPM packages. Log found at {}".format( npm_log_file_path )) @@ -173,7 +168,7 @@ def python_prereqs_installation(): def pip_install_req_file(req_file): """Pip install the requirements file.""" pip_cmd = 'pip install -q --disable-pip-version-check --exists-action w' - sh(u"{pip_cmd} -r {req_file}".format(pip_cmd=pip_cmd, req_file=req_file)) + sh("{pip_cmd} -r {req_file}".format(pip_cmd=pip_cmd, req_file=req_file)) @task @@ -198,6 +193,7 @@ PACKAGES_TO_UNINSTALL = [ "django-storages", "django-oauth2-provider", # Because now it's called edx-django-oauth2-provider. "edx-oauth2-provider", # Because it moved from github to pypi + "enum34", # Because enum34 is not needed in python>3.4 "i18n-tools", # Because now it's called edx-i18n-tools "moto", # Because we no longer use it and it conflicts with recent jsondiff versions "python-saml", # Because python3-saml shares the same directory name @@ -232,7 +228,7 @@ def uninstall_python_packages(): create_prereqs_cache_dir() if os.path.isfile(state_file_path): - with io.open(state_file_path) as state_file: + with open(state_file_path) as state_file: version = state_file.read() if version == expected_version: print('Python uninstalls unchanged, skipping...') @@ -248,7 +244,7 @@ def uninstall_python_packages(): for package_name in PACKAGES_TO_UNINSTALL: if package_in_frozen(package_name, frozen): # Uninstall the pacakge - sh(u"pip uninstall --disable-pip-version-check -y {}".format(package_name)) + sh("pip uninstall --disable-pip-version-check -y {}".format(package_name)) uninstalled = True if not uninstalled: break @@ -258,7 +254,7 @@ def uninstall_python_packages(): return # Write our version. - with io.open(state_file_path, "wb") as state_file: + with open(state_file_path, "wb") as state_file: state_file.write(expected_version.encode('utf-8')) @@ -342,8 +338,7 @@ def install_prereqs(): def log_installed_python_prereqs(): """ Logs output of pip freeze for debugging. """ - sh(u"pip freeze > {}".format(Env.GEN_LOG_DIR + "/pip_freeze.log")) - return + sh("pip freeze > {}".format(Env.GEN_LOG_DIR + "/pip_freeze.log")) def print_devstack_warning(): diff --git a/pavelib/quality.py b/pavelib/quality.py index 9681e28a047d127c769896b0ce837d21517443b8..5ec402b78e6733f88dca7b6b74ab8f193d1ac31c 100644 --- a/pavelib/quality.py +++ b/pavelib/quality.py @@ -1,19 +1,13 @@ -# pylint: disable=unicode-format-string -# coding=utf-8 - """ Check code quality using pycodestyle, pylint, and diff_quality. """ - -import io import json import os import re from datetime import datetime from xml.sax.saxutils import quoteattr -import six from paver.easy import BuildFailure, cmdopts, needs, sh, task from openedx.core.djangolib.markup import HTML @@ -22,12 +16,12 @@ from .utils.envs import Env from .utils.timer import timed ALL_SYSTEMS = 'lms,cms,common,openedx,pavelib,scripts' -JUNIT_XML_TEMPLATE = u"""<?xml version="1.0" encoding="UTF-8"?> +JUNIT_XML_TEMPLATE = """<?xml version="1.0" encoding="UTF-8"?> <testsuite name="{name}" tests="1" errors="0" failures="{failure_count}" skip="0"> <testcase classname="pavelib.quality" name="{name}" time="{seconds}">{failure_element}</testcase> </testsuite> """ -JUNIT_XML_FAILURE_TEMPLATE = u'<failure message={message}/>' +JUNIT_XML_FAILURE_TEMPLATE = '<failure message={message}/>' START_TIME = datetime.utcnow() @@ -101,7 +95,7 @@ def find_fixme(options): apps_list = ' '.join(top_python_dirs(system)) cmd = ( - u"pylint --disable all --enable=fixme " + "pylint --disable all --enable=fixme " "--output-format=parseable {apps} " "> {report_dir}/pylint_fixme.report".format( apps=apps_list, @@ -143,7 +137,7 @@ def _get_pylint_violations(systems=ALL_SYSTEMS.split(','), errors_only=False, cl system_report = report_dir / 'pylint.report' if clean or not system_report.exists(): sh( - u"pylint {flags} --output-format=parseable {apps} " + "pylint {flags} --output-format=parseable {apps} " "> {report_dir}/pylint.report".format( flags=" ".join(flags), apps=apps_list, @@ -194,7 +188,7 @@ def run_pylint(options): if num_violations < lower_violations_limit > -1: fail_quality( result_name, - u"FAILURE: Too few pylint violations. " + "FAILURE: Too few pylint violations. " "Expected to see at least {lower_limit} pylint violations. " "Either pylint is not running correctly -or- " "the limits should be lowered and/or the lower limit should be removed.".format( @@ -206,7 +200,7 @@ def run_pylint(options): if num_violations > upper_violations_limit > -1: fail_quality( result_name, - u"FAILURE: Too many pylint violations. " + "FAILURE: Too many pylint violations. " "The limit is {upper_limit}.".format(upper_limit=upper_violations_limit) ) else: @@ -268,7 +262,7 @@ def _get_pep8_violations(clean=True): Env.METRICS_DIR.makedirs_p() if not report.exists(): - sh(u'pycodestyle . | tee {} -a'.format(report)) + sh('pycodestyle . | tee {} -a'.format(report)) violations_list = _pep8_violations(report) @@ -298,7 +292,7 @@ def run_pep8(options): # pylint: disable=unused-argument violations_list = ''.join(violations_list) # Print number of violations to log - violations_count_str = u"Number of PEP 8 violations: {count}".format(count=count) + violations_count_str = "Number of PEP 8 violations: {count}".format(count=count) print(violations_count_str) print(violations_list) @@ -334,7 +328,7 @@ def run_complexity(): print("--> Calculating cyclomatic complexity of python files...") try: sh( - u"radon cc {system_string} --total-average > {complexity_report}".format( + "radon cc {system_string} --total-average > {complexity_report}".format( system_string=system_string, complexity_report=complexity_report ) @@ -345,7 +339,7 @@ def run_complexity(): (Env.METRICS_DIR / "python_complexity") ) print("--> Python cyclomatic complexity report complete.") - print(u"radon cyclomatic complexity score: {metric}".format(metric=str(complexity_metric))) + print("radon cyclomatic complexity score: {metric}".format(metric=str(complexity_metric))) except BuildFailure: print("FAILURE: Unable to calculate python-only code-complexity.") @@ -372,7 +366,7 @@ def run_eslint(options): violations_limit = int(getattr(options, 'limit', -1)) sh( - u"nodejs --max_old_space_size=4096 node_modules/.bin/eslint " + "nodejs --max_old_space_size=4096 node_modules/.bin/eslint " "--ext .js --ext .jsx --format=compact . | tee {eslint_report}".format( eslint_report=eslint_report ), @@ -384,7 +378,7 @@ def run_eslint(options): except TypeError: fail_quality( 'eslint', - u"FAILURE: Number of eslint violations could not be found in {eslint_report}".format( + "FAILURE: Number of eslint violations could not be found in {eslint_report}".format( eslint_report=eslint_report ) ) @@ -396,7 +390,7 @@ def run_eslint(options): if num_violations > violations_limit > -1: fail_quality( 'eslint', - u"FAILURE: Too many eslint violations ({count}).\nThe limit is {violations_limit}.".format( + "FAILURE: Too many eslint violations ({count}).\nThe limit is {violations_limit}.".format( count=num_violations, violations_limit=violations_limit ) ) @@ -414,7 +408,7 @@ def _get_stylelint_violations(): formatter = 'node_modules/stylelint-formatter-pretty' sh( - u"stylelint **/*.scss --custom-formatter={formatter} | tee {stylelint_report}".format( + "stylelint **/*.scss --custom-formatter={formatter} | tee {stylelint_report}".format( formatter=formatter, stylelint_report=stylelint_report, ), @@ -426,7 +420,7 @@ def _get_stylelint_violations(): except TypeError: fail_quality( 'stylelint', - u"FAILURE: Number of stylelint violations could not be found in {stylelint_report}".format( + "FAILURE: Number of stylelint violations could not be found in {stylelint_report}".format( stylelint_report=stylelint_report ) ) @@ -453,7 +447,7 @@ def run_stylelint(options): if num_violations > violations_limit > -1: fail_quality( 'stylelint', - u"FAILURE: Stylelint failed with too many violations: ({count}).\nThe limit is {violations_limit}.".format( + "FAILURE: Stylelint failed with too many violations: ({count}).\nThe limit is {violations_limit}.".format( count=num_violations, violations_limit=violations_limit, ) @@ -496,7 +490,7 @@ def run_xsslint(options): _prepare_report_dir(xsslint_report_dir) sh( - u"{repo_root}/scripts/xsslint/{xsslint_script} --rule-totals --config={cfg_module} >> {xsslint_report}".format( + "{repo_root}/scripts/xsslint/{xsslint_script} --rule-totals --config={cfg_module} >> {xsslint_report}".format( repo_root=Env.REPO_ROOT, xsslint_script=xsslint_script, xsslint_report=xsslint_report, @@ -508,21 +502,21 @@ def run_xsslint(options): xsslint_counts = _get_xsslint_counts(xsslint_report) try: - metrics_str = u"Number of {xsslint_script} violations: {num_violations}\n".format( + metrics_str = "Number of {xsslint_script} violations: {num_violations}\n".format( xsslint_script=xsslint_script, num_violations=int(xsslint_counts['total']) ) if 'rules' in xsslint_counts and any(xsslint_counts['rules']): metrics_str += "\n" rule_keys = sorted(xsslint_counts['rules'].keys()) for rule in rule_keys: - metrics_str += u"{rule} violations: {count}\n".format( + metrics_str += "{rule} violations: {count}\n".format( rule=rule, count=int(xsslint_counts['rules'][rule]) ) except TypeError: fail_quality( 'xsslint', - u"FAILURE: Number of {xsslint_script} violations could not be found in {xsslint_report}".format( + "FAILURE: Number of {xsslint_script} violations could not be found in {xsslint_report}".format( xsslint_script=xsslint_script, xsslint_report=xsslint_report ) ) @@ -531,14 +525,14 @@ def run_xsslint(options): # Record the metric _write_metric(metrics_str, metrics_report) # Print number of violations to log. - sh(u"cat {metrics_report}".format(metrics_report=metrics_report), ignore_error=True) + sh("cat {metrics_report}".format(metrics_report=metrics_report), ignore_error=True) error_message = "" # Test total violations against threshold. if 'total' in list(violation_thresholds.keys()): if violation_thresholds['total'] < xsslint_counts['total']: - error_message = u"Too many violations total ({count}).\nThe limit is {violations_limit}.".format( + error_message = "Too many violations total ({count}).\nThe limit is {violations_limit}.".format( count=xsslint_counts['total'], violations_limit=violation_thresholds['total'] ) @@ -548,14 +542,14 @@ def run_xsslint(options): for threshold_key in threshold_keys: if threshold_key not in xsslint_counts['rules']: error_message += ( - u"\nNumber of {xsslint_script} violations for {rule} could not be found in " + "\nNumber of {xsslint_script} violations for {rule} could not be found in " "{xsslint_report}." ).format( xsslint_script=xsslint_script, rule=threshold_key, xsslint_report=xsslint_report ) elif violation_thresholds['rules'][threshold_key] < xsslint_counts['rules'][threshold_key]: error_message += \ - u"\nToo many {rule} violations ({count}).\nThe {rule} limit is {violations_limit}.".format( + "\nToo many {rule} violations ({count}).\nThe {rule} limit is {violations_limit}.".format( rule=threshold_key, count=xsslint_counts['rules'][threshold_key], violations_limit=violation_thresholds['rules'][threshold_key], ) @@ -563,7 +557,7 @@ def run_xsslint(options): if error_message: fail_quality( 'xsslint', - u"FAILURE: XSSLinter Failed.\n{error_message}\n" + "FAILURE: XSSLinter Failed.\n{error_message}\n" "See {xsslint_report} or run the following command to hone in on the problem:\n" " ./scripts/xss-commit-linter.sh -h".format( error_message=error_message, xsslint_report=xsslint_report @@ -586,7 +580,7 @@ def run_xsscommitlint(): _prepare_report_dir(xsscommitlint_report_dir) sh( - u"{repo_root}/scripts/{xsscommitlint_script} | tee {xsscommitlint_report}".format( + "{repo_root}/scripts/{xsscommitlint_script} | tee {xsscommitlint_report}".format( repo_root=Env.REPO_ROOT, xsscommitlint_script=xsscommitlint_script, xsscommitlint_report=xsscommitlint_report, @@ -601,13 +595,13 @@ def run_xsscommitlint(): except TypeError: fail_quality( 'xsscommitlint', - u"FAILURE: Number of {xsscommitlint_script} violations could not be found in {xsscommitlint_report}".format( + "FAILURE: Number of {xsscommitlint_script} violations could not be found in {xsscommitlint_report}".format( xsscommitlint_script=xsscommitlint_script, xsscommitlint_report=xsscommitlint_report ) ) # Print number of violations to log. - violations_count_str = u"Number of {xsscommitlint_script} violations: {num_violations}\n".format( + violations_count_str = "Number of {xsscommitlint_script} violations: {num_violations}\n".format( xsscommitlint_script=xsscommitlint_script, num_violations=num_violations ) @@ -615,10 +609,10 @@ def run_xsscommitlint(): metrics_report = (Env.METRICS_DIR / "xsscommitlint") _write_metric(violations_count_str, metrics_report) # Output report to console. - sh(u"cat {metrics_report}".format(metrics_report=metrics_report), ignore_error=True) + sh("cat {metrics_report}".format(metrics_report=metrics_report), ignore_error=True) if num_violations: fail_quality( - u'xsscommitlint', + 'xsscommitlint', "FAILURE: XSSCommitLinter Failed.\n{error_message}\n" "See {xsscommitlint_report} or run the following command to hone in on the problem:\n" " ./scripts/xss-commit-linter.sh -h".format( @@ -637,7 +631,7 @@ def _write_metric(metric, filename): Env.METRICS_DIR.makedirs_p() with open(filename, "w") as metric_file: - metric_file.write(six.text_type(metric)) + metric_file.write(str(metric)) def _prepare_report_dir(dir_name): @@ -663,16 +657,17 @@ def _get_report_contents(filename, report_name, last_line_only=False): """ if os.path.isfile(filename): - with open(filename, 'r') as report_file: + with open(filename) as report_file: if last_line_only: lines = report_file.readlines() for line in reversed(lines): if line != '\n': return line + return None else: return report_file.read() else: - file_not_found_message = u"FAILURE: The following log file could not be found: {file}".format(file=filename) + file_not_found_message = "FAILURE: The following log file could not be found: {file}".format(file=filename) fail_quality(report_name, file_not_found_message) @@ -681,7 +676,12 @@ def _get_count_from_last_line(filename, file_type): This will return the number in the last line of a file. It is returning only the value (as a floating number). """ - last_line = _get_report_contents(filename, file_type, last_line_only=True).strip() + report_contents = _get_report_contents(filename, file_type, last_line_only=True) + + if report_contents is None: + return 0 + + last_line = report_contents.strip() if file_type == "python_complexity": # Example of the last line of a complexity report: "Average complexity: A (1.93953443446)" @@ -774,7 +774,7 @@ def _extract_missing_pii_annotations(filename): uncovered_models = 0 pii_check_passed = True if os.path.isfile(filename): - with io.open(filename, 'r') as report_file: + with open(filename, 'r') as report_file: lines = report_file.readlines() # Find the count of uncovered models. @@ -796,7 +796,7 @@ def _extract_missing_pii_annotations(filename): # Each line in lines already contains a newline. full_log = ''.join(lines) else: - fail_quality('pii', u'FAILURE: Log file could not be found: {}'.format(filename)) + fail_quality('pii', 'FAILURE: Log file could not be found: {}'.format(filename)) return (uncovered_models, pii_check_passed, full_log) @@ -822,7 +822,7 @@ def run_pii_check(options): print() print("Running {} PII Annotation check and report".format(env_name)) print("-" * 45) - run_output_file = six.text_type(output_file).format(env_name.lower()) + run_output_file = str(output_file).format(env_name.lower()) sh( "mkdir -p {} && " "export DJANGO_SETTINGS_MODULE={}; " @@ -850,7 +850,7 @@ def run_pii_check(options): # Write metric file. if uncovered_count is None: uncovered_count = 0 - metrics_str = u"Number of PII Annotation violations: {}\n".format(uncovered_count) + metrics_str = "Number of PII Annotation violations: {}\n".format(uncovered_count) _write_metric(metrics_str, (Env.METRICS_DIR / pii_report_name)) # Finally, fail the paver task if code_annotations suggests that the check failed. @@ -928,20 +928,20 @@ def run_quality(options): if is_html: lines = ['<body>\n'] sep = '-------------<br/>\n' - title = HTML(u"<h1>Quality Report: {}</h1>\n").format(linter) + title = HTML("<h1>Quality Report: {}</h1>\n").format(linter) violations_bullets = ''.join( [HTML('<li>{violation}</li><br/>\n').format(violation=violation) for violation in violations_list] ) violations_str = HTML('<ul>\n{bullets}</ul>\n').format(bullets=HTML(violations_bullets)) - violations_count_str = HTML(u"<b>Violations</b>: {count}<br/>\n") - fail_line = HTML(u"<b>FAILURE</b>: {} count should be 0<br/>\n").format(linter) + violations_count_str = HTML("<b>Violations</b>: {count}<br/>\n") + fail_line = HTML("<b>FAILURE</b>: {} count should be 0<br/>\n").format(linter) else: lines = [] sep = '-------------\n' - title = u"Quality Report: {}\n".format(linter) + title = "Quality Report: {}\n".format(linter) violations_str = ''.join(violations_list) - violations_count_str = u"Violations: {count}\n" - fail_line = u"FAILURE: {} count should be {}\n".format(linter, limit) + violations_count_str = "Violations: {count}\n" + fail_line = "FAILURE: {} count should be {}\n".format(linter, limit) violations_count_str = violations_count_str.format(count=count) @@ -968,19 +968,19 @@ def run_quality(options): # ----- Set up for diff-quality pylint call ----- # Set the string to be used for the diff-quality --compare-branch switch. - compare_branch = getattr(options, 'compare_branch', u'origin/master') - compare_commit = sh(u'git merge-base HEAD {}'.format(compare_branch), capture=True).strip() + compare_branch = getattr(options, 'compare_branch', 'origin/master') + compare_commit = sh('git merge-base HEAD {}'.format(compare_branch), capture=True).strip() if sh('git rev-parse HEAD', capture=True).strip() != compare_commit: - compare_branch_string = u'--compare-branch={0}'.format(compare_commit) + compare_branch_string = '--compare-branch={}'.format(compare_commit) # Set the string, if needed, to be used for the diff-quality --fail-under switch. diff_threshold = int(getattr(options, 'percentage', -1)) - percentage_string = u'' + percentage_string = '' if diff_threshold > -1: - percentage_string = u'--fail-under={0}'.format(diff_threshold) + percentage_string = '--fail-under={}'.format(diff_threshold) pylint_files = get_violations_reports("pylint") - pylint_reports = u' '.join(pylint_files) + pylint_reports = ' '.join(pylint_files) if not run_diff_quality( violations_type="pylint", reports=pylint_reports, @@ -992,7 +992,7 @@ def run_quality(options): failure_reasons.append('Pylint violation(s) were found in the lines of code that were added or changed.') eslint_files = get_violations_reports("eslint") - eslint_reports = u' '.join(eslint_files) + eslint_reports = ' '.join(eslint_files) if not run_diff_quality( violations_type="eslint", reports=eslint_reports, @@ -1021,7 +1021,7 @@ def run_diff_quality( """ try: sh( - u"diff-quality --violations={type} " + "diff-quality --violations={type} " "{reports} {percentage_string} {compare_branch_string} " "--html-report {dquality_dir}/diff_quality_{type}.html ".format( type=violations_type, @@ -1032,11 +1032,14 @@ def run_diff_quality( ) ) return True - except BuildFailure as error_message: - if is_percentage_failure(error_message): + except BuildFailure as failure: + if is_percentage_failure(failure.args): return False else: - fail_quality('diff_quality', 'FAILURE: {}'.format(error_message)) + fail_quality( + 'diff_quality', + 'FAILURE: See "Diff Quality Report" in Jenkins left-sidebar for details. {}'.format(failure) + ) def is_percentage_failure(error_message): diff --git a/pavelib/servers.py b/pavelib/servers.py index c6c58a0c41f5273689e3072c64b3a3d7d430aa87..cac521b72ef66b3d778be6070f03e466d3ef4d09 100644 --- a/pavelib/servers.py +++ b/pavelib/servers.py @@ -259,7 +259,7 @@ def update_db(options): fake = "--fake-initial" if getattr(options, 'fake_initial', False) else "" for system in ('lms', 'cms'): # pylint: disable=line-too-long - sh(u"NO_EDXAPP_SUDO=1 EDX_PLATFORM_SETTINGS_OVERRIDE={settings} /edx/bin/edxapp-migrate-{system} --traceback --pythonpath=. {fake}".format( + sh("NO_EDXAPP_SUDO=1 EDX_PLATFORM_SETTINGS_OVERRIDE={settings} /edx/bin/edxapp-migrate-{system} --traceback --pythonpath=. {fake}".format( settings=settings, system=system, fake=fake)) @@ -282,9 +282,9 @@ def check_settings(args): settings = args.settings[0] try: - import_cmd = u"echo 'import {system}.envs.{settings}'".format(system=system, settings=settings) + import_cmd = "echo 'import {system}.envs.{settings}'".format(system=system, settings=settings) django_shell_cmd = django_cmd(system, settings, 'shell', '--plain', '--pythonpath=.') - sh(u"{import_cmd} | {shell_cmd}".format(import_cmd=import_cmd, shell_cmd=django_shell_cmd)) + sh("{import_cmd} | {shell_cmd}".format(import_cmd=import_cmd, shell_cmd=django_shell_cmd)) except: # pylint: disable=bare-except print("Failed to import settings", file=sys.stderr) diff --git a/pavelib/tests.py b/pavelib/tests.py index 04fb0bacc9c32a9ecfd362419077a74dcec33bd3..3ff7e1e5a067293813151cfbd81d3a04922d780c 100644 --- a/pavelib/tests.py +++ b/pavelib/tests.py @@ -337,7 +337,7 @@ def coverage(options): if not combined_report_file.isfile(): # This may be that the coverage files were generated using -p, # try to combine them to the one file that we need. - sh(u"coverage combine --rcfile={}".format(rcfile)) + sh("coverage combine --rcfile={}".format(rcfile)) if not os.path.getsize(combined_report_file) > 50: # Check if the .coverage data file is larger than the base file, @@ -352,9 +352,9 @@ def coverage(options): return # Generate the coverage.py XML report - sh(u"coverage xml --rcfile={}".format(rcfile)) + sh("coverage xml --rcfile={}".format(rcfile)) # Generate the coverage.py HTML report - sh(u"coverage html --rcfile={}".format(rcfile)) + sh("coverage html --rcfile={}".format(rcfile)) diff_coverage() # pylint: disable=no-value-for-parameter @@ -390,8 +390,8 @@ def diff_coverage(options): # Generate the diff coverage reports (HTML and console) sh( - u"diff-cover {xml_report_str} --compare-branch={compare_branch} " - u"--html-report {diff_html_path}".format( + "diff-cover {xml_report_str} --compare-branch={compare_branch} " + "--html-report {diff_html_path}".format( xml_report_str=xml_report_str, compare_branch=compare_branch, diff_html_path=diff_html_path, diff --git a/pavelib/utils/db_utils.py b/pavelib/utils/db_utils.py index 7861b77f420e2def2c0fd5e3e59291f4078934b9..cddca04b0efd88e96cbcccee378f20bff39b0e08 100644 --- a/pavelib/utils/db_utils.py +++ b/pavelib/utils/db_utils.py @@ -25,9 +25,9 @@ def remove_files_from_folder(files, folder): file_with_path = os.path.join(folder, file_name) try: os.remove(file_with_path) - print(u'\tRemoved {}'.format(file_with_path)) + print('\tRemoved {}'.format(file_with_path)) except OSError: - print(u'\tCould not remove {}. Continuing.'.format(file_with_path)) + print('\tCould not remove {}. Continuing.'.format(file_with_path)) continue @@ -41,9 +41,9 @@ def reset_test_db(db_cache_files, update_cache_files=True, use_existing_db=False """ cmd = '{}/scripts/reset-test-db.sh'.format(Env.REPO_ROOT) if update_cache_files: - cmd = u'{} --rebuild_cache'.format(cmd) + cmd = '{} --rebuild_cache'.format(cmd) if use_existing_db: - cmd = u'{} --use-existing-db'.format(cmd) + cmd = '{} --use-existing-db'.format(cmd) sh(cmd) verify_files_exist(db_cache_files) @@ -78,7 +78,7 @@ def fingerprint_bokchoy_db_files(migration_output_files, all_db_files): msg = "Computing the fingerprint." print(msg) fingerprint = compute_fingerprint(file_paths) - print(u"The fingerprint for bokchoy db files is: {}".format(fingerprint)) + print("The fingerprint for bokchoy db files is: {}".format(fingerprint)) return fingerprint @@ -101,7 +101,7 @@ def verify_files_exist(files): for file_name in files: file_path = os.path.join(CACHE_FOLDER, file_name) if not os.path.isfile(file_path): - msg = u"Did not find expected file: {}".format(file_path) + msg = "Did not find expected file: {}".format(file_path) raise BuildFailure(msg) @@ -113,7 +113,7 @@ def calculate_bokchoy_migrations(migration_output_files): NOTE: the script first clears out the database, then calculates what migrations need to be run, which is all of them. """ - sh(u'{}/scripts/reset-test-db.sh --calculate_migrations'.format(Env.REPO_ROOT)) + sh('{}/scripts/reset-test-db.sh --calculate_migrations'.format(Env.REPO_ROOT)) verify_files_exist(migration_output_files) @@ -137,7 +137,7 @@ def is_fingerprint_in_bucket(fingerprint, bucket_name): conn = boto.connect_s3(anon=True) bucket = conn.get_bucket(bucket_name) except Exception as e: # pylint: disable=broad-except - print(u"Exception caught trying to reach S3 bucket {}: {}".format(bucket_name, e)) + print("Exception caught trying to reach S3 bucket {}: {}".format(bucket_name, e)) return False key = boto.s3.key.Key(bucket=bucket, name=zipfile_name) return key.exists() @@ -148,9 +148,9 @@ def get_bokchoy_db_fingerprint_from_file(): Return the value recorded in the fingerprint file. """ try: - with open(FINGERPRINT_FILEPATH, 'r') as fingerprint_file: + with open(FINGERPRINT_FILEPATH) as fingerprint_file: cached_fingerprint = fingerprint_file.read().strip() - except IOError: + except OSError: return None return cached_fingerprint @@ -159,12 +159,12 @@ def get_file_from_s3(bucket_name, zipfile_name, path): """ Get the file from s3 and save it to disk. """ - print(u"Retrieving {} from bucket {}.".format(zipfile_name, bucket_name)) + print("Retrieving {} from bucket {}.".format(zipfile_name, bucket_name)) conn = boto.connect_s3(anon=True) bucket = conn.get_bucket(bucket_name) key = boto.s3.key.Key(bucket=bucket, name=zipfile_name) if not key.exists(): - msg = u"Did not find expected file {} in the S3 bucket {}".format( + msg = "Did not find expected file {} in the S3 bucket {}".format( zipfile_name, bucket_name ) raise BuildFailure(msg) @@ -215,7 +215,7 @@ def upload_to_s3(file_name, file_path, bucket_name, replace=False): """ Upload the specified files to an s3 bucket. """ - print(u"Uploading {} to s3 bucket {}".format(file_name, bucket_name)) + print("Uploading {} to s3 bucket {}".format(file_name, bucket_name)) try: conn = boto.connect_s3() except boto.exception.NoAuthHandlerFound: @@ -231,9 +231,9 @@ def upload_to_s3(file_name, file_path, bucket_name, replace=False): key = boto.s3.key.Key(bucket=bucket, name=file_name) bytes_written = key.set_contents_from_filename(file_path, replace=replace, policy='public-read') if bytes_written: - msg = u"Wrote {} bytes to {}.".format(bytes_written, key.name) + msg = "Wrote {} bytes to {}.".format(bytes_written, key.name) else: - msg = u"File {} already existed in bucket {}.".format(key.name, bucket_name) + msg = "File {} already existed in bucket {}.".format(key.name, bucket_name) print(msg) diff --git a/pavelib/utils/envs.py b/pavelib/utils/envs.py index 54e371bb0aaa9bcc7cecb57121cee1618644dfda..56e78aa8441888607c9a051b3ed97a4ce3f8af6c 100644 --- a/pavelib/utils/envs.py +++ b/pavelib/utils/envs.py @@ -2,16 +2,12 @@ Helper functions for loading environment settings. """ - -import io import json import os -import re import sys from time import sleep import memcache -import six from lazy import lazy from path import Path as path from paver.easy import BuildFailure, sh @@ -37,7 +33,7 @@ def repo_root(): absolute_path = file_path.abspath() break except OSError: - print(u'Attempt {}/180 to get an absolute path failed'.format(attempt)) + print('Attempt {}/180 to get an absolute path failed'.format(attempt)) if attempt < 180: attempt += 1 sleep(1) @@ -47,7 +43,7 @@ def repo_root(): return absolute_path.parent.parent.parent -class Env(object): +class Env: """ Load information about the execution environment. """ @@ -258,39 +254,20 @@ class Env(object): django_cmd( system, settings, - u"print_setting {django_setting} 2>{log_file}".format( + "print_setting {django_setting} 2>{log_file}".format( django_setting=django_setting, log_file=cls.PRINT_SETTINGS_LOG_FILE ) ), capture=True ) - return six.text_type(value).strip() + return str(value).strip() except BuildFailure: - print(u"Unable to print the value of the {} setting:".format(django_setting)) - with io.open(cls.PRINT_SETTINGS_LOG_FILE, 'r') as f: + print("Unable to print the value of the {} setting:".format(django_setting)) + with open(cls.PRINT_SETTINGS_LOG_FILE, 'r') as f: print(f.read()) sys.exit(1) - @classmethod - def get_nested_django_setting(cls, django_setting, nested_django_setting, system, settings=None): - """ - Interrogate Django environment for specific nested settings values - :param django_setting: the root django setting to get - :param nested_django_setting: the nested django setting to get - :param system: the django app to use when asking for the setting (lms | cms) - :param settings: the settings file to use when asking for the value - :return: unicode value of the django setting - """ - django_setting_value = cls.get_django_setting(django_setting, system, settings) - pattern = re.compile( - u"[\"']{setting}[\"']: [\"'](?P<setting_value>.*?)[\"']".format(setting=nested_django_setting) - ) - match = pattern.search(django_setting_value) - if match: - return match.group('setting_value') - return None - @classmethod def covered_modules(cls): """ @@ -326,8 +303,8 @@ class Env(object): env_path = env_path.parent.parent / env_path.basename() if not env_path.isfile(): print( - u"Warning: could not find environment JSON file " - "at '{path}'".format(path=env_path), # pylint: disable=unicode-format-string + "Warning: could not find environment JSON file " + "at '{path}'".format(path=env_path), file=sys.stderr, ) return dict() @@ -339,8 +316,8 @@ class Env(object): except ValueError: print( - u"Error: Could not parse JSON " - "in {path}".format(path=env_path), # pylint: disable=unicode-format-string + "Error: Could not parse JSON " + "in {path}".format(path=env_path), file=sys.stderr, ) sys.exit(1) diff --git a/pavelib/utils/passthrough_opts.py b/pavelib/utils/passthrough_opts.py index 0a8491c0786f16d398181acf0dff92c285a15b3d..9ae2917a71524d1d5196d3a78b97bfd2f80961c6 100644 --- a/pavelib/utils/passthrough_opts.py +++ b/pavelib/utils/passthrough_opts.py @@ -59,9 +59,9 @@ class PassthroughOptionParser(OptionParser): if len(rargs) < nargs: if nargs == 1: - self.error(u"%s option requires an argument" % opt) + self.error("%s option requires an argument" % opt) else: - self.error(u"%s option requires %d arguments" + self.error("%s option requires %d arguments" % (opt, nargs)) elif nargs == 1: value = rargs.pop(0) @@ -70,7 +70,7 @@ class PassthroughOptionParser(OptionParser): del rargs[0:nargs] elif had_explicit_value: - self.error(u"%s option does not take a value" % opt) + self.error("%s option does not take a value" % opt) else: value = None @@ -104,9 +104,9 @@ class PassthroughOptionParser(OptionParser): nargs = option.nargs if len(rargs) < nargs: if nargs == 1: - self.error(u"%s option requires an argument" % opt) + self.error("%s option requires an argument" % opt) else: - self.error(u"%s option requires %d arguments" + self.error("%s option requires %d arguments" % (opt, nargs)) elif nargs == 1: @@ -136,11 +136,11 @@ class PassthroughTask(paver.tasks.Task): @property def parser(self): with patch.object(paver.tasks.optparse, 'OptionParser', PassthroughOptionParser): - return super(PassthroughTask, self).parser + return super().parser def __call__(self, *args, **kwargs): paver.tasks.environment.passthrough_options = self._parser.passthrough_options # pylint: disable=no-member try: - return super(PassthroughTask, self).__call__(*args, **kwargs) + return super().__call__(*args, **kwargs) finally: del paver.tasks.environment.passthrough_options diff --git a/pavelib/utils/process.py b/pavelib/utils/process.py index 95868b3daad56f90b5cc0ab7a14fa7640c4e9d8b..69d2e5e5646d91205bf46f2678df14d505e0caf2 100644 --- a/pavelib/utils/process.py +++ b/pavelib/utils/process.py @@ -69,7 +69,7 @@ def run_multi_processes(cmd_list, out_log=None, err_log=None): # pylint: disable=broad-except except Exception as err: - print(u"Error running process {}".format(err), file=sys.stderr) + print("Error running process {}".format(err), file=sys.stderr) finally: for pid in pids: diff --git a/pavelib/utils/test/bokchoy_utils.py b/pavelib/utils/test/bokchoy_utils.py index 299d7c4f8559ce991929ed931a07776989b58070..76f130c3b9e11b4dbd6cbb7f903ea3222284a211 100644 --- a/pavelib/utils/test/bokchoy_utils.py +++ b/pavelib/utils/test/bokchoy_utils.py @@ -41,16 +41,16 @@ def start_servers(options): print(cmd, logfile) run_background_process(cmd, out_log=logfile, err_log=logfile, cwd=cwd) - for service, info in six.iteritems(Env.BOK_CHOY_SERVERS): + for service, info in Env.BOK_CHOY_SERVERS.items(): address = "0.0.0.0:{}".format(info['port']) - cmd = (u"DEFAULT_STORE={default_store} ").format(default_store=options.default_store) + cmd = ("DEFAULT_STORE={default_store} ").format(default_store=options.default_store) if coveragerc: - cmd += (u"coverage run --rcfile={coveragerc} -m ").format(coveragerc=coveragerc) + cmd += ("coverage run --rcfile={coveragerc} -m ").format(coveragerc=coveragerc) else: cmd += "python -m " cmd += ( - u"manage {service} --settings {settings} runserver " - u"{address} --traceback --noreload".format( + "manage {service} --settings {settings} runserver " + "{address} --traceback --noreload".format( service=service, settings=Env.SETTINGS, address=address, @@ -58,9 +58,9 @@ def start_servers(options): ) start_server(cmd, info['log']) - for service, info in six.iteritems(Env.BOK_CHOY_STUBS): + for service, info in Env.BOK_CHOY_STUBS.items(): cmd = ( - u"python -m stubs.start {service} {port} " + "python -m stubs.start {service} {port} " "{config}".format( service=service, port=info['port'], @@ -75,7 +75,7 @@ def wait_for_server(server, port): Wait for a server to respond with status 200 """ print( - u"Checking server {server} on port {port}".format( + "Checking server {server} on port {port}".format( server=server, port=port, ) @@ -110,12 +110,12 @@ def wait_for_test_servers(): Wait until we get a successful response from the servers or time out """ - for service, info in six.iteritems(Env.BOK_CHOY_SERVERS): + for service, info in Env.BOK_CHOY_SERVERS.items(): ready = wait_for_server(info['host'], info['port']) if not ready: msg = colorize( "red", - u"Could not contact {} test server".format(service) + "Could not contact {} test server".format(service) ) print(msg) sys.exit(1) @@ -127,7 +127,7 @@ def is_mongo_running(): """ # The mongo command will connect to the service, # failing with a non-zero exit code if it cannot connect. - output = os.popen(u'mongo --host {} --eval "print(\'running\')"'.format(Env.MONGO_HOST)).read() + output = os.popen('mongo --host {} --eval "print(\'running\')"'.format(Env.MONGO_HOST)).read() return output and "running" in output @@ -159,7 +159,7 @@ def clear_mongo(): Clears mongo database. """ sh( - u"mongo --host {} {} --eval 'db.dropDatabase()' > /dev/null".format( + "mongo --host {} {} --eval 'db.dropDatabase()' > /dev/null".format( Env.MONGO_HOST, Env.BOK_CHOY_MONGO_DATABASE, ) diff --git a/pavelib/utils/test/suites/bokchoy_suite.py b/pavelib/utils/test/suites/bokchoy_suite.py index 5ca9c97e22377d752a5ce48aea79878dd97cb07d..e80e9b9a91c18d0e4f54afcbc5e96b9297267b7f 100644 --- a/pavelib/utils/test/suites/bokchoy_suite.py +++ b/pavelib/utils/test/suites/bokchoy_suite.py @@ -1,4 +1,3 @@ -# pylint: disable=unicode-format-string """ Class used for defining and running Bok Choy acceptance test suite """ @@ -44,7 +43,7 @@ def load_bok_choy_data(options): """ print('Loading data from json fixtures in db_fixtures directory') sh( - u"DEFAULT_STORE={default_store}" + "DEFAULT_STORE={default_store}" " ./manage.py lms --settings {settings} loaddata --traceback" " common/test/db_fixtures/*.json".format( default_store=options.default_store, @@ -69,11 +68,11 @@ def load_courses(options): `test_root/courses/`. """ if 'imports_dir' in options: - msg = colorize('green', u"Importing courses from {}...".format(options.imports_dir)) + msg = colorize('green', "Importing courses from {}...".format(options.imports_dir)) print(msg) sh( - u"DEFAULT_STORE={default_store}" + "DEFAULT_STORE={default_store}" " ./manage.py cms --settings={settings} import {import_dir}".format( default_store=options.default_store, import_dir=options.imports_dir, @@ -96,7 +95,7 @@ def update_fixtures(): print(msg) sh( - u" ./manage.py lms --settings={settings} update_fixtures".format( + " ./manage.py lms --settings={settings} update_fixtures".format( settings=Env.SETTINGS ) ) @@ -160,7 +159,7 @@ class BokChoyTestSuite(TestSuite): See pytest documentation: https://docs.pytest.org/en/latest/ """ def __init__(self, *args, **kwargs): - super(BokChoyTestSuite, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.test_dir = Env.BOK_CHOY_DIR / kwargs.get('test_dir', 'tests') self.log_dir = Env.BOK_CHOY_LOG_DIR self.report_dir = kwargs.get('report_dir', Env.BOK_CHOY_REPORT_DIR) @@ -183,7 +182,7 @@ class BokChoyTestSuite(TestSuite): self.save_screenshots = kwargs.get('save_screenshots', False) def __enter__(self): - super(BokChoyTestSuite, self).__enter__() + super().__enter__() # Ensure that we have a directory to put logs and reports self.log_dir.makedirs_p() @@ -230,7 +229,7 @@ class BokChoyTestSuite(TestSuite): self.run_servers_continuously() def __exit__(self, exc_type, exc_value, traceback): - super(BokChoyTestSuite, self).__exit__(exc_type, exc_value, traceback) + super().__exit__(exc_type, exc_value, traceback) # Using testsonly will leave all fixtures in place (Note: the db will also be dirtier.) if self.testsonly: @@ -240,7 +239,7 @@ class BokChoyTestSuite(TestSuite): # Clean up data we created in the databases msg = colorize('green', "Cleaning up databases...") print(msg) - sh(u"./manage.py lms --settings {settings} flush --traceback --noinput".format(settings=Env.SETTINGS)) + sh("./manage.py lms --settings {settings} flush --traceback --noinput".format(settings=Env.SETTINGS)) clear_mongo() @property @@ -253,7 +252,7 @@ class BokChoyTestSuite(TestSuite): if self.num_processes != 1: # Construct "multiprocess" pytest command command += [ - u"-n {}".format(self.num_processes), + "-n {}".format(self.num_processes), "--color=no", ] if self.verbosity < 1: @@ -261,7 +260,7 @@ class BokChoyTestSuite(TestSuite): elif self.verbosity > 1: command.append("--verbose") if self.eval_attr: - command.append(u"-a '{}'".format(self.eval_attr)) + command.append("-a '{}'".format(self.eval_attr)) return command diff --git a/pavelib/utils/test/suites/js_suite.py b/pavelib/utils/test/suites/js_suite.py index d050668c0f933c67c1ed43ec0b5a77692ce27b52..bdb741b835a3658fed1d4b44aeff969c30cbddc1 100644 --- a/pavelib/utils/test/suites/js_suite.py +++ b/pavelib/utils/test/suites/js_suite.py @@ -18,7 +18,7 @@ class JsTestSuite(TestSuite): A class for running JavaScript tests. """ def __init__(self, *args, **kwargs): - super(JsTestSuite, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.run_under_coverage = kwargs.get('with_coverage', True) self.mode = kwargs.get('mode', 'run') self.report_dir = Env.JS_REPORT_DIR @@ -28,7 +28,7 @@ class JsTestSuite(TestSuite): self.subsuites = self._default_subsuites if suite == 'all' else [JsTestSubSuite(*args, **kwargs)] def __enter__(self): - super(JsTestSuite, self).__enter__() + super().__enter__() if tasks.environment.dry_run: tasks.environment.info("make report_dir") else: @@ -55,7 +55,7 @@ class JsTestSubSuite(TestSuite): common-requirejs and xmodule """ def __init__(self, *args, **kwargs): - super(JsTestSubSuite, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.test_id = args[0] self.run_under_coverage = kwargs.get('with_coverage', True) self.mode = kwargs.get('mode', 'run') diff --git a/pavelib/utils/test/suites/pytest_suite.py b/pavelib/utils/test/suites/pytest_suite.py index 1e96ec2ec27fc6919dd75690df7cfeb482b71d04..dcf215dcc0ce6cd0fc386ecbb4fc93bd73f05636 100644 --- a/pavelib/utils/test/suites/pytest_suite.py +++ b/pavelib/utils/test/suites/pytest_suite.py @@ -1,4 +1,3 @@ -# pylint: disable=unicode-format-string """ Classes used for defining and running pytest test suites """ @@ -21,7 +20,7 @@ class PytestSuite(TestSuite): to pytest tests """ def __init__(self, *args, **kwargs): - super(PytestSuite, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.failed_only = kwargs.get('failed_only', False) self.fail_fast = kwargs.get('fail_fast', False) self.run_under_coverage = kwargs.get('with_coverage', True) @@ -51,14 +50,14 @@ class PytestSuite(TestSuite): self.with_wtw = kwargs.get('with_wtw', False) def __enter__(self): - super(PytestSuite, self).__enter__() + super().__enter__() self.report_dir.makedirs_p() def __exit__(self, exc_type, exc_value, traceback): """ Cleans mongo afer the tests run. """ - super(PytestSuite, self).__exit__(exc_type, exc_value, traceback) + super().__exit__(exc_type, exc_value, traceback) test_utils.clean_mongo() def _under_coverage_cmd(self, cmd): @@ -122,11 +121,11 @@ class SystemTestSuite(PytestSuite): TestSuite for lms and cms python unit tests """ def __init__(self, *args, **kwargs): - super(SystemTestSuite, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.eval_attr = kwargs.get('eval_attr', None) self.test_id = kwargs.get('test_id', self._default_test_id) self.fasttest = kwargs.get('fasttest', False) - + self.disable_migrations = kwargs.get('disable_migrations', True) self.processes = kwargs.get('processes', None) self.randomize = kwargs.get('randomize', None) self.settings = kwargs.get('settings', Env.TEST_SETTINGS) @@ -168,10 +167,16 @@ class SystemTestSuite(PytestSuite): if self.verbosity < 1: cmd.append("--quiet") elif self.verbosity > 1: - cmd.append("--verbose") + # currently only two verbosity settings are supported, so using `-vvv` + # in place of `--verbose`, because it is needed to see migrations. + cmd.append("-vvv") if self.disable_capture: cmd.append("-s") + + if not self.disable_migrations: + cmd.append("--migrations") + if self.xdist_ip_addresses: cmd.append('--dist=loadscope') if self.processes <= 0: @@ -180,28 +185,28 @@ class SystemTestSuite(PytestSuite): xdist_remote_processes = self.processes for ip in self.xdist_ip_addresses.split(','): # Propogate necessary env vars to xdist containers - env_var_cmd = u'export DJANGO_SETTINGS_MODULE={} DISABLE_COURSEENROLLMENT_HISTORY={} PYTHONHASHSEED=0'\ + env_var_cmd = 'export DJANGO_SETTINGS_MODULE={} DISABLE_COURSEENROLLMENT_HISTORY={} PYTHONHASHSEED=0'\ .format('{}.envs.{}'.format(self.root, self.settings), self.disable_courseenrollment_history) - xdist_string = u'--tx {}*ssh="jenkins@{} -o StrictHostKeyChecking=no"' \ + xdist_string = '--tx {}*ssh="jenkins@{} -o StrictHostKeyChecking=no"' \ '//python="source edx-venv-{}/edx-venv/bin/activate; {}; python"' \ '//chdir="edx-platform"' \ .format(xdist_remote_processes, ip, Env.PYTHON_VERSION, env_var_cmd) cmd.append(xdist_string) for rsync_dir in Env.rsync_dirs(): - cmd.append(u'--rsyncdir {}'.format(rsync_dir)) + cmd.append('--rsyncdir {}'.format(rsync_dir)) else: if self.processes == -1: cmd.append('-n auto') cmd.append('--dist=loadscope') elif self.processes != 0: - cmd.append(u'-n {}'.format(self.processes)) + cmd.append('-n {}'.format(self.processes)) cmd.append('--dist=loadscope') if not self.randomize: cmd.append('-p no:randomly') if self.eval_attr: - cmd.append(u"-a '{}'".format(self.eval_attr)) + cmd.append("-a '{}'".format(self.eval_attr)) cmd.extend(self.passthrough_options) cmd.append(self.test_id) @@ -258,7 +263,7 @@ class LibTestSuite(PytestSuite): TestSuite for edx-platform/common/lib python unit tests """ def __init__(self, *args, **kwargs): - super(LibTestSuite, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.append_coverage = kwargs.get('append_coverage', False) self.test_id = kwargs.get('test_id', self.root) self.eval_attr = kwargs.get('eval_attr', None) @@ -289,7 +294,9 @@ class LibTestSuite(PytestSuite): if self.verbosity < 1: cmd.append("--quiet") elif self.verbosity > 1: - cmd.append("--verbose") + # currently only two verbosity settings are supported, so using `-vvv` + # in place of `--verbose`, because it is needed to see migrations. + cmd.append("-vvv") if self.disable_capture: cmd.append("-s") @@ -306,16 +313,16 @@ class LibTestSuite(PytestSuite): else: django_env_var_cmd = "export DJANGO_SETTINGS_MODULE='openedx.tests.settings'" - env_var_cmd = u'{} DISABLE_COURSEENROLLMENT_HISTORY={}' \ + env_var_cmd = '{} DISABLE_COURSEENROLLMENT_HISTORY={}' \ .format(django_env_var_cmd, self.disable_courseenrollment_history) - xdist_string = u'--tx {}*ssh="jenkins@{} -o StrictHostKeyChecking=no"' \ + xdist_string = '--tx {}*ssh="jenkins@{} -o StrictHostKeyChecking=no"' \ '//python="source edx-venv-{}/edx-venv/bin/activate; {}; python"' \ '//chdir="edx-platform"' \ .format(xdist_remote_processes, ip, Env.PYTHON_VERSION, env_var_cmd) cmd.append(xdist_string) for rsync_dir in Env.rsync_dirs(): - cmd.append(u'--rsyncdir {}'.format(rsync_dir)) + cmd.append('--rsyncdir {}'.format(rsync_dir)) # "--rsyncdir" throws off the configuration root, set it explicitly if 'common/lib' in self.test_id: cmd.append('--rootdir=common/lib') @@ -327,13 +334,13 @@ class LibTestSuite(PytestSuite): cmd.append('-n auto') cmd.append('--dist=loadscope') elif self.processes != 0: - cmd.append(u'-n {}'.format(self.processes)) + cmd.append('-n {}'.format(self.processes)) cmd.append('--dist=loadscope') if not self.randomize: cmd.append("-p no:randomly") if self.eval_attr: - cmd.append(u"-a '{}'".format(self.eval_attr)) + cmd.append("-a '{}'".format(self.eval_attr)) cmd.append(self.test_id) diff --git a/pavelib/utils/test/suites/python_suite.py b/pavelib/utils/test/suites/python_suite.py index bcd4b0c716c30e814e3170e10b3b6a1db6831e8b..f1944251a34073a3d9c86fdee6f5d02e9fdd0d5b 100644 --- a/pavelib/utils/test/suites/python_suite.py +++ b/pavelib/utils/test/suites/python_suite.py @@ -18,14 +18,14 @@ class PythonTestSuite(TestSuite): A subclass of TestSuite with extra setup for python tests """ def __init__(self, *args, **kwargs): - super(PythonTestSuite, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.opts = kwargs self.disable_migrations = kwargs.get('disable_migrations', True) self.fasttest = kwargs.get('fasttest', False) self.subsuites = kwargs.get('subsuites', self._default_subsuites) def __enter__(self): - super(PythonTestSuite, self).__enter__() + super().__enter__() if self.disable_migrations: os.environ['DISABLE_MIGRATIONS'] = '1' diff --git a/pavelib/utils/test/suites/suite.py b/pavelib/utils/test/suites/suite.py index c343074a3776c479240bbb04915712903777d5ca..0ca243bb5e01cd7e742dd6a14d1c91ec4dd3a21f 100644 --- a/pavelib/utils/test/suites/suite.py +++ b/pavelib/utils/test/suites/suite.py @@ -1,4 +1,3 @@ -# pylint: disable=unicode-format-string """ A class used for defining and running test suites """ @@ -20,7 +19,7 @@ except ImportError: __test__ = False # do not collect -class TestSuite(object): +class TestSuite: """ TestSuite is a class that defines how groups of tests run. """ @@ -42,7 +41,7 @@ class TestSuite(object): i.e. Checking for and defining required directories. """ - print(u"\nSetting up for {suite_name}".format(suite_name=self.root)) + print("\nSetting up for {suite_name}".format(suite_name=self.root)) self.failed_suites = [] def __exit__(self, exc_type, exc_value, traceback): @@ -55,7 +54,7 @@ class TestSuite(object): i.e. Cleaning mongo after the lms tests run. """ - print(u"\nCleaning up after {suite_name}".format(suite_name=self.root)) + print("\nCleaning up after {suite_name}".format(suite_name=self.root)) @property def cmd(self): @@ -128,10 +127,10 @@ class TestSuite(object): Writes a list of failed_suites to sys.stderr """ if self.failed_suites: - msg = colorize('red', u"\n\n{bar}\nTests failed in the following suites:\n* ".format(bar="=" * 48)) + msg = colorize('red', "\n\n{bar}\nTests failed in the following suites:\n* ".format(bar="=" * 48)) msg += colorize('red', '\n* '.join([s.root for s in self.failed_suites]) + '\n\n') else: - msg = colorize('green', u"\n\n{bar}\nNo test failures ".format(bar="=" * 48)) + msg = colorize('green', "\n\n{bar}\nNo test failures ".format(bar="=" * 48)) print(msg) diff --git a/pavelib/utils/test/utils.py b/pavelib/utils/test/utils.py index 5cb543670da06697e7595f4a1bc5c710b32013ff..ea537f827e45129f8160f2d2825285381aa861e6 100644 --- a/pavelib/utils/test/utils.py +++ b/pavelib/utils/test/utils.py @@ -7,7 +7,6 @@ import os import re import subprocess -import six from paver.easy import cmdopts, sh, task from pavelib.utils.envs import Env @@ -41,7 +40,7 @@ def clean_test_files(): # This find command removes all the *.pyc files that aren't in the .git # directory. See this blog post for more details: # http://nedbatchelder.com/blog/201505/be_careful_deleting_files_around_git.html - sh(r"find . -name '.git' -prune -o -name '*.pyc' -exec rm {} \;") # pylint: disable=unicode-format-string + sh(r"find . -name '.git' -prune -o -name '*.pyc' -exec rm {} \;") sh("rm -rf test_root/log/auto_screenshots/*") sh("rm -rf /tmp/mako_[cl]ms") @@ -64,7 +63,7 @@ def clean_dir(directory): """ # We delete the files but preserve the directory structure # so that coverage.py has a place to put the reports. - sh(u'find {dir} -type f -delete'.format(dir=directory)) + sh('find {dir} -type f -delete'.format(dir=directory)) @task @@ -93,7 +92,7 @@ def clean_mongo(): """ Clean mongo test databases """ - sh(u"mongo {host}:{port} {repo_root}/scripts/delete-mongo-test-dbs.js".format( + sh("mongo {host}:{port} {repo_root}/scripts/delete-mongo-test-dbs.js".format( host=Env.MONGO_HOST, port=MONGO_PORT_NUM, repo_root=Env.REPO_ROOT, @@ -120,10 +119,10 @@ def check_firefox_version(): driver.close() if firefox_ver < MINIMUM_FIREFOX_VERSION: raise Exception( - u'Required firefox version not found.\n' - u'Expected: {expected_version}; Actual: {actual_version}.\n\n' - u'Make sure that the edx.devstack.firefox container is up-to-date and running\n' - u'\t{expected_version}'.format( + 'Required firefox version not found.\n' + 'Expected: {expected_version}; Actual: {actual_version}.\n\n' + 'Make sure that the edx.devstack.firefox container is up-to-date and running\n' + '\t{expected_version}'.format( actual_version=firefox_ver, expected_version=MINIMUM_FIREFOX_VERSION ) @@ -133,7 +132,7 @@ def check_firefox_version(): # Firefox will be run as a local process expected_firefox_ver = "Mozilla Firefox " + str(MINIMUM_FIREFOX_VERSION) firefox_ver_string = subprocess.check_output("firefox --version", shell=True).strip() - if isinstance(firefox_ver_string, six.binary_type): + if isinstance(firefox_ver_string, bytes): firefox_ver_string = firefox_ver_string.decode('utf-8') firefox_version_regex = re.compile(r"Mozilla Firefox (\d+.\d+)") try: @@ -143,8 +142,8 @@ def check_firefox_version(): if firefox_ver < MINIMUM_FIREFOX_VERSION: raise Exception( - u'Required firefox version not found.\n' - u'Expected: {expected_version}; Actual: {actual_version}.'.format( + 'Required firefox version not found.\n' + 'Expected: {expected_version}; Actual: {actual_version}.'.format( actual_version=firefox_ver, expected_version=expected_firefox_ver ) @@ -166,7 +165,7 @@ def fetch_coverage_test_selection_data(options): except OSError: pass # Directory already exists - sh(u'git diff $(git merge-base {} HEAD) > {}/{}'.format( + sh('git diff $(git merge-base {} HEAD) > {}/{}'.format( getattr(options, 'compare_branch', 'origin/master'), COVERAGE_CACHE_BASEPATH, WHO_TESTS_WHAT_DIFF diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 0459b5f303a2abb363a216c6242d4c757820ce82..eb055e639c614999feff32ee57e10120403fb38a 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -13,22 +13,35 @@ # (although it is advertised in the changelog as 3.1.26.) celery>=3.1.25,<4.0.0 +# Constrain until https://github.com/datadriventests/ddt/issues/83 is fixed. +ddt<1.4.0 + # Stay on the latest LTS release of Django Django<2.3 +# 0.6.0 has a missing dependency declaration on ua-parser: https://github.com/jotes/django-cookies-samesite/issues/25 +# 0.6.1 throws on some requests from iOS app: https://github.com/jotes/django-cookies-samesite/issues/28 +django-cookies-samesite<0.6.0 + # The CORS_ORIGIN_WHITELIST changes in a backwards incompatible way in 3.0.0, needs matching configuration repo changes django-cors-headers<3.0.0 # It seems like django-countries > 5.5 may cause performance issues for us. django-countries==5.5 +# 2.0.0 dropped support for Python 3.5 +django-pipeline<2.0.0 + +# 1.0.0 currently causes an AttributeError that is under investigation: https://github.com/django-ses/django-ses/issues/186 +django-ses==0.8.14 + # django-storages version 1.9 drops support for boto storage backend. django-storages<1.9 -# Support was dropped for Python 3.5, Django 2.0, Django 2.1, DRF 3.7 +# Support was dropped for Python 3.5 drf-yasg<1.17.1 -# Not properly supporting latest changing of drf-jwt +# drf-jwt 1.15.0 contains a migration that breaks on MySQL: https://github.com/Styria-Digital/django-rest-framework-jwt/issues/40 drf-jwt==1.14.0 # Upgrading to 2.12.0 breaks several test classes due to API changes, need to update our code accordingly @@ -43,12 +56,19 @@ httpretty<1.0 # 4.0.0 dropped support for Python 3.5 inflect<4.0.0 +# 0.15.0 dropped support for Python 3.5 +joblib<0.15.0 + # jsonfield2 3.1.0 drops support for python 3.5 jsonfield2<3.1.0 # kiwisolver 1.2.0 requires Python 3.6+ kiwisolver<1.2.0 +# 4.5.1 introduced a bug when used together with xmlsec: https://bugs.launchpad.net/lxml/+bug/1880251 +# Tests passed, but hit a problem in stage +lxml<4.5.1 + # Convert text markup to HTML; used in capa problems, forums, and course wikis; pin Markdown version as tests failed for its upgrade to the latest release Markdown==2.6.11 @@ -61,9 +81,6 @@ mock<4.0.0 # oauthlib>3.0.1 causes test failures oauthlib==3.0.1 -# Version 0.23.0 requires python-dateutil>=2.5.0 -pandas==0.22.0 - # path 13.2.0 drops support for Python 3.5 path<13.2.0 @@ -80,12 +97,14 @@ pytest-django<3.9.0 # Upgrading to 2.5.3 on 2020-01-03 triggered "'tzlocal' object has no attribute '_std_offset'" errors in production python-dateutil==2.4.0 -# transifex-client 0.13.5 and 0.13.6 needlessly pin six and urllib3, 0.13.7 does so for python-slugify -# https://github.com/transifex/transifex-client/issues/252 -transifex-client==0.13.4 +# stevedore 2.0.0 requires python >= 3.6 +stevedore<2.0.0 # Constraint from astroid 2.3.3 wrapt==1.11.* # zipp 2.0.0 requires Python >= 3.6 zipp==1.0.0 + +# Matplotlib 3.1 requires Python 3.6 +matplotlib<3.1 diff --git a/requirements/edx-sandbox/base.in b/requirements/edx-sandbox/base.in index 3c3cd8f375c51066cb4b33ee32abdb5a59e08c99..5eb09df1968892ef4f3e94045965219fdc86e5c1 100644 --- a/requirements/edx-sandbox/base.in +++ b/requirements/edx-sandbox/base.in @@ -16,14 +16,14 @@ -c ../constraints.txt -r shared.txt # Dependencies in common with LMS and Studio +chem # A helper library for chemistry calculations matplotlib==2.2.4 # 2D plotting library -numpy==1.7.2 # Numeric array processing utilities; used by scipy +numpy==1.16.5 # Numeric array processing utilities; used by scipy pyparsing==2.2.0 # Python Parsing module random2 # Implementation of random module that works identically under Python 2 and 3 -scipy==0.14.0 # Math, science, and engineering library -sympy==0.7.1 # Symbolic math library +scipy==1.2.1 # Math, science, and engineering library +sympy==1.4 # Symbolic math library git+https://github.com/edx/openedx-calc.git@e9b698c85ad1152002bc0868f475f153dce88952#egg=calc==0.4 -git+https://github.com/edx/openedx-chem.git@ff4e3a03d3c7610e47a9af08eb648d8aabe2eb18#egg=chem==1.0.0 # Install these packages from the edx-platform working tree # NOTE: if you change code in these packages, you MUST change the version diff --git a/requirements/edx-sandbox/base.txt b/requirements/edx-sandbox/base.txt index f3ebfe4835f2f628481b5ebd5ccfc50be5cca913..74a6a6accb87bf0f864b63199e15e019afcb5c3f 100644 --- a/requirements/edx-sandbox/base.txt +++ b/requirements/edx-sandbox/base.txt @@ -15,7 +15,6 @@ cffi==1.13.2 git+https://github.com/edx/openedx-chem.git@ff4e3a03d3c7610e47a9af08eb648d8aabe2eb18#egg=chem==1.0.0 cryptography==2.8 cycler==0.10.0 # via matplotlib -enum34==1.1.6 ipaddress==1.0.23 kiwisolver==1.1.0 # via matplotlib lxml==3.8.0 diff --git a/requirements/edx-sandbox/py35.in b/requirements/edx-sandbox/py35.in index c900ed2f798f4b34b74f50e2650b125101f6ccf0..13782a933ef8fddda19393c6ed7f92b97ce15547 100644 --- a/requirements/edx-sandbox/py35.in +++ b/requirements/edx-sandbox/py35.in @@ -15,15 +15,15 @@ -c ../constraints.txt -r shared.txt # Dependencies in common with LMS and Studio +chem matplotlib==2.2.4 # 2D plotting library networkx==2.2 # Utilities for creating, manipulating, and studying network graphs numpy==1.16.5 # Numeric array processing utilities; used by scipy +openedx-calc pyparsing==2.2.0 # Python Parsing module random2 # Implementation of random module that works identically under Python 2 and 3 scipy==1.2.1 # Math, science, and engineering library sympy==1.4 # Symbolic math library -git+https://github.com/edx/openedx-calc.git@e9b698c85ad1152002bc0868f475f153dce88952#egg=calc==0.4 -git+https://github.com/edx/openedx-chem.git@ff4e3a03d3c7610e47a9af08eb648d8aabe2eb18#egg=chem==1.0.0 # Install these packages from the edx-platform working tree # NOTE: if you change code in these packages, you MUST change the version diff --git a/requirements/edx-sandbox/py35.txt b/requirements/edx-sandbox/py35.txt index dc9c202ac46074243788312d5c027040dcbae04e..b9b2f229437abc887d6635e2d8e7ec1ff36ffa6d 100644 --- a/requirements/edx-sandbox/py35.txt +++ b/requirements/edx-sandbox/py35.txt @@ -6,32 +6,32 @@ # common/lib/sandbox-packages # via -r requirements/edx-sandbox/py35.in common/lib/symmath # via -r requirements/edx-sandbox/py35.in -git+https://github.com/edx/openedx-calc.git@e9b698c85ad1152002bc0868f475f153dce88952#egg=calc==0.4 # via -r requirements/edx-sandbox/py35.in cffi==1.14.0 # via -r requirements/edx-sandbox/shared.txt, cryptography -git+https://github.com/edx/openedx-chem.git@ff4e3a03d3c7610e47a9af08eb648d8aabe2eb18#egg=chem==1.0.0 # via -r requirements/edx-sandbox/py35.in -click==7.1.1 # via -r requirements/edx-sandbox/shared.txt, nltk -cryptography==2.9 # via -r requirements/edx-sandbox/shared.txt +chem==1.2.0 # via -r requirements/edx-sandbox/py35.in +click==7.1.2 # via -r requirements/edx-sandbox/shared.txt, nltk +cryptography==2.9.2 # via -r requirements/edx-sandbox/shared.txt cycler==0.10.0 # via matplotlib decorator==4.4.2 # via networkx -joblib==0.14.1 # via -r requirements/edx-sandbox/shared.txt, nltk +joblib==0.14.1 # via -c requirements/edx-sandbox/../constraints.txt, -r requirements/edx-sandbox/shared.txt, nltk kiwisolver==1.1.0 # via -c requirements/edx-sandbox/../constraints.txt, matplotlib -lxml==4.5.0 # via -r requirements/edx-sandbox/shared.txt +lxml==4.5.0 # via -c requirements/edx-sandbox/../constraints.txt, -r requirements/edx-sandbox/shared.txt markupsafe==1.1.1 # via chem matplotlib==2.2.4 # via -c requirements/edx-sandbox/../constraints.txt, -r requirements/edx-sandbox/py35.in mpmath==1.1.0 # via sympy networkx==2.2 # via -r requirements/edx-sandbox/py35.in nltk==3.5 # via -r requirements/edx-sandbox/shared.txt, chem -numpy==1.16.5 # via -r requirements/edx-sandbox/py35.in, calc, chem, matplotlib, scipy +numpy==1.16.5 # via -r requirements/edx-sandbox/py35.in, chem, matplotlib, openedx-calc, scipy +openedx-calc==1.0.9 # via -r requirements/edx-sandbox/py35.in pycparser==2.20 # via -r requirements/edx-sandbox/shared.txt, cffi -pyparsing==2.2.0 # via -r requirements/edx-sandbox/py35.in, calc, chem, matplotlib +pyparsing==2.2.0 # via -r requirements/edx-sandbox/py35.in, chem, matplotlib, openedx-calc python-dateutil==2.4.0 # via -c requirements/edx-sandbox/../constraints.txt, matplotlib -pytz==2019.3 # via matplotlib +pytz==2020.1 # via matplotlib random2==1.0.1 # via -r requirements/edx-sandbox/py35.in -regex==2020.4.4 # via -r requirements/edx-sandbox/shared.txt, nltk -scipy==1.2.1 # via -r requirements/edx-sandbox/py35.in, calc, chem -six==1.14.0 # via -r requirements/edx-sandbox/shared.txt, calc, cryptography, cycler, matplotlib, python-dateutil +regex==2020.6.8 # via -r requirements/edx-sandbox/shared.txt, nltk +scipy==1.2.1 # via -r requirements/edx-sandbox/py35.in, chem, openedx-calc +six==1.15.0 # via -r requirements/edx-sandbox/shared.txt, chem, cryptography, cycler, matplotlib, openedx-calc, python-dateutil sympy==1.4 # via -r requirements/edx-sandbox/py35.in, symmath -tqdm==4.45.0 # via -r requirements/edx-sandbox/shared.txt, nltk +tqdm==4.46.1 # via -r requirements/edx-sandbox/shared.txt, nltk # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/requirements/edx-sandbox/shared.txt b/requirements/edx-sandbox/shared.txt index bd66d5226d1334a1e666846d753b45e0e3c1ecfb..9b7a259baf51d6c79aa8025553697515ff29ddb0 100644 --- a/requirements/edx-sandbox/shared.txt +++ b/requirements/edx-sandbox/shared.txt @@ -5,12 +5,12 @@ # make upgrade # cffi==1.14.0 # via cryptography -click==7.1.1 # via nltk -cryptography==2.9 # via -r requirements/edx-sandbox/shared.in -joblib==0.14.1 # via nltk -lxml==4.5.0 # via -r requirements/edx-sandbox/shared.in +click==7.1.2 # via nltk +cryptography==2.9.2 # via -r requirements/edx-sandbox/shared.in +joblib==0.14.1 # via -c requirements/edx-sandbox/../constraints.txt, nltk +lxml==4.5.0 # via -c requirements/edx-sandbox/../constraints.txt, -r requirements/edx-sandbox/shared.in nltk==3.5 # via -r requirements/edx-sandbox/shared.in pycparser==2.20 # via cffi -regex==2020.4.4 # via nltk -six==1.14.0 # via cryptography -tqdm==4.45.0 # via nltk +regex==2020.6.8 # via nltk +six==1.15.0 # via cryptography +tqdm==4.46.1 # via nltk diff --git a/requirements/edx/base.in b/requirements/edx/base.in index f11888d0d8c52d7e4fab6a0b3d139ec04e87c59f..d263a126223dabb1a9576630f88e3b37cd46d378 100644 --- a/requirements/edx/base.in +++ b/requirements/edx/base.in @@ -33,11 +33,16 @@ bleach # Allowed-list-based HTML sanitizing library boto==2.39.0 # Deprecated version of the AWS SDK; we should stop using this boto3==1.4.8 # Amazon Web Services SDK for Python botocore==1.8.17 # via boto3, s3transfer +bridgekeeper # Used for determining permissions for courseware. celery # Asynchronous task execution library +chem # A helper library for chemistry calculations contextlib2 # We need contextlib2.ExitStack so we can stop using contextlib.nested which doesn't exist in python 3 +crowdsourcehinter-xblock defusedxml Django # Web application framework +django-appconf django-celery # Only used for the CacheBackend for celery results +django-cookies-samesite # Middleware which allows SameSite=None flag for session and csrf cookies in Django<3.0.5 django-config-models>=1.0.0 # Configuration models for Django allowing config management with auditing django-cors-headers # Used to allow to configure CORS headers for cross-domain requests django-countries # Country data for Django forms and model fields @@ -45,6 +50,7 @@ django-crum # Middleware that stores the current request django-fernet-fields # via edx-enterprise (should be added to its setup.py) django-filter # Allows users to filter Django querysets dynamically django-ipware # Get the client's real IP address +django-method-override # Allow use of HTTP methods normally not supported by browsers via the X-HTTP-Method-Override header django-model-utils django-mptt django-mysql @@ -60,7 +66,7 @@ django-splash django-statici18n django-storages django-user-tasks -django-waffle==0.18.0 +django-waffle django-webpack-loader # Used to wire webpack bundles into the django asset pipeline djangorestframework==3.9.4 edx-ace @@ -98,15 +104,17 @@ icalendar # .ics generator, used by calendar_sync ipaddress # Ip network support for Embargo feature jsonfield2 # Django model field for validated JSON; used in several apps laboratory # Library for testing that code refactors/infrastructure changes produce identical results +lti-consumer-xblock mailsnake # Needed for mailchimp (mailing djangoapp) -mako==1.0.2 # Primary template language used for server-side page rendering +mako # Primary template language used for server-side page rendering Markdown # Convert text markup to HTML; used in capa problems, forums, and course wikis -mongoengine==0.10.0 # Object-document mapper for MongoDB, used in the LMS dashboard +mongoengine # Object-document mapper for MongoDB, used in the LMS dashboard mysqlclient # Driver for the default production relational database newrelic # New Relic agent for performance monitoring nodeenv # Utility for managing Node.js environments; we use this for deployments and testing oauthlib # OAuth specification support for authenticating via LTI or other Open edX services openedx-calc # Library supporting mathematical calculations for Open edX +ora2 pdfminer.six # Used in shoppingcart for extracting/parsing pdf text piexif # Exif image metadata manipulation, used in the profile_images app Pillow # Image manipulation library; used for course assets, profile images, invoice PDFs, etc. @@ -140,6 +148,8 @@ simplejson sailthru-client==2.2.3 # For Sailthru integration Shapely # Geometry library, used for image click regions in capa six # Utilities for supporting Python 2 & 3 in the same codebase +social-auth-app-django +sorl-thumbnail sortedcontainers # Provides SortedKeyList, used for lists of XBlock assets sqlparse # Required by Django to run migrations.RunSQL stevedore # Support for runtime plugins, used for XBlocks and edx-platform Django app plugins @@ -151,3 +161,5 @@ web-fragments # Provides the ability to render fragments o XBlock # Courseware component architecture xblock-utils # Provides utilities used by the Discussion XBlock xss-utils # https://github.com/edx/edx-platform/pull/20633 Fix XSS via Translations +enmerkar-underscore # Implements a underscore extractor for django-babel. + diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index e069b18e31df0dd411e374bc3102a6166e5342ca..62ffc868914b803c937a9b72d008514ccd888d8e 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -9,14 +9,12 @@ -e git+https://github.com/edx/codejail.git@4127fc4bd5775cc72aee8d7f0a70e31405e22439#egg=codejail # via -r requirements/edx/github.in -e git+https://github.com/jsocol/django-ratelimit.git@72edbe8949fbf6699848e5847645a1998f121d46#egg=ratelimit # via -r requirements/edx/github.in -e git+https://github.com/edx/django-wiki.git@0.0.27#egg=django-wiki # via -r requirements/edx/github.in --e git+https://github.com/edx/DoneXBlock.git@2.0.1#egg=done-xblock # via -r requirements/edx/github.in +-e git+https://github.com/edx/DoneXBlock.git@2.0.2#egg=done-xblock # via -r requirements/edx/github.in -e git+https://github.com/jazkarta/edx-jsme.git@690dbf75441fa91c7c4899df0b83d77f7deb5458#egg=edx-jsme # via -r requirements/edx/github.in -e . # via -r requirements/edx/local.in --e git+https://github.com/dementrock/pystache_custom.git@776973740bdaad83a3b029f96e415a7d1e8bec2f#egg=pystache_custom-dev # via -r requirements/edx/github.in -e git+https://github.com/edx/RateXBlock.git@2.0#egg=rate-xblock # via -r requirements/edx/github.in -e common/lib/safe_lxml # via -r requirements/edx/local.in -e common/lib/sandbox-packages # via -r requirements/edx/local.in --e git+https://github.com/python-social-auth/social-app-django.git@c00d23c2b45c3317bd35b15ad1b959338689cef8#egg=social-auth-app-django # via -r requirements/edx/github.in -e common/lib/symmath # via -r requirements/edx/local.in -e openedx/core/lib/xblock_builtin/xblock_discussion # via -r requirements/edx/local.in -e git+https://github.com/edx-solutions/xblock-google-drive.git@2d176468e33c0713c911b563f8f65f7cf232f5b6#egg=xblock-google-drive # via -r requirements/edx/github.in @@ -25,192 +23,189 @@ amqp==1.4.9 # via kombu analytics-python==1.2.9 # via -r requirements/edx/base.in aniso8601==8.0.0 # via edx-tincan-py35 anyjson==0.3.3 # via kombu -appdirs==1.4.3 # via fs +appdirs==1.4.4 # via fs attrs==19.3.0 # via -r requirements/edx/base.in, edx-ace -babel==2.8.0 # via -r requirements/edx/base.in, django-babel, django-babel-underscore -beautifulsoup4==4.9.0 # via pynliner +babel==2.8.0 # via -r requirements/edx/base.in, enmerkar, enmerkar-underscore +beautifulsoup4==4.9.1 # via pynliner billiard==3.3.0.23 # via celery -bleach==3.1.4 # via -r requirements/edx/base.in, edx-enterprise, lti-consumer-xblock, ora2 +bleach==3.1.5 # via -r requirements/edx/base.in, edx-enterprise, lti-consumer-xblock, ora2 boto3==1.4.8 # via -r requirements/edx/base.in, fs-s3fs boto==2.39.0 # via -r requirements/edx/base.in, django-ses, edxval, ora2 botocore==1.8.17 # via -r requirements/edx/base.in, boto3, s3transfer -git+https://github.com/edx/bridgekeeper.git@2423e8d8788c2132ebeec509e1a7b17e1f5b9364#egg=bridgekeeper==0.0 # via -r requirements/edx/github.in +bridgekeeper==0.8 # via -r requirements/edx/base.in celery==3.1.26.post2 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, django-celery, django-user-tasks, edx-celeryutils, edx-enterprise -certifi==2020.4.5.1 # via -r requirements/edx/paver.txt, requests +certifi==2020.6.20 # via -r requirements/edx/paver.txt, requests cffi==1.14.0 # via -r requirements/edx/../edx-sandbox/shared.txt, cryptography chardet==3.0.4 # via -r requirements/edx/paver.txt, pdfminer.six, pysrt, requests -git+https://github.com/edx/openedx-chem.git@ff4e3a03d3c7610e47a9af08eb648d8aabe2eb18#egg=chem==1.0.0 # via -r requirements/edx/github.in -click==7.1.1 # via -r requirements/edx/../edx-sandbox/shared.txt, code-annotations, nltk, user-util -code-annotations==0.3.3 # via edx-enterprise +chem==1.2.0 # via -r requirements/edx/base.in +click==7.1.2 # via -r requirements/edx/../edx-sandbox/shared.txt, code-annotations, nltk, user-util +code-annotations==0.3.4 # via edx-enterprise contextlib2==0.6.0.post1 # via -r requirements/edx/base.in coreapi==2.3.3 # via drf-yasg coreschema==0.0.4 # via coreapi, drf-yasg -git+https://github.com/edx/crowdsourcehinter.git@2178ac72891392106ffef389651aef374177d294#egg=crowdsourcehinter-xblock==0.4 # via -r requirements/edx/github.in -cryptography==2.9 # via -r requirements/edx/../edx-sandbox/shared.txt, django-fernet-fields, edx-enterprise, social-auth-core +crowdsourcehinter-xblock==0.6 # via -r requirements/edx/base.in +cryptography==2.9.2 # via -r requirements/edx/../edx-sandbox/shared.txt, django-fernet-fields, edx-enterprise, social-auth-core cssutils==1.0.2 # via pynliner -ddt==1.3.1 # via xblock-drag-and-drop-v2, xblock-poll +ddt==1.3.1 # via -c requirements/edx/../constraints.txt, xblock-drag-and-drop-v2, xblock-poll decorator==4.4.2 # via pycontracts -defusedxml==0.6.0 # via -r requirements/edx/base.in, djangorestframework-xml, ora2, python3-openid, python3-saml, safe-lxml, social-auth-core -git+https://github.com/django-compressor/django-appconf@1526a842ee084b791aa66c931b3822091a442853#egg=django-appconf # via -r requirements/edx/github.in, django-statici18n -git+https://github.com/edx/django-babel-underscore.git@37705f7377a4d0a4e673f1431895ce28a8860cd7#egg=django-babel-underscore==0.6.0 # via -r requirements/edx/github.in -git+https://github.com/Zegocover/enmerkar.git@dbc113798aa4beabdfa2d00e6fef48248eb0f185#egg=django-babel==0.6.3.dev0 # via -r requirements/edx/github.in +defusedxml==0.7.0rc1 # via -r requirements/edx/base.in, djangorestframework-xml, ora2, python3-openid, python3-saml, safe-lxml, social-auth-core +django-appconf==1.0.4 # via -r requirements/edx/base.in, django-statici18n django-celery==3.3.1 # via -r requirements/edx/base.in django-classy-tags==1.0.0 # via django-sekizai -django-config-models==2.0.0 # via -r requirements/edx/base.in, edx-enterprise +django-config-models==2.0.2 # via -r requirements/edx/base.in, edx-enterprise +django-cookies-samesite==0.5.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in django-cors-headers==2.5.3 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in django-countries==5.5 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, edx-enterprise -django-crum==0.7.5 # via -r requirements/edx/base.in, edx-enterprise, edx-proctoring, edx-rbac, super-csv +django-crum==0.7.6 # via -r requirements/edx/base.in, edx-enterprise, edx-proctoring, edx-rbac, super-csv django-fernet-fields==0.6 # via -r requirements/edx/base.in, edx-enterprise, edxval -django-filter==2.2.0 # via -r requirements/edx/base.in, edx-enterprise +django-filter==2.3.0 # via -r requirements/edx/base.in, edx-enterprise django-ipware==2.1.0 # via -r requirements/edx/base.in, edx-enterprise, edx-proctoring django-js-asset==1.2.2 # via django-mptt -git+https://gitlab.com/Ayub-khan/django-method-override.git@5270af321be2e576d8e8b3c4191711a19975c356#egg=django-method-override==1.0.4 # via -r requirements/edx/github.in -django-model-utils==3.2.0 # via -r requirements/edx/base.in, django-user-tasks, edx-bulk-grades, edx-celeryutils, edx-completion, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-rbac, edx-submissions, edx-when, edxval, ora2, super-csv +django-method-override==1.0.4 # via -r requirements/edx/base.in +django-model-utils==4.0.0 # via -r requirements/edx/base.in, django-user-tasks, edx-bulk-grades, edx-celeryutils, edx-completion, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-rbac, edx-submissions, edx-when, edxval, ora2, super-csv django-mptt==0.11.0 # via -r requirements/edx/base.in, django-wiki django-multi-email-field==0.6.1 # via edx-enterprise -django-mysql==3.4.0 # via -r requirements/edx/base.in +django-mysql==3.7.1 # via -r requirements/edx/base.in django-oauth-toolkit==1.3.2 # via -r requirements/edx/base.in django-object-actions==2.0.0 # via edx-enterprise -django-pipeline==1.7.0 # via -r requirements/edx/base.in +django-pipeline==1.7.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in django-pyfs==2.1 # via -r requirements/edx/base.in django-ratelimit-backend==2.0 # via -r requirements/edx/base.in django-require==1.0.11 # via -r requirements/edx/base.in django-sekizai==1.1.0 # via -r requirements/edx/base.in, django-wiki -django-ses==0.8.14 # via -r requirements/edx/base.in -django-simple-history==2.8.0 # via -r requirements/edx/base.in, edx-enterprise, edx-organizations, ora2 -django-splash==0.2.7 # via -r requirements/edx/base.in +django-ses==0.8.14 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in +django-simple-history==2.11.0 # via -r requirements/edx/base.in, edx-enterprise, edx-organizations, ora2 +django-splash==0.2.9 # via -r requirements/edx/base.in django-statici18n==1.9.0 # via -r requirements/edx/base.in django-storages==1.8 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, edxval -django-user-tasks==1.0.0 # via -r requirements/edx/base.in -django-waffle==0.18.0 # via -r requirements/edx/base.in, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-proctoring +django-user-tasks==1.1.0 # via -r requirements/edx/base.in +django-waffle==1.0.0 # via -r requirements/edx/base.in, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-proctoring django-webpack-loader==0.7.0 # via -r requirements/edx/base.in, edx-proctoring -django==2.2.12 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, code-annotations, django-appconf, django-babel, django-babel-underscore, django-celery, django-classy-tags, django-config-models, django-cors-headers, django-crum, django-fernet-fields, django-filter, django-method-override, django-model-utils, django-mptt, django-multi-email-field, django-mysql, django-oauth-toolkit, django-pyfs, django-ratelimit-backend, django-sekizai, django-splash, django-statici18n, django-storages, django-user-tasks, django-wiki, drf-jwt, drf-yasg, edx-ace, edx-api-doc-tools, edx-bulk-grades, edx-celeryutils, edx-completion, edx-django-release-util, edx-django-sites-extensions, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-milestones, edx-opaque-keys, edx-organizations, edx-proctoring, edx-rbac, edx-search, edx-submissions, edx-when, edxval, event-tracking, help-tokens, jsonfield2, ora2, rest-condition, super-csv, xss-utils +django==2.2.13 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, code-annotations, django-appconf, django-celery, django-classy-tags, django-config-models, django-cors-headers, django-crum, django-fernet-fields, django-filter, django-method-override, django-model-utils, django-mptt, django-multi-email-field, django-mysql, django-oauth-toolkit, django-pyfs, django-ratelimit-backend, django-sekizai, django-splash, django-statici18n, django-storages, django-user-tasks, django-wiki, drf-jwt, drf-yasg, edx-ace, edx-api-doc-tools, edx-bulk-grades, edx-celeryutils, edx-completion, edx-django-release-util, edx-django-sites-extensions, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-milestones, edx-opaque-keys, edx-organizations, edx-proctoring, edx-rbac, edx-search, edx-submissions, edx-when, edxval, enmerkar, enmerkar-underscore, event-tracking, help-tokens, jsonfield2, lti-consumer-xblock, ora2, rest-condition, super-csv, xss-utils djangorestframework-xml==2.0.0 # via edx-enterprise djangorestframework==3.9.4 # via -r requirements/edx/base.in, django-config-models, django-user-tasks, drf-jwt, drf-yasg, edx-api-doc-tools, edx-completion, edx-drf-extensions, edx-enterprise, edx-organizations, edx-proctoring, edx-submissions, ora2, rest-condition, super-csv docopt==0.6.2 # via xmodule docutils==0.16 # via botocore drf-jwt==1.14.0 # via -c requirements/edx/../constraints.txt, edx-drf-extensions drf-yasg==1.17.0 # via -c requirements/edx/../constraints.txt, edx-api-doc-tools -edx-ace==0.1.14 # via -r requirements/edx/base.in -edx-analytics-data-api-client==0.15.5 # via -r requirements/edx/base.in -edx-api-doc-tools==1.2.0 # via -r requirements/edx/base.in +edx-ace==0.1.15 # via -r requirements/edx/base.in +edx-analytics-data-api-client==0.16.1 # via -r requirements/edx/base.in +edx-api-doc-tools==1.3.1 # via -r requirements/edx/base.in edx-bulk-grades==0.6.8 # via -r requirements/edx/base.in, staff-graded-xblock -edx-ccx-keys==1.0.1 # via -r requirements/edx/base.in +edx-ccx-keys==1.1.0 # via -r requirements/edx/base.in edx-celeryutils==0.5.0 # via -r requirements/edx/base.in, super-csv -edx-completion==3.1.1 # via -r requirements/edx/base.in -edx-django-release-util==0.4.2 # via -r requirements/edx/base.in -edx-django-sites-extensions==2.4.3 # via -r requirements/edx/base.in -edx-django-utils==3.2.0 # via -r requirements/edx/base.in, django-config-models, edx-drf-extensions, edx-enterprise, edx-rest-api-client, edx-when -edx-drf-extensions==5.0.2 # via -r requirements/edx/base.in, edx-completion, edx-enterprise, edx-organizations, edx-proctoring, edx-rbac, edx-when, edxval -edx-enterprise==3.1.0 # via -r requirements/edx/base.in -edx-i18n-tools==0.5.0 # via ora2 -edx-milestones==0.2.6 # via -r requirements/edx/base.in -edx-opaque-keys[django]==2.0.2 # via -r requirements/edx/paver.txt, edx-bulk-grades, edx-ccx-keys, edx-completion, edx-drf-extensions, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-user-state-client, edx-when, xmodule -edx-organizations==5.1.0 # via -r requirements/edx/base.in +edx-completion==3.2.1 # via -r requirements/edx/base.in +edx-django-release-util==0.4.4 # via -r requirements/edx/base.in +edx-django-sites-extensions==2.5.1 # via -r requirements/edx/base.in +edx-django-utils==3.2.3 # via -r requirements/edx/base.in, django-config-models, edx-drf-extensions, edx-enterprise, edx-rest-api-client, edx-when +edx-drf-extensions==6.0.0 # via -r requirements/edx/base.in, edx-completion, edx-enterprise, edx-organizations, edx-proctoring, edx-rbac, edx-when, edxval +edx-enterprise==3.3.11 # via -r requirements/edx/base.in +edx-i18n-tools==0.5.3 # via ora2 +edx-milestones==0.3.0 # via -r requirements/edx/base.in +edx-opaque-keys[django]==2.1.0 # via -r requirements/edx/paver.txt, edx-bulk-grades, edx-ccx-keys, edx-completion, edx-drf-extensions, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-user-state-client, edx-when, xmodule +edx-organizations==5.2.0 # via -r requirements/edx/base.in edx-proctoring-proctortrack==1.0.5 # via -r requirements/edx/base.in -edx-proctoring==2.3.3 # via -r requirements/edx/base.in, edx-proctoring-proctortrack -edx-rbac==1.1.3 # via edx-enterprise -edx-rest-api-client==5.1.0 # via -r requirements/edx/base.in, edx-enterprise, edx-proctoring -edx-search==1.3.4 # via -r requirements/edx/base.in -edx-sga==0.10.0 # via -r requirements/edx/base.in -edx-submissions==3.0.7 # via -r requirements/edx/base.in, ora2 +edx-proctoring==2.4.3 # via -r requirements/edx/base.in, edx-proctoring-proctortrack +edx-rbac==1.3.1 # via edx-enterprise +edx-rest-api-client==5.2.1 # via -r requirements/edx/base.in, edx-enterprise, edx-proctoring +edx-search==1.4.1 # via -r requirements/edx/base.in +edx-sga==0.11.0 # via -r requirements/edx/base.in +edx-submissions==3.1.11 # via -r requirements/edx/base.in, ora2 edx-tincan-py35==0.0.5 # via edx-enterprise -edx-user-state-client==1.1.2 # via -r requirements/edx/base.in -edx-when==1.2.0 # via -r requirements/edx/base.in, edx-proctoring -edxval==1.3.1 # via -r requirements/edx/base.in +edx-user-state-client==1.2.0 # via -r requirements/edx/base.in +edx-when==1.2.8 # via -r requirements/edx/base.in, edx-proctoring +edxval==1.3.8 # via -r requirements/edx/base.in elasticsearch==1.9.0 # via edx-search -enum34==1.1.10 # via edxval -event-tracking==0.3.0 # via -r requirements/edx/base.in, edx-proctoring, edx-search +enmerkar-underscore==1.0.0 # via -r requirements/edx/base.in +enmerkar==0.7.1 # via enmerkar-underscore +event-tracking==0.3.2 # via -r requirements/edx/base.in, edx-proctoring, edx-search fs-s3fs==0.1.8 # via -r requirements/edx/base.in, django-pyfs fs==2.0.18 # via -r requirements/edx/base.in, django-pyfs, fs-s3fs, xblock future==0.18.2 # via django-ses, edx-celeryutils, edx-enterprise, pycontracts, pyjwkest geoip2==3.0.0 # via -r requirements/edx/base.in glob2==0.7 # via -r requirements/edx/base.in gunicorn==20.0.4 # via -r requirements/edx/base.in -help-tokens==1.0.5 # via -r requirements/edx/base.in -html5lib==1.0.1 # via -r requirements/edx/base.in, ora2 -httplib2==0.17.2 # via oauth2 -icalendar==4.0.5 # via -r requirements/edx/base.in +help-tokens==1.1.2 # via -r requirements/edx/base.in +html5lib==1.1 # via -r requirements/edx/base.in, ora2 +icalendar==4.0.6 # via -r requirements/edx/base.in idna==2.9 # via -r requirements/edx/paver.txt, requests -importlib-metadata==1.6.0 # via -r requirements/edx/paver.txt, path -inflection==0.4.0 # via drf-yasg +importlib-metadata==1.6.1 # via -r requirements/edx/paver.txt, path +inflection==0.5.0 # via drf-yasg ipaddress==1.0.23 # via -r requirements/edx/base.in isodate==0.6.0 # via python3-saml -itypes==1.1.0 # via coreapi +itypes==1.2.0 # via coreapi jinja2==2.11.2 # via code-annotations, coreschema -jmespath==0.9.5 # via boto3, botocore -joblib==0.14.1 # via -r requirements/edx/../edx-sandbox/shared.txt, nltk +jmespath==0.10.0 # via boto3, botocore +joblib==0.14.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/../edx-sandbox/shared.txt, nltk jsondiff==1.2.0 # via edx-enterprise jsonfield2==3.0.3 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, edx-celeryutils, edx-enterprise, edx-proctoring, edx-submissions, ora2 kombu==3.0.37 # via celery laboratory==1.0.2 # via -r requirements/edx/base.in -lazy==1.4 # via -r requirements/edx/paver.txt, acid-xblock, ora2 +lazy==1.4 # via -r requirements/edx/paver.txt, acid-xblock, lti-consumer-xblock, ora2 lepl==5.1.3 # via rfc6266-parser libsass==0.10.0 # via -r requirements/edx/paver.txt, ora2 loremipsum==1.0.5 # via ora2 -git+https://github.com/edx/xblock-lti-consumer.git@v1.2.5#egg=lti_consumer-xblock==1.2.5 # via -r requirements/edx/github.in -lxml==4.5.0 # via -r requirements/edx/../edx-sandbox/shared.txt, capa, edxval, lti-consumer-xblock, ora2, safe-lxml, xblock, xmlsec +lti-consumer-xblock==1.4.2 # via -r requirements/edx/base.in +lxml==4.5.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/../edx-sandbox/shared.txt, capa, edxval, lti-consumer-xblock, ora2, safe-lxml, xblock, xmlsec mailsnake==1.6.4 # via -r requirements/edx/base.in -mako==1.0.2 # via -r requirements/edx/base.in, acid-xblock, lti-consumer-xblock, xblock-google-drive, xblock-utils +mako==1.1.3 # via -r requirements/edx/base.in, acid-xblock, lti-consumer-xblock, xblock-google-drive, xblock-utils markdown==2.6.11 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, django-wiki, staff-graded-xblock, xblock-poll -markey==0.8 # via django-babel-underscore +markey==0.8 # via enmerkar-underscore markupsafe==1.1.1 # via -r requirements/edx/paver.txt, chem, jinja2, mako, xblock -maxminddb==1.5.2 # via geoip2 +maxminddb==1.5.4 # via geoip2 mock==3.0.5 # via -c requirements/edx/../constraints.txt, -r requirements/edx/paver.txt, xblock-drag-and-drop-v2, xblock-poll git+https://github.com/edx/MongoDBProxy.git@d92bafe9888d2940f647a7b2b2383b29c752f35a#egg=MongoDBProxy==0.1.0+edx.2 # via -r requirements/edx/github.in -mongoengine==0.10.0 # via -r requirements/edx/base.in -more-itertools==8.2.0 # via -r requirements/edx/paver.txt, zipp +mongoengine==0.20.0 # via -r requirements/edx/base.in +more-itertools==8.4.0 # via -r requirements/edx/paver.txt, zipp mpmath==1.1.0 # via sympy mysqlclient==1.4.6 # via -r requirements/edx/base.in -newrelic==5.12.0.140 # via -r requirements/edx/base.in, edx-django-utils +newrelic==5.14.1.144 # via -r requirements/edx/base.in, edx-django-utils nltk==3.5 # via -r requirements/edx/../edx-sandbox/shared.txt, chem -nodeenv==1.3.5 # via -r requirements/edx/base.in -numpy==1.18.2 # via chem, openedx-calc, scipy -git+https://github.com/joestump/python-oauth2.git@b94f69b1ad195513547924e380d9265133e995fa#egg=oauth2 # via -r requirements/edx/github.in +nodeenv==1.4.0 # via -r requirements/edx/base.in +numpy==1.18.5 # via chem, openedx-calc, scipy oauthlib==3.0.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, django-oauth-toolkit, lti-consumer-xblock, requests-oauthlib, social-auth-core -openedx-calc==1.0.7 # via -r requirements/edx/base.in -git+https://github.com/edx/edx-ora2.git@2.6.25#egg=ora2==2.6.25 # via -r requirements/edx/github.in -packaging==20.3 # via drf-yasg +openedx-calc==1.0.9 # via -r requirements/edx/base.in +ora2==2.8.5 # via -r requirements/edx/base.in +packaging==20.4 # via bleach, drf-yasg path.py==12.4.0 # via edx-enterprise, edx-i18n-tools, ora2, xmodule path==13.1.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/paver.txt, path.py pathtools==0.1.2 # via -r requirements/edx/paver.txt, watchdog paver==1.3.4 # via -r requirements/edx/paver.txt pbr==5.4.5 # via -r requirements/edx/paver.txt, stevedore -pdfminer.six==20200402 # via -r requirements/edx/base.in +pdfminer.six==20200517 # via -r requirements/edx/base.in piexif==1.1.3 # via -r requirements/edx/base.in -pillow==7.1.1 # via -r requirements/edx/base.in, edx-enterprise, edx-organizations -pkgconfig==1.5.1 # via xmlsec +pillow==7.1.2 # via -r requirements/edx/base.in, edx-enterprise, edx-organizations polib==1.1.0 # via edx-i18n-tools psutil==1.2.1 # via -r requirements/edx/paver.txt, edx-django-utils py2neo==3.1.2 # via -r requirements/edx/base.in -pycontracts==1.8.12 # via -r requirements/edx/base.in, edx-user-state-client +pycontracts==1.8.14 # via -r requirements/edx/base.in, edx-user-state-client pycountry==19.8.18 # via -r requirements/edx/base.in pycparser==2.20 # via -r requirements/edx/../edx-sandbox/shared.txt, cffi -pycryptodome==3.9.7 # via pdfminer.six -pycryptodomex==3.9.7 # via -r requirements/edx/base.in, edx-proctoring, pyjwkest +pycryptodome==3.9.8 # via pdfminer.six +pycryptodomex==3.9.8 # via -r requirements/edx/base.in, edx-proctoring, pyjwkest pygments==2.6.1 # via -r requirements/edx/base.in pyjwkest==1.4.2 # via -r requirements/edx/base.in, edx-drf-extensions pyjwt==1.5.2 # via -r requirements/edx/base.in, drf-jwt, edx-rest-api-client, social-auth-core -pymongo==3.9.0 # via -r requirements/edx/base.in, -r requirements/edx/paver.txt, edx-opaque-keys, event-tracking, mongodbproxy, mongoengine +pymongo==3.10.1 # via -r requirements/edx/base.in, -r requirements/edx/paver.txt, edx-opaque-keys, event-tracking, mongodbproxy, mongoengine pynliner==0.8.0 # via -r requirements/edx/base.in -pyparsing==2.2.0 # via chem, openedx-calc, packaging, pycontracts +pyparsing==2.4.7 # via chem, openedx-calc, packaging, pycontracts pysrt==1.1.2 # via -r requirements/edx/base.in, edxval python-dateutil==2.4.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, analytics-python, botocore, edx-ace, edx-drf-extensions, edx-enterprise, edx-proctoring, icalendar, ora2, xblock python-levenshtein==0.12.0 # via -r requirements/edx/base.in python-memcached==1.59 # via -r requirements/edx/paver.txt python-slugify==4.0.0 # via code-annotations -python-swiftclient==3.9.0 # via ora2 +python-swiftclient==3.10.0 # via ora2 python3-openid==3.1.0 ; python_version >= "3" # via -r requirements/edx/base.in, social-auth-core python3-saml==1.9.0 # via -r requirements/edx/base.in -pytz==2019.3 # via -r requirements/edx/base.in, babel, capa, celery, django, django-ses, edx-completion, edx-enterprise, edx-proctoring, edx-submissions, edx-tincan-py35, event-tracking, fs, icalendar, ora2, xblock +pytz==2020.1 # via -r requirements/edx/base.in, babel, capa, celery, django, django-ses, edx-completion, edx-enterprise, edx-proctoring, edx-submissions, edx-tincan-py35, event-tracking, fs, icalendar, ora2, xblock pyuca==1.2 # via -r requirements/edx/base.in pyyaml==5.3.1 # via -r requirements/edx/base.in, code-annotations, edx-django-release-util, edx-i18n-tools, xblock random2==1.0.1 # via -r requirements/edx/base.in -recommender-xblock==1.4.5 # via -r requirements/edx/base.in +recommender-xblock==1.4.8 # via -r requirements/edx/base.in redis==2.10.6 # via -r requirements/edx/base.in -regex==2020.4.4 # via -r requirements/edx/../edx-sandbox/shared.txt, nltk +regex==2020.6.8 # via -r requirements/edx/../edx-sandbox/shared.txt, nltk requests-oauthlib==1.3.0 # via -r requirements/edx/base.in, social-auth-core -requests==2.23.0 # via -r requirements/edx/paver.txt, analytics-python, coreapi, django-oauth-toolkit, edx-analytics-data-api-client, edx-bulk-grades, edx-drf-extensions, edx-enterprise, edx-rest-api-client, geoip2, mailsnake, pyjwkest, python-swiftclient, requests-oauthlib, sailthru-client, slumber, social-auth-core +requests==2.24.0 # via -r requirements/edx/paver.txt, analytics-python, coreapi, django-oauth-toolkit, edx-analytics-data-api-client, edx-bulk-grades, edx-drf-extensions, edx-enterprise, edx-rest-api-client, geoip2, mailsnake, pyjwkest, python-swiftclient, requests-oauthlib, sailthru-client, slumber, social-auth-core rest-condition==1.0.3 # via -r requirements/edx/base.in, edx-drf-extensions rfc6266-parser==0.0.6 # via -r requirements/edx/base.in ruamel.yaml.clib==0.2.0 # via ruamel.yaml @@ -219,39 +214,40 @@ rules==2.2 # via -r requirements/edx/base.in, edx-enterprise, edx s3transfer==0.1.13 # via boto3 sailthru-client==2.2.3 # via -r requirements/edx/base.in, edx-ace scipy==1.4.1 # via chem, openedx-calc -semantic-version==2.8.4 # via edx-drf-extensions +semantic-version==2.8.5 # via edx-drf-extensions shapely==1.7.0 # via -r requirements/edx/base.in simplejson==3.17.0 # via -r requirements/edx/base.in, sailthru-client, super-csv, xblock-utils -six==1.14.0 # via -r requirements/edx/../edx-sandbox/shared.txt, -r requirements/edx/base.in, -r requirements/edx/paver.txt, analytics-python, bleach, cryptography, django-appconf, django-classy-tags, django-countries, django-pyfs, django-sekizai, django-simple-history, django-statici18n, drf-yasg, edx-ace, edx-ccx-keys, edx-django-release-util, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-milestones, edx-opaque-keys, edx-rbac, edx-search, event-tracking, fs, fs-s3fs, help-tokens, html5lib, isodate, libsass, mock, openedx-calc, packaging, paver, pycontracts, pyjwkest, python-dateutil, python-memcached, python-swiftclient, social-auth-app-django, social-auth-core, stevedore, xblock +six==1.15.0 # via -r requirements/edx/../edx-sandbox/shared.txt, -r requirements/edx/base.in, -r requirements/edx/paver.txt, analytics-python, bleach, chem, crowdsourcehinter-xblock, cryptography, django-classy-tags, django-countries, django-pyfs, django-sekizai, django-simple-history, django-statici18n, drf-yasg, edx-ace, edx-ccx-keys, edx-django-release-util, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-milestones, edx-opaque-keys, edx-rbac, edx-search, event-tracking, fs, fs-s3fs, help-tokens, html5lib, isodate, libsass, mock, openedx-calc, packaging, paver, pycontracts, pyjwkest, python-dateutil, python-memcached, python-swiftclient, social-auth-app-django, social-auth-core, stevedore, xblock slumber==0.7.1 # via edx-bulk-grades, edx-enterprise, edx-rest-api-client +social-auth-app-django==4.0.0 # via -r requirements/edx/base.in social-auth-core==3.3.3 # via -r requirements/edx/base.in, social-auth-app-django -git+https://github.com/jazzband/sorl-thumbnail.git@13bedfb7d2970809eda597e3ef79318a6fa80ac2#egg=sorl-thumbnail # via -r requirements/edx/github.in -sortedcontainers==2.1.0 # via -r requirements/edx/base.in, pdfminer.six -soupsieve==2.0 # via beautifulsoup4 +sorl-thumbnail==12.6.3 # via -r requirements/edx/base.in +sortedcontainers==2.2.2 # via -r requirements/edx/base.in, pdfminer.six +soupsieve==2.0.1 # via beautifulsoup4 sqlparse==0.3.1 # via -r requirements/edx/base.in, django -staff-graded-xblock==0.7 # via -r requirements/edx/base.in -stevedore==1.32.0 # via -r requirements/edx/base.in, -r requirements/edx/paver.txt, code-annotations, edx-ace, edx-enterprise, edx-opaque-keys -super-csv==0.9.7 # via -r requirements/edx/base.in, edx-bulk-grades -sympy==1.5.1 # via symmath -testfixtures==6.14.0 # via edx-enterprise +staff-graded-xblock==0.8 # via -r requirements/edx/base.in +stevedore==1.32.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, -r requirements/edx/paver.txt, code-annotations, edx-ace, edx-enterprise, edx-opaque-keys +super-csv==0.9.9 # via -r requirements/edx/base.in, edx-bulk-grades +sympy==1.6 # via symmath +testfixtures==6.14.1 # via edx-enterprise text-unidecode==1.3 # via python-slugify -tqdm==4.45.0 # via -r requirements/edx/../edx-sandbox/shared.txt, nltk +tqdm==4.46.1 # via -r requirements/edx/../edx-sandbox/shared.txt, nltk unicodecsv==0.14.1 # via -r requirements/edx/base.in, edx-enterprise uritemplate==3.0.1 # via coreapi, drf-yasg urllib3==1.25.9 # via -r requirements/edx/paver.txt, elasticsearch, geoip2, requests -user-util==0.1.5 # via -r requirements/edx/base.in +user-util==0.2 # via -r requirements/edx/base.in voluptuous==0.11.7 # via ora2 -watchdog==0.10.2 # via -r requirements/edx/paver.txt -web-fragments==0.3.1 # via -r requirements/edx/base.in, staff-graded-xblock, xblock, xblock-utils +watchdog==0.10.3 # via -r requirements/edx/paver.txt +web-fragments==0.3.2 # via -r requirements/edx/base.in, crowdsourcehinter-xblock, staff-graded-xblock, xblock, xblock-utils webencodings==0.5.1 # via bleach, html5lib webob==1.8.6 # via xblock, xmodule wrapt==1.11.2 # via -c requirements/edx/../constraints.txt, -r requirements/edx/paver.txt git+https://github.com/edx-solutions/xblock-drag-and-drop-v2@v2.2.10#egg=xblock-drag-and-drop-v2==2.2.10 # via -r requirements/edx/github.in git+https://github.com/open-craft/xblock-poll@da2d8fd21791a7af128595cf82bee83ee579e00f#egg=xblock-poll==1.9.6 # via -r requirements/edx/github.in -xblock-utils==2.0.0 # via -r requirements/edx/base.in, edx-sga, lti-consumer-xblock, staff-graded-xblock, xblock-drag-and-drop-v2, xblock-google-drive -xblock==1.2.9 # via -r requirements/edx/base.in, acid-xblock, crowdsourcehinter-xblock, done-xblock, edx-completion, edx-sga, edx-user-state-client, edx-when, lti-consumer-xblock, ora2, rate-xblock, staff-graded-xblock, xblock-discussion, xblock-drag-and-drop-v2, xblock-google-drive, xblock-poll, xblock-utils -xmlsec==1.3.3 # via python3-saml -xss-utils==0.1.2 # via -r requirements/edx/base.in +xblock-utils==2.1.1 # via -r requirements/edx/base.in, edx-sga, lti-consumer-xblock, staff-graded-xblock, xblock-drag-and-drop-v2, xblock-google-drive +xblock==1.3.1 # via -r requirements/edx/base.in, acid-xblock, crowdsourcehinter-xblock, done-xblock, edx-completion, edx-sga, edx-user-state-client, edx-when, lti-consumer-xblock, ora2, rate-xblock, staff-graded-xblock, xblock-discussion, xblock-drag-and-drop-v2, xblock-google-drive, xblock-poll, xblock-utils +xmlsec==1.3.8 # via python3-saml +xss-utils==0.1.3 # via -r requirements/edx/base.in zipp==1.0.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/paver.txt, importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/edx/coverage.in b/requirements/edx/coverage.in index dd0104c1dcdec3bf6dd66228680c3c0ce353184b..e52a152f87e9f424e0f2522ba7d2531ea8cf8781 100644 --- a/requirements/edx/coverage.in +++ b/requirements/edx/coverage.in @@ -14,4 +14,3 @@ coverage # Code coverage testing for Python diff-cover # Automatically find diff lines that need test coverage -pandas # Used to process warnings generated by pytest diff --git a/requirements/edx/coverage.txt b/requirements/edx/coverage.txt index 37c07ae2de787c1634a9a9d3d44da2762a2b8ce8..316c7dff8a07a752f119835b7dd8d8cd0dcf0da9 100644 --- a/requirements/edx/coverage.txt +++ b/requirements/edx/coverage.txt @@ -5,18 +5,14 @@ # make upgrade # coverage==5.1 # via -r requirements/edx/coverage.in -diff-cover==2.6.1 # via -r requirements/edx/coverage.in -importlib-metadata==1.6.0 # via inflect, pluggy +diff-cover==3.0.1 # via -r requirements/edx/coverage.in +importlib-metadata==1.6.1 # via inflect, pluggy inflect==3.0.2 # via -c requirements/edx/../constraints.txt, jinja2-pluralize jinja2-pluralize==0.3.0 # via diff-cover jinja2==2.11.2 # via diff-cover, jinja2-pluralize markupsafe==1.1.1 # via jinja2 -more-itertools==8.2.0 # via zipp -numpy==1.18.2 # via pandas -pandas==0.22.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/coverage.in +more-itertools==8.4.0 # via zipp pluggy==0.13.1 # via diff-cover pygments==2.6.1 # via diff-cover -python-dateutil==2.4.0 # via -c requirements/edx/../constraints.txt, pandas -pytz==2019.3 # via pandas -six==1.14.0 # via diff-cover, python-dateutil +six==1.15.0 # via diff-cover zipp==1.0.0 # via -c requirements/edx/../constraints.txt, importlib-metadata diff --git a/requirements/edx/development.in b/requirements/edx/development.in index 6425d57a482ee668f620ec43891a66865fc5bcf1..651478f38a56645e1502ea5750032a95fa036478 100644 --- a/requirements/edx/development.in +++ b/requirements/edx/development.in @@ -10,12 +10,12 @@ -c ../constraints.txt --r pip-tools.txt # pip-tools and its dependencies, for managing requirements files --r testing.txt # Dependencies for running the various test suites +-r pip-tools.txt # pip-tools and its dependencies, for managing requirements files +-r testing.txt # Dependencies for running the various test suites -click # Used for perf_tests utilities in modulestore -django-debug-toolbar # A set of panels that display debug information about the current request/response -edx-sphinx-theme # Documentation theme -pyinotify # More efficient checking for runserver reload trigger events -sphinxcontrib-openapi[markdown] # OpenAPI (fka Swagger) spec renderer for Sphinx -vulture # Detects possible dead/unused code, used in scripts/find-dead-code.sh +click # Used for perf_tests utilities in modulestore +django-debug-toolbar # A set of panels that display debug information about the current request/response +edx-sphinx-theme # Documentation theme +pywatchman # More efficient checking for runserver reload trigger events +sphinxcontrib-openapi[markdown]==0.6.0 # OpenAPI (fka Swagger) spec renderer for Sphinx; pinned because 0.70 requires Python >=3.6 +vulture # Detects possible dead/unused code, used in scripts/find-dead-code.sh diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index d778cad9907b2897ca18a1ff799a8ed06ed7e27d..a1b0420f3bcba114599145c454d9b47eb0665836 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -9,14 +9,12 @@ -e git+https://github.com/edx/codejail.git@4127fc4bd5775cc72aee8d7f0a70e31405e22439#egg=codejail # via -r requirements/edx/testing.txt -e git+https://github.com/jsocol/django-ratelimit.git@72edbe8949fbf6699848e5847645a1998f121d46#egg=ratelimit # via -r requirements/edx/testing.txt -e git+https://github.com/edx/django-wiki.git@0.0.27#egg=django-wiki # via -r requirements/edx/testing.txt --e git+https://github.com/edx/DoneXBlock.git@2.0.1#egg=done-xblock # via -r requirements/edx/testing.txt +-e git+https://github.com/edx/DoneXBlock.git@2.0.2#egg=done-xblock # via -r requirements/edx/testing.txt -e git+https://github.com/jazkarta/edx-jsme.git@690dbf75441fa91c7c4899df0b83d77f7deb5458#egg=edx-jsme # via -r requirements/edx/testing.txt -e . # via -r requirements/edx/testing.txt --e git+https://github.com/dementrock/pystache_custom.git@776973740bdaad83a3b029f96e415a7d1e8bec2f#egg=pystache_custom-dev # via -r requirements/edx/testing.txt -e git+https://github.com/edx/RateXBlock.git@2.0#egg=rate-xblock # via -r requirements/edx/testing.txt -e common/lib/safe_lxml # via -r requirements/edx/testing.txt -e common/lib/sandbox-packages # via -r requirements/edx/testing.txt --e git+https://github.com/python-social-auth/social-app-django.git@c00d23c2b45c3317bd35b15ad1b959338689cef8#egg=social-auth-app-django # via -r requirements/edx/testing.txt -e common/lib/symmath # via -r requirements/edx/testing.txt -e openedx/core/lib/xblock_builtin/xblock_discussion # via -r requirements/edx/testing.txt -e git+https://github.com/edx-solutions/xblock-google-drive.git@2d176468e33c0713c911b563f8f65f7cf232f5b6#egg=xblock-google-drive # via -r requirements/edx/testing.txt @@ -27,248 +25,244 @@ analytics-python==1.2.9 # via -r requirements/edx/testing.txt aniso8601==8.0.0 # via -r requirements/edx/testing.txt, edx-tincan-py35 anyjson==0.3.3 # via -r requirements/edx/testing.txt, kombu apipkg==1.5 # via -r requirements/edx/testing.txt, execnet -appdirs==1.4.3 # via -r requirements/edx/testing.txt, fs, virtualenv +appdirs==1.4.4 # via -r requirements/edx/testing.txt, fs, virtualenv astroid==2.3.3 # via -r requirements/edx/testing.txt, pylint, pylint-celery attrs==19.3.0 # via -r requirements/edx/testing.txt, edx-ace, jsonschema, pytest -babel==2.8.0 # via -r requirements/edx/testing.txt, django-babel, django-babel-underscore, sphinx -beautifulsoup4==4.9.0 # via -r requirements/edx/testing.txt, pynliner +babel==2.8.0 # via -r requirements/edx/testing.txt, enmerkar, enmerkar-underscore, sphinx +beautifulsoup4==4.9.1 # via -r requirements/edx/testing.txt, pynliner billiard==3.3.0.23 # via -r requirements/edx/testing.txt, celery -bleach==3.1.4 # via -r requirements/edx/testing.txt, edx-enterprise, lti-consumer-xblock, ora2 -bok-choy==1.0.1 # via -r requirements/edx/testing.txt +bleach==3.1.5 # via -r requirements/edx/testing.txt, edx-enterprise, lti-consumer-xblock, ora2 +bok-choy==1.1.1 # via -r requirements/edx/testing.txt boto3==1.4.8 # via -r requirements/edx/testing.txt, fs-s3fs boto==2.39.0 # via -r requirements/edx/testing.txt, django-ses, edxval, ora2 botocore==1.8.17 # via -r requirements/edx/testing.txt, boto3, s3transfer -git+https://github.com/edx/bridgekeeper.git@2423e8d8788c2132ebeec509e1a7b17e1f5b9364#egg=bridgekeeper==0.0 # via -r requirements/edx/testing.txt +bridgekeeper==0.8 # via -r requirements/edx/testing.txt celery==3.1.26.post2 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, django-celery, django-user-tasks, edx-celeryutils, edx-enterprise -certifi==2020.4.5.1 # via -r requirements/edx/testing.txt, requests +certifi==2020.6.20 # via -r requirements/edx/testing.txt, requests cffi==1.14.0 # via -r requirements/edx/testing.txt, cryptography chardet==3.0.4 # via -r requirements/edx/testing.txt, pdfminer.six, pysrt, requests -git+https://github.com/edx/openedx-chem.git@ff4e3a03d3c7610e47a9af08eb648d8aabe2eb18#egg=chem==1.0.0 # via -r requirements/edx/testing.txt +chem==1.2.0 # via -r requirements/edx/testing.txt click-log==0.3.2 # via -r requirements/edx/testing.txt, edx-lint -click==7.1.1 # via -r requirements/edx/development.in, -r requirements/edx/pip-tools.txt, -r requirements/edx/testing.txt, click-log, code-annotations, edx-lint, nltk, pip-tools, user-util -code-annotations==0.3.3 # via -r requirements/edx/testing.txt, edx-enterprise +click==7.1.2 # via -r requirements/edx/development.in, -r requirements/edx/pip-tools.txt, -r requirements/edx/testing.txt, click-log, code-annotations, edx-lint, nltk, pip-tools, user-util +code-annotations==0.3.4 # via -r requirements/edx/testing.txt, edx-enterprise colorama==0.4.1 # via -r requirements/edx/testing.txt, radon contextlib2==0.6.0.post1 # via -r requirements/edx/testing.txt coreapi==2.3.3 # via -r requirements/edx/testing.txt, drf-yasg coreschema==0.0.4 # via -r requirements/edx/testing.txt, coreapi, drf-yasg coverage==5.1 # via -r requirements/edx/testing.txt, pytest-cov -git+https://github.com/nedbat/coverage_pytest_plugin.git@29de030251471e200ff255eb9e549218cd60e872#egg=coverage_pytest_plugin==0.0 # via -r requirements/edx/testing.txt -git+https://github.com/edx/crowdsourcehinter.git@2178ac72891392106ffef389651aef374177d294#egg=crowdsourcehinter-xblock==0.4 # via -r requirements/edx/testing.txt -cryptography==2.9 # via -r requirements/edx/testing.txt, django-fernet-fields, edx-enterprise, social-auth-core +crowdsourcehinter-xblock==0.6 # via -r requirements/edx/testing.txt +cryptography==2.9.2 # via -r requirements/edx/testing.txt, django-fernet-fields, edx-enterprise, social-auth-core cssselect==1.1.0 # via -r requirements/edx/testing.txt, pyquery cssutils==1.0.2 # via -r requirements/edx/testing.txt, pynliner -ddt==1.3.1 # via -r requirements/edx/testing.txt, xblock-drag-and-drop-v2, xblock-poll +ddt==1.3.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, xblock-drag-and-drop-v2, xblock-poll decorator==4.4.2 # via -r requirements/edx/testing.txt, pycontracts -defusedxml==0.6.0 # via -r requirements/edx/testing.txt, djangorestframework-xml, ora2, python3-openid, python3-saml, safe-lxml, social-auth-core -diff-cover==2.6.1 # via -r requirements/edx/testing.txt +defusedxml==0.7.0rc1 # via -r requirements/edx/testing.txt, djangorestframework-xml, ora2, python3-openid, python3-saml, safe-lxml, social-auth-core +diff-cover==3.0.1 # via -r requirements/edx/testing.txt distlib==0.3.0 # via -r requirements/edx/testing.txt, virtualenv -git+https://github.com/django-compressor/django-appconf@1526a842ee084b791aa66c931b3822091a442853#egg=django-appconf # via -r requirements/edx/testing.txt, django-statici18n -git+https://github.com/edx/django-babel-underscore.git@37705f7377a4d0a4e673f1431895ce28a8860cd7#egg=django-babel-underscore==0.6.0 # via -r requirements/edx/testing.txt -git+https://github.com/Zegocover/enmerkar.git@dbc113798aa4beabdfa2d00e6fef48248eb0f185#egg=django-babel==0.6.3.dev0 # via -r requirements/edx/testing.txt +django-appconf==1.0.4 # via -r requirements/edx/testing.txt, django-statici18n django-celery==3.3.1 # via -r requirements/edx/testing.txt django-classy-tags==1.0.0 # via -r requirements/edx/testing.txt, django-sekizai -django-config-models==2.0.0 # via -r requirements/edx/testing.txt, edx-enterprise +django-config-models==2.0.2 # via -r requirements/edx/testing.txt, edx-enterprise +django-cookies-samesite==0.5.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt django-cors-headers==2.5.3 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt django-countries==5.5 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, edx-enterprise -django-crum==0.7.5 # via -r requirements/edx/testing.txt, edx-enterprise, edx-proctoring, edx-rbac, super-csv +django-crum==0.7.6 # via -r requirements/edx/testing.txt, edx-enterprise, edx-proctoring, edx-rbac, super-csv django-debug-toolbar==2.2 # via -r requirements/edx/development.in django-fernet-fields==0.6 # via -r requirements/edx/testing.txt, edx-enterprise, edxval -django-filter==2.2.0 # via -r requirements/edx/testing.txt, edx-enterprise +django-filter==2.3.0 # via -r requirements/edx/testing.txt, edx-enterprise django-ipware==2.1.0 # via -r requirements/edx/testing.txt, edx-enterprise, edx-proctoring django-js-asset==1.2.2 # via -r requirements/edx/testing.txt, django-mptt -git+https://gitlab.com/Ayub-khan/django-method-override.git@5270af321be2e576d8e8b3c4191711a19975c356#egg=django-method-override==1.0.4 # via -r requirements/edx/testing.txt -django-model-utils==3.2.0 # via -r requirements/edx/testing.txt, django-user-tasks, edx-bulk-grades, edx-celeryutils, edx-completion, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-rbac, edx-submissions, edx-when, edxval, ora2, super-csv +django-method-override==1.0.4 # via -r requirements/edx/testing.txt +django-model-utils==4.0.0 # via -r requirements/edx/testing.txt, django-user-tasks, edx-bulk-grades, edx-celeryutils, edx-completion, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-rbac, edx-submissions, edx-when, edxval, ora2, super-csv django-mptt==0.11.0 # via -r requirements/edx/testing.txt, django-wiki django-multi-email-field==0.6.1 # via -r requirements/edx/testing.txt, edx-enterprise -django-mysql==3.4.0 # via -r requirements/edx/testing.txt +django-mysql==3.7.1 # via -r requirements/edx/testing.txt django-oauth-toolkit==1.3.2 # via -r requirements/edx/testing.txt django-object-actions==2.0.0 # via -r requirements/edx/testing.txt, edx-enterprise -django-pipeline==1.7.0 # via -r requirements/edx/testing.txt +django-pipeline==1.7.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt django-pyfs==2.1 # via -r requirements/edx/testing.txt django-ratelimit-backend==2.0 # via -r requirements/edx/testing.txt django-require==1.0.11 # via -r requirements/edx/testing.txt django-sekizai==1.1.0 # via -r requirements/edx/testing.txt, django-wiki -django-ses==0.8.14 # via -r requirements/edx/testing.txt -django-simple-history==2.8.0 # via -r requirements/edx/testing.txt, edx-enterprise, edx-organizations, ora2 -django-splash==0.2.7 # via -r requirements/edx/testing.txt +django-ses==0.8.14 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt +django-simple-history==2.11.0 # via -r requirements/edx/testing.txt, edx-enterprise, edx-organizations, ora2 +django-splash==0.2.9 # via -r requirements/edx/testing.txt django-statici18n==1.9.0 # via -r requirements/edx/testing.txt django-storages==1.8 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, edxval -django-user-tasks==1.0.0 # via -r requirements/edx/testing.txt -django-waffle==0.18.0 # via -r requirements/edx/testing.txt, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-proctoring +django-user-tasks==1.1.0 # via -r requirements/edx/testing.txt +django-waffle==1.0.0 # via -r requirements/edx/testing.txt, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-proctoring django-webpack-loader==0.7.0 # via -r requirements/edx/testing.txt, edx-proctoring -django==2.2.12 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, code-annotations, django-appconf, django-babel, django-babel-underscore, django-celery, django-classy-tags, django-config-models, django-cors-headers, django-crum, django-debug-toolbar, django-fernet-fields, django-filter, django-method-override, django-model-utils, django-mptt, django-multi-email-field, django-mysql, django-oauth-toolkit, django-pyfs, django-ratelimit-backend, django-sekizai, django-splash, django-statici18n, django-storages, django-user-tasks, django-wiki, drf-jwt, drf-yasg, edx-ace, edx-api-doc-tools, edx-bulk-grades, edx-celeryutils, edx-completion, edx-django-release-util, edx-django-sites-extensions, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-milestones, edx-opaque-keys, edx-organizations, edx-proctoring, edx-rbac, edx-search, edx-submissions, edx-when, edxval, event-tracking, help-tokens, jsonfield2, ora2, rest-condition, super-csv, xss-utils +django==2.2.13 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, code-annotations, django-appconf, django-celery, django-classy-tags, django-config-models, django-cors-headers, django-crum, django-debug-toolbar, django-fernet-fields, django-filter, django-method-override, django-model-utils, django-mptt, django-multi-email-field, django-mysql, django-oauth-toolkit, django-pyfs, django-ratelimit-backend, django-sekizai, django-splash, django-statici18n, django-storages, django-user-tasks, django-wiki, drf-jwt, drf-yasg, edx-ace, edx-api-doc-tools, edx-bulk-grades, edx-celeryutils, edx-completion, edx-django-release-util, edx-django-sites-extensions, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-milestones, edx-opaque-keys, edx-organizations, edx-proctoring, edx-rbac, edx-search, edx-submissions, edx-when, edxval, enmerkar, enmerkar-underscore, event-tracking, help-tokens, jsonfield2, lti-consumer-xblock, ora2, rest-condition, super-csv, xss-utils djangorestframework-xml==2.0.0 # via -r requirements/edx/testing.txt, edx-enterprise djangorestframework==3.9.4 # via -r requirements/edx/testing.txt, django-config-models, django-user-tasks, drf-jwt, drf-yasg, edx-api-doc-tools, edx-completion, edx-drf-extensions, edx-enterprise, edx-organizations, edx-proctoring, edx-submissions, ora2, rest-condition, super-csv docopt==0.6.2 # via -r requirements/edx/testing.txt, xmodule docutils==0.16 # via -r requirements/edx/testing.txt, botocore, m2r, sphinx drf-jwt==1.14.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, edx-drf-extensions drf-yasg==1.17.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, edx-api-doc-tools -edx-ace==0.1.14 # via -r requirements/edx/testing.txt -edx-analytics-data-api-client==0.15.5 # via -r requirements/edx/testing.txt -edx-api-doc-tools==1.2.0 # via -r requirements/edx/testing.txt +edx-ace==0.1.15 # via -r requirements/edx/testing.txt +edx-analytics-data-api-client==0.16.1 # via -r requirements/edx/testing.txt +edx-api-doc-tools==1.3.1 # via -r requirements/edx/testing.txt edx-bulk-grades==0.6.8 # via -r requirements/edx/testing.txt, staff-graded-xblock -edx-ccx-keys==1.0.1 # via -r requirements/edx/testing.txt +edx-ccx-keys==1.1.0 # via -r requirements/edx/testing.txt edx-celeryutils==0.5.0 # via -r requirements/edx/testing.txt, super-csv -edx-completion==3.1.1 # via -r requirements/edx/testing.txt -edx-django-release-util==0.4.2 # via -r requirements/edx/testing.txt -edx-django-sites-extensions==2.4.3 # via -r requirements/edx/testing.txt -edx-django-utils==3.2.0 # via -r requirements/edx/testing.txt, django-config-models, edx-drf-extensions, edx-enterprise, edx-rest-api-client, edx-when -edx-drf-extensions==5.0.2 # via -r requirements/edx/testing.txt, edx-completion, edx-enterprise, edx-organizations, edx-proctoring, edx-rbac, edx-when, edxval -edx-enterprise==3.1.0 # via -r requirements/edx/testing.txt -edx-i18n-tools==0.5.0 # via -r requirements/edx/testing.txt, ora2 +edx-completion==3.2.1 # via -r requirements/edx/testing.txt +edx-django-release-util==0.4.4 # via -r requirements/edx/testing.txt +edx-django-sites-extensions==2.5.1 # via -r requirements/edx/testing.txt +edx-django-utils==3.2.3 # via -r requirements/edx/testing.txt, django-config-models, edx-drf-extensions, edx-enterprise, edx-rest-api-client, edx-when +edx-drf-extensions==6.0.0 # via -r requirements/edx/testing.txt, edx-completion, edx-enterprise, edx-organizations, edx-proctoring, edx-rbac, edx-when, edxval +edx-enterprise==3.3.11 # via -r requirements/edx/testing.txt +edx-i18n-tools==0.5.3 # via -r requirements/edx/testing.txt, ora2 edx-lint==1.4.1 # via -r requirements/edx/testing.txt -edx-milestones==0.2.6 # via -r requirements/edx/testing.txt -edx-opaque-keys[django]==2.0.2 # via -r requirements/edx/testing.txt, edx-bulk-grades, edx-ccx-keys, edx-completion, edx-drf-extensions, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-user-state-client, edx-when, xmodule -edx-organizations==5.1.0 # via -r requirements/edx/testing.txt +edx-milestones==0.3.0 # via -r requirements/edx/testing.txt +edx-opaque-keys[django]==2.1.0 # via -r requirements/edx/testing.txt, edx-bulk-grades, edx-ccx-keys, edx-completion, edx-drf-extensions, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-user-state-client, edx-when, xmodule +edx-organizations==5.2.0 # via -r requirements/edx/testing.txt edx-proctoring-proctortrack==1.0.5 # via -r requirements/edx/testing.txt -edx-proctoring==2.3.3 # via -r requirements/edx/testing.txt, edx-proctoring-proctortrack -edx-rbac==1.1.3 # via -r requirements/edx/testing.txt, edx-enterprise -edx-rest-api-client==5.1.0 # via -r requirements/edx/testing.txt, edx-enterprise, edx-proctoring -edx-search==1.3.4 # via -r requirements/edx/testing.txt -edx-sga==0.10.0 # via -r requirements/edx/testing.txt +edx-proctoring==2.4.3 # via -r requirements/edx/testing.txt, edx-proctoring-proctortrack +edx-rbac==1.3.1 # via -r requirements/edx/testing.txt, edx-enterprise +edx-rest-api-client==5.2.1 # via -r requirements/edx/testing.txt, edx-enterprise, edx-proctoring +edx-search==1.4.1 # via -r requirements/edx/testing.txt +edx-sga==0.11.0 # via -r requirements/edx/testing.txt edx-sphinx-theme==1.5.0 # via -r requirements/edx/development.in -edx-submissions==3.0.7 # via -r requirements/edx/testing.txt, ora2 +edx-submissions==3.1.11 # via -r requirements/edx/testing.txt, ora2 edx-tincan-py35==0.0.5 # via -r requirements/edx/testing.txt, edx-enterprise -edx-user-state-client==1.1.2 # via -r requirements/edx/testing.txt -edx-when==1.2.0 # via -r requirements/edx/testing.txt, edx-proctoring -edxval==1.3.1 # via -r requirements/edx/testing.txt +edx-user-state-client==1.2.0 # via -r requirements/edx/testing.txt +edx-when==1.2.8 # via -r requirements/edx/testing.txt, edx-proctoring +edxval==1.3.8 # via -r requirements/edx/testing.txt elasticsearch==1.9.0 # via -r requirements/edx/testing.txt, edx-search -entrypoints==0.3 # via -r requirements/edx/testing.txt, flake8 -enum34==1.1.10 # via -r requirements/edx/testing.txt, edxval -event-tracking==0.3.0 # via -r requirements/edx/testing.txt, edx-proctoring, edx-search +enmerkar-underscore==1.0.0 # via -r requirements/edx/testing.txt +enmerkar==0.7.1 # via -r requirements/edx/testing.txt, enmerkar-underscore +event-tracking==0.3.2 # via -r requirements/edx/testing.txt, edx-proctoring, edx-search execnet==1.7.1 # via -r requirements/edx/testing.txt, pytest-xdist factory-boy==2.8.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt -faker==4.0.3 # via -r requirements/edx/testing.txt, factory-boy +faker==4.1.1 # via -r requirements/edx/testing.txt, factory-boy filelock==3.0.12 # via -r requirements/edx/testing.txt, tox, virtualenv flake8-polyfill==1.0.2 # via -r requirements/edx/testing.txt, radon -flake8==3.7.9 # via -r requirements/edx/testing.txt, flake8-polyfill +flake8==3.8.3 # via -r requirements/edx/testing.txt, flake8-polyfill freezegun==0.3.12 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt fs-s3fs==0.1.8 # via -r requirements/edx/testing.txt, django-pyfs fs==2.0.18 # via -r requirements/edx/testing.txt, django-pyfs, fs-s3fs, xblock future==0.18.2 # via -r requirements/edx/testing.txt, django-ses, edx-celeryutils, edx-enterprise, pycontracts, pyjwkest, radon geoip2==3.0.0 # via -r requirements/edx/testing.txt +gitdb==4.0.5 # via -r requirements/edx/testing.txt, gitpython +gitpython==3.1.3 # via -r requirements/edx/testing.txt, transifex-client glob2==0.7 # via -r requirements/edx/testing.txt gunicorn==20.0.4 # via -r requirements/edx/testing.txt -help-tokens==1.0.5 # via -r requirements/edx/testing.txt -html5lib==1.0.1 # via -r requirements/edx/testing.txt, ora2 -httplib2==0.17.2 # via -r requirements/edx/testing.txt, oauth2 +help-tokens==1.1.2 # via -r requirements/edx/testing.txt +html5lib==1.1 # via -r requirements/edx/testing.txt, ora2 httpretty==0.9.7 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt -icalendar==4.0.5 # via -r requirements/edx/testing.txt +icalendar==4.0.6 # via -r requirements/edx/testing.txt idna==2.9 # via -r requirements/edx/testing.txt, requests imagesize==1.2.0 # via sphinx -importlib-metadata==1.6.0 # via -r requirements/edx/testing.txt, importlib-resources, inflect, jsonschema, path, pluggy, pytest, pytest-randomly, tox, virtualenv -importlib-resources==1.4.0 # via -r requirements/edx/testing.txt, virtualenv +importlib-metadata==1.6.1 # via -r requirements/edx/testing.txt, flake8, importlib-resources, inflect, jsonschema, path, pluggy, pytest, pytest-randomly, tox, virtualenv +importlib-resources==2.0.1 # via -r requirements/edx/testing.txt, virtualenv inflect==3.0.2 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, jinja2-pluralize -inflection==0.4.0 # via -r requirements/edx/testing.txt, drf-yasg +inflection==0.5.0 # via -r requirements/edx/testing.txt, drf-yasg ipaddress==1.0.23 # via -r requirements/edx/testing.txt isodate==0.6.0 # via -r requirements/edx/testing.txt, python3-saml isort==4.3.21 # via -r requirements/edx/testing.txt, pylint -itypes==1.1.0 # via -r requirements/edx/testing.txt, coreapi +itypes==1.2.0 # via -r requirements/edx/testing.txt, coreapi jinja2-pluralize==0.3.0 # via -r requirements/edx/testing.txt, diff-cover jinja2==2.11.2 # via -r requirements/edx/testing.txt, code-annotations, coreschema, diff-cover, jinja2-pluralize, sphinx -jmespath==0.9.5 # via -r requirements/edx/testing.txt, boto3, botocore -joblib==0.14.1 # via -r requirements/edx/testing.txt, nltk +jmespath==0.10.0 # via -r requirements/edx/testing.txt, boto3, botocore +joblib==0.14.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, nltk jsondiff==1.2.0 # via -r requirements/edx/testing.txt, edx-enterprise jsonfield2==3.0.3 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, edx-celeryutils, edx-enterprise, edx-proctoring, edx-submissions, ora2 jsonschema==3.2.0 # via sphinxcontrib-openapi kombu==3.0.37 # via -r requirements/edx/testing.txt, celery laboratory==1.0.2 # via -r requirements/edx/testing.txt lazy-object-proxy==1.4.3 # via -r requirements/edx/testing.txt, astroid -lazy==1.4 # via -r requirements/edx/testing.txt, acid-xblock, bok-choy, ora2 +lazy==1.4 # via -r requirements/edx/testing.txt, acid-xblock, bok-choy, lti-consumer-xblock, ora2 lepl==5.1.3 # via -r requirements/edx/testing.txt, rfc6266-parser libsass==0.10.0 # via -r requirements/edx/testing.txt, ora2 loremipsum==1.0.5 # via -r requirements/edx/testing.txt, ora2 -git+https://github.com/edx/xblock-lti-consumer.git@v1.2.5#egg=lti_consumer-xblock==1.2.5 # via -r requirements/edx/testing.txt -lxml==4.5.0 # via -r requirements/edx/testing.txt, capa, edxval, lti-consumer-xblock, ora2, pyquery, safe-lxml, xblock, xmlsec +lti-consumer-xblock==1.4.2 # via -r requirements/edx/testing.txt +lxml==4.5.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, capa, edxval, lti-consumer-xblock, ora2, pyquery, safe-lxml, xblock, xmlsec m2r==0.2.1 # via sphinxcontrib-openapi mailsnake==1.6.4 # via -r requirements/edx/testing.txt -mako==1.0.2 # via -r requirements/edx/testing.txt, acid-xblock, lti-consumer-xblock, xblock-google-drive, xblock-utils +mako==1.1.3 # via -r requirements/edx/testing.txt, acid-xblock, lti-consumer-xblock, xblock-google-drive, xblock-utils mando==0.6.4 # via -r requirements/edx/testing.txt, radon markdown==2.6.11 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, django-wiki, staff-graded-xblock, xblock-poll -markey==0.8 # via -r requirements/edx/testing.txt, django-babel-underscore +markey==0.8 # via -r requirements/edx/testing.txt, enmerkar-underscore markupsafe==1.1.1 # via -r requirements/edx/testing.txt, chem, jinja2, mako, xblock -maxminddb==1.5.2 # via -r requirements/edx/testing.txt, geoip2 +maxminddb==1.5.4 # via -r requirements/edx/testing.txt, geoip2 mccabe==0.6.1 # via -r requirements/edx/testing.txt, flake8, pylint mistune==0.8.4 # via m2r mock==3.0.5 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, xblock-drag-and-drop-v2, xblock-poll git+https://github.com/edx/MongoDBProxy.git@d92bafe9888d2940f647a7b2b2383b29c752f35a#egg=MongoDBProxy==0.1.0+edx.2 # via -r requirements/edx/testing.txt -mongoengine==0.10.0 # via -r requirements/edx/testing.txt -more-itertools==8.2.0 # via -r requirements/edx/testing.txt, pytest, zipp +mongoengine==0.20.0 # via -r requirements/edx/testing.txt +more-itertools==8.4.0 # via -r requirements/edx/testing.txt, pytest, zipp mpmath==1.1.0 # via -r requirements/edx/testing.txt, sympy mysqlclient==1.4.6 # via -r requirements/edx/testing.txt -newrelic==5.12.0.140 # via -r requirements/edx/testing.txt, edx-django-utils +newrelic==5.14.1.144 # via -r requirements/edx/testing.txt, edx-django-utils nltk==3.5 # via -r requirements/edx/testing.txt, chem -nodeenv==1.3.5 # via -r requirements/edx/testing.txt -numpy==1.18.2 # via -r requirements/edx/testing.txt, chem, openedx-calc, pandas, scipy -git+https://github.com/joestump/python-oauth2.git@b94f69b1ad195513547924e380d9265133e995fa#egg=oauth2 # via -r requirements/edx/testing.txt +nodeenv==1.4.0 # via -r requirements/edx/testing.txt +numpy==1.18.5 # via -r requirements/edx/testing.txt, chem, openedx-calc, scipy oauthlib==3.0.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, django-oauth-toolkit, lti-consumer-xblock, requests-oauthlib, social-auth-core -openedx-calc==1.0.7 # via -r requirements/edx/testing.txt -git+https://github.com/edx/edx-ora2.git@2.6.25#egg=ora2==2.6.25 # via -r requirements/edx/testing.txt -packaging==20.3 # via -r requirements/edx/testing.txt, drf-yasg, pytest, sphinx, tox -pandas==0.22.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt +openedx-calc==1.0.9 # via -r requirements/edx/testing.txt +ora2==2.8.5 # via -r requirements/edx/testing.txt +packaging==20.4 # via -r requirements/edx/testing.txt, bleach, drf-yasg, pytest, sphinx, tox path.py==12.4.0 # via -r requirements/edx/testing.txt, edx-enterprise, edx-i18n-tools, ora2, xmodule path==13.1.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, path.py pathlib2==2.3.5 # via -r requirements/edx/testing.txt, pytest pathtools==0.1.2 # via -r requirements/edx/testing.txt, watchdog paver==1.3.4 # via -r requirements/edx/testing.txt pbr==5.4.5 # via -r requirements/edx/testing.txt, stevedore -pdfminer.six==20200402 # via -r requirements/edx/testing.txt +pdfminer.six==20200517 # via -r requirements/edx/testing.txt piexif==1.1.3 # via -r requirements/edx/testing.txt -pillow==7.1.1 # via -r requirements/edx/testing.txt, edx-enterprise, edx-organizations +pillow==7.1.2 # via -r requirements/edx/testing.txt, edx-enterprise, edx-organizations pip-tools==4.5.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/pip-tools.txt -pkgconfig==1.5.1 # via -r requirements/edx/testing.txt, xmlsec pluggy==0.13.1 # via -r requirements/edx/testing.txt, diff-cover, pytest, tox polib==1.1.0 # via -r requirements/edx/testing.txt, edx-i18n-tools psutil==1.2.1 # via -r requirements/edx/testing.txt, edx-django-utils py2neo==3.1.2 # via -r requirements/edx/testing.txt -py==1.8.1 # via -r requirements/edx/testing.txt, pytest, tox -pycodestyle==2.5.0 # via -r requirements/edx/testing.txt, flake8 -pycontracts==1.8.12 # via -r requirements/edx/testing.txt, edx-user-state-client +py==1.9.0 # via -r requirements/edx/testing.txt, pytest, tox +pycodestyle==2.6.0 # via -r requirements/edx/testing.txt, flake8 +pycontracts==1.8.14 # via -r requirements/edx/testing.txt, edx-user-state-client pycountry==19.8.18 # via -r requirements/edx/testing.txt pycparser==2.20 # via -r requirements/edx/testing.txt, cffi -pycryptodome==3.9.7 # via -r requirements/edx/testing.txt, pdfminer.six -pycryptodomex==3.9.7 # via -r requirements/edx/testing.txt, edx-proctoring, pyjwkest -pyflakes==2.1.1 # via -r requirements/edx/testing.txt, flake8 +pycryptodome==3.9.8 # via -r requirements/edx/testing.txt, pdfminer.six +pycryptodomex==3.9.8 # via -r requirements/edx/testing.txt, edx-proctoring, pyjwkest +pyflakes==2.2.0 # via -r requirements/edx/testing.txt, flake8 pygments==2.6.1 # via -r requirements/edx/testing.txt, diff-cover, sphinx -pyinotify==0.9.6 # via -r requirements/edx/development.in pyjwkest==1.4.2 # via -r requirements/edx/testing.txt, edx-drf-extensions pyjwt==1.5.2 # via -r requirements/edx/testing.txt, drf-jwt, edx-rest-api-client, social-auth-core pylint-celery==0.3 # via -r requirements/edx/testing.txt, edx-lint pylint-django==2.0.11 # via -r requirements/edx/testing.txt, edx-lint pylint-plugin-utils==0.6 # via -r requirements/edx/testing.txt, pylint-celery, pylint-django pylint==2.4.2 # via -r requirements/edx/testing.txt, edx-lint, pylint-celery, pylint-django, pylint-plugin-utils -pymongo==3.9.0 # via -r requirements/edx/testing.txt, edx-opaque-keys, event-tracking, mongodbproxy, mongoengine +pymongo==3.10.1 # via -r requirements/edx/testing.txt, edx-opaque-keys, event-tracking, mongodbproxy, mongoengine pynliner==0.8.0 # via -r requirements/edx/testing.txt -pyparsing==2.2.0 # via -r requirements/edx/testing.txt, chem, openedx-calc, packaging, pycontracts +pyparsing==2.4.7 # via -r requirements/edx/testing.txt, chem, openedx-calc, packaging, pycontracts pyquery==1.4.1 # via -r requirements/edx/testing.txt pyrsistent==0.16.0 # via jsonschema pysrt==1.1.2 # via -r requirements/edx/testing.txt, edxval pytest-attrib==0.1.3 # via -r requirements/edx/testing.txt -pytest-cov==2.8.1 # via -r requirements/edx/testing.txt +pytest-cov==2.10.0 # via -r requirements/edx/testing.txt pytest-django==3.8.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt -pytest-forked==1.1.3 # via -r requirements/edx/testing.txt, pytest-xdist +pytest-forked==1.2.0 # via -r requirements/edx/testing.txt, pytest-xdist pytest-json-report==1.2.1 # via -r requirements/edx/testing.txt pytest-metadata==1.8.0 # via -r requirements/edx/testing.txt, pytest-json-report -pytest-randomly==3.3.1 # via -r requirements/edx/testing.txt -pytest-xdist==1.31.0 # via -r requirements/edx/testing.txt +pytest-randomly==3.4.0 # via -r requirements/edx/testing.txt +pytest-xdist==1.32.0 # via -r requirements/edx/testing.txt pytest==5.3.5 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, pytest-attrib, pytest-cov, pytest-django, pytest-forked, pytest-json-report, pytest-metadata, pytest-randomly, pytest-xdist -python-dateutil==2.4.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, analytics-python, botocore, edx-ace, edx-drf-extensions, edx-enterprise, edx-proctoring, faker, freezegun, icalendar, ora2, pandas, xblock +python-dateutil==2.4.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, analytics-python, botocore, edx-ace, edx-drf-extensions, edx-enterprise, edx-proctoring, faker, freezegun, icalendar, ora2, xblock python-levenshtein==0.12.0 # via -r requirements/edx/testing.txt python-memcached==1.59 # via -r requirements/edx/testing.txt python-slugify==4.0.0 # via -r requirements/edx/testing.txt, code-annotations, transifex-client -python-swiftclient==3.9.0 # via -r requirements/edx/testing.txt, ora2 +python-swiftclient==3.10.0 # via -r requirements/edx/testing.txt, ora2 python3-openid==3.1.0 ; python_version >= "3" # via -r requirements/edx/testing.txt, social-auth-core python3-saml==1.9.0 # via -r requirements/edx/testing.txt -pytz==2019.3 # via -r requirements/edx/testing.txt, babel, capa, celery, django, django-ses, edx-completion, edx-enterprise, edx-proctoring, edx-submissions, edx-tincan-py35, event-tracking, fs, icalendar, ora2, pandas, xblock +pytz==2020.1 # via -r requirements/edx/testing.txt, babel, capa, celery, django, django-ses, edx-completion, edx-enterprise, edx-proctoring, edx-submissions, edx-tincan-py35, event-tracking, fs, icalendar, ora2, xblock pyuca==1.2 # via -r requirements/edx/testing.txt +pywatchman==1.4.1 # via -r requirements/edx/development.in pyyaml==5.3.1 # via -r requirements/edx/testing.txt, code-annotations, edx-django-release-util, edx-i18n-tools, sphinxcontrib-openapi, xblock radon==4.1.0 # via -r requirements/edx/testing.txt random2==1.0.1 # via -r requirements/edx/testing.txt -recommender-xblock==1.4.5 # via -r requirements/edx/testing.txt +recommender-xblock==1.4.8 # via -r requirements/edx/testing.txt redis==2.10.6 # via -r requirements/edx/testing.txt -regex==2020.4.4 # via -r requirements/edx/testing.txt, nltk +regex==2020.6.8 # via -r requirements/edx/testing.txt, nltk requests-oauthlib==1.3.0 # via -r requirements/edx/testing.txt, social-auth-core -requests==2.23.0 # via -r requirements/edx/testing.txt, analytics-python, coreapi, django-oauth-toolkit, edx-analytics-data-api-client, edx-bulk-grades, edx-drf-extensions, edx-enterprise, edx-rest-api-client, geoip2, mailsnake, pyjwkest, python-swiftclient, requests-oauthlib, sailthru-client, slumber, social-auth-core, sphinx, transifex-client +requests==2.24.0 # via -r requirements/edx/testing.txt, analytics-python, coreapi, django-oauth-toolkit, edx-analytics-data-api-client, edx-bulk-grades, edx-drf-extensions, edx-enterprise, edx-rest-api-client, geoip2, mailsnake, pyjwkest, python-swiftclient, requests-oauthlib, sailthru-client, slumber, social-auth-core, sphinx, transifex-client rest-condition==1.0.3 # via -r requirements/edx/testing.txt, edx-drf-extensions rfc6266-parser==0.0.6 # via -r requirements/edx/testing.txt ruamel.yaml.clib==0.2.0 # via -r requirements/edx/testing.txt, ruamel.yaml @@ -278,18 +272,20 @@ s3transfer==0.1.13 # via -r requirements/edx/testing.txt, boto3 sailthru-client==2.2.3 # via -r requirements/edx/testing.txt, edx-ace scipy==1.4.1 # via -r requirements/edx/testing.txt, chem, openedx-calc selenium==3.141.0 # via -r requirements/edx/testing.txt, bok-choy -semantic-version==2.8.4 # via -r requirements/edx/testing.txt, edx-drf-extensions +semantic-version==2.8.5 # via -r requirements/edx/testing.txt, edx-drf-extensions shapely==1.7.0 # via -r requirements/edx/testing.txt simplejson==3.17.0 # via -r requirements/edx/testing.txt, sailthru-client, super-csv, xblock-utils singledispatch==3.4.0.3 # via -r requirements/edx/testing.txt -six==1.14.0 # via -r requirements/edx/pip-tools.txt, -r requirements/edx/testing.txt, analytics-python, astroid, bleach, bok-choy, cryptography, diff-cover, django-appconf, django-classy-tags, django-countries, django-pyfs, django-sekizai, django-simple-history, django-statici18n, drf-yasg, edx-ace, edx-ccx-keys, edx-django-release-util, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-lint, edx-milestones, edx-opaque-keys, edx-rbac, edx-search, edx-sphinx-theme, event-tracking, freezegun, fs, fs-s3fs, help-tokens, html5lib, httpretty, isodate, jsonschema, libsass, mando, mock, openedx-calc, packaging, pathlib2, paver, pip-tools, pycontracts, pyjwkest, pytest-xdist, python-dateutil, python-memcached, python-swiftclient, singledispatch, social-auth-app-django, social-auth-core, sphinxcontrib-httpdomain, stevedore, tox, transifex-client, virtualenv, xblock +six==1.15.0 # via -r requirements/edx/pip-tools.txt, -r requirements/edx/testing.txt, analytics-python, astroid, bleach, bok-choy, chem, crowdsourcehinter-xblock, cryptography, diff-cover, django-classy-tags, django-countries, django-pyfs, django-sekizai, django-simple-history, django-statici18n, drf-yasg, edx-ace, edx-ccx-keys, edx-django-release-util, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-lint, edx-milestones, edx-opaque-keys, edx-rbac, edx-search, edx-sphinx-theme, event-tracking, freezegun, fs, fs-s3fs, help-tokens, html5lib, httpretty, isodate, jsonschema, libsass, mando, mock, openedx-calc, packaging, pathlib2, paver, pip-tools, pycontracts, pyjwkest, pytest-xdist, python-dateutil, python-memcached, python-swiftclient, singledispatch, social-auth-app-django, social-auth-core, sphinxcontrib-httpdomain, stevedore, tox, transifex-client, virtualenv, xblock slumber==0.7.1 # via -r requirements/edx/testing.txt, edx-bulk-grades, edx-enterprise, edx-rest-api-client +smmap==3.0.4 # via -r requirements/edx/testing.txt, gitdb snowballstemmer==2.0.0 # via sphinx +social-auth-app-django==4.0.0 # via -r requirements/edx/testing.txt social-auth-core==3.3.3 # via -r requirements/edx/testing.txt, social-auth-app-django -git+https://github.com/jazzband/sorl-thumbnail.git@13bedfb7d2970809eda597e3ef79318a6fa80ac2#egg=sorl-thumbnail # via -r requirements/edx/testing.txt -sortedcontainers==2.1.0 # via -r requirements/edx/testing.txt, pdfminer.six -soupsieve==2.0 # via -r requirements/edx/testing.txt, beautifulsoup4 -sphinx==3.0.1 # via edx-sphinx-theme, sphinxcontrib-httpdomain +sorl-thumbnail==12.6.3 # via -r requirements/edx/testing.txt +sortedcontainers==2.2.2 # via -r requirements/edx/testing.txt, pdfminer.six +soupsieve==2.0.1 # via -r requirements/edx/testing.txt, beautifulsoup4 +sphinx==3.1.1 # via edx-sphinx-theme, sphinxcontrib-httpdomain sphinxcontrib-applehelp==1.0.2 # via sphinx sphinxcontrib-devhelp==1.0.2 # via sphinx sphinxcontrib-htmlhelp==1.0.3 # via sphinx @@ -299,38 +295,39 @@ sphinxcontrib-openapi[markdown]==0.6.0 # via -r requirements/edx/development.in sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.4 # via sphinx sqlparse==0.3.1 # via -r requirements/edx/testing.txt, django, django-debug-toolbar -staff-graded-xblock==0.7 # via -r requirements/edx/testing.txt -stevedore==1.32.0 # via -r requirements/edx/testing.txt, code-annotations, edx-ace, edx-enterprise, edx-opaque-keys -super-csv==0.9.7 # via -r requirements/edx/testing.txt, edx-bulk-grades -sympy==1.5.1 # via -r requirements/edx/testing.txt, symmath -testfixtures==6.14.0 # via -r requirements/edx/testing.txt, edx-enterprise +staff-graded-xblock==0.8 # via -r requirements/edx/testing.txt +stevedore==1.32.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, code-annotations, edx-ace, edx-enterprise, edx-opaque-keys +super-csv==0.9.9 # via -r requirements/edx/testing.txt, edx-bulk-grades +sympy==1.6 # via -r requirements/edx/testing.txt, symmath +testfixtures==6.14.1 # via -r requirements/edx/testing.txt, edx-enterprise text-unidecode==1.3 # via -r requirements/edx/testing.txt, faker, python-slugify -toml==0.10.0 # via -r requirements/edx/testing.txt, tox -tox-battery==0.5.2 # via -r requirements/edx/testing.txt -tox==3.14.6 # via -r requirements/edx/testing.txt, tox-battery -tqdm==4.45.0 # via -r requirements/edx/testing.txt, nltk -transifex-client==0.13.4 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt +toml==0.10.1 # via -r requirements/edx/testing.txt, tox +tox-battery==0.6.1 # via -r requirements/edx/testing.txt +tox==3.15.2 # via -r requirements/edx/testing.txt, tox-battery +tqdm==4.46.1 # via -r requirements/edx/testing.txt, nltk +transifex-client==0.13.10 # via -r requirements/edx/testing.txt typed-ast==1.4.1 # via -r requirements/edx/testing.txt, astroid unicodecsv==0.14.1 # via -r requirements/edx/testing.txt, edx-enterprise -unidiff==0.5.5 # via -r requirements/edx/testing.txt, coverage-pytest-plugin +unidiff==0.6.0 # via -r requirements/edx/testing.txt +git+https://github.com/nedbat/coverage_pytest_plugin.git@29de030251471e200ff255eb9e549218cd60e872#egg=coverage_pytest_plugin==0.0 # via -r requirements/edx/testing.txt uritemplate==3.0.1 # via -r requirements/edx/testing.txt, coreapi, drf-yasg urllib3==1.25.9 # via -r requirements/edx/testing.txt, elasticsearch, geoip2, requests, selenium, transifex-client -user-util==0.1.5 # via -r requirements/edx/testing.txt -virtualenv==20.0.18 # via -r requirements/edx/testing.txt, tox +user-util==0.2 # via -r requirements/edx/testing.txt +virtualenv==20.0.25 # via -r requirements/edx/testing.txt, tox voluptuous==0.11.7 # via -r requirements/edx/testing.txt, ora2 -vulture==1.4 # via -r requirements/edx/development.in -watchdog==0.10.2 # via -r requirements/edx/testing.txt -wcwidth==0.1.9 # via -r requirements/edx/testing.txt, pytest -web-fragments==0.3.1 # via -r requirements/edx/testing.txt, staff-graded-xblock, xblock, xblock-utils +vulture==1.5 # via -r requirements/edx/development.in +watchdog==0.10.3 # via -r requirements/edx/testing.txt +wcwidth==0.2.5 # via -r requirements/edx/testing.txt, pytest +web-fragments==0.3.2 # via -r requirements/edx/testing.txt, crowdsourcehinter-xblock, staff-graded-xblock, xblock, xblock-utils webencodings==0.5.1 # via -r requirements/edx/testing.txt, bleach, html5lib webob==1.8.6 # via -r requirements/edx/testing.txt, xblock, xmodule wrapt==1.11.2 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, astroid git+https://github.com/edx-solutions/xblock-drag-and-drop-v2@v2.2.10#egg=xblock-drag-and-drop-v2==2.2.10 # via -r requirements/edx/testing.txt git+https://github.com/open-craft/xblock-poll@da2d8fd21791a7af128595cf82bee83ee579e00f#egg=xblock-poll==1.9.6 # via -r requirements/edx/testing.txt -xblock-utils==2.0.0 # via -r requirements/edx/testing.txt, edx-sga, lti-consumer-xblock, staff-graded-xblock, xblock-drag-and-drop-v2, xblock-google-drive -xblock==1.2.9 # via -r requirements/edx/testing.txt, acid-xblock, crowdsourcehinter-xblock, done-xblock, edx-completion, edx-sga, edx-user-state-client, edx-when, lti-consumer-xblock, ora2, rate-xblock, staff-graded-xblock, xblock-discussion, xblock-drag-and-drop-v2, xblock-google-drive, xblock-poll, xblock-utils -xmlsec==1.3.3 # via -r requirements/edx/testing.txt, python3-saml -xss-utils==0.1.2 # via -r requirements/edx/testing.txt +xblock-utils==2.1.1 # via -r requirements/edx/testing.txt, edx-sga, lti-consumer-xblock, staff-graded-xblock, xblock-drag-and-drop-v2, xblock-google-drive +xblock==1.3.1 # via -r requirements/edx/testing.txt, acid-xblock, crowdsourcehinter-xblock, done-xblock, edx-completion, edx-sga, edx-user-state-client, edx-when, lti-consumer-xblock, ora2, rate-xblock, staff-graded-xblock, xblock-discussion, xblock-drag-and-drop-v2, xblock-google-drive, xblock-poll, xblock-utils +xmlsec==1.3.8 # via -r requirements/edx/testing.txt, python3-saml +xss-utils==0.1.3 # via -r requirements/edx/testing.txt zipp==1.0.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt, importlib-metadata, importlib-resources # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/edx/django.txt b/requirements/edx/django.txt index 7ed065eef7b48270387940bc4b515fac73bd0125..bc97368c7b4b93163ccc961926ecadfbe0b0c121 100644 --- a/requirements/edx/django.txt +++ b/requirements/edx/django.txt @@ -1,2 +1 @@ -django-oauth-toolkit==1.3.2 # via -r requirements/edx/base.in -django==2.2.12 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, code-annotations, django-appconf, django-babel, django-babel-underscore, django-celery, django-classy-tags, django-config-models, django-cors-headers, django-crum, django-fernet-fields, django-filter, django-method-override, django-model-utils, django-mptt, django-multi-email-field, django-mysql, django-oauth-toolkit, django-pyfs, django-ratelimit-backend, django-sekizai, django-splash, django-statici18n, django-storages, django-user-tasks, django-wiki, drf-jwt, drf-yasg, edx-ace, edx-api-doc-tools, edx-bulk-grades, edx-celeryutils, edx-completion, edx-django-release-util, edx-django-sites-extensions, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-milestones, edx-opaque-keys, edx-organizations, edx-proctoring, edx-rbac, edx-search, edx-submissions, edx-when, edxval, event-tracking, help-tokens, jsonfield2, ora2, rest-condition, super-csv, xss-utils +django==2.2.13 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, code-annotations, django-appconf, django-celery, django-classy-tags, django-config-models, django-cors-headers, django-crum, django-fernet-fields, django-filter, django-method-override, django-model-utils, django-mptt, django-multi-email-field, django-mysql, django-oauth-toolkit, django-pyfs, django-ratelimit-backend, django-sekizai, django-splash, django-statici18n, django-storages, django-user-tasks, django-wiki, drf-jwt, drf-yasg, edx-ace, edx-api-doc-tools, edx-bulk-grades, edx-celeryutils, edx-completion, edx-django-release-util, edx-django-sites-extensions, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-milestones, edx-opaque-keys, edx-organizations, edx-proctoring, edx-rbac, edx-search, edx-submissions, edx-when, edxval, enmerkar, enmerkar-underscore, event-tracking, help-tokens, jsonfield2, lti-consumer-xblock, ora2, rest-condition, super-csv, xss-utils diff --git a/requirements/edx/django111.txt b/requirements/edx/django111.txt deleted file mode 100644 index 5fd3c860e55f758c9c4310c8612766ae40038734..0000000000000000000000000000000000000000 --- a/requirements/edx/django111.txt +++ /dev/null @@ -1,2 +0,0 @@ -Django>=1.11,<1.12 -django-oauth-toolkit==1.1.3 diff --git a/requirements/edx/django20.txt b/requirements/edx/django20.txt deleted file mode 100644 index 15e047d8aef4ab79b6a6ba1b3bafd45cbe0cdba9..0000000000000000000000000000000000000000 --- a/requirements/edx/django20.txt +++ /dev/null @@ -1,2 +0,0 @@ -Django>=2.0,<2.1 -django-oauth-toolkit==1.3.2 diff --git a/requirements/edx/django21.txt b/requirements/edx/django21.txt deleted file mode 100644 index f6121d069100c49fceaea7756ade9b8c6be946e4..0000000000000000000000000000000000000000 --- a/requirements/edx/django21.txt +++ /dev/null @@ -1,3 +0,0 @@ -Django>=2.1,<2.2 -django-oauth-toolkit==1.3.2 - diff --git a/requirements/edx/django30.txt b/requirements/edx/django30.txt new file mode 100644 index 0000000000000000000000000000000000000000..d6e4bf2cdab49e289880522f31d92c3b4a898472 --- /dev/null +++ b/requirements/edx/django30.txt @@ -0,0 +1 @@ +Django>=3.0,<3.1 diff --git a/requirements/edx/github.in b/requirements/edx/github.in index 38e4c9f98b02dc9f1e776851d358449c0f1c220a..20f609d803fb16cbdaa5bf14aa044a4582bf5eb1 100644 --- a/requirements/edx/github.in +++ b/requirements/edx/github.in @@ -52,52 +52,24 @@ # Python libraries to install directly from github -git+https://github.com/edx/openedx-chem.git@ff4e3a03d3c7610e47a9af08eb648d8aabe2eb18#egg=chem==1.0.0 # Third-party: -e git+https://github.com/edx/django-wiki.git@0.0.27#egg=django-wiki git+https://github.com/edx/MongoDBProxy.git@d92bafe9888d2940f647a7b2b2383b29c752f35a#egg=MongoDBProxy==0.1.0+edx.2 --e git+https://github.com/dementrock/pystache_custom.git@776973740bdaad83a3b029f96e415a7d1e8bec2f#egg=pystache_custom-dev -e git+https://github.com/jazkarta/edx-jsme.git@690dbf75441fa91c7c4899df0b83d77f7deb5458#egg=edx-jsme --e git+https://github.com/jsocol/django-ratelimit.git@72edbe8949fbf6699848e5847645a1998f121d46#egg=ratelimit - -# This fork adds django>1.11 and django<3 compatibility for django-babel-underscore. Enmerkar is -# being installed from github to add backward compatibility for django1.11 as named versions are not -# backward compatible. -git+https://github.com/edx/django-babel-underscore.git@37705f7377a4d0a4e673f1431895ce28a8860cd7#egg=django-babel-underscore==0.6.0 -git+https://github.com/Zegocover/enmerkar.git@dbc113798aa4beabdfa2d00e6fef48248eb0f185#egg=django-babel==0.6.3.dev0 - -# Forked to get Django 2.2 support from unreleased master branch from social-app-django repo. -# This can be removed once an official social-auth-app-django Pypi release with Django 2.2 support is available in the future. --e git+https://github.com/python-social-auth/social-app-django.git@c00d23c2b45c3317bd35b15ad1b959338689cef8#egg=social-auth-app-django -# Why install sorl-thumbnail directly from github? To use the latest, Django 2.2 compatible version that is not available on PyPi yet. -# This dependency will be removed after package is updated at PyPi -git+https://github.com/jazzband/sorl-thumbnail.git@13bedfb7d2970809eda597e3ef79318a6fa80ac2#egg=sorl-thumbnail - -# Forked to fix predicate inversion and keep support for Django 1.1 alive -# Once https://github.com/excitedleigh/bridgekeeper/pull/10 is merged, and we get to django 2, we can -# remove this fork -git+https://github.com/edx/bridgekeeper.git@2423e8d8788c2132ebeec509e1a7b17e1f5b9364#egg=bridgekeeper==0.0 - -# Forked to get Django 1.11 new style middleware support from django-method-override. -# This can be removed once edx-platform is using django>=2.x. -git+https://gitlab.com/Ayub-khan/django-method-override.git@5270af321be2e576d8e8b3c4191711a19975c356#egg=django-method-override==1.0.4 +# The latest 2.0.0 release doesn't yet support Django 2.2, this commit from master does +-e git+https://github.com/jsocol/django-ratelimit.git@72edbe8949fbf6699848e5847645a1998f121d46#egg=ratelimit # Our libraries: -e git+https://github.com/edx/codejail.git@4127fc4bd5775cc72aee8d7f0a70e31405e22439#egg=codejail -e git+https://github.com/edx/acid-block.git@98aecba94ecbfa934e2d00262741c0ea9f557fc9#egg=acid-xblock -git+https://github.com/edx/edx-ora2.git@2.6.25#egg=ora2==2.6.25 -git+https://github.com/edx/crowdsourcehinter.git@2178ac72891392106ffef389651aef374177d294#egg=crowdsourcehinter-xblock==0.4 -e git+https://github.com/edx/RateXBlock.git@2.0#egg=rate-xblock --e git+https://github.com/edx/DoneXBlock.git@2.0.1#egg=done-xblock +-e git+https://github.com/edx/DoneXBlock.git@2.0.2#egg=done-xblock -e git+https://github.com/edx-solutions/xblock-google-drive.git@2d176468e33c0713c911b563f8f65f7cf232f5b6#egg=xblock-google-drive -git+https://github.com/edx/xblock-lti-consumer.git@v1.2.5#egg=lti_consumer-xblock==1.2.5 # Third Party XBlocks -git+https://github.com/joestump/python-oauth2.git@b94f69b1ad195513547924e380d9265133e995fa#egg=oauth2 git+https://github.com/open-craft/xblock-poll@da2d8fd21791a7af128595cf82bee83ee579e00f#egg=xblock-poll==1.9.6 git+https://github.com/edx-solutions/xblock-drag-and-drop-v2@v2.2.10#egg=xblock-drag-and-drop-v2==2.2.10 -git+https://github.com/django-compressor/django-appconf@1526a842ee084b791aa66c931b3822091a442853#egg=django-appconf diff --git a/requirements/edx/paver.in b/requirements/edx/paver.in index 1a4266a2bee731976892520b116fea180961a834..a5f1aa37ee70df6061a55bdd6887809fc4e00c17 100644 --- a/requirements/edx/paver.in +++ b/requirements/edx/paver.in @@ -18,7 +18,7 @@ mock # Stub out code with mock objects and make a path # Easier manipulation of filesystem paths paver # Build, distribution and deployment scripting tool psutil==1.2.1 # Library for retrieving information on running processes and system utilization -pymongo==3.9.0 # via edx-opaque-keys +pymongo # via edx-opaque-keys python-memcached # Python interface to the memcached memory cache daemon requests # Simple interface for making HTTP requests stevedore # Support for runtime plugins, used for XBlocks and edx-platform Django app plugins diff --git a/requirements/edx/paver.txt b/requirements/edx/paver.txt index 2bd1bba2651794eb470d1ce51246a3c91981861e..2272389d1a442d302b4702d38b75a308a1a79b1a 100644 --- a/requirements/edx/paver.txt +++ b/requirements/edx/paver.txt @@ -4,27 +4,27 @@ # # make upgrade # -certifi==2020.4.5.1 # via requests +certifi==2020.6.20 # via requests chardet==3.0.4 # via requests -edx-opaque-keys==2.0.2 # via -r requirements/edx/paver.in +edx-opaque-keys==2.1.0 # via -r requirements/edx/paver.in idna==2.9 # via requests -importlib-metadata==1.6.0 # via path +importlib-metadata==1.6.1 # via path lazy==1.4 # via -r requirements/edx/paver.in libsass==0.10.0 # via -r requirements/edx/paver.in markupsafe==1.1.1 # via -r requirements/edx/paver.in mock==3.0.5 # via -c requirements/edx/../constraints.txt, -r requirements/edx/paver.in -more-itertools==8.2.0 # via zipp +more-itertools==8.4.0 # via zipp path==13.1.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/paver.in pathtools==0.1.2 # via watchdog paver==1.3.4 # via -r requirements/edx/paver.in pbr==5.4.5 # via stevedore psutil==1.2.1 # via -r requirements/edx/paver.in -pymongo==3.9.0 # via -r requirements/edx/paver.in, edx-opaque-keys +pymongo==3.10.1 # via -r requirements/edx/paver.in, edx-opaque-keys python-memcached==1.59 # via -r requirements/edx/paver.in -requests==2.23.0 # via -r requirements/edx/paver.in -six==1.14.0 # via edx-opaque-keys, libsass, mock, paver, python-memcached, stevedore -stevedore==1.32.0 # via -r requirements/edx/paver.in, edx-opaque-keys +requests==2.24.0 # via -r requirements/edx/paver.in +six==1.15.0 # via edx-opaque-keys, libsass, mock, paver, python-memcached, stevedore +stevedore==1.32.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/paver.in, edx-opaque-keys urllib3==1.25.9 # via requests -watchdog==0.10.2 # via -r requirements/edx/paver.in +watchdog==0.10.3 # via -r requirements/edx/paver.in wrapt==1.11.2 # via -c requirements/edx/../constraints.txt, -r requirements/edx/paver.in zipp==1.0.0 # via -c requirements/edx/../constraints.txt, importlib-metadata diff --git a/requirements/edx/pip-tools.txt b/requirements/edx/pip-tools.txt index 5a1616c8ee0df1f91c2b56813e4c5c0ceb2fa1ec..38a6e8cbed776d976c8b941f9566b3a3c65f8c50 100644 --- a/requirements/edx/pip-tools.txt +++ b/requirements/edx/pip-tools.txt @@ -4,6 +4,6 @@ # # make upgrade # -click==7.1.1 # via pip-tools +click==7.1.2 # via pip-tools pip-tools==4.5.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/pip-tools.in -six==1.14.0 # via -r requirements/edx/pip-tools.in, pip-tools +six==1.15.0 # via -r requirements/edx/pip-tools.in, pip-tools diff --git a/requirements/edx/testing.in b/requirements/edx/testing.in index 1a5b5c279d6b503420050b7c6abe62f006a9707d..e2ce4928ec236a6e12a16e921bc4b11081be3117 100644 --- a/requirements/edx/testing.in +++ b/requirements/edx/testing.in @@ -38,6 +38,7 @@ pytest-cov # pytest plugin for measuring code coverage git+https://github.com/nedbat/coverage_pytest_plugin.git@29de030251471e200ff255eb9e549218cd60e872#egg=coverage_pytest_plugin==0.0 pytest-django # Django support for pytest pytest-json-report # Output json formatted warnings after running pytest +pytest-metadata==1.8.0 # To prevent 'make upgrade' failure, dependency of pytest-json-report pytest-randomly # pytest plugin to randomly order tests pytest-xdist # Parallel execution of tests on multiple CPU cores or hosts radon # Calculates cyclomatic complexity of Python code (code quality utility) diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index cc6cd01ce148e58156df6479b773c6d5d92bd3a2..875362483389a14cc72ac2ee6af5cfb5795418af 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -9,14 +9,12 @@ -e git+https://github.com/edx/codejail.git@4127fc4bd5775cc72aee8d7f0a70e31405e22439#egg=codejail # via -r requirements/edx/base.txt -e git+https://github.com/jsocol/django-ratelimit.git@72edbe8949fbf6699848e5847645a1998f121d46#egg=ratelimit # via -r requirements/edx/base.txt -e git+https://github.com/edx/django-wiki.git@0.0.27#egg=django-wiki # via -r requirements/edx/base.txt --e git+https://github.com/edx/DoneXBlock.git@2.0.1#egg=done-xblock # via -r requirements/edx/base.txt +-e git+https://github.com/edx/DoneXBlock.git@2.0.2#egg=done-xblock # via -r requirements/edx/base.txt -e git+https://github.com/jazkarta/edx-jsme.git@690dbf75441fa91c7c4899df0b83d77f7deb5458#egg=edx-jsme # via -r requirements/edx/base.txt -e . # via -r requirements/edx/base.txt --e git+https://github.com/dementrock/pystache_custom.git@776973740bdaad83a3b029f96e415a7d1e8bec2f#egg=pystache_custom-dev # via -r requirements/edx/base.txt -e git+https://github.com/edx/RateXBlock.git@2.0#egg=rate-xblock # via -r requirements/edx/base.txt -e common/lib/safe_lxml # via -r requirements/edx/base.txt -e common/lib/sandbox-packages # via -r requirements/edx/base.txt --e git+https://github.com/python-social-auth/social-app-django.git@c00d23c2b45c3317bd35b15ad1b959338689cef8#egg=social-auth-app-django # via -r requirements/edx/base.txt -e common/lib/symmath # via -r requirements/edx/base.txt -e openedx/core/lib/xblock_builtin/xblock_discussion # via -r requirements/edx/base.txt -e git+https://github.com/edx-solutions/xblock-google-drive.git@2d176468e33c0713c911b563f8f65f7cf232f5b6#egg=xblock-google-drive # via -r requirements/edx/base.txt @@ -26,72 +24,71 @@ analytics-python==1.2.9 # via -r requirements/edx/base.txt aniso8601==8.0.0 # via -r requirements/edx/base.txt, edx-tincan-py35 anyjson==0.3.3 # via -r requirements/edx/base.txt, kombu apipkg==1.5 # via execnet -appdirs==1.4.3 # via -r requirements/edx/base.txt, fs, virtualenv +appdirs==1.4.4 # via -r requirements/edx/base.txt, fs, virtualenv astroid==2.3.3 # via pylint, pylint-celery attrs==19.3.0 # via -r requirements/edx/base.txt, edx-ace, pytest -babel==2.8.0 # via -r requirements/edx/base.txt, django-babel, django-babel-underscore -beautifulsoup4==4.9.0 # via -r requirements/edx/base.txt, -r requirements/edx/testing.in, pynliner +babel==2.8.0 # via -r requirements/edx/base.txt, enmerkar, enmerkar-underscore +beautifulsoup4==4.9.1 # via -r requirements/edx/base.txt, -r requirements/edx/testing.in, pynliner billiard==3.3.0.23 # via -r requirements/edx/base.txt, celery -bleach==3.1.4 # via -r requirements/edx/base.txt, edx-enterprise, lti-consumer-xblock, ora2 -bok-choy==1.0.1 # via -r requirements/edx/testing.in +bleach==3.1.5 # via -r requirements/edx/base.txt, edx-enterprise, lti-consumer-xblock, ora2 +bok-choy==1.1.1 # via -r requirements/edx/testing.in boto3==1.4.8 # via -r requirements/edx/base.txt, fs-s3fs boto==2.39.0 # via -r requirements/edx/base.txt, django-ses, edxval, ora2 botocore==1.8.17 # via -r requirements/edx/base.txt, boto3, s3transfer -git+https://github.com/edx/bridgekeeper.git@2423e8d8788c2132ebeec509e1a7b17e1f5b9364#egg=bridgekeeper==0.0 # via -r requirements/edx/base.txt +bridgekeeper==0.8 # via -r requirements/edx/base.txt celery==3.1.26.post2 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, django-celery, django-user-tasks, edx-celeryutils, edx-enterprise -certifi==2020.4.5.1 # via -r requirements/edx/base.txt, requests +certifi==2020.6.20 # via -r requirements/edx/base.txt, requests cffi==1.14.0 # via -r requirements/edx/base.txt, cryptography chardet==3.0.4 # via -r requirements/edx/base.txt, pdfminer.six, pysrt, requests -git+https://github.com/edx/openedx-chem.git@ff4e3a03d3c7610e47a9af08eb648d8aabe2eb18#egg=chem==1.0.0 # via -r requirements/edx/base.txt +chem==1.2.0 # via -r requirements/edx/base.txt click-log==0.3.2 # via edx-lint -click==7.1.1 # via -r requirements/edx/base.txt, click-log, code-annotations, edx-lint, nltk, user-util -code-annotations==0.3.3 # via -r requirements/edx/base.txt, -r requirements/edx/testing.in, edx-enterprise +click==7.1.2 # via -r requirements/edx/base.txt, click-log, code-annotations, edx-lint, nltk, user-util +code-annotations==0.3.4 # via -r requirements/edx/base.txt, -r requirements/edx/testing.in, edx-enterprise colorama==0.4.1 # via radon contextlib2==0.6.0.post1 # via -r requirements/edx/base.txt coreapi==2.3.3 # via -r requirements/edx/base.txt, drf-yasg coreschema==0.0.4 # via -r requirements/edx/base.txt, coreapi, drf-yasg coverage==5.1 # via -r requirements/edx/coverage.txt, pytest-cov -git+https://github.com/nedbat/coverage_pytest_plugin.git@29de030251471e200ff255eb9e549218cd60e872#egg=coverage_pytest_plugin==0.0 # via -r requirements/edx/testing.in -git+https://github.com/edx/crowdsourcehinter.git@2178ac72891392106ffef389651aef374177d294#egg=crowdsourcehinter-xblock==0.4 # via -r requirements/edx/base.txt -cryptography==2.9 # via -r requirements/edx/base.txt, django-fernet-fields, edx-enterprise, social-auth-core +crowdsourcehinter-xblock==0.6 # via -r requirements/edx/base.txt +cryptography==2.9.2 # via -r requirements/edx/base.txt, django-fernet-fields, edx-enterprise, social-auth-core cssselect==1.1.0 # via -r requirements/edx/testing.in, pyquery cssutils==1.0.2 # via -r requirements/edx/base.txt, pynliner -ddt==1.3.1 # via -r requirements/edx/base.txt, -r requirements/edx/testing.in, xblock-drag-and-drop-v2, xblock-poll +ddt==1.3.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, -r requirements/edx/testing.in, xblock-drag-and-drop-v2, xblock-poll decorator==4.4.2 # via -r requirements/edx/base.txt, pycontracts -defusedxml==0.6.0 # via -r requirements/edx/base.txt, djangorestframework-xml, ora2, python3-openid, python3-saml, safe-lxml, social-auth-core -diff-cover==2.6.1 # via -r requirements/edx/coverage.txt +defusedxml==0.7.0rc1 # via -r requirements/edx/base.txt, djangorestframework-xml, ora2, python3-openid, python3-saml, safe-lxml, social-auth-core +diff-cover==3.0.1 # via -r requirements/edx/coverage.txt distlib==0.3.0 # via virtualenv -git+https://github.com/django-compressor/django-appconf@1526a842ee084b791aa66c931b3822091a442853#egg=django-appconf # via -r requirements/edx/base.txt, django-statici18n -git+https://github.com/edx/django-babel-underscore.git@37705f7377a4d0a4e673f1431895ce28a8860cd7#egg=django-babel-underscore==0.6.0 # via -r requirements/edx/base.txt -git+https://github.com/Zegocover/enmerkar.git@dbc113798aa4beabdfa2d00e6fef48248eb0f185#egg=django-babel==0.6.3.dev0 # via -r requirements/edx/base.txt +django-appconf==1.0.4 # via -r requirements/edx/base.txt, django-statici18n django-celery==3.3.1 # via -r requirements/edx/base.txt django-classy-tags==1.0.0 # via -r requirements/edx/base.txt, django-sekizai -django-config-models==2.0.0 # via -r requirements/edx/base.txt, edx-enterprise +django-config-models==2.0.2 # via -r requirements/edx/base.txt, edx-enterprise +django-cookies-samesite==0.5.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt django-cors-headers==2.5.3 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt django-countries==5.5 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, edx-enterprise -django-crum==0.7.5 # via -r requirements/edx/base.txt, edx-enterprise, edx-proctoring, edx-rbac, super-csv +django-crum==0.7.6 # via -r requirements/edx/base.txt, edx-enterprise, edx-proctoring, edx-rbac, super-csv django-fernet-fields==0.6 # via -r requirements/edx/base.txt, edx-enterprise, edxval -django-filter==2.2.0 # via -r requirements/edx/base.txt, edx-enterprise +django-filter==2.3.0 # via -r requirements/edx/base.txt, edx-enterprise django-ipware==2.1.0 # via -r requirements/edx/base.txt, edx-enterprise, edx-proctoring django-js-asset==1.2.2 # via -r requirements/edx/base.txt, django-mptt -git+https://gitlab.com/Ayub-khan/django-method-override.git@5270af321be2e576d8e8b3c4191711a19975c356#egg=django-method-override==1.0.4 # via -r requirements/edx/base.txt -django-model-utils==3.2.0 # via -r requirements/edx/base.txt, django-user-tasks, edx-bulk-grades, edx-celeryutils, edx-completion, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-rbac, edx-submissions, edx-when, edxval, ora2, super-csv +django-method-override==1.0.4 # via -r requirements/edx/base.txt +django-model-utils==4.0.0 # via -r requirements/edx/base.txt, django-user-tasks, edx-bulk-grades, edx-celeryutils, edx-completion, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-rbac, edx-submissions, edx-when, edxval, ora2, super-csv django-mptt==0.11.0 # via -r requirements/edx/base.txt, django-wiki django-multi-email-field==0.6.1 # via -r requirements/edx/base.txt, edx-enterprise -django-mysql==3.4.0 # via -r requirements/edx/base.txt +django-mysql==3.7.1 # via -r requirements/edx/base.txt +django-oauth-toolkit==1.3.2 # via -r requirements/edx/base.txt django-object-actions==2.0.0 # via -r requirements/edx/base.txt, edx-enterprise -django-pipeline==1.7.0 # via -r requirements/edx/base.txt +django-pipeline==1.7.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt django-pyfs==2.1 # via -r requirements/edx/base.txt django-ratelimit-backend==2.0 # via -r requirements/edx/base.txt django-require==1.0.11 # via -r requirements/edx/base.txt django-sekizai==1.1.0 # via -r requirements/edx/base.txt, django-wiki -django-ses==0.8.14 # via -r requirements/edx/base.txt -django-simple-history==2.8.0 # via -r requirements/edx/base.txt, edx-enterprise, edx-organizations, ora2 -django-splash==0.2.7 # via -r requirements/edx/base.txt +django-ses==0.8.14 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt +django-simple-history==2.11.0 # via -r requirements/edx/base.txt, edx-enterprise, edx-organizations, ora2 +django-splash==0.2.9 # via -r requirements/edx/base.txt django-statici18n==1.9.0 # via -r requirements/edx/base.txt django-storages==1.8 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, edxval -django-user-tasks==1.0.0 # via -r requirements/edx/base.txt -django-waffle==0.18.0 # via -r requirements/edx/base.txt, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-proctoring +django-user-tasks==1.1.0 # via -r requirements/edx/base.txt +django-waffle==1.0.0 # via -r requirements/edx/base.txt, edx-django-utils, edx-drf-extensions, edx-enterprise, edx-proctoring django-webpack-loader==0.7.0 # via -r requirements/edx/base.txt, edx-proctoring djangorestframework-xml==2.0.0 # via -r requirements/edx/base.txt, edx-enterprise djangorestframework==3.9.4 # via -r requirements/edx/base.txt, django-config-models, django-user-tasks, drf-jwt, drf-yasg, edx-api-doc-tools, edx-completion, edx-drf-extensions, edx-enterprise, edx-organizations, edx-proctoring, edx-submissions, ora2, rest-condition, super-csv @@ -99,126 +96,124 @@ docopt==0.6.2 # via -r requirements/edx/base.txt, xmodule docutils==0.16 # via -r requirements/edx/base.txt, botocore drf-jwt==1.14.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, edx-drf-extensions drf-yasg==1.17.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, edx-api-doc-tools -edx-ace==0.1.14 # via -r requirements/edx/base.txt -edx-analytics-data-api-client==0.15.5 # via -r requirements/edx/base.txt -edx-api-doc-tools==1.2.0 # via -r requirements/edx/base.txt +edx-ace==0.1.15 # via -r requirements/edx/base.txt +edx-analytics-data-api-client==0.16.1 # via -r requirements/edx/base.txt +edx-api-doc-tools==1.3.1 # via -r requirements/edx/base.txt edx-bulk-grades==0.6.8 # via -r requirements/edx/base.txt, staff-graded-xblock -edx-ccx-keys==1.0.1 # via -r requirements/edx/base.txt +edx-ccx-keys==1.1.0 # via -r requirements/edx/base.txt edx-celeryutils==0.5.0 # via -r requirements/edx/base.txt, super-csv -edx-completion==3.1.1 # via -r requirements/edx/base.txt -edx-django-release-util==0.4.2 # via -r requirements/edx/base.txt -edx-django-sites-extensions==2.4.3 # via -r requirements/edx/base.txt -edx-django-utils==3.2.0 # via -r requirements/edx/base.txt, django-config-models, edx-drf-extensions, edx-enterprise, edx-rest-api-client, edx-when -edx-drf-extensions==5.0.2 # via -r requirements/edx/base.txt, edx-completion, edx-enterprise, edx-organizations, edx-proctoring, edx-rbac, edx-when, edxval -edx-enterprise==3.1.0 # via -r requirements/edx/base.txt -edx-i18n-tools==0.5.0 # via -r requirements/edx/base.txt, -r requirements/edx/testing.in, ora2 +edx-completion==3.2.1 # via -r requirements/edx/base.txt +edx-django-release-util==0.4.4 # via -r requirements/edx/base.txt +edx-django-sites-extensions==2.5.1 # via -r requirements/edx/base.txt +edx-django-utils==3.2.3 # via -r requirements/edx/base.txt, django-config-models, edx-drf-extensions, edx-enterprise, edx-rest-api-client, edx-when +edx-drf-extensions==6.0.0 # via -r requirements/edx/base.txt, edx-completion, edx-enterprise, edx-organizations, edx-proctoring, edx-rbac, edx-when, edxval +edx-enterprise==3.3.11 # via -r requirements/edx/base.txt +edx-i18n-tools==0.5.3 # via -r requirements/edx/base.txt, -r requirements/edx/testing.in, ora2 edx-lint==1.4.1 # via -r requirements/edx/testing.in -edx-milestones==0.2.6 # via -r requirements/edx/base.txt -edx-opaque-keys[django]==2.0.2 # via -r requirements/edx/base.txt, edx-bulk-grades, edx-ccx-keys, edx-completion, edx-drf-extensions, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-user-state-client, edx-when, xmodule -edx-organizations==5.1.0 # via -r requirements/edx/base.txt +edx-milestones==0.3.0 # via -r requirements/edx/base.txt +edx-opaque-keys[django]==2.1.0 # via -r requirements/edx/base.txt, edx-bulk-grades, edx-ccx-keys, edx-completion, edx-drf-extensions, edx-enterprise, edx-milestones, edx-organizations, edx-proctoring, edx-user-state-client, edx-when, xmodule +edx-organizations==5.2.0 # via -r requirements/edx/base.txt edx-proctoring-proctortrack==1.0.5 # via -r requirements/edx/base.txt -edx-proctoring==2.3.3 # via -r requirements/edx/base.txt, edx-proctoring-proctortrack -edx-rbac==1.1.3 # via -r requirements/edx/base.txt, edx-enterprise -edx-rest-api-client==5.1.0 # via -r requirements/edx/base.txt, edx-enterprise, edx-proctoring -edx-search==1.3.4 # via -r requirements/edx/base.txt -edx-sga==0.10.0 # via -r requirements/edx/base.txt -edx-submissions==3.0.7 # via -r requirements/edx/base.txt, ora2 +edx-proctoring==2.4.3 # via -r requirements/edx/base.txt, edx-proctoring-proctortrack +edx-rbac==1.3.1 # via -r requirements/edx/base.txt, edx-enterprise +edx-rest-api-client==5.2.1 # via -r requirements/edx/base.txt, edx-enterprise, edx-proctoring +edx-search==1.4.1 # via -r requirements/edx/base.txt +edx-sga==0.11.0 # via -r requirements/edx/base.txt +edx-submissions==3.1.11 # via -r requirements/edx/base.txt, ora2 edx-tincan-py35==0.0.5 # via -r requirements/edx/base.txt, edx-enterprise -edx-user-state-client==1.1.2 # via -r requirements/edx/base.txt -edx-when==1.2.0 # via -r requirements/edx/base.txt, edx-proctoring -edxval==1.3.1 # via -r requirements/edx/base.txt +edx-user-state-client==1.2.0 # via -r requirements/edx/base.txt +edx-when==1.2.8 # via -r requirements/edx/base.txt, edx-proctoring +edxval==1.3.8 # via -r requirements/edx/base.txt elasticsearch==1.9.0 # via -r requirements/edx/base.txt, edx-search -entrypoints==0.3 # via flake8 -enum34==1.1.10 # via -r requirements/edx/base.txt, edxval -event-tracking==0.3.0 # via -r requirements/edx/base.txt, edx-proctoring, edx-search +enmerkar-underscore==1.0.0 # via -r requirements/edx/base.txt +enmerkar==0.7.1 # via -r requirements/edx/base.txt, enmerkar-underscore +event-tracking==0.3.2 # via -r requirements/edx/base.txt, edx-proctoring, edx-search execnet==1.7.1 # via pytest-xdist factory-boy==2.8.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.in -faker==4.0.3 # via factory-boy +faker==4.1.1 # via factory-boy filelock==3.0.12 # via tox, virtualenv flake8-polyfill==1.0.2 # via radon -flake8==3.7.9 # via flake8-polyfill +flake8==3.8.3 # via flake8-polyfill freezegun==0.3.12 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.in fs-s3fs==0.1.8 # via -r requirements/edx/base.txt, django-pyfs fs==2.0.18 # via -r requirements/edx/base.txt, django-pyfs, fs-s3fs, xblock future==0.18.2 # via -r requirements/edx/base.txt, django-ses, edx-celeryutils, edx-enterprise, pycontracts, pyjwkest, radon geoip2==3.0.0 # via -r requirements/edx/base.txt +gitdb==4.0.5 # via gitpython +gitpython==3.1.3 # via transifex-client glob2==0.7 # via -r requirements/edx/base.txt gunicorn==20.0.4 # via -r requirements/edx/base.txt -help-tokens==1.0.5 # via -r requirements/edx/base.txt -html5lib==1.0.1 # via -r requirements/edx/base.txt, ora2 -httplib2==0.17.2 # via -r requirements/edx/base.txt, oauth2 +help-tokens==1.1.2 # via -r requirements/edx/base.txt +html5lib==1.1 # via -r requirements/edx/base.txt, ora2 httpretty==0.9.7 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.in -icalendar==4.0.5 # via -r requirements/edx/base.txt +icalendar==4.0.6 # via -r requirements/edx/base.txt idna==2.9 # via -r requirements/edx/base.txt, requests -importlib-metadata==1.6.0 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, importlib-resources, inflect, path, pluggy, pytest, pytest-randomly, tox, virtualenv -importlib-resources==1.4.0 # via virtualenv +importlib-metadata==1.6.1 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, flake8, importlib-resources, inflect, path, pluggy, pytest, pytest-randomly, tox, virtualenv +importlib-resources==2.0.1 # via virtualenv inflect==3.0.2 # via -c requirements/edx/../constraints.txt, -r requirements/edx/coverage.txt, jinja2-pluralize -inflection==0.4.0 # via -r requirements/edx/base.txt, drf-yasg +inflection==0.5.0 # via -r requirements/edx/base.txt, drf-yasg ipaddress==1.0.23 # via -r requirements/edx/base.txt isodate==0.6.0 # via -r requirements/edx/base.txt, python3-saml isort==4.3.21 # via -r requirements/edx/testing.in, pylint -itypes==1.1.0 # via -r requirements/edx/base.txt, coreapi +itypes==1.2.0 # via -r requirements/edx/base.txt, coreapi jinja2-pluralize==0.3.0 # via -r requirements/edx/coverage.txt, diff-cover jinja2==2.11.2 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, code-annotations, coreschema, diff-cover, jinja2-pluralize -jmespath==0.9.5 # via -r requirements/edx/base.txt, boto3, botocore -joblib==0.14.1 # via -r requirements/edx/base.txt, nltk +jmespath==0.10.0 # via -r requirements/edx/base.txt, boto3, botocore +joblib==0.14.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, nltk jsondiff==1.2.0 # via -r requirements/edx/base.txt, edx-enterprise jsonfield2==3.0.3 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, edx-celeryutils, edx-enterprise, edx-proctoring, edx-submissions, ora2 kombu==3.0.37 # via -r requirements/edx/base.txt, celery laboratory==1.0.2 # via -r requirements/edx/base.txt lazy-object-proxy==1.4.3 # via astroid -lazy==1.4 # via -r requirements/edx/base.txt, acid-xblock, bok-choy, ora2 +lazy==1.4 # via -r requirements/edx/base.txt, acid-xblock, bok-choy, lti-consumer-xblock, ora2 lepl==5.1.3 # via -r requirements/edx/base.txt, rfc6266-parser libsass==0.10.0 # via -r requirements/edx/base.txt, ora2 loremipsum==1.0.5 # via -r requirements/edx/base.txt, ora2 -git+https://github.com/edx/xblock-lti-consumer.git@v1.2.5#egg=lti_consumer-xblock==1.2.5 # via -r requirements/edx/base.txt -lxml==4.5.0 # via -r requirements/edx/base.txt, capa, edxval, lti-consumer-xblock, ora2, pyquery, safe-lxml, xblock, xmlsec +lti-consumer-xblock==1.4.2 # via -r requirements/edx/base.txt +lxml==4.5.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, capa, edxval, lti-consumer-xblock, ora2, pyquery, safe-lxml, xblock, xmlsec mailsnake==1.6.4 # via -r requirements/edx/base.txt -mako==1.0.2 # via -r requirements/edx/base.txt, acid-xblock, lti-consumer-xblock, xblock-google-drive, xblock-utils +mako==1.1.3 # via -r requirements/edx/base.txt, acid-xblock, lti-consumer-xblock, xblock-google-drive, xblock-utils mando==0.6.4 # via radon markdown==2.6.11 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, django-wiki, staff-graded-xblock, xblock-poll -markey==0.8 # via -r requirements/edx/base.txt, django-babel-underscore +markey==0.8 # via -r requirements/edx/base.txt, enmerkar-underscore markupsafe==1.1.1 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, chem, jinja2, mako, xblock -maxminddb==1.5.2 # via -r requirements/edx/base.txt, geoip2 +maxminddb==1.5.4 # via -r requirements/edx/base.txt, geoip2 mccabe==0.6.1 # via flake8, pylint mock==3.0.5 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, xblock-drag-and-drop-v2, xblock-poll git+https://github.com/edx/MongoDBProxy.git@d92bafe9888d2940f647a7b2b2383b29c752f35a#egg=MongoDBProxy==0.1.0+edx.2 # via -r requirements/edx/base.txt -mongoengine==0.10.0 # via -r requirements/edx/base.txt -more-itertools==8.2.0 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, pytest, zipp +mongoengine==0.20.0 # via -r requirements/edx/base.txt +more-itertools==8.4.0 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, pytest, zipp mpmath==1.1.0 # via -r requirements/edx/base.txt, sympy mysqlclient==1.4.6 # via -r requirements/edx/base.txt -newrelic==5.12.0.140 # via -r requirements/edx/base.txt, edx-django-utils +newrelic==5.14.1.144 # via -r requirements/edx/base.txt, edx-django-utils nltk==3.5 # via -r requirements/edx/base.txt, chem -nodeenv==1.3.5 # via -r requirements/edx/base.txt -numpy==1.18.2 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, chem, openedx-calc, pandas, scipy -git+https://github.com/joestump/python-oauth2.git@b94f69b1ad195513547924e380d9265133e995fa#egg=oauth2 # via -r requirements/edx/base.txt +nodeenv==1.4.0 # via -r requirements/edx/base.txt +numpy==1.18.5 # via -r requirements/edx/base.txt, chem, openedx-calc, scipy oauthlib==3.0.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, django-oauth-toolkit, lti-consumer-xblock, requests-oauthlib, social-auth-core -openedx-calc==1.0.7 # via -r requirements/edx/base.txt -git+https://github.com/edx/edx-ora2.git@2.6.25#egg=ora2==2.6.25 # via -r requirements/edx/base.txt -packaging==20.3 # via -r requirements/edx/base.txt, drf-yasg, pytest, tox -pandas==0.22.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/coverage.txt +openedx-calc==1.0.9 # via -r requirements/edx/base.txt +ora2==2.8.5 # via -r requirements/edx/base.txt +packaging==20.4 # via -r requirements/edx/base.txt, bleach, drf-yasg, pytest, tox path.py==12.4.0 # via -r requirements/edx/base.txt, edx-enterprise, edx-i18n-tools, ora2, xmodule path==13.1.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, path.py pathlib2==2.3.5 # via pytest pathtools==0.1.2 # via -r requirements/edx/base.txt, watchdog paver==1.3.4 # via -r requirements/edx/base.txt pbr==5.4.5 # via -r requirements/edx/base.txt, stevedore -pdfminer.six==20200402 # via -r requirements/edx/base.txt +pdfminer.six==20200517 # via -r requirements/edx/base.txt piexif==1.1.3 # via -r requirements/edx/base.txt -pillow==7.1.1 # via -r requirements/edx/base.txt, edx-enterprise, edx-organizations -pkgconfig==1.5.1 # via -r requirements/edx/base.txt, xmlsec +pillow==7.1.2 # via -r requirements/edx/base.txt, edx-enterprise, edx-organizations pluggy==0.13.1 # via -r requirements/edx/coverage.txt, diff-cover, pytest, tox polib==1.1.0 # via -r requirements/edx/base.txt, -r requirements/edx/testing.in, edx-i18n-tools psutil==1.2.1 # via -r requirements/edx/base.txt, edx-django-utils py2neo==3.1.2 # via -r requirements/edx/base.txt -py==1.8.1 # via pytest, tox -pycodestyle==2.5.0 # via -r requirements/edx/testing.in, flake8 -pycontracts==1.8.12 # via -r requirements/edx/base.txt, edx-user-state-client +py==1.9.0 # via pytest, tox +pycodestyle==2.6.0 # via -r requirements/edx/testing.in, flake8 +pycontracts==1.8.14 # via -r requirements/edx/base.txt, edx-user-state-client pycountry==19.8.18 # via -r requirements/edx/base.txt pycparser==2.20 # via -r requirements/edx/base.txt, cffi -pycryptodome==3.9.7 # via -r requirements/edx/base.txt, pdfminer.six -pycryptodomex==3.9.7 # via -r requirements/edx/base.txt, edx-proctoring, pyjwkest -pyflakes==2.1.1 # via flake8 +pycryptodome==3.9.8 # via -r requirements/edx/base.txt, pdfminer.six +pycryptodomex==3.9.8 # via -r requirements/edx/base.txt, edx-proctoring, pyjwkest +pyflakes==2.2.0 # via flake8 pygments==2.6.1 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, diff-cover pyjwkest==1.4.2 # via -r requirements/edx/base.txt, edx-drf-extensions pyjwt==1.5.2 # via -r requirements/edx/base.txt, drf-jwt, edx-rest-api-client, social-auth-core @@ -226,37 +221,37 @@ pylint-celery==0.3 # via edx-lint pylint-django==2.0.11 # via edx-lint pylint-plugin-utils==0.6 # via pylint-celery, pylint-django pylint==2.4.2 # via edx-lint, pylint-celery, pylint-django, pylint-plugin-utils -pymongo==3.9.0 # via -r requirements/edx/base.txt, edx-opaque-keys, event-tracking, mongodbproxy, mongoengine +pymongo==3.10.1 # via -r requirements/edx/base.txt, edx-opaque-keys, event-tracking, mongodbproxy, mongoengine pynliner==0.8.0 # via -r requirements/edx/base.txt -pyparsing==2.2.0 # via -r requirements/edx/base.txt, chem, openedx-calc, packaging, pycontracts +pyparsing==2.4.7 # via -r requirements/edx/base.txt, chem, openedx-calc, packaging, pycontracts pyquery==1.4.1 # via -r requirements/edx/testing.in pysrt==1.1.2 # via -r requirements/edx/base.txt, edxval pytest-attrib==0.1.3 # via -r requirements/edx/testing.in -pytest-cov==2.8.1 # via -r requirements/edx/testing.in +pytest-cov==2.10.0 # via -r requirements/edx/testing.in pytest-django==3.8.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.in -pytest-forked==1.1.3 # via pytest-xdist +pytest-forked==1.2.0 # via pytest-xdist pytest-json-report==1.2.1 # via -r requirements/edx/testing.in -pytest-metadata==1.8.0 # via pytest-json-report -pytest-randomly==3.3.1 # via -r requirements/edx/testing.in -pytest-xdist==1.31.0 # via -r requirements/edx/testing.in +pytest-metadata==1.8.0 # via -r requirements/edx/testing.in, pytest-json-report +pytest-randomly==3.4.0 # via -r requirements/edx/testing.in +pytest-xdist==1.32.0 # via -r requirements/edx/testing.in pytest==5.3.5 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.in, pytest-attrib, pytest-cov, pytest-django, pytest-forked, pytest-json-report, pytest-metadata, pytest-randomly, pytest-xdist -python-dateutil==2.4.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, analytics-python, botocore, edx-ace, edx-drf-extensions, edx-enterprise, edx-proctoring, faker, freezegun, icalendar, ora2, pandas, xblock +python-dateutil==2.4.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, analytics-python, botocore, edx-ace, edx-drf-extensions, edx-enterprise, edx-proctoring, faker, freezegun, icalendar, ora2, xblock python-levenshtein==0.12.0 # via -r requirements/edx/base.txt python-memcached==1.59 # via -r requirements/edx/base.txt python-slugify==4.0.0 # via -r requirements/edx/base.txt, code-annotations, transifex-client -python-swiftclient==3.9.0 # via -r requirements/edx/base.txt, ora2 +python-swiftclient==3.10.0 # via -r requirements/edx/base.txt, ora2 python3-openid==3.1.0 ; python_version >= "3" # via -r requirements/edx/base.txt, social-auth-core python3-saml==1.9.0 # via -r requirements/edx/base.txt -pytz==2019.3 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, babel, capa, celery, django, django-ses, edx-completion, edx-enterprise, edx-proctoring, edx-submissions, edx-tincan-py35, event-tracking, fs, icalendar, ora2, pandas, xblock +pytz==2020.1 # via -r requirements/edx/base.txt, babel, capa, celery, django, django-ses, edx-completion, edx-enterprise, edx-proctoring, edx-submissions, edx-tincan-py35, event-tracking, fs, icalendar, ora2, xblock pyuca==1.2 # via -r requirements/edx/base.txt pyyaml==5.3.1 # via -r requirements/edx/base.txt, code-annotations, edx-django-release-util, edx-i18n-tools, xblock radon==4.1.0 # via -r requirements/edx/testing.in random2==1.0.1 # via -r requirements/edx/base.txt -recommender-xblock==1.4.5 # via -r requirements/edx/base.txt +recommender-xblock==1.4.8 # via -r requirements/edx/base.txt redis==2.10.6 # via -r requirements/edx/base.txt -regex==2020.4.4 # via -r requirements/edx/base.txt, nltk +regex==2020.6.8 # via -r requirements/edx/base.txt, nltk requests-oauthlib==1.3.0 # via -r requirements/edx/base.txt, social-auth-core -requests==2.23.0 # via -r requirements/edx/base.txt, analytics-python, coreapi, django-oauth-toolkit, edx-analytics-data-api-client, edx-bulk-grades, edx-drf-extensions, edx-enterprise, edx-rest-api-client, geoip2, mailsnake, pyjwkest, python-swiftclient, requests-oauthlib, sailthru-client, slumber, social-auth-core, transifex-client +requests==2.24.0 # via -r requirements/edx/base.txt, analytics-python, coreapi, django-oauth-toolkit, edx-analytics-data-api-client, edx-bulk-grades, edx-drf-extensions, edx-enterprise, edx-rest-api-client, geoip2, mailsnake, pyjwkest, python-swiftclient, requests-oauthlib, sailthru-client, slumber, social-auth-core, transifex-client rest-condition==1.0.3 # via -r requirements/edx/base.txt, edx-drf-extensions rfc6266-parser==0.0.6 # via -r requirements/edx/base.txt ruamel.yaml.clib==0.2.0 # via -r requirements/edx/base.txt, ruamel.yaml @@ -266,48 +261,51 @@ s3transfer==0.1.13 # via -r requirements/edx/base.txt, boto3 sailthru-client==2.2.3 # via -r requirements/edx/base.txt, edx-ace scipy==1.4.1 # via -r requirements/edx/base.txt, chem, openedx-calc selenium==3.141.0 # via -r requirements/edx/testing.in, bok-choy -semantic-version==2.8.4 # via -r requirements/edx/base.txt, edx-drf-extensions +semantic-version==2.8.5 # via -r requirements/edx/base.txt, edx-drf-extensions shapely==1.7.0 # via -r requirements/edx/base.txt simplejson==3.17.0 # via -r requirements/edx/base.txt, sailthru-client, super-csv, xblock-utils singledispatch==3.4.0.3 # via -r requirements/edx/testing.in -six==1.14.0 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, analytics-python, astroid, bleach, bok-choy, cryptography, diff-cover, django-appconf, django-classy-tags, django-countries, django-pyfs, django-sekizai, django-simple-history, django-statici18n, drf-yasg, edx-ace, edx-ccx-keys, edx-django-release-util, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-lint, edx-milestones, edx-opaque-keys, edx-rbac, edx-search, event-tracking, freezegun, fs, fs-s3fs, help-tokens, html5lib, httpretty, isodate, libsass, mando, mock, openedx-calc, packaging, pathlib2, paver, pycontracts, pyjwkest, pytest-xdist, python-dateutil, python-memcached, python-swiftclient, singledispatch, social-auth-app-django, social-auth-core, stevedore, tox, transifex-client, virtualenv, xblock +six==1.15.0 # via -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, analytics-python, astroid, bleach, bok-choy, chem, crowdsourcehinter-xblock, cryptography, diff-cover, django-classy-tags, django-countries, django-pyfs, django-sekizai, django-simple-history, django-statici18n, drf-yasg, edx-ace, edx-ccx-keys, edx-django-release-util, edx-drf-extensions, edx-enterprise, edx-i18n-tools, edx-lint, edx-milestones, edx-opaque-keys, edx-rbac, edx-search, event-tracking, freezegun, fs, fs-s3fs, help-tokens, html5lib, httpretty, isodate, libsass, mando, mock, openedx-calc, packaging, pathlib2, paver, pycontracts, pyjwkest, pytest-xdist, python-dateutil, python-memcached, python-swiftclient, singledispatch, social-auth-app-django, social-auth-core, stevedore, tox, transifex-client, virtualenv, xblock slumber==0.7.1 # via -r requirements/edx/base.txt, edx-bulk-grades, edx-enterprise, edx-rest-api-client +smmap==3.0.4 # via gitdb +social-auth-app-django==4.0.0 # via -r requirements/edx/base.txt social-auth-core==3.3.3 # via -r requirements/edx/base.txt, social-auth-app-django -git+https://github.com/jazzband/sorl-thumbnail.git@13bedfb7d2970809eda597e3ef79318a6fa80ac2#egg=sorl-thumbnail # via -r requirements/edx/base.txt -sortedcontainers==2.1.0 # via -r requirements/edx/base.txt, pdfminer.six -soupsieve==2.0 # via -r requirements/edx/base.txt, beautifulsoup4 +sorl-thumbnail==12.6.3 # via -r requirements/edx/base.txt +sortedcontainers==2.2.2 # via -r requirements/edx/base.txt, pdfminer.six +soupsieve==2.0.1 # via -r requirements/edx/base.txt, beautifulsoup4 sqlparse==0.3.1 # via -r requirements/edx/base.txt, django -staff-graded-xblock==0.7 # via -r requirements/edx/base.txt -stevedore==1.32.0 # via -r requirements/edx/base.txt, code-annotations, edx-ace, edx-enterprise, edx-opaque-keys -super-csv==0.9.7 # via -r requirements/edx/base.txt, edx-bulk-grades -sympy==1.5.1 # via -r requirements/edx/base.txt, symmath -testfixtures==6.14.0 # via -r requirements/edx/base.txt, -r requirements/edx/testing.in, edx-enterprise +staff-graded-xblock==0.8 # via -r requirements/edx/base.txt +stevedore==1.32.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, code-annotations, edx-ace, edx-enterprise, edx-opaque-keys +super-csv==0.9.9 # via -r requirements/edx/base.txt, edx-bulk-grades +sympy==1.6 # via -r requirements/edx/base.txt, symmath +testfixtures==6.14.1 # via -r requirements/edx/base.txt, -r requirements/edx/testing.in, edx-enterprise text-unidecode==1.3 # via -r requirements/edx/base.txt, faker, python-slugify -toml==0.10.0 # via tox -tox-battery==0.5.2 # via -r requirements/edx/testing.in -tox==3.14.6 # via -r requirements/edx/testing.in, tox-battery -tqdm==4.45.0 # via -r requirements/edx/base.txt, nltk -transifex-client==0.13.4 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.in +toml==0.10.1 # via tox +tox-battery==0.6.1 # via -r requirements/edx/testing.in +tox==3.15.2 # via -r requirements/edx/testing.in, tox-battery +tqdm==4.46.1 # via -r requirements/edx/base.txt, nltk +transifex-client==0.13.10 # via -r requirements/edx/testing.in typed-ast==1.4.1 # via astroid unicodecsv==0.14.1 # via -r requirements/edx/base.txt, edx-enterprise -unidiff==0.5.5 # via -r requirements/edx/testing.in, coverage-pytest-plugin +unidiff==0.6.0 # via -r requirements/edx/testing.in +git+https://github.com/nedbat/coverage_pytest_plugin.git@29de030251471e200ff255eb9e549218cd60e872#egg=coverage_pytest_plugin==0.0 # via -r requirements/edx/testing.in uritemplate==3.0.1 # via -r requirements/edx/base.txt, coreapi, drf-yasg urllib3==1.25.9 # via -r requirements/edx/base.txt, elasticsearch, geoip2, requests, selenium, transifex-client -user-util==0.1.5 # via -r requirements/edx/base.txt -virtualenv==20.0.18 # via tox +user-util==0.2 # via -r requirements/edx/base.txt +virtualenv==20.0.25 # via tox voluptuous==0.11.7 # via -r requirements/edx/base.txt, ora2 -watchdog==0.10.2 # via -r requirements/edx/base.txt -wcwidth==0.1.9 # via pytest -web-fragments==0.3.1 # via -r requirements/edx/base.txt, staff-graded-xblock, xblock, xblock-utils +watchdog==0.10.3 # via -r requirements/edx/base.txt +wcwidth==0.2.5 # via pytest +web-fragments==0.3.2 # via -r requirements/edx/base.txt, crowdsourcehinter-xblock, staff-graded-xblock, xblock, xblock-utils webencodings==0.5.1 # via -r requirements/edx/base.txt, bleach, html5lib webob==1.8.6 # via -r requirements/edx/base.txt, xblock, xmodule wrapt==1.11.2 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, astroid git+https://github.com/edx-solutions/xblock-drag-and-drop-v2@v2.2.10#egg=xblock-drag-and-drop-v2==2.2.10 # via -r requirements/edx/base.txt git+https://github.com/open-craft/xblock-poll@da2d8fd21791a7af128595cf82bee83ee579e00f#egg=xblock-poll==1.9.6 # via -r requirements/edx/base.txt -xblock-utils==2.0.0 # via -r requirements/edx/base.txt, edx-sga, lti-consumer-xblock, staff-graded-xblock, xblock-drag-and-drop-v2, xblock-google-drive -xblock==1.2.9 # via -r requirements/edx/base.txt, acid-xblock, crowdsourcehinter-xblock, done-xblock, edx-completion, edx-sga, edx-user-state-client, edx-when, lti-consumer-xblock, ora2, rate-xblock, staff-graded-xblock, xblock-discussion, xblock-drag-and-drop-v2, xblock-google-drive, xblock-poll, xblock-utils -xmlsec==1.3.3 # via -r requirements/edx/base.txt, python3-saml -xss-utils==0.1.2 # via -r requirements/edx/base.txt +xblock-utils==2.1.1 # via -r requirements/edx/base.txt, edx-sga, lti-consumer-xblock, staff-graded-xblock, xblock-drag-and-drop-v2, xblock-google-drive +xblock==1.3.1 # via -r requirements/edx/base.txt, acid-xblock, crowdsourcehinter-xblock, done-xblock, edx-completion, edx-sga, edx-user-state-client, edx-when, lti-consumer-xblock, ora2, rate-xblock, staff-graded-xblock, xblock-discussion, xblock-drag-and-drop-v2, xblock-google-drive, xblock-poll, xblock-utils +xmlsec==1.3.8 # via -r requirements/edx/base.txt, python3-saml +xss-utils==0.1.3 # via -r requirements/edx/base.txt zipp==1.0.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt, -r requirements/edx/coverage.txt, importlib-metadata, importlib-resources # The following packages are considered to be unsafe in a requirements file: diff --git a/scripts/jenkins-common.sh b/scripts/jenkins-common.sh index b1a56b1f39cded8e35b94affd491c623ee25dc58..d4048817d93ec1310442d3f6fecdaa372a37d035 100644 --- a/scripts/jenkins-common.sh +++ b/scripts/jenkins-common.sh @@ -45,6 +45,12 @@ fi # Activate the Python virtualenv source $VENV_PATH/edx-venv/bin/activate +# Hack to fix up egg-link files given that the virtualenv is not relocatable +sed -i "s|^/home/jenkins/shallow-clone|`pwd`|" -- \ + $VENV_PATH/edx-venv/lib/python*/site-packages/*.egg-link +pip install -qr requirements/edx/pip-tools.txt +pip-sync -q requirements/edx/testing.txt requirements/edx/django.txt + # add the node packages dir to PATH PATH=$PATH:node_modules/.bin diff --git a/scripts/paver_autocomplete.sh b/scripts/paver_autocomplete.sh new file mode 100644 index 0000000000000000000000000000000000000000..8a6aacf933260489332ca491c881cc6694de6f55 --- /dev/null +++ b/scripts/paver_autocomplete.sh @@ -0,0 +1,139 @@ +# Courtesy of Gregory Nicholas + +_subcommand_opts() +{ + local awkfile command cur usage + command=$1 + cur=${COMP_WORDS[COMP_CWORD]} + awkfile=/tmp/paver-option-awkscript-$$.awk + echo ' +BEGIN { + opts = ""; +} + +{ + for (i = 1; i <= NF; i = i + 1) { + # Match short options (-a, -S, -3) + # or long options (--long-option, --another_option) + # in output from paver help [subcommand] + if ($i ~ /^(-[A-Za-z0-9]|--[A-Za-z][A-Za-z0-9_-]*)/) { + opt = $i; + # remove trailing , and = characters. + match(opt, "[,=]"); + if (RSTART > 0) { + opt = substr(opt, 0, RSTART); + } + opts = opts " " opt; + } + } +} + +END { + print opts +}' > $awkfile + + usage=`paver help $command` + options=`echo "$usage"|awk -f $awkfile` + + COMPREPLY=( $(compgen -W "$options" -- "$cur") ) +} + + +_paver() +{ + local cur prev + COMPREPLY=() + # Variable to hold the current word + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD - 1]}" + + # Build a list of the available tasks from: `paver --help --quiet` + local cmds=$(paver -hq | awk '/^ ([a-zA-Z][a-zA-Z0-9_]+)/ {print $1}') + + subcmd="${COMP_WORDS[1]}" + # Generate possible matches and store them in the + # array variable COMPREPLY + + if [[ -n $subcmd ]] + then + case $subcmd in + test_system) + + _test_system_args + if [[ -n $COMPREPLY ]] + then + return 0 + fi + ;; + test_bokchoy) + _test_bokchoy_args + if [[ -n $COMPREPLY ]] + then + return 0 + fi + ;; + *) + ;; + esac + + if [[ ${#COMP_WORDS[*]} == 3 ]] + then + _subcommand_opts $subcmd + return 0 + else + if [[ "$cur" == -* ]] + then + _subcommand_opts $subcmd + return 0 + else + COMPREPLY=( $(compgen -o nospace -- "$cur") ) + fi + fi + fi + + if [[ ${#COMP_WORDS[*]} == 2 ]] + then + COMPREPLY=( $(compgen -W "${cmds}" -- "$cur") ) + fi +} + +_test_system_args() +{ + local cur prev + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD - 1]}" + + case "$prev" in + -s|--system) + COMPREPLY=( $(compgen -W "lms cms" -- "$cur") ) + return 0 + ;; + *) + ;; + esac +} + +_test_bokchoy_args() +{ + local bokchoy_tests cur prev + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD - 1]}" + + case "$prev" in + -d|--test_dir) + bokchoy_tests=`find common/test/acceptance -name \*.py| sed 's:common/test/acceptance/::'` + COMPREPLY=( $(compgen -o filenames -W "$bokchoy_tests" -- $cur) ) + return 0 + ;; + -t|--test_spec) + bokchoy_tests=`find common/test/acceptance/tests -name \*.py| sed 's:common/test/acceptance/::'` + COMPREPLY=( $(compgen -o filenames -W "$bokchoy_tests" -- $cur) ) + return 0 + ;; + *) + ;; + esac +} +# Assign the auto-completion function for our command. + +complete -F _paver -o default paver diff --git a/scripts/thresholds.sh b/scripts/thresholds.sh index b10fbc1ad907a1f9f3df8492edd2dfb492cc9a46..8a81f0d22ce018d464d69cd65aa343038dd7f671 100755 --- a/scripts/thresholds.sh +++ b/scripts/thresholds.sh @@ -2,6 +2,6 @@ set -e export LOWER_PYLINT_THRESHOLD=1000 -export UPPER_PYLINT_THRESHOLD=3990 +export UPPER_PYLINT_THRESHOLD=3300 export ESLINT_THRESHOLD=5530 export STYLELINT_THRESHOLD=880 diff --git a/scripts/xblock/requirements.txt b/scripts/xblock/requirements.txt index a9987ce0be5b1611e7b519c45c6ea5063f2e8757..9912f07354fd76915a130f55b1f445b4b3e6ac4f 100644 --- a/scripts/xblock/requirements.txt +++ b/scripts/xblock/requirements.txt @@ -4,8 +4,8 @@ # # make upgrade # -certifi==2020.4.5.1 # via requests +certifi==2020.6.20 # via requests chardet==3.0.4 # via requests idna==2.9 # via requests -requests==2.23.0 # via -r scripts/xblock/requirements.in +requests==2.24.0 # via -r scripts/xblock/requirements.in urllib3==1.25.9 # via requests diff --git a/scripts/xdist/find_order_dependent_test_failures.py b/scripts/xdist/find_order_dependent_test_failures.py new file mode 100644 index 0000000000000000000000000000000000000000..a3191602c9963a68ff8786db0f26da542292d162 --- /dev/null +++ b/scripts/xdist/find_order_dependent_test_failures.py @@ -0,0 +1,223 @@ +""" +This script can be used to find the fewest number of tests required to get a +failure, in cases where a test failure is dependent on test order. + +The script performs the following: +1. It strips the console log of a pytest-xdist Jenkins run into the test +lists of each pytest worker until it finds the first failure. +2. It makes sure that running the single failing test doesn't fail on its +own. +3. It then finds the fewest number of tests required to continue to see the +failure, and outputs the pytest command needed to replicate. + +Sample usage:: + + python scripts/xdist/find_dependent_test_failures.py --log-file console.txt --test-suite lms-unit + +""" + + +import io +import os +import re +import shutil +import tempfile + +import click + +OUTPUT_FOLDER_NAME = "worker_list_files" +test_suite_option = None +fast_option = None +verbose_option = None + + +@click.command() +@click.option( + '--log-file', + help="File name of console log .txt file from a Jenkins build " + "that ran pytest-xdist. This can be acquired by running: " + "curl -o console.txt https://build.testeng.edx.org/job/JOBNAME/BUILDNUMBER/consoleText", + required=True +) +@click.option( + '--test-suite', + help="Test suite that the pytest worker ran.", + type=click.Choice(['lms-unit', 'cms-unit', 'commonlib-unit']), + required=True +) +@click.option( + '--fast/--slow', + help="Fast looks for issues in setup/teardown by running one test per class or file.", + default=True +) +@click.option( + '--verbose/--quiet', + help="Verbose includes the test output.", + default=None +) +def main(log_file, test_suite, fast, verbose): + global test_suite_option + global fast_option + global verbose_option + test_suite_option = test_suite + fast_option = fast + verbose_option = verbose + + _clean_output_folder() + + failing_test_list = _strip_console_for_tests_with_failure(log_file, test_suite) + + if not failing_test_list: + print('No failures found in log file.') + return + + if _create_and_check_test_files_for_failures(failing_test_list[-1:], 'SINGLE'): + print("Single test failed. Failures not dependent on order.") + return + + test_list_with_failures, pytest_command = _find_fewest_tests_with_failures(failing_test_list, 'ALL') + if test_list_with_failures: + print('Found failures running {} tests.'.format(len(test_list_with_failures))) + print('Use: {}'.format(pytest_command)) + return + + if fast_option: + print('No tests failed locally with --fast option. Try running again with --slow to include more tests.') + return + + print('No tests failed locally.') + + +def _clean_output_folder(): + if os.path.isdir(OUTPUT_FOLDER_NAME): + shutil.rmtree(OUTPUT_FOLDER_NAME) + os.mkdir(OUTPUT_FOLDER_NAME) + + +def _strip_console_for_tests_with_failure(log_file, test_suite): + """ + Returns list of tests ending with a failing test, or None if no failures found. + """ + global fast_option + worker_test_dict = {} + test_base_included = {} + failing_worker_num = None + with io.open(log_file, 'r') as console_file: + for line in console_file: + regex_search = re.search(r'\[gw(\d+)] (PASSED|FAILED|SKIPPED|ERROR) (\S+)'.format(test_suite), line) + if regex_search: + worker_num_string = regex_search.group(1) + pass_fail_string = regex_search.group(2) + if worker_num_string not in worker_test_dict: + worker_test_dict[worker_num_string] = [] + test = regex_search.group(3) + if test_suite == "commonlib-unit": + if "pavelib" not in test and not test.startswith('scripts'): + test = u"common/lib/{}".format(test) + if fast_option and pass_fail_string == 'PASSED': + # fast option will only take one test per class or module, in case + # the failure is a setup/teardown failure. + test_base = '::'.join(test.split('::')[:-1]) + if test_base not in test_base_included: + worker_test_dict[worker_num_string].append(test) + test_base_included[test_base] = True + elif (not fast_option or (fast_option and pass_fail_string == 'FAILED')): + worker_test_dict[worker_num_string].append(test) + if pass_fail_string == 'FAILED': + failing_worker_num = worker_num_string + break + if failing_worker_num: + return worker_test_dict[failing_worker_num] + + +def _get_pytest_command(output_file_name): + """ + Return the pytest command to run. + """ + return "pytest -p 'no:randomly' `cat {}`".format(output_file_name) + + +def _run_tests_and_check_for_failures(output_file_name): + """ + Runs tests and returns True if failures are found. + """ + global verbose_option + pytest_command = _get_pytest_command(output_file_name) + test_output = os.popen(pytest_command).read() + if verbose_option: + print(test_output) + failures_search = re.search(r'=== (\d+) failed', test_output) + return bool(failures_search) and int(failures_search.group(1)) > 0 + + +def _create_and_check_test_files_for_failures(test_list, test_type): + """ + Run the test list to see if there are any failures. + + Keeps around any test files that produced a failure, and deletes + the passing files. + + Returns the pytest command to run if failures are found. + """ + print("Testing {}, includes {} test(s)...".format(test_type, len(test_list))) + global test_suite_option + output_file_name = "{}_failing_test_list_{}_{}.txt".format( + OUTPUT_FOLDER_NAME, test_suite_option, test_type, len(test_list) + ) + output_file_path = os.path.join(OUTPUT_FOLDER_NAME, output_file_name) + # Note: We don't really need a temporary file, and could just output the tests directly + # to the command line, but this keeps the verbose output cleaner. + temp_file = tempfile.NamedTemporaryFile(prefix=output_file_name, dir=OUTPUT_FOLDER_NAME, delete=False) + + with io.open(temp_file.name, 'w') as output_file: + for line in test_list: + output_file.write(line + "\n") + temp_file.close() + + if _run_tests_and_check_for_failures(temp_file.name): + os.rename(temp_file.name, output_file_path) + print('- test failures found.') + return _get_pytest_command(output_file_path) + + os.remove(temp_file.name) + print('- no failures found.') + return None + + +def _find_fewest_tests_with_failures(test_list, test_type): + """ + Recursively tests half the tests, finding the smallest number of tests to obtain a failure. + + Returns: + (test_list, pytest_command): Tuple with the smallest test_list and the pytest_command + to be used for testing. Returns (None, None) if no failures are found. + """ + if len(test_list) <= 1: + return None, None + + pytest_command = _create_and_check_test_files_for_failures(test_list, test_type) + if not pytest_command: + return None, None + + if len(test_list) == 2: + return test_list, pytest_command + + half_tests_num = round((len(test_list) - 1) / 2) + failing_test = test_list[-1:] + test_list_a = test_list[0:half_tests_num] + failing_test + test_list_b = test_list[half_tests_num:] + failing_test_list_a, pytest_command_a = _find_fewest_tests_with_failures(test_list_a, 'GROUP-A') + if failing_test_list_a: + return failing_test_list_a, pytest_command_a + + failing_test_list_b, pytest_command_b = _find_fewest_tests_with_failures(test_list_b, 'GROUP-B') + if failing_test_list_b: + return failing_test_list_b, pytest_command_b + + # This could occur if there is a complex set of dependencies where the + # original list fails, but neither of its halves (A or B) fail. + return test_list, pytest_command + + +if __name__ == "__main__": + main() diff --git a/scripts/xdist/get_worker_test_list.py b/scripts/xdist/get_worker_test_list.py index 6800b4f37156e63403527f544203d57116eb8666..62939ffd1f312315fce5ac88f32febc759c33ce2 100644 --- a/scripts/xdist/get_worker_test_list.py +++ b/scripts/xdist/get_worker_test_list.py @@ -32,12 +32,12 @@ def main(log_file, test_suite): worker_test_dict = {} with io.open(log_file, 'r') as console_file: for line in console_file: - regex_search = re.search(r'\[gw(\d+)] (PASSED|FAILED|SKIPPED|ERROR)'.format(test_suite), line) + regex_search = re.search(r'\[gw(\d+)] (PASSED|FAILED|SKIPPED|ERROR) (\S+)'.format(test_suite), line) if regex_search: worker_num_string = regex_search.group(1) if worker_num_string not in worker_test_dict: worker_test_dict[worker_num_string] = [] - test = line.split()[2] + test = regex_search.group(3) if test_suite == "commonlib-unit": if "pavelib" not in test and not test.startswith('scripts'): test = u"common/lib/{}".format(test) diff --git a/scripts/xdist/prepare_xdist_nodes.sh b/scripts/xdist/prepare_xdist_nodes.sh index 8a4d964bc14a6af932bdc72f4729a696c58241c6..a4c10af5ad3a52c1a45dbe9c7be1f6d2becb1169 100644 --- a/scripts/xdist/prepare_xdist_nodes.sh +++ b/scripts/xdist/prepare_xdist_nodes.sh @@ -12,13 +12,9 @@ python scripts/xdist/pytest_worker_manager.py -a up -n ${XDIST_NUM_WORKERS} \ # Install the correct version of Django depending on which tox environment (if any) is in use if [[ -z ${TOXENV+x} ]] || [[ ${TOXENV} == 'null' ]]; then - DJANGO_REQUIREMENT="-r requirements/edx/django.txt" -elif [[ ${TOXENV} == *'django20'* ]]; then - DJANGO_REQUIREMENT="-r requirements/edx/django20.txt" -elif [[ ${TOXENV} == *'django21'* ]]; then - DJANGO_REQUIREMENT="-r requirements/edx/django21.txt" -elif [[ ${TOXENV} == *'django22'* ]]; then - DJANGO_REQUIREMENT="-r requirements/edx/django.txt" + DJANGO_REQUIREMENT="requirements/edx/django.txt" +elif [[ ${TOXENV} == *'django30'* ]]; then + DJANGO_REQUIREMENT="requirements/edx/django30.txt" fi ip_list=$(<pytest_worker_ips.txt) @@ -27,10 +23,7 @@ do worker_reqs_cmd="ssh -o StrictHostKeyChecking=no jenkins@$ip 'git clone --branch master --depth 1 -q https://github.com/edx/edx-platform.git; cd edx-platform; git fetch -fq origin ${XDIST_GIT_REFSPEC}; git checkout -q ${XDIST_GIT_BRANCH}; - rm -rf /home/jenkins/edx-venv-${PYTHON_VERSION}/edx-venv; - tar -C /home/jenkins/edx-venv-${PYTHON_VERSION} -xf /home/jenkins/edx-venv_clean-${PYTHON_VERSION}.tar.gz; - source ../edx-venv-${PYTHON_VERSION}/edx-venv/bin/activate; - pip install -q ${DJANGO_REQUIREMENT} -r requirements/edx/testing.txt; mkdir reports' & " + scripts/xdist/setup_worker.sh -p $PYTHON_VERSION -d $DJANGO_REQUIREMENT' & " cmd=$cmd$worker_reqs_cmd done diff --git a/scripts/xdist/setup_worker.sh b/scripts/xdist/setup_worker.sh new file mode 100755 index 0000000000000000000000000000000000000000..1fd4f8c24f71e6fc8b9d9dbc2e3f106a07bfb575 --- /dev/null +++ b/scripts/xdist/setup_worker.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Set up worker node. + +while getopts 'p:d:' opt; do + case "$opt" in + p) PYTHON_VERSION="$OPTARG";; + d) DJANGO_REQUIREMENT="$OPTARG";; + [?]) + print >&2 "Usage: $0 -p python-version -d django-reqs-file" + exit 1 + ;; + esac +done + +venv_parent=/home/jenkins/edx-venv-${PYTHON_VERSION} +venv=$venv_parent/edx-venv +rm -rf $venv +tar -C $venv_parent -xf /home/jenkins/edx-venv_clean-${PYTHON_VERSION}.tar.gz +source $venv/bin/activate + +# Hack to fix up egg-link files given that the virtualenv is not relocatable +sed -i "s|\(^/home/jenkins\)/shallow-clone|\1/edx-platform|" -- \ + $venv/lib/python*/site-packages/*.egg-link +pip install -qr requirements/edx/pip-tools.txt +pip-sync -q requirements/edx/testing.txt "${DJANGO_REQUIREMENT}" + +mkdir reports diff --git a/scripts/xsslint/tests/test_linters.py b/scripts/xsslint/tests/test_linters.py index ce18bfea13cb44b2c03dbeef91244207253e9a86..e3556fa80010579312d1f3bb1e912d460ec81773 100644 --- a/scripts/xsslint/tests/test_linters.py +++ b/scripts/xsslint/tests/test_linters.py @@ -403,27 +403,19 @@ class TestJavaScriptLinter(TestLinter): linter.check_javascript_file_is_safe(data['template'], results) self._validate_data_rules(data, results) - @data( - {'template': 'StringUtils.interpolate()', 'rule': None}, - {'template': 'HtmlUtils.interpolateHtml()', 'rule': None}, - {'template': 'interpolate(anything)', 'rule': JAVASCRIPT_LINTER_RULESET.javascript_interpolate}, - ) - def test_javascript_interpolate(self, data): - """ - Test check_javascript_file_is_safe with interpolate() - """ - linter = _build_javascript_linter() - results = FileResults('') - - linter.check_javascript_file_is_safe(data['template'], results) - - self._validate_data_rules(data, results) - @data( {'template': '_.escape(message)', 'rule': None}, - {'template': 'anything.escape(message)', 'rule': JAVASCRIPT_LINTER_RULESET.javascript_escape}, + {'template': 'anything.escape(message)', 'rule': None}, + {'template': 'anythingescape(message)', 'rule': None}, + {'template': '$escape(message)', 'rule': None}, + {'template': '_escape(message)', 'rule': None}, + {'template': 'escape(message)', 'rule': JAVASCRIPT_LINTER_RULESET.javascript_escape}, + {'template': '(escape(message))', 'rule': JAVASCRIPT_LINTER_RULESET.javascript_escape}, + {'template': ' escape(message))', 'rule': JAVASCRIPT_LINTER_RULESET.javascript_escape}, + {'template': 'window.escape(message)', 'rule': JAVASCRIPT_LINTER_RULESET.javascript_escape}, + {'template': '(window.escape(message)', 'rule': JAVASCRIPT_LINTER_RULESET.javascript_escape}, ) - def test_javascript_interpolate(self, data): + def test_javascript_escape(self, data): """ Test check_javascript_file_is_safe with interpolate() """ diff --git a/scripts/xsslint/xsslint/linters.py b/scripts/xsslint/xsslint/linters.py index d345483f0d0fa5dd913db589495fc778eee06855..50ef4b0ba468f6178bc0d4d58b619d66fd9352f9 100644 --- a/scripts/xsslint/xsslint/linters.py +++ b/scripts/xsslint/xsslint/linters.py @@ -329,7 +329,6 @@ class JavaScriptLinter(BaseLinter): javascript_jquery_html='javascript-jquery-html', javascript_concat_html='javascript-concat-html', javascript_escape='javascript-escape', - javascript_interpolate='javascript-interpolate', ) def __init__(self, underscore_linter, javascript_skip_dirs=None): @@ -401,7 +400,6 @@ class JavaScriptLinter(BaseLinter): file_contents, "html", self.ruleset.javascript_jquery_html, no_caller_check, self._is_jquery_html_argument_safe, results ) - self._check_javascript_interpolate(file_contents, results) self._check_javascript_escape(file_contents, results) self._check_concat_with_html(file_contents, self.ruleset.javascript_concat_html, results) self.underscore_linter.check_underscore_file_is_safe(file_contents, results) @@ -435,37 +433,18 @@ class JavaScriptLinter(BaseLinter): expression = Expression(start_index) return expression - def _check_javascript_interpolate(self, file_contents, results): - """ - Checks that interpolate() calls are safe. - - Only use of StringUtils.interpolate() or HtmlUtils.interpolateText() - are safe. - - Arguments: - file_contents: The contents of the JavaScript file. - results: A file results objects to which violations will be added. - - """ - # Ignores calls starting with "StringUtils.", because those are safe - regex = re.compile(r"(?<!StringUtils).interpolate\(") - for function_match in regex.finditer(file_contents): - expression = self._get_expression_for_function(file_contents, function_match) - results.violations.append(ExpressionRuleViolation(self.ruleset.javascript_interpolate, expression)) - def _check_javascript_escape(self, file_contents, results): """ - Checks that only necessary escape() are used. - - Allows for _.escape(), although this shouldn't be the recommendation. + Checks that escape() is not used. escape() is not recommended. + ref. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape Arguments: file_contents: The contents of the JavaScript file. results: A file results objects to which violations will be added. """ - # Ignores calls starting with "_.", because those are safe - regex = regex = re.compile(r"(?<!_).escape\(") + # Regex to match uses of escape() or window.escape(). + regex = re.compile(r"(?:^|(?<=window\.)|(?<![\w.$]))escape\(") for function_match in regex.finditer(file_contents): expression = self._get_expression_for_function(file_contents, function_match) results.violations.append(ExpressionRuleViolation(self.ruleset.javascript_escape, expression)) diff --git a/scripts/xsslint_thresholds.json b/scripts/xsslint_thresholds.json index 92dcf35764020c3977a688435f831be3565eadac..bd51cf7943a3f9202284019d551836cb8f3f9295 100644 --- a/scripts/xsslint_thresholds.json +++ b/scripts/xsslint_thresholds.json @@ -1,19 +1,18 @@ { "rules": { - "javascript-concat-html": 142, - "javascript-escape": 7, - "javascript-interpolate": 23, - "javascript-jquery-append": 68, - "javascript-jquery-html": 146, + "javascript-concat-html": 100, + "javascript-escape": 5, + "javascript-jquery-append": 50, + "javascript-jquery-html": 112, "javascript-jquery-insert-into-target": 18, - "javascript-jquery-insertion": 19, - "javascript-jquery-prepend": 6, + "javascript-jquery-insertion": 14, + "javascript-jquery-prepend": 5, "mako-html-entities": 0, - "mako-invalid-html-filter": 7, - "mako-invalid-js-filter": 59, + "mako-invalid-html-filter": 5, + "mako-invalid-js-filter": 20, "mako-js-html-string": 0, "mako-js-missing-quotes": 0, - "mako-missing-default": 83, + "mako-missing-default": 67, "mako-multiple-page-tags": 0, "mako-unknown-context": 0, "mako-unparseable-expression": 0, @@ -22,20 +21,20 @@ "python-concat-html": 0, "python-custom-escape": 5, "python-deprecated-display-name": 4, - "python-interpolate-html": 26, + "python-interpolate-html": 23, "python-parse-error": 0, "python-requires-html-or-text": 0, - "python-wrap-html": 68, - "underscore-not-escaped": 437, - "django-trans-missing-escape": 18, + "python-wrap-html": 32, + "underscore-not-escaped": 399, + "django-trans-missing-escape": 13, "django-trans-invalid-escape-filter": 0, "django-trans-escape-variable-mismatch": 0, - "django-blocktrans-missing-escape-filter": 12, + "django-blocktrans-missing-escape-filter": 7, "django-blocktrans-parse-error": 0, "django-blocktrans-escape-filter-parse-error": 0, "django-html-interpolation-missing-safe-filter": 0, - "django-html-interpolation-missing": 1, + "django-html-interpolation-missing": 0, "django-html-interpolation-invalid-tag": 0 }, - "total": 1150 + "total": 888 } diff --git a/setup.cfg b/setup.cfg index 177cd5220a3427fa6904e022d7b08351fdf903a8..954ce7b8186e8d81ba03367e45db4094a41701e3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,10 +16,10 @@ python_files = tests.py test_*.py tests_*.py *_tests.py __init__.py [pycodestyle] # error codes: https://pycodestyle.readthedocs.io/en/latest/intro.html#error-codes # E501: line too long -# E265: block comment should start with ‘# ‘ +# E265: block comment should start with '# ' # We ignore this because pep8 used to erroneously lump E266 into it also. # We should probably fix these now. -# E266: too many leading ‘#’ for block comment +# E266: too many leading '#' for block comment # We have lots of comments that look like "##### HEADING #####" which violate # this rule, because they don't have a space after the first #. However, # they're still perfectly reasonable comments, so we disable this rule. diff --git a/setup.py b/setup.py index 86259da331cb6fe3e5c7226d1d896d83080e01b3..257131cb2e1ea1e466cb4d21ce9a9dc5af3dc355 100644 --- a/setup.py +++ b/setup.py @@ -42,6 +42,7 @@ setup( "course_updates = openedx.features.course_experience.plugins:CourseUpdatesTool", "course_reviews = openedx.features.course_experience.plugins:CourseReviewsTool", "verified_upgrade = lms.djangoapps.courseware.course_tools:VerifiedUpgradeTool", + "financial_assistance = lms.djangoapps.courseware.course_tools:FinancialAssistanceTool", ], "openedx.user_partition_scheme": [ "random = openedx.core.djangoapps.user_api.partition_schemes:RandomUserPartitionScheme", @@ -108,5 +109,9 @@ setup( 'openedx.learning_context': [ 'lib = openedx.core.djangoapps.content_libraries.library_context:LibraryContextImpl', ], + 'openedx.dynamic_partition_generator': [ + 'enrollment_track = common.lib.xmodule.xmodule.partitions.enrollment_track_partition_generator:create_enrollment_track_partition', + 'content_type_gating = openedx.features.content_type_gating.partitions:create_content_gating_partition' + ], } ) diff --git a/themes/edge.edx.org/lms/static/sass/partials/lms/theme/_certificates.scss b/themes/edge.edx.org/lms/static/sass/partials/lms/theme/_certificates.scss index e6f97bb693e492e13622dad73deecff7713b5595..7a01da04188d2d128e29fd3f98ca78dd946f689b 100644 --- a/themes/edge.edx.org/lms/static/sass/partials/lms/theme/_certificates.scss +++ b/themes/edge.edx.org/lms/static/sass/partials/lms/theme/_certificates.scss @@ -4,7 +4,8 @@ // Note: edx.org no longer supports audit certificates, but there are // legacy certificates that might be rendered. In this situation, they // are styled as honor certificates. - &.mode-honor, &.mode-audit { + &.mode-honor, + &.mode-audit { border-color: $honor-mode-color; .card-logo { diff --git a/themes/edx.org/lms/static/images/quote_prompt.png b/themes/edx.org/lms/static/images/quote_prompt.png new file mode 100644 index 0000000000000000000000000000000000000000..d183adb69cf6db1b85a7cef4d37b08f5e5533fc3 Binary files /dev/null and b/themes/edx.org/lms/static/images/quote_prompt.png differ diff --git a/themes/edx.org/lms/static/sass/partials/lms/theme/_dashboard.scss b/themes/edx.org/lms/static/sass/partials/lms/theme/_dashboard.scss new file mode 100644 index 0000000000000000000000000000000000000000..5cc422202d85f8af0976ac5a2f09dd392ec57e0b --- /dev/null +++ b/themes/edx.org/lms/static/sass/partials/lms/theme/_dashboard.scss @@ -0,0 +1,58 @@ +.dashboard { + .demographics-banner { + background-color: #23419f; + border-radius: 12px; + @media (min-width: 1200px) { + height: 64px; + } + .demographics-banner-icon { + height: 140px; + } + .demographics-banner-prompt { + font-size: 24px; + line-height: 24px; + } + .demographics-banner-btn { + color: #23419f; + border-radius: 20px; + font-size: 14px; + min-width: 150px; + /* Below are to override the overly-broad `button` selectors in lms/static/sass/shared/_forms.scss */ + box-shadow: unset; + text-shadow: unset; + font: unset; + letter-spacing: unset; + background-image: unset; + + .fa-thumbs-up { + font-size: 24px; + } + } + } + .side-container { + .wrapper-coaching { + border: 1px solid $gray-500; + margin-bottom: $baseline * 0.5; + + .coaching-signup { + padding: 20px; + + .coaching-prompt { + font-size: 20px; + line-height: 28px; + font-weight: bold; + } + + + .coaching-link .btn-neutral { + display: block; + text-align: center; + margin: 20px 20px 0; + border-radius: 20px; + padding: 10px; + border: 1px solid theme-color('primary'); + } + } + } + } +} diff --git a/themes/edx.org/lms/static/sass/partials/lms/theme/_extras.scss b/themes/edx.org/lms/static/sass/partials/lms/theme/_extras.scss index 449252f3ffebb36799e45b7b18861319066d7054..1f104fa2e0a77224f4a2da1b2f75a692e9c8070a 100644 --- a/themes/edx.org/lms/static/sass/partials/lms/theme/_extras.scss +++ b/themes/edx.org/lms/static/sass/partials/lms/theme/_extras.scss @@ -7,6 +7,7 @@ // rules into modular pieces. @import 'certificates'; +@import 'dashboard'; // Ensure the header matches the edx.org marketing site header @@ -14,7 +15,7 @@ @include media-breakpoint-down(md) { margin-left: calc(50% - 30px) !important; - .logo{ + .logo { margin-left: 0 !important; width: $header-logo-width; height: auto !important; diff --git a/themes/edx.org/lms/templates/dashboard.html b/themes/edx.org/lms/templates/dashboard.html index b3f7276bdaf6165f97da073977143b37086b982a..4538d6cd428fc5e454fe2575882c3417e9376b13 100644 --- a/themes/edx.org/lms/templates/dashboard.html +++ b/themes/edx.org/lms/templates/dashboard.html @@ -136,16 +136,30 @@ from student.models import CourseEnrollment % endfor </div> %endif - - ${static.renderReact( - component="EnterpriseLearnerPortalBanner", - id="enterprise-learner-portal-banner", - props={} - )} </div> <section class="dashboard" id="dashboard-main"> <main class="main-container" id="main" aria-label="Content" tabindex="-1"> + <% + MB_SLUG = "microbachelors" + enrolled_in_mb_program = MB_SLUG in enrolled_program_types + account_mfe_url = getattr(settings, 'ACCOUNT_MICROFRONTEND_URL', '') or '' + %> + % if getattr(settings, 'ENABLE_DEMOGRAPHICS_COLLECTION', False) and enrolled_in_mb_program: + <a href="${account_mfe_url}#demographics"> + <div + class="demographics-banner d-flex justify-content-left align-items-center flex-column flex-lg-row py-1 px-4 mb-2 mb-lg-4"> + <img class="demographics-banner-icon d-none d-lg-inline-block" src="${static.url('edx.org/images/quote_prompt.png')}" alt="" aria-hidden="true"> + <div class="demographics-banner-prompt d-inline-block font-weight-bold text-white py-4 px-2 px-lg-3"> + ${_("Want to make edX better for everyone?")} + </div> + <button class="demographics-banner-btn d-flex align-items-center bg-white font-weight-bold border-0 py-2 px-3 mx-2 mb-3 m-lg-0 shadow"> + <span class="fa fa-thumbs-up px-2" aria-hidden="true"></span> + ${_("Get started")} + </button> + </div> + </a> + % endif <section class="my-courses" id="my-courses"> <header class="wrapper-header-courses"> <h2 class="header-courses">${_("My Courses")}</h2> @@ -185,7 +199,10 @@ from student.models import CourseEnrollment pseudo_session = unfulfilled_entitlement_pseudo_sessions[str(entitlement.uuid)] if not pseudo_session: continue - enrollment = CourseEnrollment(user=user, course=CourseOverview.get_from_id(pseudo_session['key']), mode=pseudo_session['type']) + pseudo_key = pseudo_session['key'] + if not isinstance(pseudo_key, CourseKey): + pseudo_key = CourseKey.from_string(pseudo_session['key']) + enrollment = CourseEnrollment(user=user, course=CourseOverview.get_from_id(pseudo_key), mode=pseudo_session['type']) # We only show email settings for entitlement cards if the entitlement has an associated enrollment show_email_settings = is_fulfilled_entitlement and (entitlement_session.course_id in show_email_settings_for) else: @@ -199,7 +216,6 @@ from student.models import CourseEnrollment credit_status = credit_statuses.get(session_id) course_mode_info = all_course_modes.get(session_id) is_paid_course = True if entitlement else (session_id in enrolled_courses_either_paid) - is_course_blocked = (session_id in block_courses) course_verification_status = verification_status_by_course.get(session_id, {}) course_requirements = courses_requirements_not_met.get(session_id) related_programs = inverted_programs.get(six.text_type(entitlement.course_uuid if is_unfulfilled_entitlement else session_id)) @@ -207,7 +223,7 @@ from student.models import CourseEnrollment course_overview = enrollment.course_overview resume_button_url = resume_button_urls[dashboard_index] %> - <%include file='dashboard/_dashboard_course_listing.html' args='course_overview=course_overview, course_card_index=dashboard_index, enrollment=enrollment, is_unfulfilled_entitlement=is_unfulfilled_entitlement, is_fulfilled_entitlement=is_fulfilled_entitlement, entitlement=entitlement, entitlement_session=entitlement_session, entitlement_available_sessions=entitlement_available_sessions, entitlement_expiration_date=entitlement_expiration_date, entitlement_expired_at=entitlement_expired_at, show_courseware_link=show_courseware_link, cert_status=cert_status, can_refund_entitlement=can_refund_entitlement, can_unenroll=can_unenroll, credit_status=credit_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, is_paid_course=is_paid_course, is_course_blocked=is_course_blocked, verification_status=course_verification_status, course_requirements=course_requirements, dashboard_index=dashboard_index, share_settings=share_settings, user=user, related_programs=related_programs, display_course_modes_on_dashboard=display_course_modes_on_dashboard, show_consent_link=show_consent_link, enterprise_customer_name=enterprise_customer_name, resume_button_url=resume_button_url' /> + <%include file='dashboard/_dashboard_course_listing.html' args='course_overview=course_overview, course_card_index=dashboard_index, enrollment=enrollment, is_unfulfilled_entitlement=is_unfulfilled_entitlement, is_fulfilled_entitlement=is_fulfilled_entitlement, entitlement=entitlement, entitlement_session=entitlement_session, entitlement_available_sessions=entitlement_available_sessions, entitlement_expiration_date=entitlement_expiration_date, entitlement_expired_at=entitlement_expired_at, show_courseware_link=show_courseware_link, cert_status=cert_status, can_refund_entitlement=can_refund_entitlement, can_unenroll=can_unenroll, credit_status=credit_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, is_paid_course=is_paid_course, verification_status=course_verification_status, course_requirements=course_requirements, dashboard_index=dashboard_index, share_settings=share_settings, user=user, related_programs=related_programs, display_course_modes_on_dashboard=display_course_modes_on_dashboard, show_consent_link=show_consent_link, enterprise_customer_name=enterprise_customer_name, resume_button_url=resume_button_url' /> % endfor % if show_load_all_courses_link: <br/> @@ -288,7 +304,10 @@ from student.models import CourseEnrollment </div> % endif - <% account_mfe_url = getattr(settings, 'ACCOUNT_MICROFRONTEND_URL', '') or '' %> + <% + account_mfe_url = getattr(settings, 'ACCOUNT_MICROFRONTEND_URL', '') or '' + coaching_consent_url = "%s/coaching_consent?next=%s" % (account_mfe_url, getattr(settings, 'LMS_ROOT_URL', '') + reverse('dashboard')) + %> % if plugins.get("coaching", {}).get("show_coaching_aside"): <div class="wrapper-coaching"> <div class="coaching-signup"> @@ -296,7 +315,7 @@ from student.models import CourseEnrollment ${_("Take advantage of free coaching!")} </div> <div class="coaching-link"> - <a class="btn-neutral" href="${account_mfe_url}"> + <a class="btn-neutral" href="${coaching_consent_url}"> ${_("Get Started")} </a> </div> diff --git a/themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html b/themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html index 5329d60b265470cc7683d759e0af8a7197fd3b60..025fc3a20b5764f2df57ddb3699bffb8ea747e95 100644 --- a/themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html +++ b/themes/edx.org/lms/templates/dashboard/_dashboard_course_resume.html @@ -1,8 +1,10 @@ -<%page args="resume_button_url, course_overview, enrollment, is_unfulfilled_entitlement, is_course_blocked, course_target, related_programs" expression_filter="h"/> +<%page args="resume_button_url, course_overview, enrollment, is_unfulfilled_entitlement, course_target, related_programs" expression_filter="h"/> <%! import six from django.utils.translation import ugettext as _ + +MICROBACHELORS_SLUG = 'microbachelors' %> % if resume_button_url != '': @@ -11,7 +13,7 @@ from django.utils.translation import ugettext as _ show_coaching_consent_form = plugins.get("coaching", {}).get("show_coaching_consent_form") if related_programs and account_mfe_url != '' and show_coaching_consent_form: for program in related_programs: - if program.get('type') == 'MicroBachelors': + if program.get('type_attrs', {}).get('slug') == MICROBACHELORS_SLUG: resume_button_url = "%s/coaching_consent?next=%s" % (account_mfe_url, getattr(settings, 'LMS_ROOT_URL', '') + resume_button_url) %> <a href="${resume_button_url}" @@ -22,13 +24,13 @@ from django.utils.translation import ugettext as _ ${course_overview.display_name_with_default} </span> </a> -% elif not is_course_blocked: +% else: <% account_mfe_url = getattr(settings, 'ACCOUNT_MICROFRONTEND_URL', '') or '' show_coaching_consent_form = plugins.get("coaching", {}).get("show_coaching_consent_form") if related_programs and account_mfe_url != '' and show_coaching_consent_form: for program in related_programs: - if program.get('type') == 'MicroBachelors': + if program.get('type_attrs', {}).get('slug') == MICROBACHELORS_SLUG: course_target = "%s/coaching_consent?next=%s" % (account_mfe_url, getattr(settings, 'LMS_ROOT_URL', '') + course_target) %> <a href="${course_target}" @@ -39,12 +41,4 @@ from django.utils.translation import ugettext as _ ${course_overview.display_name_with_default} </span> </a> -% else: - <a class="enter-course-blocked" - data-course-key="${enrollment.course_id}"> - ${_('View Course')} - <span class="sr"> - ${course_overview.display_name_with_default} - </span> - </a> % endif diff --git a/themes/edx.org/lms/templates/header/navbar-authenticated.html b/themes/edx.org/lms/templates/header/navbar-authenticated.html index 23495cfa052d1b35d102bbfe0e5b1faeb1e7518f..5d595aadb7502767d67f5047d86f1494d81a6ced 100644 --- a/themes/edx.org/lms/templates/header/navbar-authenticated.html +++ b/themes/edx.org/lms/templates/header/navbar-authenticated.html @@ -58,13 +58,6 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_ </div> <div class="secondary"> - % if should_display_shopping_cart_func() and not (course and static.is_request_in_themed_site()): # see shoppingcart.context_processor.user_has_cart_context_processor - <div class="mobile-nav-item hidden-mobile nav-item"> - <a class="shopping-cart" href="${reverse('shoppingcart.views.show_cart')}"> - <span class="icon fa fa-shopping-cart" aria-hidden="true"></span> ${_("Shopping Cart")} - </a> - </div> - % endif <div class="mobile-nav-item hidden-mobile nav-item"> % if online_help_token == "instructor": <a class="help-link" href="${get_online_help_info(online_help_token)['doc_url']}" rel="noopener" target="_blank">${_("Help")}</a> diff --git a/themes/red-theme/lms/templates/ace_common/edx_ace/common/base_body.html b/themes/red-theme/lms/templates/ace_common/edx_ace/common/base_body.html index 548fa6dc878d0d93e33284a4699985200b79071e..8d51b16498d7e9f1c0a9f36a9ccc9e1ddfb2de98 100644 --- a/themes/red-theme/lms/templates/ace_common/edx_ace/common/base_body.html +++ b/themes/red-theme/lms/templates/ace_common/edx_ace/common/base_body.html @@ -64,7 +64,7 @@ <td width="70"> <a href="{% with_link_tracking homepage_url %}"><img src="http://localhost:18000/static/red-theme/images/logo.png" - alt="{% blocktrans %}Go to {{ platform_name }} Home Page{% endblocktrans %}"/></a> + alt="{% filter force_escape %} {% blocktrans %}Go to {{ platform_name }} Home Page{% endblocktrans %} {% endfilter %}"/></a> </td> <td align="right" style="text-align: {{ LANGUAGE_BIDI|yesno:"left,right" }};"> <a class="login" href="{% with_link_tracking dashboard_url %}" style="color: #960909;">{% trans "Sign In" %}</a> @@ -97,7 +97,7 @@ <td height="32" width="42"> <a href="{{ social_media_urls.linkedin|safe }}"> <img src="https://media.sailthru.com/595/1k1/8/o/599f354ec70cb.png" - width="32" height="32" alt="{% blocktrans %}{{ platform_name }} on LinkedIn{% endblocktrans %}"/> + width="32" height="32" alt="{% filter force_escape %} {% blocktrans %}{{ platform_name }} on LinkedIn{% endblocktrans %} {% endfilter %}"/> </a> </td> {% endif %} @@ -105,7 +105,7 @@ <td height="32" width="42"> <a href="{{ social_media_urls.twitter|safe }}"> <img src="https://media.sailthru.com/595/1k1/8/o/599f354d9c26e.png" - width="32" height="32" alt="{% blocktrans %}{{ platform_name }} on Twitter{% endblocktrans %}"/> + width="32" height="32" alt="{% filter force_escape %} {% blocktrans %}{{ platform_name }} on Twitter{% endblocktrans %} {% endfilter %}"/> </a> </td> {% endif %} @@ -113,7 +113,7 @@ <td height="32" width="42"> <a href="{{ social_media_urls.facebook|safe }}"> <img src="https://media.sailthru.com/595/1k1/8/o/599f355052c8e.png" - width="32" height="32" alt="{% blocktrans %}{{ platform_name }} on Facebook{% endblocktrans %}"/> + width="32" height="32" alt="{% filter force_escape %} {% blocktrans %}{{ platform_name }} on Facebook{% endblocktrans %} {% endfilter %}"/> </a> </td> {% endif %} @@ -121,7 +121,7 @@ <td height="32" width="42"> <a href="{{ social_media_urls.google_plus|safe }}"> <img src="https://media.sailthru.com/595/1k1/8/o/599f354fc554a.png" - width="32" height="32" alt="{% blocktrans %}{{ platform_name }} on Google Plus{% endblocktrans %}"/> + width="32" height="32" alt="{% filter force_escape %} {% blocktrans %}{{ platform_name }} on Google Plus{% endblocktrans %} {% endfilter %}"/> </a> </td> {% endif %} @@ -129,7 +129,7 @@ <td height="32" width="42"> <a href="{{ social_media_urls.reddit|safe }}"> <img src="https://media.sailthru.com/595/1k1/8/o/599f354e326b9.png" - width="32" height="32" alt="{% blocktrans %}{{ platform_name }} on Reddit{% endblocktrans %}"/> + width="32" height="32" alt="{% filter force_escape %} {% blocktrans %}{{ platform_name }} on Reddit{% endblocktrans %} {% endfilter %}"/> </a> </td> {% endif %} @@ -143,14 +143,14 @@ {% if mobile_store_urls.apple %} <a href="{{ mobile_store_urls.apple|safe }}" style="text-decoration: none"> <img src="https://media.sailthru.com/595/1k1/6/2/5931cfbba391b.png" - alt="{% trans "Download the iOS app on the Apple Store" %}" + alt="{% trans "Download the iOS app on the Apple Store" as tmsg %}{{ tmsg | force_escape }}" width="136" height="50" style="margin-{{ LANGUAGE_BIDI|yesno:"left,right" }}: 10px"/> </a> {% endif %} {% if mobile_store_urls.google %} <a href="{{ mobile_store_urls.google|safe }}" style="text-decoration: none"> <img src="https://media.sailthru.com/595/1k1/6/2/5931cf879a033.png" - alt="{% trans "Download the Android app on the Google Play Store" %}" + alt="{% trans "Download the Android app on the Google Play Store" as tmsg %}{{ tmsg | force_escape }}" width="136" height="50"/> </a> {% endif %} @@ -171,9 +171,9 @@ <tr> <!-- COPYRIGHT --> <td> - © {% now "Y" %} {{ platform_name }}, {% trans "All rights reserved" %}.<br/> + © {% now "Y" %} {{ platform_name }}, {% trans "All rights reserved" as tmsg %}{{ tmsg | force_escape }}.<br/> <br/> - {% trans "Our mailing address is" %}:<br/> + {% trans "Our mailing address is" as tmsg %}{{ tmsg | force_escape }}:<br/> {{ contact_mailing_address }} </td> </tr> diff --git a/themes/stanford-style/lms/templates/courseware/course_about_sidebar_header.html b/themes/stanford-style/lms/templates/courseware/course_about_sidebar_header.html index e1694ce3d06fd5ce40a458397203d1c673a1c5a3..ee6566d91cdfddd65c177a09f12867224bc4108e 100644 --- a/themes/stanford-style/lms/templates/courseware/course_about_sidebar_header.html +++ b/themes/stanford-style/lms/templates/courseware/course_about_sidebar_header.html @@ -1,3 +1,4 @@ +<%page expression_filter="h"/> <%! from django.utils.translation import ugettext as _ %> @@ -5,10 +6,10 @@ from django.utils.translation import ugettext as _ <header> <div class="social-sharing"> <div class="sharing-message">${_("Share with friends and family!")}</div> - <a href="http://twitter.com/intent/tweet?text=I+just+enrolled+in+${course.number}+${course.display_name_with_default_escaped}!+(http://class.stanford.edu)" class="share"> + <a href="http://twitter.com/intent/tweet?text=I+just+enrolled+in+${course.number}+${course.display_name_with_default}!+(http://class.stanford.edu)" class="share"> <span class="icon fa fa-twitter" aria-hidden="true"></span><span class="sr">${_("Tweet that you've enrolled in this course")}</span> </a> - <a href="mailto:?subject=Take%20a%20course%20at%20Stanford%20online!&body=I%20just%20enrolled%20in%20${course.number}%20${course.display_name_with_default_escaped}+(http://class.stanford.edu)" class="share"> + <a href="mailto:?subject=Take%20a%20course%20at%20Stanford%20online!&body=I%20just%20enrolled%20in%20${course.number}%20${course.display_name_with_default}+(http://class.stanford.edu)" class="share"> <span class="icon fa fa-envelope" aria-hidden="true"></span><span class="sr">${_("Email someone to say you've enrolled in this course")}</span> </a> </div> diff --git a/tox.ini b/tox.ini index c9fb47e6fcdb361eb997b1451dcd72176ef68412..06e8fbca9d91f95119e5fe1b0c9f7b186e233762 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{35,36,37}-django{111,20,21,22} +envlist = py{35}-django{22},py{38}-django{22,30} # This is needed to prevent the lms, cms, and openedx packages inside the "Open # edX" package (defined in setup.py) from getting installed into site-packages @@ -68,10 +68,8 @@ passenv = XDIST_WORKER_SUBNET deps = - django111: -r requirements/edx/django111.txt - django20: -r requirements/edx/django20.txt - django21: -r requirements/edx/django21.txt django22: -r requirements/edx/django.txt + django30: -r requirements/edx/django30.txt -r requirements/edx/testing.txt whitelist_externals = /bin/bash diff --git a/webpack.common.config.js b/webpack.common.config.js index 565a102d0e4461a3c58a85bf5a2d7d9eae80f08d..1dae57f447396d9b50061a97830fd30fb0b7c2b3 100644 --- a/webpack.common.config.js +++ b/webpack.common.config.js @@ -58,7 +58,7 @@ var workerConfig = function() { extensions: ['.js'] } } - } + }; } catch (err) { return null; } @@ -92,8 +92,6 @@ module.exports = Merge.smart({ StudentAccountDeletion: './lms/static/js/student_account/components/StudentAccountDeletion.jsx', StudentAccountDeletionInitializer: './lms/static/js/student_account/StudentAccountDeletionInitializer.js', ProblemBrowser: './lms/djangoapps/instructor/static/instructor/ProblemBrowser/index.jsx', - CustomUserMenuLinks: './lms/static/js/custom_user_menu_links/CustomUserMenuLinks.js', - EnterpriseLearnerPortalBanner: './lms/static/js/learner_dashboard/EnterpriseLearnerPortalBanner.jsx', // Learner Dashboard EntitlementFactory: './lms/static/js/learner_dashboard/course_entitlement_factory.js', diff --git a/webpack.dev.config.js b/webpack.dev.config.js index c560486dd3e89c3ea539566d264b304e5a19b037..913d773caca3da41851f8602c65c88ca2d2beb6a 100644 --- a/webpack.dev.config.js +++ b/webpack.dev.config.js @@ -20,10 +20,7 @@ module.exports = _.values(Merge.smart(commonConfig, { debug: true }), new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify('development'), - 'process.env.LMS_ROOT_URL': JSON.stringify('https://localhost:18000'), - 'process.env.JWT_AUTH_COOKIE_HEADER_PAYLOAD': JSON.stringify('edx-jwt-cookie-header-payload'), - 'process.env.EDXMKTG_USER_INFO_COOKIE_NAME': JSON.stringify('edx-user-info') + 'process.env.NODE_ENV': JSON.stringify('development') }) ], module: { diff --git a/webpack.prod.config.js b/webpack.prod.config.js index 23c87f8ecd192746ee52b9ac08a4d9d13fb4005b..360ab56d4d01db713ac0b6965b4e8a7b2a33847c 100644 --- a/webpack.prod.config.js +++ b/webpack.prod.config.js @@ -17,10 +17,7 @@ var optimizedConfig = Merge.smart(commonConfig, { devtool: false, plugins: [ new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify('production'), - 'process.env.LMS_ROOT_URL': JSON.stringify(process.env.LMS_ROOT_URL), - 'process.env.JWT_AUTH_COOKIE_HEADER_PAYLOAD': JSON.stringify(process.env.JWT_AUTH_COOKIE_HEADER_PAYLOAD), - 'process.env.EDXMKTG_USER_INFO_COOKIE_NAME': JSON.stringify(process.env.EDXMKTG_USER_INFO_COOKIE_NAME) + 'process.env.NODE_ENV': JSON.stringify('production') }), new webpack.LoaderOptionsPlugin({ // This may not be needed; legacy option for loaders written for webpack 1 minimize: true